test
This commit is contained in:
2025-02-05 16:38:56 +01:00
parent 974223249c
commit 580c2e7dc9
21 changed files with 246 additions and 75 deletions

View File

@@ -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"] }

View File

@@ -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
View 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()
}
}

View File

@@ -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;

View 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,
}

View File

@@ -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,
}
}
}

View 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(())
// }
}

View File

@@ -0,0 +1 @@
pub mod benutzer;