Spaces:
Runtime error
Runtime error
| from fastapi import APIRouter, HTTPException, status, Request | |
| from backend.core.dependencies import DbSession, AdminUser | |
| from backend.schemas.group import ( | |
| GroupCreate, GroupUpdate, GroupResponse, GroupDetailResponse, | |
| GroupMemberResponse, GroupSiteResponse, | |
| AssignUserToGroupRequest, AssignSiteToGroupRequest | |
| ) | |
| from backend.models import Group, User, Site, UserGroup, GroupSite, AuditLog | |
| router = APIRouter() | |
| def list_groups(db: DbSession, admin: AdminUser): | |
| groups = db.query(Group).all() | |
| return [ | |
| GroupResponse( | |
| id=g.id, | |
| name=g.name, | |
| description=g.description, | |
| created_at=g.created_at, | |
| updated_at=g.updated_at, | |
| member_count=len(g.members), | |
| site_count=len(g.sites) | |
| ) | |
| for g in groups | |
| ] | |
| def create_group(group_data: GroupCreate, db: DbSession, admin: AdminUser, request: Request): | |
| existing = db.query(Group).filter(Group.name == group_data.name).first() | |
| if existing: | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Group with this name already exists" | |
| ) | |
| group = Group(name=group_data.name, description=group_data.description) | |
| db.add(group) | |
| db.commit() | |
| db.refresh(group) | |
| # Audit log | |
| audit = AuditLog( | |
| user_id=admin.id, | |
| action="group_created", | |
| resource_type="group", | |
| resource_id=group.id, | |
| details={"name": group.name, "description": group.description}, | |
| ip_address=request.client.host if request.client else None | |
| ) | |
| db.add(audit) | |
| db.commit() | |
| return GroupResponse( | |
| id=group.id, | |
| name=group.name, | |
| description=group.description, | |
| created_at=group.created_at, | |
| updated_at=group.updated_at, | |
| member_count=0, | |
| site_count=0 | |
| ) | |
| def get_group(group_id: str, db: DbSession, admin: AdminUser): | |
| group = db.query(Group).filter(Group.id == group_id).first() | |
| if not group: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail="Group not found" | |
| ) | |
| members = [ | |
| GroupMemberResponse( | |
| user_id=ug.user.id, | |
| email=ug.user.email, | |
| full_name=ug.user.full_name, | |
| role=ug.role | |
| ) | |
| for ug in group.members | |
| ] | |
| sites = [ | |
| GroupSiteResponse( | |
| site_id=gs.site.id, | |
| site_code=gs.site.site_code, | |
| site_name=gs.site.name | |
| ) | |
| for gs in group.sites | |
| ] | |
| return GroupDetailResponse( | |
| id=group.id, | |
| name=group.name, | |
| description=group.description, | |
| created_at=group.created_at, | |
| updated_at=group.updated_at, | |
| member_count=len(members), | |
| site_count=len(sites), | |
| members=members, | |
| sites=sites | |
| ) | |
| def update_group(group_id: str, group_data: GroupUpdate, db: DbSession, admin: AdminUser, request: Request): | |
| group = db.query(Group).filter(Group.id == group_id).first() | |
| if not group: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail="Group not found" | |
| ) | |
| changes = {} | |
| old_name = group.name | |
| if group_data.name is not None: | |
| # Check for duplicate name | |
| existing = db.query(Group).filter(Group.name == group_data.name, Group.id != group_id).first() | |
| if existing: | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Group with this name already exists" | |
| ) | |
| if group_data.name != group.name: | |
| changes["name"] = {"old": group.name, "new": group_data.name} | |
| group.name = group_data.name | |
| if group_data.description is not None: | |
| if group_data.description != group.description: | |
| changes["description"] = {"old": group.description, "new": group_data.description} | |
| group.description = group_data.description | |
| db.commit() | |
| db.refresh(group) | |
| # Audit log | |
| if changes: | |
| audit = AuditLog( | |
| user_id=admin.id, | |
| action="group_updated", | |
| resource_type="group", | |
| resource_id=group.id, | |
| details={"group_name": old_name, "changes": changes}, | |
| ip_address=request.client.host if request.client else None | |
| ) | |
| db.add(audit) | |
| db.commit() | |
| return GroupResponse( | |
| id=group.id, | |
| name=group.name, | |
| description=group.description, | |
| created_at=group.created_at, | |
| updated_at=group.updated_at, | |
| member_count=len(group.members), | |
| site_count=len(group.sites) | |
| ) | |
| def delete_group(group_id: str, db: DbSession, admin: AdminUser, request: Request): | |
| group = db.query(Group).filter(Group.id == group_id).first() | |
| if not group: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail="Group not found" | |
| ) | |
| # Audit log before deletion | |
| audit = AuditLog( | |
| user_id=admin.id, | |
| action="group_deleted", | |
| resource_type="group", | |
| resource_id=group.id, | |
| details={"name": group.name, "member_count": len(group.members), "site_count": len(group.sites)}, | |
| ip_address=request.client.host if request.client else None | |
| ) | |
| db.add(audit) | |
| db.delete(group) | |
| db.commit() | |
| def assign_user_to_group(group_id: str, data: AssignUserToGroupRequest, db: DbSession, admin: AdminUser, request: Request): | |
| group = db.query(Group).filter(Group.id == group_id).first() | |
| if not group: | |
| raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Group not found") | |
| user = db.query(User).filter(User.id == data.user_id).first() | |
| if not user: | |
| raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found") | |
| existing = db.query(UserGroup).filter( | |
| UserGroup.user_id == data.user_id, | |
| UserGroup.group_id == group_id | |
| ).first() | |
| action = "user_role_updated" if existing else "user_assigned_to_group" | |
| old_role = existing.role if existing else None | |
| if existing: | |
| existing.role = data.role | |
| else: | |
| ug = UserGroup(user_id=data.user_id, group_id=group_id, role=data.role) | |
| db.add(ug) | |
| db.commit() | |
| # Audit log | |
| details = { | |
| "user_email": user.email, | |
| "group_name": group.name, | |
| "role": data.role | |
| } | |
| if old_role: | |
| details["old_role"] = old_role | |
| audit = AuditLog( | |
| user_id=admin.id, | |
| action=action, | |
| resource_type="user_group", | |
| resource_id=f"{user.id}:{group.id}", | |
| details=details, | |
| ip_address=request.client.host if request.client else None | |
| ) | |
| db.add(audit) | |
| db.commit() | |
| return {"message": "User assigned to group"} | |
| def remove_user_from_group(group_id: str, user_id: str, db: DbSession, admin: AdminUser, request: Request): | |
| ug = db.query(UserGroup).filter( | |
| UserGroup.user_id == user_id, | |
| UserGroup.group_id == group_id | |
| ).first() | |
| if not ug: | |
| raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not in group") | |
| # Get names for audit log | |
| user = db.query(User).filter(User.id == user_id).first() | |
| group = db.query(Group).filter(Group.id == group_id).first() | |
| # Audit log before deletion | |
| audit = AuditLog( | |
| user_id=admin.id, | |
| action="user_removed_from_group", | |
| resource_type="user_group", | |
| resource_id=f"{user_id}:{group_id}", | |
| details={ | |
| "user_email": user.email if user else user_id, | |
| "group_name": group.name if group else group_id, | |
| "role": ug.role | |
| }, | |
| ip_address=request.client.host if request.client else None | |
| ) | |
| db.add(audit) | |
| db.delete(ug) | |
| db.commit() | |
| def assign_site_to_group(group_id: str, data: AssignSiteToGroupRequest, db: DbSession, admin: AdminUser, request: Request): | |
| group = db.query(Group).filter(Group.id == group_id).first() | |
| if not group: | |
| raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Group not found") | |
| site = db.query(Site).filter(Site.id == data.site_id).first() | |
| if not site: | |
| raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Site not found") | |
| existing = db.query(GroupSite).filter( | |
| GroupSite.site_id == data.site_id, | |
| GroupSite.group_id == group_id | |
| ).first() | |
| if existing: | |
| return {"message": "Site already in group"} | |
| gs = GroupSite(site_id=data.site_id, group_id=group_id) | |
| db.add(gs) | |
| db.commit() | |
| # Audit log | |
| audit = AuditLog( | |
| user_id=admin.id, | |
| action="site_assigned_to_group", | |
| resource_type="group_site", | |
| resource_id=f"{group.id}:{site.id}", | |
| details={ | |
| "site_code": site.site_code, | |
| "site_name": site.name, | |
| "group_name": group.name | |
| }, | |
| ip_address=request.client.host if request.client else None | |
| ) | |
| db.add(audit) | |
| db.commit() | |
| return {"message": "Site assigned to group"} | |
| def remove_site_from_group(group_id: str, site_id: str, db: DbSession, admin: AdminUser, request: Request): | |
| gs = db.query(GroupSite).filter( | |
| GroupSite.site_id == site_id, | |
| GroupSite.group_id == group_id | |
| ).first() | |
| if not gs: | |
| raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Site not in group") | |
| # Get names for audit log | |
| site = db.query(Site).filter(Site.id == site_id).first() | |
| group = db.query(Group).filter(Group.id == group_id).first() | |
| # Audit log before deletion | |
| audit = AuditLog( | |
| user_id=admin.id, | |
| action="site_removed_from_group", | |
| resource_type="group_site", | |
| resource_id=f"{group_id}:{site_id}", | |
| details={ | |
| "site_code": site.site_code if site else site_id, | |
| "site_name": site.name if site else None, | |
| "group_name": group.name if group else group_id | |
| }, | |
| ip_address=request.client.host if request.client else None | |
| ) | |
| db.add(audit) | |
| db.delete(gs) | |
| db.commit() | |