Skip to content

Commit 349539a

Browse files
committed
fix: update workspace invitation flow to use token for validation
- Modified the invite link to include a token for enhanced security. - Updated the WorkspaceJoinEndpoint to validate the token instead of the email. - Adjusted the workspace invitation task to generate links with the token. - Refactored the frontend to handle token in the invitation process.
1 parent b83d460 commit 349539a

File tree

4 files changed

+15
-16
lines changed

4 files changed

+15
-16
lines changed

apps/api/plane/app/serializers/workspace.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class WorkSpaceMemberInviteSerializer(BaseSerializer):
107107
invite_link = serializers.SerializerMethodField()
108108

109109
def get_invite_link(self, obj):
110-
return f"/workspace-invitations/?invitation_id={obj.id}&email={obj.email}&slug={obj.workspace.slug}"
110+
return f"/workspace-invitations/?invitation_id={obj.id}&slug={obj.workspace.slug}&token={obj.token}"
111111

112112
class Meta:
113113
model = WorkspaceMemberInvite

apps/api/plane/app/views/workspace/invite.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,10 @@ class WorkspaceJoinEndpoint(BaseAPIView):
159159
def post(self, request, slug, pk):
160160
workspace_invite = WorkspaceMemberInvite.objects.get(pk=pk, workspace__slug=slug)
161161

162-
email = request.data.get("email", "")
162+
token = request.data.get("token", "")
163163

164-
# Check the email
165-
if email == "" or workspace_invite.email != email:
164+
# Validate the token to verify the user received the invitation email
165+
if not token or workspace_invite.token != token:
166166
return Response(
167167
{"error": "You do not have permission to join the workspace"},
168168
status=status.HTTP_403_FORBIDDEN,
@@ -176,7 +176,7 @@ def post(self, request, slug, pk):
176176

177177
if workspace_invite.accepted:
178178
# Check if the user created account after invitation
179-
user = User.objects.filter(email=email).first()
179+
user = User.objects.filter(email=workspace_invite.email).first()
180180

181181
# If the user is present then create the workspace member
182182
if user is not None:

apps/api/plane/bgtasks/workspace_invitation_task.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def workspace_invitation(email, workspace_id, token, current_site, inviter):
2525

2626
# Relative link
2727
relative_link = (
28-
f"/workspace-invitations/?invitation_id={workspace_member_invite.id}&email={email}&slug={workspace.slug}" # noqa: E501
28+
f"/workspace-invitations/?invitation_id={workspace_member_invite.id}&slug={workspace.slug}&token={token}" # noqa: E501
2929
)
3030

3131
# The complete url including the domain

apps/web/app/(all)/workspace-invitations/page.tsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import React from "react";
21
import { observer } from "mobx-react";
32
import { useSearchParams } from "next/navigation";
43
import useSWR from "swr";
@@ -28,8 +27,8 @@ function WorkspaceInvitationPage() {
2827
// query params
2928
const searchParams = useSearchParams();
3029
const invitation_id = searchParams.get("invitation_id");
31-
const email = searchParams.get("email");
3230
const slug = searchParams.get("slug");
31+
const token = searchParams.get("token");
3332
// store hooks
3433
const { data: currentUser } = useUser();
3534

@@ -45,29 +44,29 @@ function WorkspaceInvitationPage() {
4544
workspaceService
4645
.joinWorkspace(invitationDetail.workspace.slug, invitationDetail.id, {
4746
accepted: true,
48-
email: invitationDetail.email,
47+
token: token,
4948
})
5049
.then(() => {
51-
if (email === currentUser?.email) {
50+
if (invitationDetail.email === currentUser?.email) {
5251
router.push(`/${invitationDetail.workspace.slug}`);
5352
} else {
54-
router.push(`/?${searchParams.toString()}`);
53+
router.push("/");
5554
}
5655
})
57-
.catch((err) => console.error(err));
56+
.catch((err: unknown) => console.error(err));
5857
};
5958

6059
const handleReject = () => {
61-
if (!invitationDetail) return;
62-
workspaceService
60+
if (!invitationDetail || !token) return;
61+
void workspaceService
6362
.joinWorkspace(invitationDetail.workspace.slug, invitationDetail.id, {
6463
accepted: false,
65-
email: invitationDetail.email,
64+
token: token,
6665
})
6766
.then(() => {
6867
router.push("/");
6968
})
70-
.catch((err) => console.error(err));
69+
.catch((err: unknown) => console.error(err));
7170
};
7271

7372
return (

0 commit comments

Comments
 (0)