test
test
This commit is contained in:
parent
974223249c
commit
580c2e7dc9
14
Cargo.toml
14
Cargo.toml
@ -2,3 +2,17 @@
|
|||||||
resolver = "3"
|
resolver = "3"
|
||||||
|
|
||||||
members = ["migration", "database", "main"]
|
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"
|
||||||
|
@ -13,5 +13,5 @@ sea-orm-cli generate -h
|
|||||||
sea-orm-cli generate entity -h
|
sea-orm-cli generate entity -h
|
||||||
|
|
||||||
# Generate Seaography entities
|
# 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
|
||||||
```
|
```
|
||||||
|
@ -4,3 +4,11 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[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"] }
|
||||||
|
@ -12,7 +12,7 @@ pub struct Model {
|
|||||||
pub e_mail: String,
|
pub e_mail: String,
|
||||||
#[sea_orm(unique)]
|
#[sea_orm(unique)]
|
||||||
pub kennung: String,
|
pub kennung: String,
|
||||||
pub password_hash: String,
|
pub password_hash: Option<String>,
|
||||||
pub nachname: String,
|
pub nachname: String,
|
||||||
pub vorname: String,
|
pub vorname: String,
|
||||||
pub erstellt_am: DateTimeWithTimeZone,
|
pub erstellt_am: DateTimeWithTimeZone,
|
45
database/src/error.rs
Normal file
45
database/src/error.rs
Normal file
@ -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()
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,4 @@
|
|||||||
pub fn add(left: u64, right: u64) -> u64 {
|
mod entity;
|
||||||
left + right
|
pub mod error;
|
||||||
}
|
pub mod model;
|
||||||
|
pub mod repository;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
42
database/src/model/benutzer.rs
Normal file
42
database/src/model/benutzer.rs
Normal file
@ -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<String>,
|
||||||
|
|
||||||
|
#[validate(length(min = 8, max = 8))]
|
||||||
|
pub kennung: Option<String>,
|
||||||
|
|
||||||
|
#[validate(length(max = 100))]
|
||||||
|
pub nachname: Option<String>,
|
||||||
|
|
||||||
|
#[validate(length(max = 100))]
|
||||||
|
pub vorname: Option<String>,
|
||||||
|
|
||||||
|
pub ist_akiv: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct LoescheBenutzer {
|
||||||
|
pub id: Uuid,
|
||||||
|
}
|
@ -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<String>,
|
|
||||||
pub status: String,
|
|
||||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conversion from Entity to Response Model
|
|
||||||
impl From<entities::devices::Model> 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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
90
database/src/repository/benutzer.rs
Normal file
90
database/src/repository/benutzer.rs
Normal file
@ -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<Option<benutzer::Model>, DbErr> {
|
||||||
|
benutzer::Entity::find_by_id(id).one(&self.db).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_user(
|
||||||
|
&self,
|
||||||
|
Json(response): Json<ErstelleBenutzer>,
|
||||||
|
) -> Result<Json<benutzer::Model>, 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::Model, DbErr> {
|
||||||
|
// 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<String>,
|
||||||
|
// email: Option<String>,
|
||||||
|
// ) -> Result<user::Model, DbErr> {
|
||||||
|
// 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(())
|
||||||
|
// }
|
||||||
|
}
|
1
database/src/repository/mod.rs
Normal file
1
database/src/repository/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod benutzer;
|
@ -5,3 +5,9 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
database = { path = "../database" }
|
database = { path = "../database" }
|
||||||
|
|
||||||
|
sea-orm = { workspace = true }
|
||||||
|
tokio = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
axum = { workspace = true }
|
||||||
|
dotenvy = { workspace = true }
|
||||||
|
@ -1,10 +1,31 @@
|
|||||||
use database::add;
|
use std::env;
|
||||||
use database::sub;
|
|
||||||
|
|
||||||
fn main() {
|
use axum::Json;
|
||||||
let test = add(2, 5);
|
use database::repository::benutzer::BenutzerRepository;
|
||||||
let sub = sub(10, 5);
|
use database::{error::AppError, model::benutzer::ErstelleBenutzer};
|
||||||
|
use sea_orm::Database;
|
||||||
|
|
||||||
println!("{test}");
|
#[tokio::main]
|
||||||
println!("{sub}");
|
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(())
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,9 @@ name = "migration"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-std = { version = "1", features = ["attributes", "tokio1"] }
|
async-std = { version = "1.13.0", features = ["attributes", "tokio1"] }
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4.39", features = ["serde"] }
|
||||||
|
|
||||||
[dependencies.sea-orm-migration]
|
[dependencies.sea-orm-migration]
|
||||||
version = "1.1.4"
|
version = "1.1.4"
|
||||||
features = [
|
features = ["runtime-tokio-rustls", "sqlx-postgres", "with-chrono"]
|
||||||
"runtime-tokio-rustls", # `ASYNC_RUNTIME` feature
|
|
||||||
"sqlx-postgres", # `DATABASE_DRIVER` feature
|
|
||||||
"with-chrono",
|
|
||||||
]
|
|
||||||
|
@ -13,9 +13,9 @@ impl MigrationTrait for Migration {
|
|||||||
.table(Benutzer::Table)
|
.table(Benutzer::Table)
|
||||||
.if_not_exists()
|
.if_not_exists()
|
||||||
.col(pk_uuid(Benutzer::Id))
|
.col(pk_uuid(Benutzer::Id))
|
||||||
.col(string(Benutzer::EMail))
|
.col(string(Benutzer::EMail).not_null())
|
||||||
.col(string(Benutzer::Kennung))
|
.col(string(Benutzer::Kennung))
|
||||||
.col(string(Benutzer::PasswordHash))
|
.col(string_null(Benutzer::PasswordHash))
|
||||||
.col(string(Benutzer::Nachname))
|
.col(string(Benutzer::Nachname))
|
||||||
.col(string(Benutzer::Vorname))
|
.col(string(Benutzer::Vorname))
|
||||||
.col(
|
.col(
|
||||||
@ -28,7 +28,7 @@ impl MigrationTrait for Migration {
|
|||||||
.not_null()
|
.not_null()
|
||||||
.default(Utc::now()),
|
.default(Utc::now()),
|
||||||
)
|
)
|
||||||
.col(boolean(Benutzer::IstAktiv))
|
.col(boolean(Benutzer::IstAktiv).default(true))
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user