init
This commit is contained in:
136
backend/src/services/role_service.rs
Normal file
136
backend/src/services/role_service.rs
Normal file
@ -0,0 +1,136 @@
|
||||
use sea_orm::{EntityTrait, ColumnTrait, QueryFilter, PaginatorTrait, ActiveModelTrait, Set, QueryOrder};
|
||||
use sea_orm::prelude::DateTimeWithTimeZone;
|
||||
use crate::{db::Db, models::role, error::AppError};
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize)]
|
||||
pub struct RoleInfo { pub id: i64, pub name: String, pub code: String, pub description: Option<String>, pub status: i32, pub created_at: DateTimeWithTimeZone }
|
||||
impl From<role::Model> for RoleInfo { fn from(m: role::Model) -> Self { Self { id: m.id, name: m.name, code: m.code, description: m.description, status: m.status, created_at: m.created_at } } }
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize)]
|
||||
pub struct PageResp<T> { pub items: Vec<T>, pub total: u64, pub page: u64, pub page_size: u64 }
|
||||
|
||||
pub async fn list(db: &Db, page: u64, page_size: u64, keyword: Option<String>) -> Result<PageResp<RoleInfo>, AppError> {
|
||||
let mut selector = role::Entity::find();
|
||||
if let Some(k) = keyword { let like = format!("%{}%", k); selector = selector.filter(role::Column::Name.like(like.clone()).or(role::Column::Code.like(like))); }
|
||||
let paginator = selector.order_by_desc(role::Column::Id).paginate(db, page_size);
|
||||
let total = paginator.num_items().await? as u64;
|
||||
let models = paginator.fetch_page(if page>0 { page-1 } else { 0 }).await?;
|
||||
Ok(PageResp { items: models.into_iter().map(Into::into).collect(), total, page, page_size })
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct CreateRoleInput { pub name: String, pub code: String, pub description: Option<String>, pub status: Option<i32> }
|
||||
|
||||
pub async fn create(db: &Db, input: CreateRoleInput) -> Result<RoleInfo, AppError> {
|
||||
if role::Entity::find().filter(role::Column::Code.eq(input.code.clone())).one(db).await?.is_some() {
|
||||
return Err(AppError::BadRequest("role code already exists".into()));
|
||||
}
|
||||
let mut am: role::ActiveModel = Default::default();
|
||||
am.name = Set(input.name);
|
||||
am.code = Set(input.code);
|
||||
am.description = Set(input.description);
|
||||
am.status = Set(input.status.unwrap_or(1));
|
||||
let m = am.insert(db).await?;
|
||||
Ok(m.into())
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct UpdateRoleInput { pub name: Option<String>, pub description: Option<String>, pub status: Option<i32> }
|
||||
|
||||
pub async fn update(db: &Db, id: i64, input: UpdateRoleInput) -> Result<RoleInfo, AppError> {
|
||||
let m = role::Entity::find_by_id(id).one(db).await?.ok_or(AppError::NotFound)?;
|
||||
let mut am: role::ActiveModel = m.into();
|
||||
if let Some(v) = input.name { am.name = Set(v); }
|
||||
if let Some(v) = input.description { am.description = Set(Some(v)); }
|
||||
if let Some(v) = input.status { am.status = Set(v); }
|
||||
let m = am.update(db).await?;
|
||||
Ok(m.into())
|
||||
}
|
||||
|
||||
// --- Role assignments: menus only ---
|
||||
use crate::models::{role_menu, user_role};
|
||||
use sea_orm::{TransactionTrait, QuerySelect};
|
||||
|
||||
|
||||
pub async fn get_menu_ids(db: &Db, role_id: i64) -> Result<Vec<i64>, AppError> {
|
||||
let ids = role_menu::Entity::find()
|
||||
.filter(role_menu::Column::RoleId.eq(role_id))
|
||||
.select_only()
|
||||
.column(role_menu::Column::MenuId)
|
||||
.into_tuple::<i64>()
|
||||
.all(db)
|
||||
.await?;
|
||||
Ok(ids)
|
||||
}
|
||||
|
||||
pub async fn set_menu_ids(db: &Db, role_id: i64, ids: Vec<i64>) -> Result<(), AppError> {
|
||||
let txn = db.begin().await?;
|
||||
role_menu::Entity::delete_many()
|
||||
.filter(role_menu::Column::RoleId.eq(role_id))
|
||||
.exec(&txn)
|
||||
.await?;
|
||||
if !ids.is_empty() {
|
||||
let mut items: Vec<role_menu::ActiveModel> = Vec::with_capacity(ids.len());
|
||||
for mid in ids { let mut am: role_menu::ActiveModel = Default::default(); am.role_id = Set(role_id); am.menu_id = Set(mid); items.push(am); }
|
||||
role_menu::Entity::insert_many(items).exec(&txn).await?;
|
||||
}
|
||||
txn.commit().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_role_ids_by_user_id(db: &Db, user_id: i64) -> Result<Vec<i64>, AppError> {
|
||||
let ids = user_role::Entity::find()
|
||||
.filter(user_role::Column::UserId.eq(user_id))
|
||||
.select_only()
|
||||
.column(user_role::Column::RoleId)
|
||||
.into_tuple::<i64>()
|
||||
.all(db)
|
||||
.await?;
|
||||
Ok(ids)
|
||||
}
|
||||
|
||||
pub async fn get_menu_ids_by_user_id(db: &Db, user_id: i64) -> Result<Vec<i64>, AppError> {
|
||||
let role_ids = get_role_ids_by_user_id(db, user_id).await?;
|
||||
if role_ids.is_empty() { return Ok(vec![]); }
|
||||
let mut ids = role_menu::Entity::find()
|
||||
.filter(role_menu::Column::RoleId.is_in(role_ids))
|
||||
.select_only()
|
||||
.column(role_menu::Column::MenuId)
|
||||
.into_tuple::<i64>()
|
||||
.all(db)
|
||||
.await?;
|
||||
ids.sort_unstable();
|
||||
ids.dedup();
|
||||
Ok(ids)
|
||||
}
|
||||
|
||||
pub async fn set_role_ids_by_user_id(db: &Db, user_id: i64, role_ids: Vec<i64>) -> Result<(), AppError> {
|
||||
let txn = db.begin().await?;
|
||||
user_role::Entity::delete_many()
|
||||
.filter(user_role::Column::UserId.eq(user_id))
|
||||
.exec(&txn)
|
||||
.await?;
|
||||
if !role_ids.is_empty() {
|
||||
let mut items: Vec<user_role::ActiveModel> = Vec::with_capacity(role_ids.len());
|
||||
for rid in role_ids {
|
||||
let mut am: user_role::ActiveModel = Default::default();
|
||||
am.user_id = Set(user_id);
|
||||
am.role_id = Set(rid);
|
||||
items.push(am);
|
||||
}
|
||||
user_role::Entity::insert_many(items).exec(&txn).await?;
|
||||
}
|
||||
txn.commit().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 新增:删除角色(清理用户与权限、菜单关联)
|
||||
pub async fn delete(db: &Db, id: i64) -> Result<(), AppError> {
|
||||
let _ = role::Entity::find_by_id(id).one(db).await?.ok_or(AppError::NotFound)?;
|
||||
let txn = db.begin().await?;
|
||||
role_menu::Entity::delete_many().filter(role_menu::Column::RoleId.eq(id)).exec(&txn).await?;
|
||||
user_role::Entity::delete_many().filter(user_role::Column::RoleId.eq(id)).exec(&txn).await?;
|
||||
let _ = role::Entity::delete_by_id(id).exec(&txn).await?;
|
||||
txn.commit().await?;
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user