first commit

This commit is contained in:
Peter Schiwy 2024-05-10 01:32:11 +02:00
commit a4fe41985d
15 changed files with 2497 additions and 0 deletions

2199
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

23
Cargo.toml Normal file
View File

@ -0,0 +1,23 @@
[package]
name = "axum-test"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
axum = "0.7.5"
derive_more = "0.99.17"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115"
tokio = { version = "1.37.0", features = ["full"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
sqlx = { version = "0.7.4", features = [
# "runtime-tokio-rustls",
"runtime-tokio",
"postgres",
"uuid",
"chrono",
"json",
] }

0
README.md Normal file
View File

10
src/db_pool.rs Normal file
View File

@ -0,0 +1,10 @@
use sqlx::postgres::PgPoolOptions;
pub async fn create_pool() -> Result<sqlx::PgPool, sqlx::Error> {
let pool = PgPoolOptions::new()
.max_connections(5)
.connect("postgres://peter:peter@192.168.188.249:5432/test")
.await?;
Ok(pool)
}

81
src/errors.rs Normal file
View File

@ -0,0 +1,81 @@
use std::fmt;
use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
pub enum ErrorType {
DbError,
Axum,
Tokio,
}
#[derive(Debug, Clone)]
pub struct AppError {
pub message: Option<String>,
pub cause: Option<String>,
pub error_type: ErrorType,
}
impl AppError {
pub fn message(&self) -> String {
match self {
AppError {
message: Some(message),
..
} => message.clone(),
AppError {
error_type: ErrorType::Tokio,
..
} => "Server Error".to_string(),
AppError {
error_type: ErrorType::DbError,
..
} => "The requested item was not found".to_string(),
_ => "An unexpected error has occurred".to_string(),
}
}
}
impl fmt::Display for AppError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", self.message())
}
}
// impl From<std::io::Error> for AppError {
// fn from(error: std::io::Error) -> Self {
// AppError {
// message: None,
// cause: Some(error.to_string()),
// error_type: ErrorType::Standard,
// }
// }
// }
impl From<sqlx::Error> for AppError {
fn from(error: sqlx::Error) -> AppError {
AppError {
message: None,
cause: Some(error.to_string()),
error_type: ErrorType::DbError,
}
}
}
impl From<axum::Error> for AppError {
fn from(error: axum::Error) -> Self {
AppError {
message: None,
cause: Some(error.to_string()),
error_type: ErrorType::Axum,
}
}
}
impl From<tokio::io::Error> for AppError {
fn from(error: tokio::io::Error) -> Self {
AppError {
message: None,
cause: Some(error.to_string()),
error_type: ErrorType::Tokio,
}
}
}

38
src/main.rs Normal file
View File

@ -0,0 +1,38 @@
mod db_pool;
mod errors;
mod models;
mod routers;
use axum::{
routing::{get, post},
Router,
};
use errors::AppError;
use crate::routers::benutzer::erstelle_benutzer;
#[tokio::main]
async fn main() -> Result<(), AppError> {
let pool = db_pool::create_pool().await?;
// let row: (i64) = sqlx::query_as("SELECT $1")
// .bind(150_i64)
// .fetch_one(&pool)
// .await?;
// println!("Row: {:?}", row);
let app = Router::new()
.route("/", get(root))
.route("/benutzer", post(erstelle_benutzer));
let listener = tokio::net::TcpListener::bind("1127.0.0.1:3000").await?;
tracing::debug!("listening on {}", listener.local_addr()?);
axum::serve(listener, app).await?;
Ok(())
}
async fn root() -> &'static str {
"Hello, World!"
}

View File

@ -0,0 +1,34 @@
use super::kategorien::Kategorie;
use serde::{Deserialize, Serialize};
use std::io::Error;
#[derive(Deserialize, Serialize, Debug)]
pub struct Amtsbezeichnung {
pub id: u64,
pub name: String,
pub kategorie: Kategorie,
}
pub struct AmtsbezeichnungErstellen {
pub name: String,
pub kategorie_id: u64,
}
// pub struct AmtsbezeichnungAendern {
// pub id: u64,
// pub name: Option<String>,
// pub kategorie_id: Option<u64>,
// }
pub trait Check {
fn check_id(&self) -> Result<(), Error>;
}
impl Check for AmtsbezeichnungErstellen {
fn check_id(&self) -> Result<(), Error> {
if self.kategorie_id == 0 {
return Err(Error::new(std::io::ErrorKind::Other, "Kategorie-ID fehlt"));
}
Ok(())
}
}

35
src/models/benutzer.rs Normal file
View File

@ -0,0 +1,35 @@
use super::amtsbezeichnungen::Amtsbezeichnung;
use super::dienststellen::Dienststelle;
use super::gruppen::Gruppe;
use super::rollen::Rolle;
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
pub struct ErstelleBenutzer {
pub kennung: String,
pub vorname: String,
pub nachname: String,
pub telefon: String,
pub rollen: Option<Vec<Rolle>>,
pub gruppen: Option<Vec<Gruppe>>,
}
#[derive(Serialize)]
pub struct UpdateBenutzer {
pub id: u64,
pub kennung: String,
}
#[derive(Serialize, Debug)]
pub struct Benutzer {
pub id: u64,
pub kennung: String,
pub vorname: String,
pub nachname: String,
pub telefon: String,
pub amtsbezeichnung: Amtsbezeichnung,
pub dienststelle: Dienststelle,
pub abweichende_dienststelle: Option<Dienststelle>,
pub rollen: Option<Vec<Rolle>>,
pub gruppen: Option<Vec<Gruppe>>,
}

View File

@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Debug)]
pub struct Dienststelle {
pub id: u64,
pub name: String,
}

7
src/models/gruppen.rs Normal file
View File

@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Debug)]
pub struct Gruppe {
pub id: u64,
pub name: String,
}

7
src/models/kategorien.rs Normal file
View File

@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Debug)]
pub struct Kategorie {
pub id: u64,
pub name: String,
}

6
src/models/mod.rs Normal file
View File

@ -0,0 +1,6 @@
pub mod amtsbezeichnungen;
pub mod benutzer;
pub mod dienststellen;
pub mod gruppen;
pub mod kategorien;
pub mod rollen;

9
src/models/rollen.rs Normal file
View File

@ -0,0 +1,9 @@
use super::gruppen::Gruppe;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Debug)]
pub struct Rolle {
pub id: u64,
pub name: String,
pub gruppen: Vec<Gruppe>,
}

40
src/routers/benutzer.rs Normal file
View File

@ -0,0 +1,40 @@
use axum::{http::StatusCode, response::IntoResponse, Json};
use crate::models::amtsbezeichnungen::Amtsbezeichnung;
use crate::models::benutzer::{Benutzer, ErstelleBenutzer};
use crate::models::dienststellen::Dienststelle;
use crate::models::kategorien::Kategorie;
pub async fn erstelle_benutzer(Json(payload): Json<ErstelleBenutzer>) -> impl IntoResponse {
let kat = Kategorie {
id: 1337,
name: String::from("Kategorie"),
};
let ab = Amtsbezeichnung {
id: 1337,
name: String::from("Dienstgrad"),
kategorie: kat,
};
let dst = Dienststelle {
id: 1,
name: String::from("test"),
};
let user = Benutzer {
id: 1337,
kennung: payload.kennung,
nachname: payload.nachname,
vorname: payload.vorname,
amtsbezeichnung: ab,
dienststelle: dst,
telefon: payload.telefon,
abweichende_dienststelle: None,
gruppen: None,
rollen: None,
};
tracing::debug!("Benutzer: {:?}", user);
(StatusCode::CREATED, Json(user))
}

1
src/routers/mod.rs Normal file
View File

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