dev: instance refactor (#3015)

* dev: remove license engine communication

* dev: remove license engine base url

* dev: update instance configuration function

* chore: removed the print statement

* chore: changed config variables

* chore: cleanup

* chore: added SKIP_ENV_VAR

* chore: changed the EMAIL_FROM

* dev: patch endpoint for workspace

* dev: custom port for takeoff script

* chore: changed my sequence

* fix: update operaton for member invitations in workspace

* clean-up: remove logs

---------

Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
Co-authored-by: gurusainath <gurusainath007@gmail.com>
This commit is contained in:
Nikhil 2023-12-07 14:51:27 +05:30 committed by sriram veeraghanta
parent 9d16b39c15
commit e755ce3272
23 changed files with 485 additions and 546 deletions

View file

@ -95,6 +95,16 @@ class WorkSpaceMemberInviteSerializer(BaseSerializer):
class Meta:
model = WorkspaceMemberInvite
fields = "__all__"
read_only_fields = [
"id",
"email",
"token",
"workspace",
"message",
"responded_at",
"created_at",
"updated_at",
]
class TeamSerializer(BaseSerializer):

View file

@ -65,6 +65,7 @@ urlpatterns = [
{
"delete": "destroy",
"get": "retrieve",
"patch": "partial_update",
}
),
name="workspace-invitations",

View file

@ -34,7 +34,7 @@ from plane.app.serializers import (
from plane.db.models import User, WorkspaceMemberInvite
from plane.license.utils.instance_value import get_configuration_value
from plane.bgtasks.forgot_password_task import forgot_password
from plane.license.models import Instance, InstanceConfiguration
from plane.license.models import Instance
from plane.settings.redis import redis_instance
from plane.bgtasks.magic_link_code_task import magic_link
from plane.bgtasks.event_tracking_task import auth_events
@ -321,8 +321,19 @@ class EmailCheckEndpoint(BaseAPIView):
status=status.HTTP_400_BAD_REQUEST,
)
# Get the configurations
instance_configuration = InstanceConfiguration.objects.values("key", "value")
# Get configuration values
ENABLE_SIGNUP, ENABLE_MAGIC_LINK_LOGIN = get_configuration_value(
[
{
"key": "ENABLE_SIGNUP",
"default": os.environ.get("ENABLE_SIGNUP"),
},
{
"key": "ENABLE_MAGIC_LINK_LOGIN",
"default": os.environ.get("ENABLE_MAGIC_LINK_LOGIN"),
},
]
)
email = request.data.get("email", False)
@ -347,12 +358,7 @@ class EmailCheckEndpoint(BaseAPIView):
if user is None:
# Create the user
if (
get_configuration_value(
instance_configuration,
"ENABLE_SIGNUP",
os.environ.get("ENABLE_SIGNUP", "0"),
)
== "0"
ENABLE_SIGNUP == "0"
and not WorkspaceMemberInvite.objects.filter(
email=email,
).exists()
@ -372,13 +378,8 @@ class EmailCheckEndpoint(BaseAPIView):
is_password_autoset=True,
)
if not bool(
get_configuration_value(
instance_configuration,
"ENABLE_MAGIC_LINK_LOGIN",
os.environ.get("ENABLE_MAGIC_LINK_LOGIN"),
),
ENABLE_MAGIC_LINK_LOGIN,
):
return Response(
{"error": "Magic link sign in is disabled."},
@ -386,16 +387,15 @@ class EmailCheckEndpoint(BaseAPIView):
)
# Send event
if settings.POSTHOG_API_KEY and settings.POSTHOG_HOST:
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium="MAGIC_LINK",
first_time=True,
)
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium="MAGIC_LINK",
first_time=True,
)
key, token, current_attempt = generate_magic_token(email=email)
if not current_attempt:
return Response(
@ -413,28 +413,21 @@ class EmailCheckEndpoint(BaseAPIView):
else:
if user.is_password_autoset:
## Generate a random token
if not bool(
get_configuration_value(
instance_configuration,
"ENABLE_MAGIC_LINK_LOGIN",
os.environ.get("ENABLE_MAGIC_LINK_LOGIN"),
),
):
if not bool(ENABLE_MAGIC_LINK_LOGIN):
return Response(
{"error": "Magic link sign in is disabled."},
status=status.HTTP_400_BAD_REQUEST,
)
if settings.POSTHOG_API_KEY and settings.POSTHOG_HOST:
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium="MAGIC_LINK",
first_time=False,
)
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium="MAGIC_LINK",
first_time=False,
)
# Generate magic token
key, token, current_attempt = generate_magic_token(email=email)
@ -454,16 +447,15 @@ class EmailCheckEndpoint(BaseAPIView):
status=status.HTTP_200_OK,
)
else:
if settings.POSTHOG_API_KEY and settings.POSTHOG_HOST:
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium="EMAIL",
first_time=False,
)
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium="EMAIL",
first_time=False,
)
# User should enter password to login
return Response(

View file

@ -27,7 +27,7 @@ from plane.db.models import (
ProjectMember,
)
from plane.settings.redis import redis_instance
from plane.license.models import InstanceConfiguration, Instance
from plane.license.models import Instance
from plane.license.utils.instance_value import get_configuration_value
from plane.bgtasks.event_tracking_task import auth_events
@ -52,8 +52,6 @@ class SignUpEndpoint(BaseAPIView):
status=status.HTTP_400_BAD_REQUEST,
)
instance_configuration = InstanceConfiguration.objects.values("key", "value")
email = request.data.get("email", False)
password = request.data.get("password", False)
## Raise exception if any of the above are missing
@ -73,14 +71,20 @@ class SignUpEndpoint(BaseAPIView):
status=status.HTTP_400_BAD_REQUEST,
)
# get configuration values
# Get configuration values
ENABLE_SIGNUP, = get_configuration_value(
[
{
"key": "ENABLE_SIGNUP",
"default": os.environ.get("ENABLE_SIGNUP"),
},
]
)
# If the sign up is not enabled and the user does not have invite disallow him from creating the account
if (
get_configuration_value(
instance_configuration,
"ENABLE_SIGNUP",
os.environ.get("ENABLE_SIGNUP", "0"),
)
== "0"
ENABLE_SIGNUP == "0"
and not WorkspaceMemberInvite.objects.filter(
email=email,
).exists()
@ -169,16 +173,17 @@ class SignInEndpoint(BaseAPIView):
# Create the user
else:
# Get the configurations
instance_configuration = InstanceConfiguration.objects.values("key", "value")
ENABLE_SIGNUP, = get_configuration_value(
[
{
"key": "ENABLE_SIGNUP",
"default": os.environ.get("ENABLE_SIGNUP"),
},
]
)
# Create the user
if (
get_configuration_value(
instance_configuration,
"ENABLE_SIGNUP",
os.environ.get("ENABLE_SIGNUP", "0"),
)
== "0"
ENABLE_SIGNUP == "0"
and not WorkspaceMemberInvite.objects.filter(
email=email,
).exists()
@ -264,16 +269,15 @@ class SignInEndpoint(BaseAPIView):
workspace_member_invites.delete()
project_member_invites.delete()
# Send event
if settings.POSTHOG_API_KEY and settings.POSTHOG_HOST:
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium="EMAIL",
first_time=False,
)
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium="EMAIL",
first_time=False,
)
access_token, refresh_token = get_tokens_for_user(user)
data = {
@ -347,16 +351,15 @@ class MagicSignInEndpoint(BaseAPIView):
status=status.HTTP_403_FORBIDDEN,
)
# Send event
if settings.POSTHOG_API_KEY and settings.POSTHOG_HOST:
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium="MAGIC_LINK",
first_time=False,
)
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium="MAGIC_LINK",
first_time=False,
)
user.is_active = True
user.is_email_verified = True

View file

@ -11,7 +11,6 @@ from rest_framework.response import Response
# Module imports
from .base import BaseAPIView
from plane.license.models import InstanceConfiguration
from plane.license.utils.instance_value import get_configuration_value
@ -21,89 +20,101 @@ class ConfigurationEndpoint(BaseAPIView):
]
def get(self, request):
instance_configuration = InstanceConfiguration.objects.values("key", "value")
# Get all the configuration
(
GOOGLE_CLIENT_ID,
GITHUB_CLIENT_ID,
GITHUB_APP_NAME,
EMAIL_HOST_USER,
EMAIL_HOST_PASSWORD,
ENABLE_MAGIC_LINK_LOGIN,
ENABLE_EMAIL_PASSWORD,
SLACK_CLIENT_ID,
POSTHOG_API_KEY,
POSTHOG_HOST,
UNSPLASH_ACCESS_KEY,
OPENAI_API_KEY,
) = get_configuration_value(
[
{
"key": "GOOGLE_CLIENT_ID",
"default": os.environ.get("GOOGLE_CLIENT_ID", None),
},
{
"key": "GITHUB_CLIENT_ID",
"default": os.environ.get("GITHUB_CLIENT_ID", None),
},
{
"key": "GITHUB_APP_NAME",
"default": os.environ.get("GITHUB_APP_NAME", None),
},
{
"key": "EMAIL_HOST_USER",
"default": os.environ.get("EMAIL_HOST_USER", None),
},
{
"key": "EMAIL_HOST_PASSWORD",
"default": os.environ.get("EMAIL_HOST_PASSWORD", None),
},
{
"key": "ENABLE_MAGIC_LINK_LOGIN",
"default": os.environ.get("ENABLE_MAGIC_LINK_LOGIN", "1"),
},
{
"key": "ENABLE_EMAIL_PASSWORD",
"default": os.environ.get("ENABLE_EMAIL_PASSWORD", "1"),
},
{
"key": "SLACK_CLIENT_ID",
"default": os.environ.get("SLACK_CLIENT_ID", "1"),
},
{
"key": "POSTHOG_API_KEY",
"default": os.environ.get("POSTHOG_API_KEY", "1"),
},
{
"key": "POSTHOG_HOST",
"default": os.environ.get("POSTHOG_HOST", "1"),
},
{
"key": "UNSPLASH_ACCESS_KEY",
"default": os.environ.get("UNSPLASH_ACCESS_KEY", "1"),
},
{
"key": "OPENAI_API_KEY",
"default": os.environ.get("OPENAI_API_KEY", "1"),
},
]
)
data = {}
# Authentication
data["google_client_id"] = get_configuration_value(
instance_configuration,
"GOOGLE_CLIENT_ID",
os.environ.get("GOOGLE_CLIENT_ID", None),
)
data["github_client_id"] = get_configuration_value(
instance_configuration,
"GITHUB_CLIENT_ID",
os.environ.get("GITHUB_CLIENT_ID", None),
)
data["github_app_name"] = get_configuration_value(
instance_configuration,
"GITHUB_APP_NAME",
os.environ.get("GITHUB_APP_NAME", None),
)
data["google_client_id"] = GOOGLE_CLIENT_ID
data["github_client_id"] = GITHUB_CLIENT_ID
data["github_app_name"] = GITHUB_APP_NAME
data["magic_login"] = (
bool(
get_configuration_value(
instance_configuration,
"EMAIL_HOST_USER",
os.environ.get("EMAIL_HOST_USER", None),
),
)
and bool(
get_configuration_value(
instance_configuration,
"EMAIL_HOST_PASSWORD",
os.environ.get("EMAIL_HOST_PASSWORD", None),
)
)
) and get_configuration_value(
instance_configuration, "ENABLE_MAGIC_LINK_LOGIN", "1"
) == "1"
bool(EMAIL_HOST_USER) and bool(EMAIL_HOST_PASSWORD)
) and ENABLE_MAGIC_LINK_LOGIN == "1"
data["email_password_login"] = (
get_configuration_value(
instance_configuration, "ENABLE_EMAIL_PASSWORD", "1"
)
== "1"
)
data["email_password_login"] = ENABLE_EMAIL_PASSWORD == "1"
# Slack client
data["slack_client_id"] = get_configuration_value(
instance_configuration,
"SLACK_CLIENT_ID",
os.environ.get("SLACK_CLIENT_ID", None),
)
data["slack_client_id"] = SLACK_CLIENT_ID
# Posthog
data["posthog_api_key"] = get_configuration_value(
instance_configuration,
"POSTHOG_API_KEY",
os.environ.get("POSTHOG_API_KEY", None),
)
data["posthog_host"] = get_configuration_value(
instance_configuration,
"POSTHOG_HOST",
os.environ.get("POSTHOG_HOST", None),
)
data["posthog_api_key"] = POSTHOG_API_KEY
data["posthog_host"] = POSTHOG_HOST
# Unsplash
data["has_unsplash_configured"] = bool(
get_configuration_value(
instance_configuration,
"UNSPLASH_ACCESS_KEY",
os.environ.get("UNSPLASH_ACCESS_KEY", None),
)
)
data["has_unsplash_configured"] = UNSPLASH_ACCESS_KEY
# Open AI settings
data["has_openai_configured"] = bool(
get_configuration_value(
instance_configuration,
"OPENAI_API_KEY",
os.environ.get("OPENAI_API_KEY", None),
)
)
data["has_openai_configured"] = bool(OPENAI_API_KEY)
# File size settings
data["file_size_limit"] = float(os.environ.get("FILE_SIZE_LIMIT", 5242880))
# is self managed
data["is_self_managed"] = bool(int(os.environ.get("IS_SELF_MANAGED", "1")))
return Response(data, status=status.HTTP_200_OK)

View file

@ -1,6 +1,7 @@
# Python imports
import requests
import os
# Third party imports
from openai import OpenAI
from rest_framework.response import Response
@ -15,23 +16,31 @@ from plane.app.permissions import ProjectEntityPermission
from plane.db.models import Workspace, Project
from plane.app.serializers import ProjectLiteSerializer, WorkspaceLiteSerializer
from plane.utils.integrations.github import get_release_notes
from plane.license.models import InstanceConfiguration
from plane.license.utils.instance_value import get_configuration_value
class GPTIntegrationEndpoint(BaseAPIView):
permission_classes = [
ProjectEntityPermission,
]
def post(self, request, slug, project_id):
OPENAI_API_KEY, GPT_ENGINE = get_configuration_value(
[
{
"key": "OPENAI_API_KEY",
"default": os.environ.get("OPENAI_API_KEY", None),
},
{
"key": "GPT_ENGINE",
"default": os.environ.get("GPT_ENGINE", "gpt-3.5-turbo"),
},
]
)
# Get the configuration value
instance_configuration = InstanceConfiguration.objects.values("key", "value")
api_key = get_configuration_value(instance_configuration, "OPENAI_API_KEY", os.environ.get("OPENAI_API_KEY"))
gpt_engine = get_configuration_value(instance_configuration, "GPT_ENGINE", os.environ.get("GPT_ENGINE", "gpt-3.5-turbo"))
# Check the keys
if not api_key or not gpt_engine:
if not OPENAI_API_KEY or not GPT_ENGINE:
return Response(
{"error": "OpenAI API key and engine is required"},
status=status.HTTP_400_BAD_REQUEST,
@ -48,11 +57,11 @@ class GPTIntegrationEndpoint(BaseAPIView):
final_text = task + "\n" + prompt
client = OpenAI(
api_key=api_key,
api_key=OPENAI_API_KEY,
)
response = client.chat.completions.create(
model=gpt_engine,
model=GPT_ENGINE,
messages=[{"role": "user", "content": final_text}],
)
@ -79,13 +88,17 @@ class ReleaseNotesEndpoint(BaseAPIView):
class UnsplashEndpoint(BaseAPIView):
def get(self, request):
instance_configuration = InstanceConfiguration.objects.values("key", "value")
unsplash_access_key = get_configuration_value(instance_configuration, "UNSPLASH_ACCESS_KEY", os.environ.get("UNSPLASH_ACCESS_KEY"))
UNSPLASH_ACCESS_KEY, = get_configuration_value(
[
{
"key": "UNSPLASH_ACCESS_KEY",
"default": os.environ.get("UNSPLASH_ACCESS_KEY"),
}
]
)
# Check unsplash access key
if not unsplash_access_key:
if not UNSPLASH_ACCESS_KEY:
return Response([], status=status.HTTP_200_OK)
# Query parameters
@ -94,9 +107,9 @@ class UnsplashEndpoint(BaseAPIView):
per_page = request.GET.get("per_page", 20)
url = (
f"https://api.unsplash.com/search/photos/?client_id={unsplash_access_key}&query={query}&page=${page}&per_page={per_page}"
f"https://api.unsplash.com/search/photos/?client_id={UNSPLASH_ACCESS_KEY}&query={query}&page=${page}&per_page={per_page}"
if query
else f"https://api.unsplash.com/photos/?client_id={unsplash_access_key}&page={page}&per_page={per_page}"
else f"https://api.unsplash.com/photos/?client_id={UNSPLASH_ACCESS_KEY}&page={page}&per_page={per_page}"
)
headers = {

View file

@ -30,7 +30,7 @@ from plane.db.models import (
)
from plane.bgtasks.event_tracking_task import auth_events
from .base import BaseAPIView
from plane.license.models import InstanceConfiguration, Instance
from plane.license.models import Instance
from plane.license.utils.instance_value import get_configuration_value
@ -147,18 +147,20 @@ class OauthEndpoint(BaseAPIView):
id_token = request.data.get("credential", False)
client_id = request.data.get("clientId", False)
instance_configuration = InstanceConfiguration.objects.values(
"key", "value"
GOOGLE_CLIENT_ID, GITHUB_CLIENT_ID = get_configuration_value(
[
{
"key": "GOOGLE_CLIENT_ID",
"default": os.environ.get("GOOGLE_CLIENT_ID"),
},
{
"key": "GITHUB_CLIENT_ID",
"default": os.environ.get("GITHUB_CLIENT_ID"),
},
]
)
if not get_configuration_value(
instance_configuration,
"GOOGLE_CLIENT_ID",
os.environ.get("GOOGLE_CLIENT_ID"),
) or not get_configuration_value(
instance_configuration,
"GITHUB_CLIENT_ID",
os.environ.get("GITHUB_CLIENT_ID"),
):
if not GOOGLE_CLIENT_ID or not GITHUB_CLIENT_ID:
return Response(
{"error": "Github or Google login is not configured"},
status=status.HTTP_400_BAD_REQUEST,
@ -278,16 +280,15 @@ class OauthEndpoint(BaseAPIView):
)
# Send event
if settings.POSTHOG_API_KEY and settings.POSTHOG_HOST:
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium=medium.upper(),
first_time=False,
)
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium=medium.upper(),
first_time=False,
)
access_token, refresh_token = get_tokens_for_user(user)
@ -298,17 +299,16 @@ class OauthEndpoint(BaseAPIView):
return Response(data, status=status.HTTP_200_OK)
except User.DoesNotExist:
## Signup Case
instance_configuration = InstanceConfiguration.objects.values(
"key", "value"
ENABLE_SIGNUP, = get_configuration_value(
[
{
"key": "ENABLE_SIGNUP",
"default": os.environ.get("ENABLE_SIGNUP", "0"),
}
]
)
if (
get_configuration_value(
instance_configuration,
"ENABLE_SIGNUP",
os.environ.get("ENABLE_SIGNUP", "0"),
)
== "0"
ENABLE_SIGNUP == "0"
and not WorkspaceMemberInvite.objects.filter(
email=email,
).exists()
@ -411,16 +411,15 @@ class OauthEndpoint(BaseAPIView):
project_member_invites.delete()
# Send event
if settings.POSTHOG_API_KEY and settings.POSTHOG_HOST:
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium=medium.upper(),
first_time=True,
)
auth_events.delay(
user=user.id,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="SIGN_IN",
medium=medium.upper(),
first_time=True,
)
SocialLoginConnection.objects.update_or_create(
medium=medium,

View file

@ -408,15 +408,14 @@ class WorkspaceJoinEndpoint(BaseAPIView):
workspace_invite.delete()
# Send event
if settings.POSTHOG_API_KEY and settings.POSTHOG_HOST:
workspace_invite_event.delay(
user=user.id if user is not None else None,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="MEMBER_ACCEPTED",
accepted_from="EMAIL",
)
workspace_invite_event.delay(
user=user.id if user is not None else None,
email=email,
user_agent=request.META.get("HTTP_USER_AGENT"),
ip=request.META.get("REMOTE_ADDR"),
event_name="MEMBER_ACCEPTED",
accepted_from="EMAIL",
)
return Response(
{"message": "Workspace Invitation Accepted"},