test
test
This commit is contained in:
parent
974223249c
commit
580c2e7dc9
14
Cargo.toml
14
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"
|
||||
|
@ -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
|
||||
```
|
||||
|
@ -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"] }
|
||||
|
@ -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<String>,
|
||||
pub nachname: String,
|
||||
pub vorname: String,
|
||||
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 {
|
||||
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;
|
||||
|
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]
|
||||
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 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(())
|
||||
}
|
||||
|
@ -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"]
|
||||
|
@ -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?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user