From 580c2e7dc95263e2039688a507a6c0dd33ba2995 Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 5 Feb 2025 16:38:56 +0100 Subject: [PATCH] test test --- Cargo.toml | 14 +++ README.md | 2 +- database/Cargo.toml | 8 ++ database/src/{entities => entity}/benutzer.rs | 2 +- database/src/{entities => entity}/hardware.rs | 0 .../{entities => entity}/hardware_events.rs | 0 database/src/{entities => entity}/mod.rs | 0 database/src/{entities => entity}/prelude.rs | 0 .../sea_orm_active_enums.rs | 0 database/src/error.rs | 45 ++++++++++ database/src/lib.rs | 22 +---- database/src/model/benutzer.rs | 42 +++++++++ database/src/{models => model}/mod.rs | 0 database/src/{models => model}/prelude.rs | 0 database/src/models/benutzer.rs | 38 -------- database/src/repository/benutzer.rs | 90 +++++++++++++++++++ database/src/repository/mod.rs | 1 + main/Cargo.toml | 6 ++ main/src/main.rs | 35 ++++++-- migration/Cargo.toml | 10 +-- migration/src/m20250202_000233_benutzer.rs | 6 +- 21 files changed, 246 insertions(+), 75 deletions(-) rename database/src/{entities => entity}/benutzer.rs (96%) rename database/src/{entities => entity}/hardware.rs (100%) rename database/src/{entities => entity}/hardware_events.rs (100%) rename database/src/{entities => entity}/mod.rs (100%) rename database/src/{entities => entity}/prelude.rs (100%) rename database/src/{entities => entity}/sea_orm_active_enums.rs (100%) create mode 100644 database/src/error.rs create mode 100644 database/src/model/benutzer.rs rename database/src/{models => model}/mod.rs (100%) rename database/src/{models => model}/prelude.rs (100%) delete mode 100644 database/src/models/benutzer.rs create mode 100644 database/src/repository/benutzer.rs create mode 100644 database/src/repository/mod.rs diff --git a/Cargo.toml b/Cargo.toml index fa7b494..4b72118 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,3 +2,17 @@ resolver = "3" members = ["migration", "database", "main"] + +[workspace.dependencies] +sea-orm = { version = "1.1.4", features = [ + "sqlx-postgres", + "runtime-tokio-rustls", + "macros", +] } + +axum = { version = "0.8.1", features = ["json"] } +serde = { version = "1.0.217", features = ["derive"] } +uuid = { version = "1.12.1", features = ["v4", "serde"] } +tokio = { version = "1.43.0", features = ["full"] } +thiserror = { version = "2.0.11" } +dotenvy = "0.15.7" diff --git a/README.md b/README.md index 1334667..2431c14 100644 --- a/README.md +++ b/README.md @@ -13,5 +13,5 @@ sea-orm-cli generate -h sea-orm-cli generate entity -h # Generate Seaography entities -sea-orm-cli generate entity --output-dir ./database/src/entities --with-serde both --with-copy-enums +sea-orm-cli generate entity --output-dir ./database/src/entity/ --with-serde both --with-copy-enums ``` diff --git a/database/Cargo.toml b/database/Cargo.toml index 407f7da..be0ba53 100644 --- a/database/Cargo.toml +++ b/database/Cargo.toml @@ -4,3 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] +migration = { path = "../migration" } + +sea-orm = { workspace = true } +serde = { workspace = true } +uuid = { workspace = true } +axum = { workspace = true } +thiserror = { workspace = true } +validator = { version = "0.20.0", features = ["derive"] } diff --git a/database/src/entities/benutzer.rs b/database/src/entity/benutzer.rs similarity index 96% rename from database/src/entities/benutzer.rs rename to database/src/entity/benutzer.rs index b75cb85..8ed3f09 100644 --- a/database/src/entities/benutzer.rs +++ b/database/src/entity/benutzer.rs @@ -12,7 +12,7 @@ pub struct Model { pub e_mail: String, #[sea_orm(unique)] pub kennung: String, - pub password_hash: String, + pub password_hash: Option, pub nachname: String, pub vorname: String, pub erstellt_am: DateTimeWithTimeZone, diff --git a/database/src/entities/hardware.rs b/database/src/entity/hardware.rs similarity index 100% rename from database/src/entities/hardware.rs rename to database/src/entity/hardware.rs diff --git a/database/src/entities/hardware_events.rs b/database/src/entity/hardware_events.rs similarity index 100% rename from database/src/entities/hardware_events.rs rename to database/src/entity/hardware_events.rs diff --git a/database/src/entities/mod.rs b/database/src/entity/mod.rs similarity index 100% rename from database/src/entities/mod.rs rename to database/src/entity/mod.rs diff --git a/database/src/entities/prelude.rs b/database/src/entity/prelude.rs similarity index 100% rename from database/src/entities/prelude.rs rename to database/src/entity/prelude.rs diff --git a/database/src/entities/sea_orm_active_enums.rs b/database/src/entity/sea_orm_active_enums.rs similarity index 100% rename from database/src/entities/sea_orm_active_enums.rs rename to database/src/entity/sea_orm_active_enums.rs diff --git a/database/src/error.rs b/database/src/error.rs new file mode 100644 index 0000000..b9eb4af --- /dev/null +++ b/database/src/error.rs @@ -0,0 +1,45 @@ +use axum::{ + http::StatusCode, + response::{IntoResponse, Response}, +}; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum AppError { + #[error("Authentication required")] + Unauthorized, + + #[error("Forbidden")] + Forbidden, + + #[error("User not found")] + UserNotFound, + + #[error("Invalid credentials")] + InvalidCredentials, + + #[error("Database error")] + DbError(#[from] sea_orm::DbErr), + + #[error("Validierungsfehler: {0}")] + ValidationError(#[from] validator::ValidationErrors), + + #[error("Fehler in .env")] + Err(#[from] std::env::VarError), +} + +impl IntoResponse for AppError { + fn into_response(self) -> Response { + let status = match self { + AppError::Unauthorized => StatusCode::UNAUTHORIZED, + AppError::Forbidden => todo!(), + AppError::UserNotFound => todo!(), + AppError::InvalidCredentials => todo!(), + AppError::ValidationError(_) => todo!(), + AppError::Err(_) => todo!(), + AppError::DbError(db_err) => todo!(), + // ... weitere Matches + }; + (status, self.to_string()).into_response() + } +} diff --git a/database/src/lib.rs b/database/src/lib.rs index 1777d0b..fafa09d 100644 --- a/database/src/lib.rs +++ b/database/src/lib.rs @@ -1,18 +1,4 @@ -pub fn add(left: u64, right: u64) -> u64 { - left + right -} - -pub fn sub(left: u64, right: u64) -> u64 { - left - right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +mod entity; +pub mod error; +pub mod model; +pub mod repository; diff --git a/database/src/model/benutzer.rs b/database/src/model/benutzer.rs new file mode 100644 index 0000000..bb2f9d4 --- /dev/null +++ b/database/src/model/benutzer.rs @@ -0,0 +1,42 @@ +use serde::{Deserialize, Serialize}; +use uuid::Uuid; +use validator::Validate; + +#[derive(Debug, Serialize, Deserialize, Validate)] +pub struct ErstelleBenutzer { + #[validate(length(min = 10, max = 255))] + pub email: String, + + #[validate(length(min = 8, max = 8))] + pub kennung: String, + + #[validate(length(max = 100))] + pub nachname: String, + + #[validate(length(max = 100))] + pub vorname: String, +} + +#[derive(Debug, Serialize, Deserialize, Validate)] +pub struct AktualisiereBenutzer { + pub id: Uuid, + + #[validate(length(min = 10, max = 255))] + pub email: Option, + + #[validate(length(min = 8, max = 8))] + pub kennung: Option, + + #[validate(length(max = 100))] + pub nachname: Option, + + #[validate(length(max = 100))] + pub vorname: Option, + + pub ist_akiv: Option, +} + +#[derive(Debug, Deserialize)] +pub struct LoescheBenutzer { + pub id: Uuid, +} diff --git a/database/src/models/mod.rs b/database/src/model/mod.rs similarity index 100% rename from database/src/models/mod.rs rename to database/src/model/mod.rs diff --git a/database/src/models/prelude.rs b/database/src/model/prelude.rs similarity index 100% rename from database/src/models/prelude.rs rename to database/src/model/prelude.rs diff --git a/database/src/models/benutzer.rs b/database/src/models/benutzer.rs deleted file mode 100644 index 1b37068..0000000 --- a/database/src/models/benutzer.rs +++ /dev/null @@ -1,38 +0,0 @@ -#[derive(Debug, Serialize, Deserialize, Validate)] -pub struct ErstelleBenutzerDto { - #[validate(length(min = 10, max = 255))] - pub e_mail: String, - - #[validate(length(min = 8, max = 8))] - pub kennung: String, - - #[validate(length(max = 100))] - pub nachname: String, - - #[validate(length(max = 100))] - pub vorname: String, -} - -#[derive(Debug, Serialize)] -pub struct DeviceResponse { - pub id: Uuid, - pub name: String, - pub serial_number: String, - pub description: Option, - pub status: String, - pub created_at: chrono::DateTime, -} - -// Conversion from Entity to Response Model -impl From for DeviceResponse { - fn from(entity: entities::devices::Model) -> Self { - Self { - id: entity.id, - name: entity.name, - serial_number: entity.serial_number, - description: entity.description, - status: entity.status, - created_at: entity.created_at, - } - } -} diff --git a/database/src/repository/benutzer.rs b/database/src/repository/benutzer.rs new file mode 100644 index 0000000..d2628c5 --- /dev/null +++ b/database/src/repository/benutzer.rs @@ -0,0 +1,90 @@ +use crate::entity::benutzer::{self}; +use crate::error::AppError; +use crate::model::benutzer::ErstelleBenutzer; +use axum::Json; +use sea_orm::{prelude::*, ActiveValue, DatabaseConnection, DbErr}; +use validator::Validate; + +pub struct BenutzerRepository { + db: DatabaseConnection, +} + +impl BenutzerRepository { + pub fn new(db: DatabaseConnection) -> Self { + Self { db } + } + + // Benutzer nach ID suchen + pub async fn find_by_id(&self, id: uuid::Uuid) -> Result, DbErr> { + benutzer::Entity::find_by_id(id).one(&self.db).await + } + + pub async fn create_user( + &self, + Json(response): Json, + ) -> Result, AppError> { + response.validate()?; + + let ersteller_benutzer = benutzer::ActiveModel { + id: ActiveValue::Set(uuid::Uuid::new_v4()), + kennung: ActiveValue::Set(response.kennung), + vorname: ActiveValue::Set(response.vorname), + nachname: ActiveValue::Set(response.nachname), + e_mail: ActiveValue::Set(response.email), + ..Default::default() + } + .insert(&self.db) + .await?; + + Ok(Json(ersteller_benutzer)) + } + + // // Benutzer erstellen + // pub async fn create_user( + // &self, + // kennung: String, + // nachname: String, + // vorname: String, + // email: String, + // ) -> Result { + // benutzer::ActiveModel { + // id: ActiveValue::Set(uuid::Uuid::new_v4()), + // kennung: ActiveValue::Set(kennung), + // vorname: ActiveValue::Set(vorname), + // nachname: ActiveValue::Set(nachname), + // e_mail: ActiveValue::Set(email), + // ..Default::default() + // } + // .insert(&self.db) + // .await + // } + + // // Benutzer aktualisieren + // pub async fn update_user( + // &self, + // id: i32, + // name: Option, + // email: Option, + // ) -> Result { + // let user = user::Entity::find_by_id(id) + // .one(&self.db) + // .await? + // .ok_or(DbErr::Custom("User not found.".to_owned()))?; + // + // let mut user: user::ActiveModel = user.into(); + // if let Some(name) = name { + // user.name = ActiveValue::Set(name); + // } + // if let Some(email) = email { + // user.email = ActiveValue::Set(email); + // } + // + // user.update(&self.db).await + // } + // + // // Benutzer löschen + // pub async fn delete_user(&self, id: i32) -> Result<(), DbErr> { + // user::Entity::delete_by_id(id).exec(&self.db).await?; + // Ok(()) + // } +} diff --git a/database/src/repository/mod.rs b/database/src/repository/mod.rs new file mode 100644 index 0000000..4c39041 --- /dev/null +++ b/database/src/repository/mod.rs @@ -0,0 +1 @@ +pub mod benutzer; diff --git a/main/Cargo.toml b/main/Cargo.toml index 2249043..d437836 100644 --- a/main/Cargo.toml +++ b/main/Cargo.toml @@ -5,3 +5,9 @@ edition = "2021" [dependencies] database = { path = "../database" } + +sea-orm = { workspace = true } +tokio = { workspace = true } +thiserror = { workspace = true } +axum = { workspace = true } +dotenvy = { workspace = true } diff --git a/main/src/main.rs b/main/src/main.rs index 20a5f81..f8e4afe 100644 --- a/main/src/main.rs +++ b/main/src/main.rs @@ -1,10 +1,31 @@ -use database::add; -use database::sub; +use std::env; -fn main() { - let test = add(2, 5); - let sub = sub(10, 5); +use axum::Json; +use database::repository::benutzer::BenutzerRepository; +use database::{error::AppError, model::benutzer::ErstelleBenutzer}; +use sea_orm::Database; - println!("{test}"); - println!("{sub}"); +#[tokio::main] +async fn main() -> Result<(), AppError> { + dotenvy::dotenv().unwrap(); + // Datenbankverbindung herstellen + // let root = Path::new("/"); + // env::set_current_dir(root); + // + let db = Database::connect(env::var("DATABASE_URL").unwrap()).await?; + + // Service initialisieren + let user_service = BenutzerRepository::new(db); + + let benutzer = ErstelleBenutzer { + kennung: "12345243".into(), + nachname: "Doe".into(), + vorname: "John".into(), + email: "222H2@example.com".into(), + }; + + let b = user_service.create_user(Json(benutzer)).await?; + println!("{:?}", b); + + Ok(()) } diff --git a/migration/Cargo.toml b/migration/Cargo.toml index e0a06dc..b626a00 100644 --- a/migration/Cargo.toml +++ b/migration/Cargo.toml @@ -9,13 +9,9 @@ name = "migration" path = "src/lib.rs" [dependencies] -async-std = { version = "1", features = ["attributes", "tokio1"] } -chrono = { version = "0.4", features = ["serde"] } +async-std = { version = "1.13.0", features = ["attributes", "tokio1"] } +chrono = { version = "0.4.39", features = ["serde"] } [dependencies.sea-orm-migration] version = "1.1.4" -features = [ - "runtime-tokio-rustls", # `ASYNC_RUNTIME` feature - "sqlx-postgres", # `DATABASE_DRIVER` feature - "with-chrono", -] +features = ["runtime-tokio-rustls", "sqlx-postgres", "with-chrono"] diff --git a/migration/src/m20250202_000233_benutzer.rs b/migration/src/m20250202_000233_benutzer.rs index 21fd1e4..5f3af82 100644 --- a/migration/src/m20250202_000233_benutzer.rs +++ b/migration/src/m20250202_000233_benutzer.rs @@ -13,9 +13,9 @@ impl MigrationTrait for Migration { .table(Benutzer::Table) .if_not_exists() .col(pk_uuid(Benutzer::Id)) - .col(string(Benutzer::EMail)) + .col(string(Benutzer::EMail).not_null()) .col(string(Benutzer::Kennung)) - .col(string(Benutzer::PasswordHash)) + .col(string_null(Benutzer::PasswordHash)) .col(string(Benutzer::Nachname)) .col(string(Benutzer::Vorname)) .col( @@ -28,7 +28,7 @@ impl MigrationTrait for Migration { .not_null() .default(Utc::now()), ) - .col(boolean(Benutzer::IstAktiv)) + .col(boolean(Benutzer::IstAktiv).default(true)) .to_owned(), ) .await?;