diff --git a/.deepsource.toml b/.deepsource.toml index 85de1a5e8..2b40af672 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -1,5 +1,11 @@ version = 1 +exclude_patterns = [ + "bin/**", + "**/node_modules/", + "**/*.min.js" +] + [[analyzers]] name = "shell" diff --git a/apiserver/plane/app/serializers/user.py b/apiserver/plane/app/serializers/user.py index 46ab3c4a4..5381995fd 100644 --- a/apiserver/plane/app/serializers/user.py +++ b/apiserver/plane/app/serializers/user.py @@ -159,10 +159,10 @@ class ChangePasswordSerializer(serializers.Serializer): def validate(self, data): if data.get("old_password") == data.get("new_password"): - raise serializers.ValidationError("New password cannot be same as old password.") + raise serializers.ValidationError({"error": "New password cannot be same as old password."}) if data.get("new_password") != data.get("confirm_password"): - raise serializers.ValidationError("confirm password should be same as the new password.") + raise serializers.ValidationError({"error": "Confirm password should be same as the new password."}) return data diff --git a/apiserver/plane/app/views/auth_extended.py b/apiserver/plane/app/views/auth_extended.py index da3130e64..37c8b3d85 100644 --- a/apiserver/plane/app/views/auth_extended.py +++ b/apiserver/plane/app/views/auth_extended.py @@ -133,7 +133,7 @@ class ChangePasswordEndpoint(BaseAPIView): if serializer.is_valid(): if not user.check_password(serializer.data.get("old_password")): return Response( - {"old_password": ["Wrong password."]}, + {"error": "Old password is not correct"}, status=status.HTTP_400_BAD_REQUEST, ) # set_password also hashes the password that the user will get diff --git a/apiserver/plane/app/views/authentication.py b/apiserver/plane/app/views/authentication.py index 93d381117..e315ee9c6 100644 --- a/apiserver/plane/app/views/authentication.py +++ b/apiserver/plane/app/views/authentication.py @@ -1,4 +1,5 @@ # Python imports +import os import uuid import random import string @@ -32,7 +33,8 @@ from plane.db.models import ( ) from plane.settings.redis import redis_instance from plane.bgtasks.magic_link_code_task import magic_link - +from plane.license.models import InstanceConfiguration +from plane.license.utils.instance_value import get_configuration_value def get_tokens_for_user(user): refresh = RefreshToken.for_user(user) @@ -46,7 +48,17 @@ class SignUpEndpoint(BaseAPIView): permission_classes = (AllowAny,) def post(self, request): - if not settings.ENABLE_SIGNUP: + instance_configuration = InstanceConfiguration.objects.values("key", "value") + if ( + not get_configuration_value( + instance_configuration, + "ENABLE_SIGNUP", + os.environ.get("ENABLE_SIGNUP", "0"), + ) + and not WorkspaceMemberInvite.objects.filter( + email=request.user.email + ).exists() + ): return Response( { "error": "New account creation is disabled. Please contact your site administrator" @@ -224,15 +236,9 @@ class SignInEndpoint(BaseAPIView): }, status=status.HTTP_403_FORBIDDEN, ) - if not user.is_active: - return Response( - { - "error": "Your account has been deactivated. Please contact your site administrator." - }, - status=status.HTTP_403_FORBIDDEN, - ) # settings last active for the user + user.is_active = True user.last_active = timezone.now() user.last_login_time = timezone.now() user.last_login_ip = request.META.get("REMOTE_ADDR") @@ -360,6 +366,24 @@ class MagicSignInGenerateEndpoint(BaseAPIView): def post(self, request): email = request.data.get("email", False) + instance_configuration = InstanceConfiguration.objects.values("key", "value") + if ( + not get_configuration_value( + instance_configuration, + "ENABLE_MAGIC_LINK_LOGIN", + os.environ.get("ENABLE_MAGIC_LINK_LOGIN"), + ) + and not WorkspaceMemberInvite.objects.filter( + email=request.user.email + ).exists() + ): + return Response( + { + "error": "New account creation is disabled. Please contact your site administrator" + }, + status=status.HTTP_400_BAD_REQUEST, + ) + if not email: return Response( {"error": "Please provide a valid email address"}, @@ -443,13 +467,6 @@ class MagicSignInEndpoint(BaseAPIView): if str(token) == str(user_token): if User.objects.filter(email=email).exists(): user = User.objects.get(email=email) - if not user.is_active: - return Response( - { - "error": "Your account has been deactivated. Please contact your site administrator." - }, - status=status.HTTP_403_FORBIDDEN, - ) try: # Send event to Jitsu for tracking if settings.ANALYTICS_BASE_API: @@ -506,6 +523,7 @@ class MagicSignInEndpoint(BaseAPIView): except RequestException as e: capture_exception(e) + user.is_active = True user.last_active = timezone.now() user.last_login_time = timezone.now() user.last_login_ip = request.META.get("REMOTE_ADDR") diff --git a/apiserver/plane/app/views/config.py b/apiserver/plane/app/views/config.py index 3052b6077..a585fc82e 100644 --- a/apiserver/plane/app/views/config.py +++ b/apiserver/plane/app/views/config.py @@ -45,23 +45,23 @@ class ConfigurationEndpoint(BaseAPIView): get_configuration_value( instance_configuration, "EMAIL_HOST_USER", - os.environ.get("GITHUB_APP_NAME", None), + os.environ.get("EMAIL_HOST_USER", None), ), ) and bool( get_configuration_value( instance_configuration, "EMAIL_HOST_PASSWORD", - os.environ.get("GITHUB_APP_NAME", None), + os.environ.get("EMAIL_HOST_PASSWORD", None), ) ) ) and get_configuration_value( - instance_configuration, "ENABLE_MAGIC_LINK_LOGIN", "0" + instance_configuration, "ENABLE_MAGIC_LINK_LOGIN", "1" ) == "1" data["email_password_login"] = ( get_configuration_value( - instance_configuration, "ENABLE_EMAIL_PASSWORD", "0" + instance_configuration, "ENABLE_EMAIL_PASSWORD", "1" ) == "1" ) diff --git a/apiserver/plane/app/views/issue.py b/apiserver/plane/app/views/issue.py index e7605bf14..722b89f66 100644 --- a/apiserver/plane/app/views/issue.py +++ b/apiserver/plane/app/views/issue.py @@ -371,6 +371,7 @@ class IssueListGroupedEndpoint(BaseAPIView): issue_queryset = ( Issue.objects.filter(workspace__slug=slug, project_id=project_id) + .filter(~Q(state="Triage")) .select_related("project") .select_related("workspace") .select_related("state") diff --git a/apiserver/plane/app/views/oauth.py b/apiserver/plane/app/views/oauth.py index 31b28415a..514d90050 100644 --- a/apiserver/plane/app/views/oauth.py +++ b/apiserver/plane/app/views/oauth.py @@ -30,6 +30,8 @@ from plane.db.models import ( ProjectMember, ) from .base import BaseAPIView +from plane.license.models import InstanceConfiguration +from plane.license.utils.instance_value import get_configuration_value def get_tokens_for_user(user): @@ -137,6 +139,30 @@ class OauthEndpoint(BaseAPIView): id_token = request.data.get("credential", False) client_id = request.data.get("clientId", False) + instance_configuration = InstanceConfiguration.objects.values( + "key", "value" + ) + 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"), + ) + ) and not WorkspaceMemberInvite.objects.filter( + email=request.user.email + ).exists(): + return Response( + { + "error": "New account creation is disabled. Please contact your site administrator" + }, + status=status.HTTP_400_BAD_REQUEST, + ) + if not medium or not id_token: return Response( { @@ -174,15 +200,7 @@ class OauthEndpoint(BaseAPIView): status=status.HTTP_400_BAD_REQUEST, ) - ## Login Case - if not user.is_active: - return Response( - { - "error": "Your account has been deactivated. Please contact your site administrator." - }, - status=status.HTTP_403_FORBIDDEN, - ) - + user.is_active = True user.last_active = timezone.now() user.last_login_time = timezone.now() user.last_login_ip = request.META.get("REMOTE_ADDR") @@ -239,7 +257,8 @@ class OauthEndpoint(BaseAPIView): else 15, member=user, created_by_id=project_member_invite.created_by_id, - ) for project_member_invite in project_member_invites + ) + for project_member_invite in project_member_invites ], ignore_conflicts=True, ) @@ -373,7 +392,8 @@ class OauthEndpoint(BaseAPIView): else 15, member=user, created_by_id=project_member_invite.created_by_id, - ) for project_member_invite in project_member_invites + ) + for project_member_invite in project_member_invites ], ignore_conflicts=True, ) @@ -420,4 +440,4 @@ class OauthEndpoint(BaseAPIView): "access_token": access_token, "refresh_token": refresh_token, } - return Response(data, status=status.HTTP_201_CREATED) \ No newline at end of file + return Response(data, status=status.HTTP_201_CREATED) diff --git a/packages/editor/document-editor/package.json b/packages/editor/document-editor/package.json index 5f82a35f7..0016d5261 100644 --- a/packages/editor/document-editor/package.json +++ b/packages/editor/document-editor/package.json @@ -1,6 +1,6 @@ { "name": "@plane/document-editor", - "version": "0.0.1", + "version": "0.1.0", "description": "Package that powers Plane's Pages Editor", "main": "./dist/index.mjs", "module": "./dist/index.mjs", diff --git a/packages/editor/document-editor/src/ui/components/heading-component.tsx b/packages/editor/document-editor/src/ui/components/heading-component.tsx index 629d3b427..2a71beebf 100644 --- a/packages/editor/document-editor/src/ui/components/heading-component.tsx +++ b/packages/editor/document-editor/src/ui/components/heading-component.tsx @@ -8,6 +8,7 @@ export const HeadingComp = ({

{heading}

@@ -23,6 +24,7 @@ export const SubheadingComp = ({

{subHeading}

diff --git a/packages/editor/document-editor/src/ui/components/page-renderer.tsx b/packages/editor/document-editor/src/ui/components/page-renderer.tsx index 194152dd3..cff043171 100644 --- a/packages/editor/document-editor/src/ui/components/page-renderer.tsx +++ b/packages/editor/document-editor/src/ui/components/page-renderer.tsx @@ -18,7 +18,7 @@ export const PageRenderer = (props: IPageRenderer) => { } = props; return ( -
+

{documentDetails.title}

diff --git a/packages/editor/document-editor/src/ui/components/summary-popover.tsx b/packages/editor/document-editor/src/ui/components/summary-popover.tsx index 7c85ed945..46b99d048 100644 --- a/packages/editor/document-editor/src/ui/components/summary-popover.tsx +++ b/packages/editor/document-editor/src/ui/components/summary-popover.tsx @@ -44,7 +44,7 @@ export const SummaryPopover: React.FC = (props) => { {!sidePeekVisible && (
-
-
+
+
-
-
+
+
{
{/* name */} -
+
{issue.name}
diff --git a/space/helpers/common.helper.ts b/space/helpers/common.helper.ts index 758d7c370..7c3d14157 100644 --- a/space/helpers/common.helper.ts +++ b/space/helpers/common.helper.ts @@ -1 +1,6 @@ -export const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ? process.env.NEXT_PUBLIC_API_BASE_URL : ""; +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? ""; + +export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs)); \ No newline at end of file diff --git a/space/package.json b/space/package.json index 5f3f60dc9..ddab959ab 100644 --- a/space/package.json +++ b/space/package.json @@ -17,9 +17,10 @@ "@emotion/styled": "^11.11.0", "@headlessui/react": "^1.7.13", "@mui/material": "^5.14.1", - "@plane/ui": "*", "@plane/lite-text-editor": "*", "@plane/rich-text-editor": "*", + "@plane/ui": "*", + "@plane/document-editor": "*", "axios": "^1.3.4", "clsx": "^2.0.0", "js-cookie": "^3.0.1", @@ -35,7 +36,7 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.38.0", "swr": "^2.2.2", - "tailwind-merge": "^1.14.0", + "tailwind-merge": "^2.0.0", "typescript": "4.9.5", "uuid": "^9.0.0" }, @@ -43,7 +44,7 @@ "@types/js-cookie": "^3.0.3", "@types/node": "18.14.1", "@types/nprogress": "^0.2.0", - "@types/react": "18.0.28", + "@types/react": "18.2.35", "@types/react-dom": "18.0.11", "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.48.2", diff --git a/web/components/api-token/ApiTokenForm/ApiTokenDescription.tsx b/web/components/api-token/ApiTokenForm/ApiTokenDescription.tsx deleted file mode 100644 index d17e4662e..000000000 --- a/web/components/api-token/ApiTokenForm/ApiTokenDescription.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { TextArea } from "@plane/ui"; -import { Control, Controller, FieldErrors } from "react-hook-form"; -import { IApiToken } from "types/api_token"; -import { IApiFormFields } from "./types"; -import { Dispatch, SetStateAction } from "react"; - -interface IApiTokenDescription { - generatedToken: IApiToken | null | undefined; - control: Control; - focusDescription: boolean; - setFocusTitle: Dispatch>; - setFocusDescription: Dispatch>; -} - -export const ApiTokenDescription = ({ - generatedToken, - control, - focusDescription, - setFocusTitle, - setFocusDescription, -}: IApiTokenDescription) => ( - - focusDescription ? ( -