feat(role_management): add assign roles to user api

This commit is contained in:
icecheng 2025-07-21 10:20:28 +08:00
parent 795c1262c6
commit ca0bfb155f
10 changed files with 105 additions and 6 deletions

View File

@ -0,0 +1,40 @@
from typing import Optional, List
from fastapi.exceptions import RequestValidationError
from backend.models.permission.models import RoleDoc, UserRoleDoc
from beanie import PydanticObjectId
class UserRoleHandler:
def __init__(self):
pass
async def assign_roles_to_user(self, user_id: str, role_ids: List[str]) -> Optional[UserRoleDoc]:
"""Assign roles to a user by updating or creating the UserRoleDoc"""
if not user_id or not role_ids:
raise RequestValidationError("user_id and role_ids are required.")
# Validate that all role_ids exist in the role collection
for role_id in role_ids:
role_doc = await RoleDoc.get(PydanticObjectId(role_id))
if not role_doc:
raise RequestValidationError(f"Role with id {role_id} not found.")
# Remove duplicates from role_ids
unique_role_ids = list(dict.fromkeys(role_ids))
# Check if UserRoleDoc already exists for this user
existing_user_role = await UserRoleDoc.find_one(UserRoleDoc.user_id == user_id)
if existing_user_role:
# Update existing UserRoleDoc
existing_user_role.role_ids = unique_role_ids
await existing_user_role.save()
return existing_user_role
else:
# Create new UserRoleDoc
user_role_doc = UserRoleDoc(
user_id=user_id,
role_ids=unique_role_ids
)
await user_role_doc.insert()
return user_role_doc

View File

@ -1,3 +1,3 @@
from .models import PermissionDoc, RoleDoc
from .models import PermissionDoc, RoleDoc, UserRoleDoc
permission_models = [PermissionDoc, RoleDoc]
permission_models = [PermissionDoc, RoleDoc, UserRoleDoc]

View File

@ -1,6 +1,6 @@
from beanie import Document
from datetime import datetime
from typing import Optional
from typing import Optional, List
class PermissionDoc(Document):
@ -34,4 +34,17 @@ class RoleDoc(Document):
name = "_role"
indexes = [
"role_level"
]
class UserRoleDoc(Document):
"""User role doc"""
user_id: str
role_ids: Optional[List[str]]
class Settings:
# Default collections created by Freeleaps for tenant databases use '_' prefix
# to prevent naming conflicts with tenant-created collections
name = "_user_role"
indexes = [
"user_id"
]

View File

@ -18,7 +18,6 @@ class UserAccountDoc(Document):
service_plan_id: Optional[str]
properties: UserAccountProperty
capabilities: Capability
user_role_ids: List[str]
user_role: int = AdministrativeRole.NONE
preferred_region: UserRegion = UserRegion.ZH_CN

View File

@ -1,5 +1,6 @@
from backend.models.permission.models import UserRoleDoc
from common.log.module_logger import ModuleLogger
from typing import Optional
from typing import Optional, List
from backend.models.user.constants import (
NewUserMethod,
@ -16,6 +17,9 @@ from backend.infra.auth.user_auth_handler import (
from backend.infra.user_profile.user_profile_handler import (
UserProfileHandler,
)
from backend.infra.permission.user_role_handler import (
UserRoleHandler,
)
from common.log.log_utils import log_entry_exit_async
from common.constants.region import UserRegion
@ -24,6 +28,7 @@ class UserManagementService:
def __init__(self) -> None:
self.user_auth_handler = UserAuthHandler()
self.user_profile_handler = UserProfileHandler()
self.user_role_handler = UserRoleHandler()
self.module_logger = ModuleLogger(sender_id=UserManagementService)
@log_entry_exit_async
@ -97,3 +102,7 @@ class UserManagementService:
async def get_account_by_id(self, user_id: str) -> UserAccountDoc:
return await self.user_profile_handler.get_account_by_id(user_id)
async def assign_roles_to_user(self, user_id: str, role_ids: List[str]) -> UserRoleDoc:
"""Assign roles to a user by updating or creating the UserRoleDoc"""
return await self.user_role_handler.assign_roles_to_user(user_id, role_ids)

View File

@ -4,11 +4,13 @@ from .tokens import router as token_router
from .auth import router as auth_router
from .permission import router as permission_router
from .role import router as role_router
from .user import router as user_router
api_router = APIRouter(prefix="/auth")
api_router.include_router(signin_router, tags=["user"])
api_router.include_router(signin_router, tags=["signin"])
api_router.include_router(token_router, tags=["token"])
api_router.include_router(auth_router, tags=["auth"])
api_router.include_router(permission_router, tags=["permission"])
api_router.include_router(role_router, tags=["role"])
api_router.include_router(user_router, tags=["user"])
websocket_router = APIRouter()

View File

@ -0,0 +1,6 @@
from fastapi import APIRouter
from .assign_roles import router as assign_role_router
router = APIRouter()
router.include_router(assign_role_router, prefix="/user", tags=["user"])

View File

@ -0,0 +1,30 @@
from fastapi import APIRouter
from pydantic import BaseModel
from typing import List, Optional
from backend.services.user.user_management_service import UserManagementService
from common.token.token_manager import TokenManager
router = APIRouter()
token_manager = TokenManager()
user_management_service = UserManagementService()
class AssignRolesRequest(BaseModel):
user_id: str
role_ids: List[str]
class UserRoleResponse(BaseModel):
user_id: str
role_ids: Optional[List[str]]
@router.post(
"/assign-roles",
response_model=UserRoleResponse,
operation_id="assign-roles-to-user",
summary="Assign Roles to User",
description="Assign roles to a user by updating or creating the UserRoleDoc."
)
async def assign_roles_to_user(
req: AssignRolesRequest,
) -> UserRoleResponse:
doc = await user_management_service.assign_roles_to_user(req.user_id, req.role_ids)
return UserRoleResponse(**doc.dict())