diff --git a/apps/api/src/services/users/users.py b/apps/api/src/services/users/users.py index da5620db..70d6ddc4 100644 --- a/apps/api/src/services/users/users.py +++ b/apps/api/src/services/users/users.py @@ -3,6 +3,7 @@ from typing import Literal from uuid import uuid4 from fastapi import HTTPException, Request, UploadFile, status from sqlmodel import Session, select +from src.services.users.usergroups import add_users_to_usergroup from src.services.users.emails import ( send_account_creation_email, ) @@ -124,20 +125,27 @@ async def create_user_with_invite( ): # Check if invite code exists - inviteCOde = await get_invite_code( + inviteCode = await get_invite_code( request, org_id, invite_code, current_user, db_session ) - # Check if invite code contains UserGroup - #TODO - - - if not inviteCOde: + if not inviteCode: raise HTTPException( status_code=400, detail="Invite code is incorrect", ) + # Check if invite code contains UserGroup + if inviteCode.usergroup_id: + # Add user to UserGroup + await add_users_to_usergroup( + request, + db_session, + current_user, + inviteCode.usergroup_id, + user_object.username, + ) + user = await create_user(request, db_session, current_user, user_object, org_id) return user @@ -350,6 +358,7 @@ async def update_user_password( return user + async def read_user_by_id( request: Request, db_session: Session, @@ -467,8 +476,10 @@ async def authorize_user_action( ) # RBAC check - authorized = await authorization_verify_based_on_roles_and_authorship_and_usergroups( - request, current_user.id, action, resource_uuid, db_session + authorized = ( + await authorization_verify_based_on_roles_and_authorship_and_usergroups( + request, current_user.id, action, resource_uuid, db_session + ) ) if authorized: diff --git a/apps/web/app/orgs/[orgslug]/dash/users/settings/[subpage]/page.tsx b/apps/web/app/orgs/[orgslug]/dash/users/settings/[subpage]/page.tsx index 9a04c539..8d364a22 100644 --- a/apps/web/app/orgs/[orgslug]/dash/users/settings/[subpage]/page.tsx +++ b/apps/web/app/orgs/[orgslug]/dash/users/settings/[subpage]/page.tsx @@ -29,12 +29,12 @@ function UsersSettingsPage({ params }: { params: SettingsParams }) { setH2Label('Manage your organization users, assign roles and permissions') } if (params.subpage == 'signups') { - setH1Label('Signup Access') + setH1Label('Signups & Invite Codes') setH2Label('Choose from where users can join your organization') } if (params.subpage == 'add') { - setH1Label('Invite users') - setH2Label('Invite users to join your organization') + setH1Label('Invite Members') + setH2Label('Invite members to join your organization') } if (params.subpage == 'usergroups') { setH1Label('UserGroups') @@ -95,23 +95,6 @@ function UsersSettingsPage({ params }: { params: SettingsParams }) { - -
-
- -
Invite users
-
-
-
-
Signup Access
+
Signups & Invite Codes
+ +
+
+ +
Invite Members
+
+
+ + { onClick={validateCode} className="flex w-fit space-x-2 bg-black px-6 py-2 text-md rounded-lg font-semibold h-fit text-white items-center shadow-md" > - +

Submit

diff --git a/apps/web/components/Dashboard/Course/EditCourseAccess/EditCourseAccess.tsx b/apps/web/components/Dashboard/Course/EditCourseAccess/EditCourseAccess.tsx index fb274c41..9fa1abc3 100644 --- a/apps/web/components/Dashboard/Course/EditCourseAccess/EditCourseAccess.tsx +++ b/apps/web/components/Dashboard/Course/EditCourseAccess/EditCourseAccess.tsx @@ -109,7 +109,7 @@ function EditCourseAccess(props: EditCourseAccessProps) { status="info" > - + {!isPublic ? ( ) : null} ) @@ -137,7 +137,7 @@ function UserGroupsSection({ usergroups }: { usergroups: any[] }) {

UserGroups

{' '} - Choose which UserGroups can access this course{' '} + You can choose to give access to this course to specific groups of users only by linking it to a UserGroup{' '}

@@ -186,13 +186,14 @@ function UserGroupsSection({ usergroups }: { usergroups: any[] }) { setUserGroupModal(!userGroupModal) } minHeight="no-min" + minWidth='md' dialogContent={ } dialogTitle="Link Course to a UserGroup" dialogDescription={ - 'Choose which UserGroups can access this course' + 'Choose a UserGroup to link this course to, Users from this UserGroup will have access to this course.' } dialogTrigger={ + @@ -188,6 +185,19 @@ function OrgAccess() { )} +
Code Signup linkType Expiration date Actions
+ {invite.usergroup_id ? ( +
+ + Linked to a UserGroup +
+ ) : ( +
+ + Normal +
+ )} +
{dayjs(invite.expiration_date) .add(1, 'year') @@ -215,13 +225,36 @@ function OrgAccess() {
-
+
+ + setInvitesModal(!invitesModal) + } + minHeight="no-min" + minWidth='lg' + dialogContent={ + + } + dialogTitle="Generate Invite Code" + dialogDescription={ + 'Generate a new invite code for your organization' + } + dialogTrigger={ + + } + /> + +
diff --git a/apps/web/components/Objects/Modals/Dash/EditCourseAccess/LinkToUserGroup.tsx b/apps/web/components/Objects/Modals/Dash/EditCourseAccess/LinkToUserGroup.tsx index 81e1716c..56976fba 100644 --- a/apps/web/components/Objects/Modals/Dash/EditCourseAccess/LinkToUserGroup.tsx +++ b/apps/web/components/Objects/Modals/Dash/EditCourseAccess/LinkToUserGroup.tsx @@ -4,6 +4,7 @@ import { useOrg } from '@components/Contexts/OrgContext'; import { getAPIUrl } from '@services/config/config'; import { linkResourcesToUserGroup } from '@services/usergroups/usergroups'; import { swrFetcher } from '@services/utils/ts/requests'; +import { AlertTriangle, Info } from 'lucide-react'; import React, { useEffect } from 'react' import toast from 'react-hot-toast'; import useSWR, { mutate } from 'swr' @@ -47,9 +48,14 @@ function LinkToUserGroup(props: LinkToUserGroupProps) { , [usergroups]) return ( -
- -
+
+
+ +

Users that are not part of the UserGroup will no longer have access to this course

+
+
+ +
UserGroup Name + {usergroups?.map((usergroup: any) => ( + + ))} + +
+ +
+
+
+
+
+
+

Normal Invite Code

+

On Signup, User will not be linked to any UserGroup

+
+ +
+
+
+
+ ) +} + +export default OrgInviteCodeGenerate \ No newline at end of file diff --git a/apps/web/services/organizations/invites.ts b/apps/web/services/organizations/invites.ts index 06fdbd10..2fbb2bd2 100644 --- a/apps/web/services/organizations/invites.ts +++ b/apps/web/services/organizations/invites.ts @@ -10,6 +10,15 @@ export async function createInviteCode(org_id: any) { return res } +export async function createInviteCodeWithUserGroup(org_id: any, usergroup_id: number) { + const result = await fetch( + `${getAPIUrl()}orgs/${org_id}/invites_with_usergroups?usergroup_id=${usergroup_id}`, + RequestBody('POST', null, null) + ) + const res = await getResponseMetadata(result) + return res +} + export async function deleteInviteCode( org_id: any, org_invite_code_uuid: string