feat(auth): add SeaORM entities and DTOs for auth module
- 11 entity files mapping to all auth migration tables - DTOs with validation: LoginReq, CreateUserReq, CreateRoleReq, etc. - Response DTOs: UserResp, RoleResp, PermissionResp, OrganizationResp, etc. - Added workspace dependencies: jsonwebtoken, argon2, validator, thiserror, utoipa
This commit is contained in:
@@ -5,6 +5,7 @@ edition.workspace = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erp-core.workspace = true
|
erp-core.workspace = true
|
||||||
|
erp-common.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
@@ -14,3 +15,8 @@ axum.workspace = true
|
|||||||
sea-orm.workspace = true
|
sea-orm.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
|
thiserror.workspace = true
|
||||||
|
jsonwebtoken.workspace = true
|
||||||
|
argon2.workspace = true
|
||||||
|
validator.workspace = true
|
||||||
|
utoipa.workspace = true
|
||||||
|
|||||||
185
crates/erp-auth/src/dto.rs
Normal file
185
crates/erp-auth/src/dto.rs
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use utoipa::ToSchema;
|
||||||
|
use uuid::Uuid;
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
|
// --- Auth DTOs ---
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||||
|
pub struct LoginReq {
|
||||||
|
#[validate(length(min = 1, message = "用户名不能为空"))]
|
||||||
|
pub username: String,
|
||||||
|
#[validate(length(min = 1, message = "密码不能为空"))]
|
||||||
|
pub password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, ToSchema)]
|
||||||
|
pub struct LoginResp {
|
||||||
|
pub access_token: String,
|
||||||
|
pub refresh_token: String,
|
||||||
|
pub expires_in: u64,
|
||||||
|
pub user: UserResp,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, ToSchema)]
|
||||||
|
pub struct RefreshReq {
|
||||||
|
pub refresh_token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- User DTOs ---
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, ToSchema)]
|
||||||
|
pub struct UserResp {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub username: String,
|
||||||
|
pub email: Option<String>,
|
||||||
|
pub phone: Option<String>,
|
||||||
|
pub display_name: Option<String>,
|
||||||
|
pub avatar_url: Option<String>,
|
||||||
|
pub status: String,
|
||||||
|
pub roles: Vec<RoleResp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||||
|
pub struct CreateUserReq {
|
||||||
|
#[validate(length(min = 1, max = 50))]
|
||||||
|
pub username: String,
|
||||||
|
#[validate(length(min = 6, max = 128))]
|
||||||
|
pub password: String,
|
||||||
|
#[validate(email)]
|
||||||
|
pub email: Option<String>,
|
||||||
|
pub phone: Option<String>,
|
||||||
|
pub display_name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, ToSchema)]
|
||||||
|
pub struct UpdateUserReq {
|
||||||
|
pub email: Option<String>,
|
||||||
|
pub phone: Option<String>,
|
||||||
|
pub display_name: Option<String>,
|
||||||
|
pub status: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Role DTOs ---
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, ToSchema)]
|
||||||
|
pub struct RoleResp {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub code: String,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub is_system: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||||
|
pub struct CreateRoleReq {
|
||||||
|
#[validate(length(min = 1, max = 50))]
|
||||||
|
pub name: String,
|
||||||
|
#[validate(length(min = 1, max = 50))]
|
||||||
|
pub code: String,
|
||||||
|
pub description: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, ToSchema)]
|
||||||
|
pub struct UpdateRoleReq {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub description: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, ToSchema)]
|
||||||
|
pub struct AssignRolesReq {
|
||||||
|
pub role_ids: Vec<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Permission DTOs ---
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, ToSchema)]
|
||||||
|
pub struct PermissionResp {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub code: String,
|
||||||
|
pub name: String,
|
||||||
|
pub resource: String,
|
||||||
|
pub action: String,
|
||||||
|
pub description: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, ToSchema)]
|
||||||
|
pub struct AssignPermissionsReq {
|
||||||
|
pub permission_ids: Vec<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Organization DTOs ---
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, ToSchema)]
|
||||||
|
pub struct OrganizationResp {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub code: Option<String>,
|
||||||
|
pub parent_id: Option<Uuid>,
|
||||||
|
pub path: Option<String>,
|
||||||
|
pub level: i32,
|
||||||
|
pub sort_order: i32,
|
||||||
|
pub children: Vec<OrganizationResp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||||
|
pub struct CreateOrganizationReq {
|
||||||
|
#[validate(length(min = 1))]
|
||||||
|
pub name: String,
|
||||||
|
pub code: Option<String>,
|
||||||
|
pub parent_id: Option<Uuid>,
|
||||||
|
pub sort_order: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, ToSchema)]
|
||||||
|
pub struct UpdateOrganizationReq {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub code: Option<String>,
|
||||||
|
pub sort_order: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Department DTOs ---
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, ToSchema)]
|
||||||
|
pub struct DepartmentResp {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub org_id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub code: Option<String>,
|
||||||
|
pub parent_id: Option<Uuid>,
|
||||||
|
pub manager_id: Option<Uuid>,
|
||||||
|
pub path: Option<String>,
|
||||||
|
pub sort_order: i32,
|
||||||
|
pub children: Vec<DepartmentResp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||||
|
pub struct CreateDepartmentReq {
|
||||||
|
#[validate(length(min = 1))]
|
||||||
|
pub name: String,
|
||||||
|
pub code: Option<String>,
|
||||||
|
pub parent_id: Option<Uuid>,
|
||||||
|
pub manager_id: Option<Uuid>,
|
||||||
|
pub sort_order: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Position DTOs ---
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, ToSchema)]
|
||||||
|
pub struct PositionResp {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub dept_id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub code: Option<String>,
|
||||||
|
pub level: i32,
|
||||||
|
pub sort_order: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||||
|
pub struct CreatePositionReq {
|
||||||
|
#[validate(length(min = 1))]
|
||||||
|
pub name: String,
|
||||||
|
pub code: Option<String>,
|
||||||
|
pub level: Option<i32>,
|
||||||
|
pub sort_order: Option<i32>,
|
||||||
|
}
|
||||||
68
crates/erp-auth/src/entity/department.rs
Normal file
68
crates/erp-auth/src/entity/department.rs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "departments")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub id: Uuid,
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub org_id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub code: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub parent_id: Option<Uuid>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub manager_id: Option<Uuid>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub path: Option<String>,
|
||||||
|
pub sort_order: i32,
|
||||||
|
pub created_at: DateTimeUtc,
|
||||||
|
pub updated_at: DateTimeUtc,
|
||||||
|
pub created_by: Uuid,
|
||||||
|
pub updated_by: Uuid,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deleted_at: Option<DateTimeUtc>,
|
||||||
|
pub version: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::organization::Entity",
|
||||||
|
from = "Column::OrgId",
|
||||||
|
to = "super::organization::Column::Id",
|
||||||
|
on_delete = "Restrict"
|
||||||
|
)]
|
||||||
|
Organization,
|
||||||
|
#[sea_orm(has_many = "super::position::Entity")]
|
||||||
|
Position,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::user::Entity",
|
||||||
|
from = "Column::ManagerId",
|
||||||
|
to = "super::user::Column::Id",
|
||||||
|
on_delete = "SetNull"
|
||||||
|
)]
|
||||||
|
Manager,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::organization::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Organization.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::position::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Position.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::user::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Manager.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
10
crates/erp-auth/src/entity/mod.rs
Normal file
10
crates/erp-auth/src/entity/mod.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
pub mod user;
|
||||||
|
pub mod user_credential;
|
||||||
|
pub mod user_token;
|
||||||
|
pub mod role;
|
||||||
|
pub mod permission;
|
||||||
|
pub mod role_permission;
|
||||||
|
pub mod user_role;
|
||||||
|
pub mod organization;
|
||||||
|
pub mod department;
|
||||||
|
pub mod position;
|
||||||
40
crates/erp-auth/src/entity/organization.rs
Normal file
40
crates/erp-auth/src/entity/organization.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "organizations")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub id: Uuid,
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub code: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub parent_id: Option<Uuid>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub path: Option<String>,
|
||||||
|
pub level: i32,
|
||||||
|
pub sort_order: i32,
|
||||||
|
pub created_at: DateTimeUtc,
|
||||||
|
pub updated_at: DateTimeUtc,
|
||||||
|
pub created_by: Uuid,
|
||||||
|
pub updated_by: Uuid,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deleted_at: Option<DateTimeUtc>,
|
||||||
|
pub version: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(has_many = "super::department::Entity")]
|
||||||
|
Department,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::department::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Department.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
37
crates/erp-auth/src/entity/permission.rs
Normal file
37
crates/erp-auth/src/entity/permission.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "permissions")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub id: Uuid,
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub code: String,
|
||||||
|
pub name: String,
|
||||||
|
pub resource: String,
|
||||||
|
pub action: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub created_at: DateTimeUtc,
|
||||||
|
pub updated_at: DateTimeUtc,
|
||||||
|
pub created_by: Uuid,
|
||||||
|
pub updated_by: Uuid,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deleted_at: Option<DateTimeUtc>,
|
||||||
|
pub version: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(has_many = "super::role_permission::Entity")]
|
||||||
|
RolePermission,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::role_permission::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::RolePermission.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
42
crates/erp-auth/src/entity/position.rs
Normal file
42
crates/erp-auth/src/entity/position.rs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "positions")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub id: Uuid,
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub dept_id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub code: Option<String>,
|
||||||
|
pub level: i32,
|
||||||
|
pub sort_order: i32,
|
||||||
|
pub created_at: DateTimeUtc,
|
||||||
|
pub updated_at: DateTimeUtc,
|
||||||
|
pub created_by: Uuid,
|
||||||
|
pub updated_by: Uuid,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deleted_at: Option<DateTimeUtc>,
|
||||||
|
pub version: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::department::Entity",
|
||||||
|
from = "Column::DeptId",
|
||||||
|
to = "super::department::Column::Id",
|
||||||
|
on_delete = "Restrict"
|
||||||
|
)]
|
||||||
|
Department,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::department::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Department.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
44
crates/erp-auth/src/entity/role.rs
Normal file
44
crates/erp-auth/src/entity/role.rs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "roles")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub id: Uuid,
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub code: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub is_system: bool,
|
||||||
|
pub created_at: DateTimeUtc,
|
||||||
|
pub updated_at: DateTimeUtc,
|
||||||
|
pub created_by: Uuid,
|
||||||
|
pub updated_by: Uuid,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deleted_at: Option<DateTimeUtc>,
|
||||||
|
pub version: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(has_many = "super::role_permission::Entity")]
|
||||||
|
RolePermission,
|
||||||
|
#[sea_orm(has_many = "super::user_role::Entity")]
|
||||||
|
UserRole,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::role_permission::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::RolePermission.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::user_role::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::UserRole.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
51
crates/erp-auth/src/entity/role_permission.rs
Normal file
51
crates/erp-auth/src/entity/role_permission.rs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "role_permissions")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub role_id: Uuid,
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub permission_id: Uuid,
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub created_at: DateTimeUtc,
|
||||||
|
pub updated_at: DateTimeUtc,
|
||||||
|
pub created_by: Uuid,
|
||||||
|
pub updated_by: Uuid,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deleted_at: Option<DateTimeUtc>,
|
||||||
|
pub version: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::role::Entity",
|
||||||
|
from = "Column::RoleId",
|
||||||
|
to = "super::role::Column::Id",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Role,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::permission::Entity",
|
||||||
|
from = "Column::PermissionId",
|
||||||
|
to = "super::permission::Column::Id",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Permission,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::role::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Role.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::permission::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Permission.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
59
crates/erp-auth/src/entity/user.rs
Normal file
59
crates/erp-auth/src/entity/user.rs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "users")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub id: Uuid,
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub username: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub email: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub phone: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub display_name: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub avatar_url: Option<String>,
|
||||||
|
pub status: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub last_login_at: Option<DateTimeUtc>,
|
||||||
|
pub created_at: DateTimeUtc,
|
||||||
|
pub updated_at: DateTimeUtc,
|
||||||
|
pub created_by: Uuid,
|
||||||
|
pub updated_by: Uuid,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deleted_at: Option<DateTimeUtc>,
|
||||||
|
pub version: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(has_many = "super::user_credential::Entity")]
|
||||||
|
UserCredential,
|
||||||
|
#[sea_orm(has_many = "super::user_token::Entity")]
|
||||||
|
UserToken,
|
||||||
|
#[sea_orm(has_many = "super::user_role::Entity")]
|
||||||
|
UserRole,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::user_credential::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::UserCredential.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::user_token::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::UserToken.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::user_role::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::UserRole.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
41
crates/erp-auth/src/entity/user_credential.rs
Normal file
41
crates/erp-auth/src/entity/user_credential.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "user_credentials")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub id: Uuid,
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub user_id: Uuid,
|
||||||
|
pub credential_type: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub credential_data: Option<serde_json::Value>,
|
||||||
|
pub verified: bool,
|
||||||
|
pub created_at: DateTimeUtc,
|
||||||
|
pub updated_at: DateTimeUtc,
|
||||||
|
pub created_by: Uuid,
|
||||||
|
pub updated_by: Uuid,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deleted_at: Option<DateTimeUtc>,
|
||||||
|
pub version: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::user::Entity",
|
||||||
|
from = "Column::UserId",
|
||||||
|
to = "super::user::Column::Id",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
User,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::user::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::User.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
51
crates/erp-auth/src/entity/user_role.rs
Normal file
51
crates/erp-auth/src/entity/user_role.rs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "user_roles")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub user_id: Uuid,
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub role_id: Uuid,
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub created_at: DateTimeUtc,
|
||||||
|
pub updated_at: DateTimeUtc,
|
||||||
|
pub created_by: Uuid,
|
||||||
|
pub updated_by: Uuid,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deleted_at: Option<DateTimeUtc>,
|
||||||
|
pub version: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::user::Entity",
|
||||||
|
from = "Column::UserId",
|
||||||
|
to = "super::user::Column::Id",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
User,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::role::Entity",
|
||||||
|
from = "Column::RoleId",
|
||||||
|
to = "super::role::Column::Id",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Role,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::user::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::User.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::role::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Role.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
44
crates/erp-auth/src/entity/user_token.rs
Normal file
44
crates/erp-auth/src/entity/user_token.rs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
|
#[sea_orm(table_name = "user_tokens")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub id: Uuid,
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub user_id: Uuid,
|
||||||
|
pub token_hash: String,
|
||||||
|
pub token_type: String,
|
||||||
|
pub expires_at: DateTimeUtc,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub revoked_at: Option<DateTimeUtc>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub device_info: Option<String>,
|
||||||
|
pub created_at: DateTimeUtc,
|
||||||
|
pub updated_at: DateTimeUtc,
|
||||||
|
pub created_by: Uuid,
|
||||||
|
pub updated_by: Uuid,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deleted_at: Option<DateTimeUtc>,
|
||||||
|
pub version: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::user::Entity",
|
||||||
|
from = "Column::UserId",
|
||||||
|
to = "super::user::Column::Id",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
User,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::user::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::User.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
@@ -1 +1,2 @@
|
|||||||
// erp-auth: 身份与权限模块 (Phase 2)
|
pub mod dto;
|
||||||
|
pub mod entity;
|
||||||
|
|||||||
Reference in New Issue
Block a user