✨ Añade pagetop-user, con autenticación y RBAC
Identidad de usuario, sesiones en base de datos, roles y permisos (RBAC) con "authenticated" implícito, contraseñas con Argon2id, tokens de un solo uso para verificación de email y restablecimiento de contraseña, y la UI de administración completa (usuarios, roles, permisos) sobre pagetop-admin. Incluye datos de demostración opcionales tras la feature `demo-data`.
This commit is contained in:
parent
043873a954
commit
def0513246
57 changed files with 7409 additions and 0 deletions
40
extensions/pagetop-user/src/entity/role.rs
Normal file
40
extensions/pagetop-user/src/entity/role.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use pagetop_seaorm::db::*;
|
||||
|
||||
use pagetop::datetime::NaiveDateTime;
|
||||
|
||||
#[derive(Clone, Debug, DeriveEntityModel, PartialEq)]
|
||||
#[sea_orm(table_name = "roles")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: i32,
|
||||
#[sea_orm(unique)]
|
||||
pub machine_name: String,
|
||||
pub label: String,
|
||||
pub description: Option<String>,
|
||||
pub weight: i32,
|
||||
pub locked: bool,
|
||||
pub created_at: NaiveDateTime,
|
||||
pub updated_at: NaiveDateTime,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, DeriveRelation, EnumIter)]
|
||||
pub enum Relation {
|
||||
#[sea_orm(has_many = "super::role_permission::Entity")]
|
||||
RolePermissions,
|
||||
#[sea_orm(has_many = "super::user_role::Entity")]
|
||||
UserRoles,
|
||||
}
|
||||
|
||||
impl Related<super::role_permission::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::RolePermissions.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::user_role::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::UserRoles.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
32
extensions/pagetop-user/src/entity/role_permission.rs
Normal file
32
extensions/pagetop-user/src/entity/role_permission.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use pagetop_seaorm::db::*;
|
||||
|
||||
use pagetop::datetime::NaiveDateTime;
|
||||
|
||||
#[derive(Clone, Debug, DeriveEntityModel, PartialEq)]
|
||||
#[sea_orm(table_name = "role_permissions")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub role_id: i32,
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub permission_key: String,
|
||||
pub granted_at: NaiveDateTime,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, DeriveRelation, EnumIter)]
|
||||
pub enum Relation {
|
||||
#[sea_orm(
|
||||
belongs_to = "super::role::Entity",
|
||||
from = "Column::RoleId",
|
||||
to = "super::role::Column::Id",
|
||||
on_delete = "Cascade"
|
||||
)]
|
||||
Role,
|
||||
}
|
||||
|
||||
impl Related<super::role::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Role.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
34
extensions/pagetop-user/src/entity/session.rs
Normal file
34
extensions/pagetop-user/src/entity/session.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use pagetop_seaorm::db::*;
|
||||
|
||||
use pagetop::datetime::NaiveDateTime;
|
||||
|
||||
#[derive(Clone, Debug, DeriveEntityModel, PartialEq)]
|
||||
#[sea_orm(table_name = "sessions")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub sid: String,
|
||||
pub user_id: i32,
|
||||
pub data: String,
|
||||
pub last_activity_at: Option<NaiveDateTime>,
|
||||
pub expires_at: NaiveDateTime,
|
||||
pub created_at: NaiveDateTime,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, DeriveRelation, EnumIter)]
|
||||
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 {}
|
||||
58
extensions/pagetop-user/src/entity/user.rs
Normal file
58
extensions/pagetop-user/src/entity/user.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
use pagetop_seaorm::db::*;
|
||||
|
||||
use pagetop::datetime::NaiveDateTime;
|
||||
|
||||
#[derive(Clone, Debug, DeriveEntityModel, PartialEq)]
|
||||
#[sea_orm(table_name = "users")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: i32,
|
||||
#[sea_orm(unique)]
|
||||
pub username: String,
|
||||
#[sea_orm(unique)]
|
||||
pub email: String,
|
||||
pub email_verified_at: Option<NaiveDateTime>,
|
||||
pub password_hash: String,
|
||||
pub status: i16,
|
||||
pub language: Option<String>,
|
||||
pub timezone: Option<String>,
|
||||
pub display_name: Option<String>,
|
||||
pub last_login_at: Option<NaiveDateTime>,
|
||||
pub last_access_at: Option<NaiveDateTime>,
|
||||
pub failed_login_count: i32,
|
||||
pub locked_until: Option<NaiveDateTime>,
|
||||
/// Acceso irrestricto al sistema, sin pasar por roles ni permisos.
|
||||
pub is_admin: bool,
|
||||
pub created_at: NaiveDateTime,
|
||||
pub updated_at: NaiveDateTime,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, DeriveRelation, EnumIter)]
|
||||
pub enum Relation {
|
||||
#[sea_orm(has_many = "super::user_role::Entity")]
|
||||
UserRoles,
|
||||
#[sea_orm(has_many = "super::session::Entity")]
|
||||
Sessions,
|
||||
#[sea_orm(has_many = "super::user_token::Entity")]
|
||||
UserTokens,
|
||||
}
|
||||
|
||||
impl Related<super::user_role::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::UserRoles.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::session::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Sessions.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::user_token::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::UserTokens.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
42
extensions/pagetop-user/src/entity/user_role.rs
Normal file
42
extensions/pagetop-user/src/entity/user_role.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use pagetop_seaorm::db::*;
|
||||
|
||||
#[derive(Clone, Debug, DeriveEntityModel, PartialEq)]
|
||||
#[sea_orm(table_name = "user_roles")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub user_id: i32,
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub role_id: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, DeriveRelation, EnumIter)]
|
||||
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 {}
|
||||
37
extensions/pagetop-user/src/entity/user_token.rs
Normal file
37
extensions/pagetop-user/src/entity/user_token.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
use pagetop_seaorm::db::*;
|
||||
|
||||
use pagetop::datetime::NaiveDateTime;
|
||||
|
||||
#[derive(Clone, Debug, DeriveEntityModel, PartialEq)]
|
||||
#[sea_orm(table_name = "user_tokens")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: i32,
|
||||
pub user_id: i32,
|
||||
pub kind: String,
|
||||
#[sea_orm(unique)]
|
||||
pub token_hash: String,
|
||||
pub expires_at: NaiveDateTime,
|
||||
pub consumed_at: Option<NaiveDateTime>,
|
||||
pub created_at: NaiveDateTime,
|
||||
pub updated_at: NaiveDateTime,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, DeriveRelation, EnumIter)]
|
||||
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 {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue