feat: more models implemented

This commit is contained in:
Gabor Körber 2024-07-02 08:35:29 +02:00
parent 5c02867273
commit bce450f744
10 changed files with 333 additions and 13 deletions

50
entity/readme.md Normal file
View File

@ -0,0 +1,50 @@
# Entities for rear
## User
Should be compatible to Django-user to be able to easily share the db
```
class models.User
User objects have the following fields:
username¶
Required. 150 characters or fewer. Usernames may contain alphanumeric, _, @, +, . and - characters.
The max_length should be sufficient for many use cases. If you need a longer length, please use a custom user model. If you use MySQL with the utf8mb4 encoding (recommended for proper Unicode support), specify at most max_length=191 because MySQL can only create unique indexes with 191 characters in that case by default.
first_name¶
Optional (blank=True). 150 characters or fewer.
last_name¶
Optional (blank=True). 150 characters or fewer.
email¶
Optional (blank=True). Email address.
password¶
Required. A hash of, and metadata about, the password. (Django doesnt store the raw password.) Raw passwords can be arbitrarily long and can contain any character. See the password documentation.
groups¶
Many-to-many relationship to Group
user_permissions¶
Many-to-many relationship to Permission
is_staff¶
Boolean. Allows this user to access the admin site.
is_active¶
Boolean. Marks this user account as active. We recommend that you set this flag to False instead of deleting accounts. That way, if your applications have any foreign keys to users, the foreign keys wont break.
This doesnt necessarily control whether or not the user can log in. Authentication backends arent required to check for the is_active flag but the default backend (ModelBackend) and the RemoteUserBackend do. You can use AllowAllUsersModelBackend or AllowAllUsersRemoteUserBackend if you want to allow inactive users to login. In this case, youll also want to customize the AuthenticationForm used by the LoginView as it rejects inactive users. Be aware that the permission-checking methods such as has_perm() and the authentication in the Django admin all return False for inactive users.
is_superuser¶
Boolean. Treats this user as having all permissions without assigning any permission to it in particular.
last_login¶
A datetime of the users last login.
date_joined¶
The date/time when the account was created.
```

18
entity/src/group.rs Normal file
View File

@ -0,0 +1,18 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "groups")]
pub struct Model {
#[sea_orm(primary_key)]
#[serde(skip_deserializing)]
pub id: i32,
#[sea_orm(index = "group_names")]
pub name: String,
// permissions: many-to-many to Permission.
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

View File

@ -0,0 +1,65 @@
use sea_orm::entity::prelude::*;
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
pub struct Entity;
impl EntityName for Entity {
fn table_name(&self) -> &str {
"group_permission"
}
}
#[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
pub struct Model {
pub group_id: i32,
pub permission_id: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
pub enum Column {
GroupId,
PermissionId,
}
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
pub enum PrimaryKey {
GroupId,
PermissionId,
}
impl PrimaryKeyTrait for PrimaryKey {
type ValueType = (i32, i32);
fn auto_increment() -> bool {
false
}
}
impl ColumnTrait for Column {
type EntityName = Entity;
fn def(&self) -> ColumnDef {
match self {
Self::GroupId => ColumnType::Integer.def(),
Self::PermissionId => ColumnType::Integer.def(),
}
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::group::Entity",
from = "Column::GroupId",
to = "super::group::Column::Id"
)]
Group,
#[sea_orm(
belongs_to = "super::permission::Entity",
from = "Column::PermissionId",
to = "super::permission::Column::Id"
)]
Permission,
}
impl ActiveModelBehavior for ActiveModel {}

View File

@ -1,5 +1,13 @@
pub mod user;
pub mod group;
pub mod group_permission;
pub mod permission;
pub mod user;
pub mod user_group;
pub mod user_permission;
pub use user::Entity as User;
pub use group::Entity as Group;
pub use group_permission::Entity as GroupPermission;
pub use permission::Entity as Permission;
pub use user::Entity as User;
pub use user_group::Entity as UserGroup;
pub use user_permission::Entity as UserPermission;

View File

@ -1,7 +1,11 @@
use sea_orm::{DbConn, EntityTrait, Schema, DatabaseConnection, Database, ConnectionTrait};
use sea_orm::{ConnectionTrait, Database, DatabaseConnection, DbConn, EntityTrait, Schema};
mod user;
mod group;
mod group_permission;
mod permission;
mod user;
mod user_group;
mod user_permission;
async fn create_table<E>(db: &DbConn, entity: E)
where
@ -12,7 +16,7 @@ where
let mut table_create_statement = schema.create_table_from_entity(entity);
// we need to shadow the mutable instance X, because if_not_exists() returns &mut X
let table_create_statement = table_create_statement.if_not_exists();
let table_create_statement = table_create_statement.if_not_exists();
// we need to reborrow after dereferencing, which transforms our &mut X into &X
let stmt = backend.build(&*table_create_statement);
@ -31,7 +35,10 @@ pub async fn create_tables(db: &DbConn) {
async fn main() {
// Running Entities manually creates the tables from the entities in their latest incarnation.
println!("Connecting to database...");
let db: DatabaseConnection = Database::connect("postgresql://miniweb:miniweb@localhost:54321/miniweb").await.unwrap();
let db: DatabaseConnection =
Database::connect("postgresql://miniweb:miniweb@localhost:54321/miniweb")
.await
.unwrap();
println!("Creating tables for entities...");
create_tables(&db).await;
}

View File

@ -9,10 +9,12 @@ pub struct Model {
pub id: i32,
#[sea_orm(index = "permission_names")]
pub name: String,
#[sea_orm(index = "permission_codes")]
pub codename: String,
pub level: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
impl ActiveModelBehavior for ActiveModel {}

View File

@ -1,18 +1,58 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
use super::group::Entity as Group;
use super::permission::Entity as Permission;
use super::user_group::Relation as UserGroupRelation;
use super::user_permission::Relation as UserPermissionRelation;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "users")]
pub struct Model {
#[sea_orm(primary_key)]
#[serde(skip_deserializing)]
pub id: i64,
#[sea_orm(index = "user_usernames")]
pub username: String,
#[sea_orm(column_type = "Text")]
pub description: Option<String>,
pub password: String,
pub first_name: Option<String>,
pub last_name: Option<String>,
pub email: Option<String>,
// groups: many-to-many to Group
// user_permissions: many-to-many to Permission
pub is_staff: bool,
pub is_active: bool,
pub is_superuser: bool,
pub last_login: Option<DateTimeWithTimeZone>,
pub date_joined: Option<DateTimeWithTimeZone>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
impl Related<Group> for Entity {
// The final relation is User -> UserGroup -> Group
fn to() -> RelationDef {
UserGroupRelation::Group.def()
}
fn via() -> Option<RelationDef> {
// The original relation is UserGroup -> User,
// after `rev` it becomes User -> UserGroup
Some(UserGroupRelation::Group.def().rev())
}
}
impl Related<Permission> for Entity {
fn to() -> RelationDef {
UserPermissionRelation::Permission.def()
}
fn via() -> Option<RelationDef> {
Some(UserPermissionRelation::Permission.def().rev())
}
}

65
entity/src/user_group.rs Normal file
View File

@ -0,0 +1,65 @@
use sea_orm::entity::prelude::*;
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
pub struct Entity;
impl EntityName for Entity {
fn table_name(&self) -> &str {
"user_group"
}
}
#[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
pub struct Model {
pub user_id: i32,
pub group_id: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
pub enum Column {
UserId,
GroupId,
}
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
pub enum PrimaryKey {
UserId,
GroupId,
}
impl PrimaryKeyTrait for PrimaryKey {
type ValueType = (i32, i32);
fn auto_increment() -> bool {
false
}
}
impl ColumnTrait for Column {
type EntityName = Entity;
fn def(&self) -> ColumnDef {
match self {
Self::UserId => ColumnType::Integer.def(),
Self::GroupId => ColumnType::Integer.def(),
}
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::user::Entity",
from = "Column::UserId",
to = "super::user::Column::Id"
)]
User,
#[sea_orm(
belongs_to = "super::group::Entity",
from = "Column::GroupId",
to = "super::group::Column::Id"
)]
Group,
}
impl ActiveModelBehavior for ActiveModel {}

View File

@ -0,0 +1,65 @@
use sea_orm::entity::prelude::*;
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
pub struct Entity;
impl EntityName for Entity {
fn table_name(&self) -> &str {
"user_permission"
}
}
#[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
pub struct Model {
pub user_id: i32,
pub permission_id: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
pub enum Column {
UserId,
PermissionId,
}
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
pub enum PrimaryKey {
UserId,
PermissionId,
}
impl PrimaryKeyTrait for PrimaryKey {
type ValueType = (i32, i32);
fn auto_increment() -> bool {
false
}
}
impl ColumnTrait for Column {
type EntityName = Entity;
fn def(&self) -> ColumnDef {
match self {
Self::UserId => ColumnType::Integer.def(),
Self::PermissionId => ColumnType::Integer.def(),
}
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::user::Entity",
from = "Column::UserId",
to = "super::user::Column::Id"
)]
User,
#[sea_orm(
belongs_to = "super::permission::Entity",
from = "Column::PermissionId",
to = "super::permission::Column::Id"
)]
Permission,
}
impl ActiveModelBehavior for ActiveModel {}

View File

@ -89,8 +89,8 @@ impl AdminRepository for UserRepository {
..Default::default()
};
if let Some(value) = data.get("description") {
user.description = Set(value.as_str().map(|s| s.to_owned()));
if let Some(value) = data.get("password") {
user.password = Set(value.as_str().unwrap().to_owned());
}
if let Ok(user) = user.insert(&self.connection).await {
@ -120,8 +120,8 @@ impl AdminRepository for UserRepository {
}
}
if let Some(value) = data.get("description") {
user.description = Set(value.as_str().map(|s| s.to_owned()));
if let Some(value) = data.get("password") {
user.password = Set(value.as_str().unwrap().to_owned());
}
// update