use axum::Extension; use axum::extract::{FromRef, Path, Query, State}; use axum::response::Json; use validator::Validate; use erp_core::error::AppError; use erp_core::types::{ApiResponse, PaginatedResponse, Pagination, TenantContext}; use uuid::Uuid; use crate::auth_state::AuthState; use crate::dto::{AssignPermissionsReq, CreateRoleReq, PermissionResp, RoleResp, UpdateRoleReq}; use crate::service::permission_service::PermissionService; use crate::service::role_service::RoleService; use erp_core::rbac::require_permission; #[utoipa::path( get, path = "/api/v1/roles", params(Pagination), responses( (status = 200, description = "成功", body = ApiResponse>), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), ), security(("bearer_auth" = [])), tag = "角色管理" )] /// GET /api/v1/roles /// /// List roles within the current tenant with pagination. /// Requires the `role.list` permission. pub async fn list_roles( State(state): State, Extension(ctx): Extension, Query(pagination): Query, ) -> Result>>, AppError> where AuthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "role.list")?; let (roles, total) = RoleService::list(ctx.tenant_id, &pagination, &state.db).await?; let page = pagination.page.unwrap_or(1); let page_size = pagination.limit(); let total_pages = total.div_ceil(page_size); Ok(Json(ApiResponse::ok(PaginatedResponse { data: roles, total, page, page_size, total_pages, }))) } #[utoipa::path( post, path = "/api/v1/roles", request_body = CreateRoleReq, responses( (status = 200, description = "创建成功", body = ApiResponse), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), ), security(("bearer_auth" = [])), tag = "角色管理" )] /// POST /api/v1/roles /// /// Create a new role within the current tenant. /// Requires the `role.create` permission. pub async fn create_role( State(state): State, Extension(ctx): Extension, Json(req): Json, ) -> Result>, AppError> where AuthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "role.create")?; req.validate() .map_err(|e| AppError::Validation(e.to_string()))?; let role = RoleService::create( ctx.tenant_id, ctx.user_id, &req.name, &req.code, &req.description, &state.db, &state.event_bus, ) .await?; Ok(Json(ApiResponse::ok(role))) } #[utoipa::path( get, path = "/api/v1/roles/{id}", params(("id" = Uuid, Path, description = "角色ID")), responses( (status = 200, description = "成功", body = ApiResponse), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), (status = 404, description = "角色不存在"), ), security(("bearer_auth" = [])), tag = "角色管理" )] /// GET /api/v1/roles/:id /// /// Fetch a single role by ID within the current tenant. /// Requires the `role.read` permission. pub async fn get_role( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> Result>, AppError> where AuthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "role.read")?; let role = RoleService::get_by_id(id, ctx.tenant_id, &state.db).await?; Ok(Json(ApiResponse::ok(role))) } #[utoipa::path( put, path = "/api/v1/roles/{id}", params(("id" = Uuid, Path, description = "角色ID")), request_body = UpdateRoleReq, responses( (status = 200, description = "更新成功", body = ApiResponse), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), (status = 404, description = "角色不存在"), ), security(("bearer_auth" = [])), tag = "角色管理" )] /// PUT /api/v1/roles/:id /// /// Update editable role fields (name, description). /// Requires the `role.update` permission. pub async fn update_role( State(state): State, Extension(ctx): Extension, Path(id): Path, Json(req): Json, ) -> Result>, AppError> where AuthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "role.update")?; let role = RoleService::update( id, ctx.tenant_id, ctx.user_id, &req.name, &req.description, req.version, &state.db, ) .await?; Ok(Json(ApiResponse::ok(role))) } #[utoipa::path( delete, path = "/api/v1/roles/{id}", params(("id" = Uuid, Path, description = "角色ID")), responses( (status = 200, description = "角色已删除"), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), (status = 404, description = "角色不存在"), ), security(("bearer_auth" = [])), tag = "角色管理" )] /// DELETE /api/v1/roles/:id /// /// Soft-delete a role by ID within the current tenant. /// System roles cannot be deleted. /// Requires the `role.delete` permission. pub async fn delete_role( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> Result>, AppError> where AuthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "role.delete")?; RoleService::delete(id, ctx.tenant_id, ctx.user_id, &state.db, &state.event_bus).await?; Ok(Json(ApiResponse { success: true, data: None, message: Some("角色已删除".to_string()), })) } #[utoipa::path( post, path = "/api/v1/roles/{id}/permissions", params(("id" = Uuid, Path, description = "角色ID")), request_body = AssignPermissionsReq, responses( (status = 200, description = "权限分配成功"), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), (status = 404, description = "角色不存在"), ), security(("bearer_auth" = [])), tag = "角色管理" )] /// POST /api/v1/roles/:id/permissions /// /// Replace all permission assignments for a role. /// Requires the `role.update` permission. pub async fn assign_permissions( State(state): State, Extension(ctx): Extension, Path(id): Path, Json(req): Json, ) -> Result>, AppError> where AuthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "role.update")?; RoleService::assign_permissions( id, ctx.tenant_id, ctx.user_id, &req.permission_ids, &state.db, ) .await?; Ok(Json(ApiResponse { success: true, data: None, message: Some("权限分配成功".to_string()), })) } #[utoipa::path( get, path = "/api/v1/roles/{id}/permissions", params(("id" = Uuid, Path, description = "角色ID")), responses( (status = 200, description = "成功", body = ApiResponse>), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), (status = 404, description = "角色不存在"), ), security(("bearer_auth" = [])), tag = "角色管理" )] /// GET /api/v1/roles/:id/permissions /// /// Fetch all permissions assigned to a role. /// Requires the `role.read` permission. pub async fn get_role_permissions( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> Result>>, AppError> where AuthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "role.read")?; let perms = RoleService::get_role_permissions(id, ctx.tenant_id, &state.db).await?; Ok(Json(ApiResponse::ok(perms))) } #[utoipa::path( get, path = "/api/v1/permissions", responses( (status = 200, description = "成功", body = ApiResponse>), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), ), security(("bearer_auth" = [])), tag = "权限管理" )] /// GET /api/v1/permissions /// /// List all permissions within the current tenant. /// Requires the `permission.list` permission. pub async fn list_permissions( State(state): State, Extension(ctx): Extension, ) -> Result>>, AppError> where AuthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "permission.list")?; let perms = PermissionService::list(ctx.tenant_id, &state.db).await?; Ok(Json(ApiResponse::ok(perms))) }