permission_service.rs
175 lignes · 5922 octets
use crate::error::AppError; use crate::models::{permission, role_permission, user_role}; use chrono::Utc; use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, Set}; use uuid::Uuid; /// Service for managing permissions and role-permission assignments. pub struct PermissionService; impl PermissionService { /// Return all permissions stored in the database. pub async fn list_all(db: &DatabaseConnection) -> Result<Vec<permission::Model>, AppError> { let perms = permission::Entity::find().all(db).await?; Ok(perms) } /// Return a single permission by its UUID, or `None` if not found. pub async fn get_by_id( db: &DatabaseConnection, id: Uuid, ) -> Result<Option<permission::Model>, AppError> { let perm = permission::Entity::find_by_id(id).one(db).await?; Ok(perm) } /// Return a single permission by its unique name, or `None` if not found. pub async fn get_by_name( db: &DatabaseConnection, name: &str, ) -> Result<Option<permission::Model>, AppError> { let perm = permission::Entity::find() .filter(permission::Column::Name.eq(name)) .one(db) .await?; Ok(perm) } /// Create and persist a new permission. pub async fn create( db: &DatabaseConnection, name: String, description: Option<String>, category: String, ) -> Result<permission::Model, AppError> { let perm = permission::ActiveModel { id: Set(Uuid::new_v4()), name: Set(name), description: Set(description), category: Set(category), created_at: Set(Utc::now()), }; let result = perm.insert(db).await?; Ok(result) } /// Delete a permission by its UUID. pub async fn delete(db: &DatabaseConnection, id: Uuid) -> Result<(), AppError> { permission::Entity::delete_by_id(id).exec(db).await?; Ok(()) } /// Get all permission names for a given user (union of all role permissions). pub async fn get_permissions_for_user( db: &DatabaseConnection, user_id: Uuid, ) -> Result<Vec<String>, AppError> { let ur_rows = user_role::Entity::find() .filter(user_role::Column::UserId.eq(user_id)) .all(db) .await?; let role_ids: Vec<Uuid> = ur_rows.iter().map(|ur| ur.role_id).collect(); if role_ids.is_empty() { return Ok(vec![]); } let rp_rows = role_permission::Entity::find() .filter(role_permission::Column::RoleId.is_in(role_ids)) .all(db) .await?; let perm_ids: Vec<Uuid> = rp_rows.iter().map(|rp| rp.permission_id).collect(); if perm_ids.is_empty() { return Ok(vec![]); } let perms = permission::Entity::find() .filter(permission::Column::Id.is_in(perm_ids)) .all(db) .await?; let names: Vec<String> = perms.into_iter().map(|p| p.name).collect(); Ok(names) } /// Get permissions assigned to a specific role. pub async fn get_permissions_for_role( db: &DatabaseConnection, role_id: Uuid, ) -> Result<Vec<permission::Model>, AppError> { let rp_rows = role_permission::Entity::find() .filter(role_permission::Column::RoleId.eq(role_id)) .all(db) .await?; let perm_ids: Vec<Uuid> = rp_rows.iter().map(|rp| rp.permission_id).collect(); if perm_ids.is_empty() { return Ok(vec![]); } let perms = permission::Entity::find() .filter(permission::Column::Id.is_in(perm_ids)) .all(db) .await?; Ok(perms) } /// Replace the permissions of a role atomically. pub async fn set_role_permissions( db: &DatabaseConnection, role_id: Uuid, permission_ids: Vec<Uuid>, ) -> Result<(), AppError> { // Delete existing role permissions role_permission::Entity::delete_many() .filter(role_permission::Column::RoleId.eq(role_id)) .exec(db) .await?; // Insert new for perm_id in permission_ids { let rp = role_permission::ActiveModel { role_id: Set(role_id), permission_id: Set(perm_id), }; rp.insert(db).await?; } Ok(()) } /// Seed default permissions (idempotent). pub async fn initialize_default_permissions(db: &DatabaseConnection) -> Result<(), AppError> { let defaults = vec![ ("users.list", "View the list of users", "users"), ("users.create", "Create new users", "users"), ("users.edit", "Edit existing users", "users"), ("users.delete", "Delete users", "users"), ("users.reset_password", "Reset user passwords", "users"), ("roles.list", "View the list of roles", "roles"), ("roles.create", "Create new roles", "roles"), ("roles.edit", "Edit existing roles", "roles"), ("roles.delete", "Delete roles", "roles"), ("settings.view", "View application settings", "settings"), ("settings.edit", "Edit application settings", "settings"), ("audit.view", "View audit logs", "audit"), ]; for (name, desc, category) in defaults { if Self::get_by_name(db, name).await?.is_none() { Self::create( db, name.to_string(), Some(desc.to_string()), category.to_string(), ) .await?; tracing::info!("Created default permission: {}", name); } } Ok(()) } }
GitRust