diff --git a/Cargo.lock b/Cargo.lock index 6d9160d..fdb8f9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1041,6 +1041,7 @@ name = "entity" version = "0.1.0" dependencies = [ "sea-orm", + "serde", ] [[package]] diff --git a/crates/backend/src/controller.rs b/crates/backend/src/controller.rs index d243ed8..2b55317 100644 --- a/crates/backend/src/controller.rs +++ b/crates/backend/src/controller.rs @@ -1,5 +1,7 @@ mod auth; +mod license; mod user; pub use auth::AuthController; +pub use license::LicenseController; pub use user::UserController; diff --git a/crates/backend/src/controller/license.rs b/crates/backend/src/controller/license.rs new file mode 100644 index 0000000..db698e5 --- /dev/null +++ b/crates/backend/src/controller/license.rs @@ -0,0 +1,63 @@ +use actix_web::{error::ErrorInternalServerError, web, Responder}; +use sea_orm::{ActiveModelTrait, ActiveValue, EntityTrait, IntoActiveModel}; +use serde::{Deserialize, Serialize}; + +use crate::{auth::AuthedUser, AppState}; + +use super::user::UserWithoutPassword; + +#[derive(Serialize)] +struct GroupWithLicenses { + #[serde(flatten)] + group: entity::license_group::Model, + licenses: Vec, +} + +pub struct LicenseController; + +impl LicenseController { + pub async fn list_groups( + state: web::Data, + _executor: AuthedUser, + ) -> actix_web::Result { + let db = &state.db; + let groups = entity::prelude::LicenseGroup::find() + .find_with_related(entity::prelude::License) + .all(db) + .await + .map_err(ErrorInternalServerError)? + .into_iter() + .map(|(group, licenses)| GroupWithLicenses { group, licenses }) + .collect::>(); + Ok(web::Json(groups)) + } + + pub async fn create_group( + state: web::Data, + group: web::Json, + _executor: AuthedUser, + ) -> actix_web::Result { + let db = &state.db; + let group = group.into_inner(); + let mut group = group.into_active_model(); + group.id = ActiveValue::NotSet; + + let res = group.insert(db).await.map_err(ErrorInternalServerError)?; + + Ok(web::Json(res)) + } + pub async fn create_license( + state: web::Data, + license: web::Json, + _executor: AuthedUser, + ) -> actix_web::Result { + let db = &state.db; + let license = license.into_inner(); + let mut license = license.into_active_model(); + license.id = ActiveValue::NotSet; + + let res = license.insert(db).await.map_err(ErrorInternalServerError)?; + + Ok(web::Json(res)) + } +} diff --git a/crates/backend/src/routes.rs b/crates/backend/src/routes.rs index e4b7cac..86816b0 100644 --- a/crates/backend/src/routes.rs +++ b/crates/backend/src/routes.rs @@ -1,4 +1,4 @@ -use crate::controller::{AuthController, UserController}; +use crate::controller::{AuthController, LicenseController, UserController}; use actix_web::web; pub fn config(cfg: &mut web::ServiceConfig) { @@ -10,6 +10,12 @@ pub fn config(cfg: &mut web::ServiceConfig) { .post(UserController::create_user), ) .service(web::resource("/users/{user_id}")) + .service( + web::resource("/license") + .get(LicenseController::list_groups) + .post(LicenseController::create_license), + ) + .route("/group", web::post().to(LicenseController::create_group)) .service(web::scope("/auth").route("/login", web::post().to(AuthController::login))), ); } diff --git a/crates/entity/Cargo.toml b/crates/entity/Cargo.toml index 849ca04..09040fa 100644 --- a/crates/entity/Cargo.toml +++ b/crates/entity/Cargo.toml @@ -5,4 +5,5 @@ edition = "2021" [dependencies] +serde = { version = "*", features = ["derive"] } sea-orm = { version = "0.12" } diff --git a/crates/entity/src/lib.rs b/crates/entity/src/lib.rs index 412b614..9f019b6 100644 --- a/crates/entity/src/lib.rs +++ b/crates/entity/src/lib.rs @@ -2,4 +2,6 @@ pub mod prelude; +pub mod license; +pub mod license_group; pub mod user; diff --git a/crates/entity/src/license.rs b/crates/entity/src/license.rs new file mode 100644 index 0000000..d6a0161 --- /dev/null +++ b/crates/entity/src/license.rs @@ -0,0 +1,38 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "license")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + #[serde(skip_deserializing)] + pub id: Uuid, + pub name: String, + pub start: Option, + pub end: Option, + pub amount: Option, + pub key: String, + pub group_id: Uuid, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::license_group::Entity", + from = "Column::GroupId", + to = "super::license_group::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + LicenseGroup, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::LicenseGroup.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/entity/src/license_group.rs b/crates/entity/src/license_group.rs new file mode 100644 index 0000000..2ab36c4 --- /dev/null +++ b/crates/entity/src/license_group.rs @@ -0,0 +1,27 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "license_group")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + #[serde(skip_deserializing)] + pub id: Uuid, + pub name: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::license::Entity")] + License, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::License.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/crates/entity/src/prelude.rs b/crates/entity/src/prelude.rs index d60b621..5fcfa92 100644 --- a/crates/entity/src/prelude.rs +++ b/crates/entity/src/prelude.rs @@ -1,3 +1,5 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 +pub use super::license::Entity as License; +pub use super::license_group::Entity as LicenseGroup; pub use super::user::Entity as User; diff --git a/crates/entity/src/user.rs b/crates/entity/src/user.rs index 653e299..984cd24 100644 --- a/crates/entity/src/user.rs +++ b/crates/entity/src/user.rs @@ -1,11 +1,13 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.15 use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] #[sea_orm(table_name = "user")] pub struct Model { #[sea_orm(primary_key, auto_increment = false)] + #[serde(skip_deserializing)] pub id: Uuid, pub name: String, #[sea_orm(unique)] diff --git a/crates/migration/src/lib.rs b/crates/migration/src/lib.rs index b6f111f..e451df9 100644 --- a/crates/migration/src/lib.rs +++ b/crates/migration/src/lib.rs @@ -4,6 +4,8 @@ pub struct Migrator; mod m20240705_100914_create_user; mod m20240708_085852_create_admin_user; +mod m20240709_095319_create_license_group; +mod m20240709_095325_create_license; #[async_trait::async_trait] impl MigratorTrait for Migrator { @@ -11,6 +13,8 @@ impl MigratorTrait for Migrator { vec![ Box::new(m20240705_100914_create_user::Migration), Box::new(m20240708_085852_create_admin_user::Migration), + Box::new(m20240709_095319_create_license_group::Migration), + Box::new(m20240709_095325_create_license::Migration), ] } } diff --git a/crates/migration/src/m20240709_095319_create_license_group.rs b/crates/migration/src/m20240709_095319_create_license_group.rs new file mode 100644 index 0000000..41cd0ed --- /dev/null +++ b/crates/migration/src/m20240709_095319_create_license_group.rs @@ -0,0 +1,39 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(LicenseGroup::Table) + .if_not_exists() + .col( + ColumnDef::new(LicenseGroup::Id) + .uuid() + .not_null() + .primary_key() + .extra("DEFAULT gen_random_uuid()"), + ) + .col(ColumnDef::new(LicenseGroup::Name).string().not_null()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(LicenseGroup::Table).to_owned()) + .await + } +} + +#[derive(DeriveIden)] +enum LicenseGroup { + Table, + Id, + Name, +} diff --git a/crates/migration/src/m20240709_095325_create_license.rs b/crates/migration/src/m20240709_095325_create_license.rs new file mode 100644 index 0000000..7aac510 --- /dev/null +++ b/crates/migration/src/m20240709_095325_create_license.rs @@ -0,0 +1,63 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(License::Table) + .if_not_exists() + .col( + ColumnDef::new(License::Id) + .uuid() + .not_null() + .primary_key() + .extra("DEFAULT gen_random_uuid()"), + ) + .col(ColumnDef::new(License::Name).string().not_null()) + .col(ColumnDef::new(License::Start).date_time()) + .col(ColumnDef::new(License::End).date_time()) + .col(ColumnDef::new(License::Amount).date_time()) + .col(ColumnDef::new(License::Key).string().not_null()) + .col(ColumnDef::new(License::GroupId).uuid().not_null()) + .foreign_key( + ForeignKey::create() + .name("fk-license-group_id") + .from(License::Table, License::GroupId) + .to(LicenseGroup::Table, LicenseGroup::Id) + .on_update(ForeignKeyAction::Cascade) + .on_delete(ForeignKeyAction::Cascade), + ) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(License::Table).to_owned()) + .await + } +} + +#[derive(DeriveIden)] +enum License { + Table, + Id, + Name, + Start, + End, + Amount, + Key, + GroupId, +} + +#[derive(DeriveIden)] +enum LicenseGroup { + Table, + Id, +}