mirror of
https://github.com/makeplane/plane.git
synced 2026-07-12 13:29:56 +02:00
Merge branch 'master' of github.com:makeplane/plane-ee into uat
This commit is contained in:
@@ -10,9 +10,14 @@ from rest_framework.views import APIView
|
||||
# Module imports
|
||||
from plane.authentication.utils.host import user_ip
|
||||
from plane.db.models import User
|
||||
from plane.app.authentication.session import BaseSessionAuthentication
|
||||
|
||||
|
||||
class MobileSignOutAuthEndpoint(APIView):
|
||||
authentication_classes = [
|
||||
BaseSessionAuthentication,
|
||||
]
|
||||
|
||||
def post(self, request):
|
||||
# Get user
|
||||
try:
|
||||
|
||||
@@ -9,7 +9,7 @@ from asgiref.sync import sync_to_async
|
||||
|
||||
# Django Imports
|
||||
from django.utils import timezone
|
||||
from django.db.models import Q
|
||||
from django.db.models import Q, Exists, OuterRef
|
||||
|
||||
# Strawberry Imports
|
||||
from strawberry.types import Info
|
||||
@@ -17,7 +17,7 @@ from strawberry.scalars import JSON
|
||||
from strawberry.permission import PermissionExtension
|
||||
|
||||
# Module Imports
|
||||
from plane.db.models import Cycle, Issue, CycleUserProperties
|
||||
from plane.db.models import Cycle, Issue, CycleUserProperties, UserFavorite
|
||||
from plane.graphql.types.cycle import CycleType, CycleUserPropertyType
|
||||
from plane.graphql.types.issue import (
|
||||
IssuesInformationType,
|
||||
@@ -43,6 +43,13 @@ class CycleQuery:
|
||||
slug: str,
|
||||
project: strawberry.ID,
|
||||
) -> list[CycleType]:
|
||||
subquery = UserFavorite.objects.filter(
|
||||
user=info.context.user,
|
||||
entity_type="cycle",
|
||||
entity_identifier=OuterRef("pk"),
|
||||
project_id=project,
|
||||
)
|
||||
|
||||
# get cycles those are current and upcoming cycles based on the start_date and end_date
|
||||
cycles = await sync_to_async(list)(
|
||||
Cycle.objects.filter(workspace__slug=slug, project_id=project)
|
||||
@@ -62,6 +69,7 @@ class CycleQuery:
|
||||
)
|
||||
)
|
||||
.order_by("start_date")
|
||||
.annotate(is_favorite=Exists(subquery))
|
||||
)
|
||||
return cycles
|
||||
|
||||
|
||||
@@ -20,6 +20,14 @@ from strawberry.permission import PermissionExtension
|
||||
from plane.graphql.permissions.workspace import WorkspaceBasePermission
|
||||
from plane.db.models import Issue
|
||||
from plane.graphql.types.issue import IssueLiteType
|
||||
from plane.graphql.types.paginator import PaginatorResponse
|
||||
from plane.graphql.utils.paginator import paginate
|
||||
|
||||
|
||||
@sync_to_async
|
||||
def get_issue_details(issue_id):
|
||||
issue = Issue.objects.get(id=issue_id)
|
||||
return issue
|
||||
|
||||
|
||||
@strawberry.type
|
||||
@@ -43,7 +51,8 @@ class IssuesSearchQuery:
|
||||
relationType: Optional[bool] = False,
|
||||
subIssues: Optional[bool] = False,
|
||||
search: Optional[str] = None,
|
||||
) -> list[IssueLiteType]:
|
||||
cursor: Optional[str] = None,
|
||||
) -> PaginatorResponse[IssueLiteType]:
|
||||
issue_queryset = Issue.issue_objects.filter(
|
||||
workspace__slug=slug,
|
||||
project__project_projectmember__member=info.context.user,
|
||||
@@ -81,15 +90,13 @@ class IssuesSearchQuery:
|
||||
|
||||
# sub issues
|
||||
if subIssues and issue:
|
||||
current_issue = await sync_to_async(Issue.issue_objects.get)(
|
||||
pk=issue
|
||||
)
|
||||
current_issue = await get_issue_details(issue)
|
||||
issue_queryset = issue_queryset.filter(
|
||||
Q(parent__isNull=True), ~Q(parent=issue)
|
||||
Q(parent__isnull=True), ~Q(pk=issue)
|
||||
)
|
||||
if current_issue.parent:
|
||||
issue_queryset = issue_queryset.filter(
|
||||
~Q(parent=current_issue.parent)
|
||||
~Q(pk=current_issue.parent_id)
|
||||
)
|
||||
|
||||
# apply search filter
|
||||
@@ -123,4 +130,8 @@ class IssuesSearchQuery:
|
||||
issue["project_identifier"] = issue["project__identifier"]
|
||||
del issue["project__identifier"]
|
||||
|
||||
return [IssueLiteType(**issue) for issue in issues]
|
||||
listed_issues: list[IssueLiteType] = [
|
||||
IssueLiteType(**issue) for issue in issues
|
||||
]
|
||||
|
||||
return paginate(results_object=listed_issues, cursor=cursor)
|
||||
|
||||
@@ -7,13 +7,16 @@ import strawberry
|
||||
# Python Standard Library Imports
|
||||
from asgiref.sync import sync_to_async
|
||||
|
||||
# Django Imports
|
||||
from django.db.models import Exists, OuterRef
|
||||
|
||||
# Strawberry Imports
|
||||
from strawberry.types import Info
|
||||
from strawberry.scalars import JSON
|
||||
from strawberry.permission import PermissionExtension
|
||||
|
||||
# Module Imports
|
||||
from plane.db.models import Module, Issue, ModuleUserProperties
|
||||
from plane.db.models import Module, Issue, ModuleUserProperties, UserFavorite
|
||||
from plane.graphql.types.module import ModuleType, ModuleUserPropertyType
|
||||
from plane.graphql.types.issue import (
|
||||
IssuesInformationType,
|
||||
@@ -40,6 +43,13 @@ class ModuleQuery:
|
||||
project: strawberry.ID,
|
||||
cursor: Optional[str] = None,
|
||||
) -> PaginatorResponse[ModuleType]:
|
||||
subquery = UserFavorite.objects.filter(
|
||||
user=info.context.user,
|
||||
entity_type="module",
|
||||
entity_identifier=OuterRef("pk"),
|
||||
project_id=project,
|
||||
)
|
||||
|
||||
modules = await sync_to_async(list)(
|
||||
Module.objects.filter(workspace__slug=slug)
|
||||
.filter(project_id=project)
|
||||
@@ -47,6 +57,7 @@ class ModuleQuery:
|
||||
project__project_projectmember__member=info.context.user,
|
||||
project__project_projectmember__is_active=True,
|
||||
)
|
||||
.annotate(is_favorite=Exists(subquery))
|
||||
)
|
||||
|
||||
return paginate(results_object=modules, cursor=cursor)
|
||||
|
||||
@@ -169,12 +169,11 @@ class YourWorkQuery:
|
||||
|
||||
# issues
|
||||
issues = await sync_to_async(list)(
|
||||
Issue.objects.filter(workspace__slug=slug)
|
||||
Issue.issue_objects.filter(workspace__slug=slug)
|
||||
.filter(
|
||||
Q(
|
||||
project__project_projectmember__member=info.context.user,
|
||||
project__project_projectmember__is_active=True,
|
||||
# state__group__in=["unstarted", "started"],
|
||||
assignees__in=[info.context.user],
|
||||
),
|
||||
)
|
||||
|
||||
@@ -39,6 +39,7 @@ class CycleType:
|
||||
updated_at: datetime
|
||||
total_issues: int
|
||||
completed_issues: int
|
||||
is_favorite: bool
|
||||
owned_by: Optional[UserType]
|
||||
|
||||
@strawberry.field
|
||||
|
||||
@@ -41,6 +41,7 @@ class ModuleType:
|
||||
logo_props: Optional[JSON]
|
||||
total_issues: int
|
||||
completed_issues: int
|
||||
is_favorite: bool
|
||||
lead: Optional[UserType]
|
||||
|
||||
@strawberry.field
|
||||
|
||||
@@ -14,6 +14,8 @@ import {
|
||||
} from "@/helpers/authentication.helper";
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { checkEmailValidity } from "@/helpers/string.helper";
|
||||
// plane web services
|
||||
import mobileAuthService from "@/plane-web/services/mobile.service";
|
||||
// services
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
|
||||
@@ -47,9 +49,28 @@ export const MobileAuthEmailValidationForm: FC<TMobileAuthEmailValidationForm> =
|
||||
const handleFormSubmit = async (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
|
||||
let isUserSignOut = false;
|
||||
try {
|
||||
await mobileAuthService.currentUser();
|
||||
isUserSignOut = true;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
let isEmailShouldBeVerified = true;
|
||||
if (isUserSignOut) {
|
||||
try {
|
||||
await mobileAuthService.signOut();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
isEmailShouldBeVerified = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEmailShouldBeVerified) return;
|
||||
|
||||
handleEmail(email);
|
||||
setIsSubmitting(true);
|
||||
|
||||
const payload: IEmailCheckData = {
|
||||
email: email,
|
||||
};
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
// components
|
||||
import { AuthBanner } from "@/components/account";
|
||||
// helpers
|
||||
import {
|
||||
authErrorHandler,
|
||||
@@ -11,12 +13,8 @@ import {
|
||||
EErrorAlertType,
|
||||
TAuthErrorInfo,
|
||||
} from "@/helpers/authentication.helper";
|
||||
// components
|
||||
import { AuthBanner } from "@/components/account";
|
||||
// hooks
|
||||
import { useInstance } from "@/hooks/store";
|
||||
// services
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
// plane web components
|
||||
import {
|
||||
MobileTermsAndConditions,
|
||||
@@ -24,6 +22,8 @@ import {
|
||||
MobileAuthUniqueCodeForm,
|
||||
MobileAuthPasswordForm,
|
||||
} from "@/plane-web/components/mobile";
|
||||
// services
|
||||
import { AuthService } from "@/services/auth.service";
|
||||
|
||||
// service initialization
|
||||
const authService = new AuthService();
|
||||
@@ -53,7 +53,7 @@ const UNIQUE_CODE_ERROR_CODES = [
|
||||
|
||||
const PASSWORD_ERROR_CODES = [EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN];
|
||||
|
||||
export const AuthRoot: FC = observer((props) => {
|
||||
export const AuthRoot: FC = observer(() => {
|
||||
// router
|
||||
const searchParams = useSearchParams();
|
||||
// query params
|
||||
|
||||
36
web/ee/services/mobile.service.ts
Normal file
36
web/ee/services/mobile.service.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import axios, { AxiosInstance } from "axios";
|
||||
import { IUser } from "@plane/types";
|
||||
// helpers
|
||||
import { API_BASE_URL } from "@/helpers/common.helper";
|
||||
|
||||
export class MobileAuthService {
|
||||
axiosInstance: AxiosInstance;
|
||||
constructor() {
|
||||
this.axiosInstance = axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
withCredentials: true,
|
||||
});
|
||||
}
|
||||
|
||||
async currentUser(): Promise<IUser> {
|
||||
return this.axiosInstance
|
||||
.get("/api/users/me/")
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async signOut(): Promise<void> {
|
||||
return this.axiosInstance
|
||||
.post("/auth/mobile/sign-out/", {})
|
||||
.then((response) => response.data)
|
||||
.catch((error) => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const mobileAuthService = new MobileAuthService();
|
||||
|
||||
export default mobileAuthService;
|
||||
Reference in New Issue
Block a user