forked from github/plane
chore: enable/disable signup in self hosted environments (#1271)
* dev: new onboarding workflow for self hosted instance * dev: additional flag on user creation * dev: segregate sign up and sign in endpoint * dev: update sign in endpoint for not existing users
This commit is contained in:
parent
02111d779b
commit
592fe94cb4
@ -65,4 +65,6 @@ NGINX_PORT=80
|
|||||||
DEFAULT_EMAIL="captain@plane.so"
|
DEFAULT_EMAIL="captain@plane.so"
|
||||||
DEFAULT_PASSWORD="password123"
|
DEFAULT_PASSWORD="password123"
|
||||||
|
|
||||||
|
# SignUps
|
||||||
|
ENABLE_SIGNUP="1"
|
||||||
# Auto generated and Required that will be generated from setup.sh
|
# Auto generated and Required that will be generated from setup.sh
|
@ -5,6 +5,7 @@ from django.urls import path
|
|||||||
|
|
||||||
from plane.api.views import (
|
from plane.api.views import (
|
||||||
# Authentication
|
# Authentication
|
||||||
|
SignUpEndpoint,
|
||||||
SignInEndpoint,
|
SignInEndpoint,
|
||||||
SignOutEndpoint,
|
SignOutEndpoint,
|
||||||
MagicSignInEndpoint,
|
MagicSignInEndpoint,
|
||||||
@ -154,6 +155,7 @@ urlpatterns = [
|
|||||||
# Social Auth
|
# Social Auth
|
||||||
path("social-auth/", OauthEndpoint.as_view(), name="oauth"),
|
path("social-auth/", OauthEndpoint.as_view(), name="oauth"),
|
||||||
# Auth
|
# Auth
|
||||||
|
path("sign-up/", SignUpEndpoint.as_view(), name="sign-up"),
|
||||||
path("sign-in/", SignInEndpoint.as_view(), name="sign-in"),
|
path("sign-in/", SignInEndpoint.as_view(), name="sign-in"),
|
||||||
path("sign-out/", SignOutEndpoint.as_view(), name="sign-out"),
|
path("sign-out/", SignOutEndpoint.as_view(), name="sign-out"),
|
||||||
# Magic Sign In/Up
|
# Magic Sign In/Up
|
||||||
|
@ -79,6 +79,7 @@ from .auth_extended import (
|
|||||||
|
|
||||||
|
|
||||||
from .authentication import (
|
from .authentication import (
|
||||||
|
SignUpEndpoint,
|
||||||
SignInEndpoint,
|
SignInEndpoint,
|
||||||
SignOutEndpoint,
|
SignOutEndpoint,
|
||||||
MagicSignInEndpoint,
|
MagicSignInEndpoint,
|
||||||
|
@ -36,11 +36,19 @@ def get_tokens_for_user(user):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SignInEndpoint(BaseAPIView):
|
class SignUpEndpoint(BaseAPIView):
|
||||||
permission_classes = (AllowAny,)
|
permission_classes = (AllowAny,)
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
try:
|
try:
|
||||||
|
if not settings.ENABLE_SIGNUP:
|
||||||
|
return Response(
|
||||||
|
{
|
||||||
|
"error": "New account creation is disabled. Please contact your site administrator"
|
||||||
|
},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
|
||||||
email = request.data.get("email", False)
|
email = request.data.get("email", False)
|
||||||
password = request.data.get("password", False)
|
password = request.data.get("password", False)
|
||||||
|
|
||||||
@ -61,10 +69,13 @@ class SignInEndpoint(BaseAPIView):
|
|||||||
status=status.HTTP_400_BAD_REQUEST,
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
user = User.objects.filter(email=email).first()
|
# Check if the user already exists
|
||||||
|
if User.objects.filter(email=email).exists():
|
||||||
|
return Response(
|
||||||
|
{"error": "User already exist please sign in"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
|
||||||
# Sign up Process
|
|
||||||
if user is None:
|
|
||||||
user = User.objects.create(email=email, username=uuid.uuid4().hex)
|
user = User.objects.create(email=email, username=uuid.uuid4().hex)
|
||||||
user.set_password(password)
|
user.set_password(password)
|
||||||
|
|
||||||
@ -109,8 +120,51 @@ class SignInEndpoint(BaseAPIView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return Response(data, status=status.HTTP_200_OK)
|
return Response(data, status=status.HTTP_200_OK)
|
||||||
# Sign in Process
|
|
||||||
else:
|
except Exception as e:
|
||||||
|
capture_exception(e)
|
||||||
|
return Response(
|
||||||
|
{"error": "Something went wrong please try again later"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SignInEndpoint(BaseAPIView):
|
||||||
|
permission_classes = (AllowAny,)
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
try:
|
||||||
|
email = request.data.get("email", False)
|
||||||
|
password = request.data.get("password", False)
|
||||||
|
|
||||||
|
## Raise exception if any of the above are missing
|
||||||
|
if not email or not password:
|
||||||
|
return Response(
|
||||||
|
{"error": "Both email and password are required"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
|
||||||
|
email = email.strip().lower()
|
||||||
|
|
||||||
|
try:
|
||||||
|
validate_email(email)
|
||||||
|
except ValidationError as e:
|
||||||
|
return Response(
|
||||||
|
{"error": "Please provide a valid email address."},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
|
||||||
|
user = User.objects.filter(email=email).first()
|
||||||
|
|
||||||
|
if user is None:
|
||||||
|
return Response(
|
||||||
|
{
|
||||||
|
"error": "Sorry, we could not find a user with the provided credentials. Please try again."
|
||||||
|
},
|
||||||
|
status=status.HTTP_403_FORBIDDEN,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sign up Process
|
||||||
if not user.check_password(password):
|
if not user.check_password(password):
|
||||||
return Response(
|
return Response(
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import jwt
|
import jwt
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
from uuid import uuid4
|
||||||
# Django imports
|
# Django imports
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
from django.db.models import Prefetch
|
from django.db.models import Prefetch
|
||||||
@ -249,6 +249,17 @@ class InviteWorkspaceEndpoint(BaseAPIView):
|
|||||||
email__in=[email.get("email") for email in emails]
|
email__in=[email.get("email") for email in emails]
|
||||||
).select_related("workspace")
|
).select_related("workspace")
|
||||||
|
|
||||||
|
# create the user if signup is disabled
|
||||||
|
if settings.DOCKERIZED and not settings.ENABLE_SIGNUP:
|
||||||
|
_ = User.objects.bulk_create([
|
||||||
|
User(
|
||||||
|
email=email.get("email"),
|
||||||
|
password=str(uuid4().hex),
|
||||||
|
is_password_autoset=True
|
||||||
|
)
|
||||||
|
for email in emails
|
||||||
|
], batch_size=100)
|
||||||
|
|
||||||
for invitation in workspace_invitations:
|
for invitation in workspace_invitations:
|
||||||
workspace_invitation.delay(
|
workspace_invitation.delay(
|
||||||
invitation.email,
|
invitation.email,
|
||||||
|
@ -91,3 +91,5 @@ CELERY_RESULT_BACKEND = os.environ.get("REDIS_URL")
|
|||||||
CELERY_BROKER_URL = os.environ.get("REDIS_URL")
|
CELERY_BROKER_URL = os.environ.get("REDIS_URL")
|
||||||
|
|
||||||
GITHUB_ACCESS_TOKEN = os.environ.get("GITHUB_ACCESS_TOKEN", False)
|
GITHUB_ACCESS_TOKEN = os.environ.get("GITHUB_ACCESS_TOKEN", False)
|
||||||
|
|
||||||
|
ENABLE_SIGNUP = os.environ.get("ENABLE_SIGNUP", "1") == "1"
|
@ -258,3 +258,6 @@ else:
|
|||||||
CELERY_BROKER_URL = broker_url
|
CELERY_BROKER_URL = broker_url
|
||||||
|
|
||||||
GITHUB_ACCESS_TOKEN = os.environ.get("GITHUB_ACCESS_TOKEN", False)
|
GITHUB_ACCESS_TOKEN = os.environ.get("GITHUB_ACCESS_TOKEN", False)
|
||||||
|
|
||||||
|
|
||||||
|
ENABLE_SIGNUP = os.environ.get("ENABLE_SIGNUP", "1") == "1"
|
||||||
|
@ -211,3 +211,5 @@ CELERY_RESULT_BACKEND = broker_url
|
|||||||
CELERY_BROKER_URL = broker_url
|
CELERY_BROKER_URL = broker_url
|
||||||
|
|
||||||
GITHUB_ACCESS_TOKEN = os.environ.get("GITHUB_ACCESS_TOKEN", False)
|
GITHUB_ACCESS_TOKEN = os.environ.get("GITHUB_ACCESS_TOKEN", False)
|
||||||
|
|
||||||
|
ENABLE_SIGNUP = os.environ.get("ENABLE_SIGNUP", "1") == "1"
|
||||||
|
@ -54,6 +54,7 @@ services:
|
|||||||
DEFAULT_EMAIL: ${DEFAULT_EMAIL}
|
DEFAULT_EMAIL: ${DEFAULT_EMAIL}
|
||||||
DEFAULT_PASSWORD: ${DEFAULT_PASSWORD}
|
DEFAULT_PASSWORD: ${DEFAULT_PASSWORD}
|
||||||
USE_MINIO: ${USE_MINIO}
|
USE_MINIO: ${USE_MINIO}
|
||||||
|
ENABLE_SIGNUP: ${ENABLE_SIGNUP}
|
||||||
depends_on:
|
depends_on:
|
||||||
- plane-db
|
- plane-db
|
||||||
- plane-redis
|
- plane-redis
|
||||||
@ -91,6 +92,7 @@ services:
|
|||||||
DEFAULT_EMAIL: ${DEFAULT_EMAIL:-captain@plane.so}
|
DEFAULT_EMAIL: ${DEFAULT_EMAIL:-captain@plane.so}
|
||||||
DEFAULT_PASSWORD: ${DEFAULT_PASSWORD:-password123}
|
DEFAULT_PASSWORD: ${DEFAULT_PASSWORD:-password123}
|
||||||
USE_MINIO: ${USE_MINIO}
|
USE_MINIO: ${USE_MINIO}
|
||||||
|
ENABLE_SIGNUP: ${ENABLE_SIGNUP}
|
||||||
depends_on:
|
depends_on:
|
||||||
- plane-api
|
- plane-api
|
||||||
- plane-db
|
- plane-db
|
||||||
|
Loading…
Reference in New Issue
Block a user