diff --git a/apps/api/src/routers/usergroups.py b/apps/api/src/routers/usergroups.py
index 74160f43..5c2c30b4 100644
--- a/apps/api/src/routers/usergroups.py
+++ b/apps/api/src/routers/usergroups.py
@@ -1,22 +1,20 @@
-from typing import Literal
-from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile
+from fastapi import APIRouter, Depends, Request
from sqlmodel import Session
-from src.services.users.users import delete_user_by_id
from src.db.usergroups import UserGroupCreate, UserGroupRead, UserGroupUpdate
-from src.db.users import PublicUser
+from src.db.users import PublicUser, UserRead
from src.services.users.usergroups import (
add_resources_to_usergroup,
add_users_to_usergroup,
create_usergroup,
delete_usergroup_by_id,
get_usergroups_by_resource,
+ get_users_linked_to_usergroup,
read_usergroup_by_id,
read_usergroups_by_org_id,
remove_resources_from_usergroup,
remove_users_from_usergroup,
update_usergroup_by_id,
)
-from src.services.orgs.orgs import get_org_join_mechanism
from src.security.auth import get_current_user
from src.core.events.database import get_db_session
@@ -52,6 +50,22 @@ async def api_get_usergroup(
return await read_usergroup_by_id(request, db_session, current_user, usergroup_id)
+@router.get("/{usergroup_id}/users", response_model=list[UserRead], tags=["usergroups"])
+async def api_get_users_linked_to_usergroup(
+ *,
+ request: Request,
+ db_session: Session = Depends(get_db_session),
+ current_user: PublicUser = Depends(get_current_user),
+ usergroup_id: int,
+) -> list[UserRead]:
+ """
+ Get Users linked to UserGroup
+ """
+ return await get_users_linked_to_usergroup(
+ request, db_session, current_user, usergroup_id
+ )
+
+
@router.get("/org/{org_id}", response_model=list[UserGroupRead], tags=["usergroups"])
async def api_get_usergroups(
*,
@@ -65,7 +79,10 @@ async def api_get_usergroups(
"""
return await read_usergroups_by_org_id(request, db_session, current_user, org_id)
-@router.get("/resource/{resource_uuid}", response_model=list[UserGroupRead], tags=["usergroups"])
+
+@router.get(
+ "/resource/{resource_uuid}", response_model=list[UserGroupRead], tags=["usergroups"]
+)
async def api_get_usergroupsby_resource(
*,
request: Request,
@@ -76,7 +93,9 @@ async def api_get_usergroupsby_resource(
"""
Get UserGroups by Org
"""
- return await get_usergroups_by_resource(request, db_session, current_user, resource_uuid)
+ return await get_usergroups_by_resource(
+ request, db_session, current_user, resource_uuid
+ )
@router.put("/{usergroup_id}", response_model=UserGroupRead, tags=["usergroups"])
diff --git a/apps/api/src/services/courses/courses.py b/apps/api/src/services/courses/courses.py
index e240bee4..3e2458ea 100644
--- a/apps/api/src/services/courses/courses.py
+++ b/apps/api/src/services/courses/courses.py
@@ -1,10 +1,7 @@
-import stat
from typing import Literal
from uuid import uuid4
-from regex import R
-from sqlalchemy import exists, union
-from sqlmodel import Session, select, and_, or_
-from src.db.usergroups import UserGroup
+from sqlalchemy import union
+from sqlmodel import Session, select
from src.db.usergroup_resources import UserGroupResource
from src.db.usergroup_user import UserGroupUser
from src.db.organizations import Organization
diff --git a/apps/api/src/services/users/usergroups.py b/apps/api/src/services/users/usergroups.py
index cc497762..1ad62e4b 100644
--- a/apps/api/src/services/users/usergroups.py
+++ b/apps/api/src/services/users/usergroups.py
@@ -6,14 +6,13 @@ from fastapi import HTTPException, Request
from sqlmodel import Session, select
from src.security.rbac.rbac import (
authorization_verify_based_on_roles_and_authorship_and_usergroups,
- authorization_verify_if_element_is_public,
authorization_verify_if_user_is_anon,
)
from src.db.usergroup_resources import UserGroupResource
from src.db.usergroup_user import UserGroupUser
from src.db.organizations import Organization
from src.db.usergroups import UserGroup, UserGroupCreate, UserGroupRead, UserGroupUpdate
-from src.db.users import AnonymousUser, PublicUser, User
+from src.db.users import AnonymousUser, PublicUser, User, UserRead
async def create_usergroup(
@@ -89,6 +88,48 @@ async def read_usergroup_by_id(
return usergroup
+async def get_users_linked_to_usergroup(
+ request: Request,
+ db_session: Session,
+ current_user: PublicUser | AnonymousUser,
+ usergroup_id: int,
+) -> list[UserRead]:
+
+ statement = select(UserGroup).where(UserGroup.id == usergroup_id)
+ usergroup = db_session.exec(statement).first()
+
+ if not usergroup:
+ raise HTTPException(
+ status_code=404,
+ detail="UserGroup not found",
+ )
+
+ # RBAC check
+ await rbac_check(
+ request,
+ usergroup_uuid=usergroup.usergroup_uuid,
+ current_user=current_user,
+ action="read",
+ db_session=db_session,
+ )
+
+ statement = select(UserGroupUser).where(UserGroupUser.usergroup_id == usergroup_id)
+ usergroup_users = db_session.exec(statement).all()
+
+ user_ids = [usergroup_user.user_id for usergroup_user in usergroup_users]
+
+ # get users
+ users = []
+ for user_id in user_ids:
+ statement = select(User).where(User.id == user_id)
+ user = db_session.exec(statement).first()
+ users.append(user)
+
+ users = [UserRead.from_orm(user) for user in users]
+
+ return users
+
+
async def read_usergroups_by_org_id(
request: Request,
db_session: Session,
@@ -99,8 +140,6 @@ async def read_usergroups_by_org_id(
statement = select(UserGroup).where(UserGroup.org_id == org_id)
usergroups = db_session.exec(statement).all()
-
-
# RBAC check
await rbac_check(
request,
@@ -236,6 +275,8 @@ async def add_users_to_usergroup(
status_code=404,
detail="UserGroup not found",
)
+
+
# RBAC check
await rbac_check(
@@ -252,6 +293,17 @@ async def add_users_to_usergroup(
statement = select(User).where(User.id == user_id)
user = db_session.exec(statement).first()
+ # Check if User is already Linked to UserGroup
+ statement = select(UserGroupUser).where(
+ UserGroupUser.usergroup_id == usergroup_id,
+ UserGroupUser.user_id == user_id,
+ )
+ usergroup_user = db_session.exec(statement).first()
+
+ if usergroup_user:
+ logging.error(f"User with id {user_id} already exists in UserGroup")
+ continue
+
if user:
# Add user to UserGroup
if user.id is not None:
@@ -301,7 +353,7 @@ async def remove_users_from_usergroup(
user_ids_array = user_ids.split(",")
for user_id in user_ids_array:
- statement = select(UserGroupUser).where(UserGroupUser.user_id == user_id)
+ statement = select(UserGroupUser).where(UserGroupUser.user_id == user_id, UserGroupUser.usergroup_id == usergroup_id)
usergroup_user = db_session.exec(statement).first()
if usergroup_user:
diff --git a/apps/web/app/orgs/[orgslug]/signup/InviteOnlySignUp.tsx b/apps/web/app/orgs/[orgslug]/signup/InviteOnlySignUp.tsx
index 0e9f93c8..6827fc20 100644
--- a/apps/web/app/orgs/[orgslug]/signup/InviteOnlySignUp.tsx
+++ b/apps/web/app/orgs/[orgslug]/signup/InviteOnlySignUp.tsx
@@ -66,6 +66,7 @@ function InviteOnlySignUpComponent(props: InviteOnlySignUpProps) {
last_name: '',
},
validate,
+ enableReinitialize: true,
onSubmit: async (values) => {
setError('')
setMessage('')
diff --git a/apps/web/app/orgs/[orgslug]/signup/OpenSignup.tsx b/apps/web/app/orgs/[orgslug]/signup/OpenSignup.tsx
index a4b6333a..9c4bbc4d 100644
--- a/apps/web/app/orgs/[orgslug]/signup/OpenSignup.tsx
+++ b/apps/web/app/orgs/[orgslug]/signup/OpenSignup.tsx
@@ -62,6 +62,7 @@ function OpenSignUpComponent() {
last_name: '',
},
validate,
+ enableReinitialize: true,
onSubmit: async (values) => {
setError('')
setMessage('')
diff --git a/apps/web/components/Dashboard/Users/OrgUserGroups/OrgUserGroups.tsx b/apps/web/components/Dashboard/Users/OrgUserGroups/OrgUserGroups.tsx
index fa84eca3..8a874b95 100644
--- a/apps/web/components/Dashboard/Users/OrgUserGroups/OrgUserGroups.tsx
+++ b/apps/web/components/Dashboard/Users/OrgUserGroups/OrgUserGroups.tsx
@@ -74,9 +74,11 @@ function OrgUserGroups() {
onOpenChange={() =>
handleUserGroupManagementModal(usergroup.id)
}
- minHeight="no-min"
+ minHeight="lg"
+ minWidth='lg'
dialogContent={
| User | +Linked | +Actions | +
|---|---|---|
| + + {user.user.first_name + ' ' + user.user.last_name} + + + @{user.user.username} + + | +
+ {isUserPartOfGroup(user.user.id) ?
+
+
+ :
+
+
+ }
+ |
+ + + + + | +