Die Tabellen Benutzer, Rollen und Gruppen hinzugefügt

This commit is contained in:
Peter Schiwy
2024-11-29 10:35:10 +01:00
parent a290bcceb3
commit fdc57ab13a
48 changed files with 771 additions and 267 deletions

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

@@ -0,0 +1,78 @@
use async_graphql::{Context, FieldResult, Object};
use sqlx::PgPool;
use crate::{models::gruppe::Gruppe, scalar::Id};
use super::rolle::Rolle;
pub struct Benutzer {
pub id: Id,
pub kennung: String,
pub vorname: String,
pub nachname: String,
}
#[Object]
impl Benutzer {
pub async fn id(&self) -> Id {
self.id
}
pub async fn kennung(&self) -> &str {
&self.kennung
}
pub async fn vorname(&self) -> &str {
&self.vorname
}
pub async fn nachname(&self) -> &str {
&self.nachname
}
pub async fn rollen<'ctx>(&self, ctx: &Context<'ctx>) -> FieldResult<Vec<Rolle>> {
let pool = ctx.data::<PgPool>()?;
let rows = sqlx::query_as!(
Rolle,
r#"
SELECT
r.id,
r.rollenname,
r.erstellt_am,
r.geaendert_am
FROM rollen AS r
LEFT JOIN benutzer_rollen AS br ON r.id = br.rolle_id
WHERE br.benutzer_id = $1;
"#,
&self.id
)
.fetch_all(pool)
.await?;
Ok(rows)
}
pub async fn gruppen<'ctx>(&self, ctx: &Context<'ctx>) -> FieldResult<Vec<Gruppe>> {
let pool = ctx.data::<PgPool>()?;
let rows = sqlx::query_as!(
Gruppe,
r#"
SELECT
g.id,
g.gruppenname,
g.erstellt_am,
g.geaendert_am
FROM gruppen AS g
LEFT JOIN benutzer_gruppen AS bg ON g.id = bg.gruppe_id
WHERE bg.benutzer_id = $1;
"#,
&self.id
)
.fetch_all(pool)
.await?;
Ok(rows)
}
}

30
src/models/gruppe.rs Normal file
View File

@@ -0,0 +1,30 @@
use async_graphql::Object;
use crate::scalar::{Id, Time};
pub struct Gruppe {
pub id: Id,
pub gruppenname: String,
pub erstellt_am: Time,
pub geaendert_am: Time,
}
#[Object]
impl Gruppe {
pub async fn id(&self) -> Id {
self.id
}
pub async fn gruppenname(&self) -> &str {
&self.gruppenname
}
pub async fn erstellt_am(&self) -> Time {
self.erstellt_am
}
pub async fn geaendert_am(&self) -> Time {
self.geaendert_am
}
}

View File

@@ -2,33 +2,36 @@ use anyhow::Result;
use async_graphql::{InputObject, SimpleObject};
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, PgPool};
use ulid::Ulid;
use crate::scalar::Id;
#[derive(SimpleObject, Debug, FromRow, Deserialize, Serialize, sqlx::Type)]
pub struct Hersteller {
/// Die Datenbank-ID
pub id: i32,
pub id: Id,
/// Der Name eines Herstellers
name: String,
herstellername: String,
}
#[derive(InputObject, Debug)]
pub struct HerstellerCreateInput {
/// Der Name eines Herstellers
pub name: String,
pub herstellername: String,
}
#[derive(InputObject, Debug)]
pub struct HerstellerUpdateInput {
/// Die Datenbank-ID
pub id: i32,
pub id: Id,
/// Der Name eines Herstellers
pub name: Option<String>,
pub herstellername: Option<String>,
}
impl Hersteller {
pub async fn read_one(pool: &PgPool, id: &i32) -> Result<Hersteller> {
pub async fn read_one(pool: &PgPool, id: &Id) -> Result<Hersteller> {
let row = sqlx::query_as!(Hersteller, "SELECT * FROM hersteller WHERE id = $1", id)
.fetch_one(pool)
.await?;
@@ -37,7 +40,7 @@ impl Hersteller {
}
pub async fn read_all(pool: &PgPool) -> Result<Vec<Hersteller>> {
let rows = sqlx::query_as!(Hersteller, "SELECT id, name FROM hersteller")
let rows = sqlx::query_as!(Hersteller, "SELECT id, herstellername FROM hersteller")
.fetch_all(pool)
.await?;
@@ -45,21 +48,21 @@ impl Hersteller {
}
pub async fn create(pool: &PgPool, input: &HerstellerCreateInput) -> Result<Hersteller> {
let row = sqlx::query!(
"INSERT INTO hersteller(name) VALUES ($1) RETURNING id",
input.name
)
.fetch_one(pool)
.await?;
const QUERY: &str = "INSERT INTO hersteller (id, herstellername) VALUES ($1, $2) RETURNING id, herstellername";
let result: Hersteller = sqlx::query_as::<_, Hersteller>(QUERY)
.bind::<Id>(Ulid::new().into())
.bind(&input.herstellername)
.fetch_one(pool)
.await?;
let result = Self::read_one(pool, &row.id).await?;
Ok(result)
}
pub async fn update(pool: &PgPool, input: &HerstellerUpdateInput) -> Result<Hersteller> {
sqlx::query!(
"UPDATE hersteller SET name=$1 WHERE id = $2",
input.name,
"UPDATE hersteller SET herstellername=$1 WHERE id = $2",
input.herstellername,
input.id
)
.execute(pool)
@@ -70,7 +73,7 @@ impl Hersteller {
Ok(t)
}
pub async fn delete(pool: &PgPool, id: &i32) -> Result<bool> {
pub async fn delete(pool: &PgPool, id: &Id) -> Result<bool> {
let result = sqlx::query!("DELETE FROM hersteller WHERE id = $1", id)
.execute(pool)
.await?;

View File

@@ -1,3 +1,6 @@
pub mod benutzer;
pub mod gruppe;
pub mod hersteller;
pub mod modell;
pub mod rolle;
pub mod typ;

View File

@@ -2,13 +2,17 @@ use anyhow::Result;
use async_graphql::{InputObject, SimpleObject};
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, PgPool};
use ulid::Ulid;
use uuid::Uuid;
use crate::scalar::Id;
use super::{hersteller::Hersteller, typ::Typ};
#[derive(SimpleObject, FromRow, Deserialize, Serialize, Debug)]
pub struct Modell {
/// Die Datenbank-ID
pub id: i32,
pub id: Id,
/// Der Geräte-Typ z.B. Monitor
typ: Typ,
@@ -17,38 +21,44 @@ pub struct Modell {
hersteller: Hersteller,
/// Der Name eines Modells
name: String,
modellname: String,
}
#[derive(InputObject, Debug)]
pub struct ModellCreateInput {
pub name: String,
pub typ_id: i32,
pub hersteller_id: i32,
/// Der Name eines Modells
pub modellname: String,
/// Die Id eines Geräte-Typs z.B. Monitor
pub typ_id: Id,
/// Die Id eines Geräte-Herstellers z.B. Dell
pub hersteller_id: Id,
}
#[derive(InputObject, Debug)]
pub struct ModellUpdateInput {
pub id: i32,
pub name: Option<String>,
pub typ_id: Option<i32>,
pub hersteller_id: Option<i32>,
pub id: Id,
pub modellname: Option<String>,
pub typ_id: Option<Id>,
pub hersteller_id: Option<Id>,
}
impl Modell {
pub async fn read_one(pool: &PgPool, id: &i32) -> Result<Modell> {
pub async fn read_one(pool: &PgPool, id: &Id) -> Result<Modell> {
let row = sqlx::query_as!(
Modell,
r#"
select
m.id, m.name,
(t.id, t.name) as "typ!: Typ",
(h.id, h.name) as "hersteller!: Hersteller"
from modelle as m
join typen as t on t.id = m.typ_id
join hersteller as h on h.id = m.hersteller_id
where m.id = $1;
"#,
SELECT
m.id,
m.modellname,
(t.id, t.typname) AS "typ!: Typ",
(h.id, h.herstellername) AS "hersteller!: Hersteller"
FROM modelle AS m
JOIN typen AS t ON t.id = m.typ_id
JOIN hersteller AS h ON h.id = m.hersteller_id
WHERE m.id = $1;
"#,
id
)
.fetch_one(pool)
@@ -61,14 +71,15 @@ impl Modell {
let row = sqlx::query_as!(
Modell,
r#"
select
m.id, m.name,
(t.id, t.name) as "typ!: Typ",
(h.id, h.name) as "hersteller!: Hersteller"
from modelle as m
join typen as t on t.id = m.typ_id
join hersteller as h on h.id = m.hersteller_id
"#
SELECT
m.id,
m.modellname,
(t.id, t.typname) AS "typ!: Typ",
(h.id, h.herstellername) AS "hersteller!: Hersteller"
FROM modelle AS m
LEFT JOIN typen AS t ON t.id = m.typ_id
LEFT JOIN hersteller AS h ON h.id = m.hersteller_id
"#
)
.fetch_all(pool)
.await?;
@@ -77,22 +88,25 @@ impl Modell {
}
pub async fn create(pool: &PgPool, input: &ModellCreateInput) -> Result<Modell> {
let row = sqlx::query!(
r#"INSERT INTO modelle(typ_id, hersteller_id, name) VALUES ($1, $2, $3) RETURNING id"#,
input.typ_id,
input.hersteller_id,
input.name
)
.fetch_one(pool)
.await?;
const QUERY: &str = "INSERT INTO modelle (id, typ_id, hersteller_id, modellname) VALUES ($1, $2, $3, $4) RETURNING id";
Self::read_one(pool, &row.id).await
let row: (Uuid,) = sqlx::query_as(QUERY)
.bind::<Id>(Ulid::new().into())
.bind(input.typ_id)
.bind(input.hersteller_id)
.bind(&input.modellname)
.fetch_one(pool)
.await?;
let modell = Modell::read_one(pool, &row.0).await?;
Ok(modell)
}
pub async fn update(pool: &PgPool, input: &ModellUpdateInput) -> Result<Modell> {
sqlx::query!(
"UPDATE modelle SET name=COALESCE($1, name), typ_id=COALESCE($2, typ_id), hersteller_id=COALESCE($3, hersteller_id) WHERE id = $4",
input.name,
"UPDATE modelle SET modellname=COALESCE($1, modellname), typ_id=COALESCE($2, typ_id), hersteller_id=COALESCE($3, hersteller_id) WHERE id = $4",
input.modellname,
input.typ_id,
input.hersteller_id,
input.id
@@ -105,7 +119,7 @@ impl Modell {
Ok(t)
}
pub async fn delete(pool: &PgPool, id: &i32) -> Result<bool> {
pub async fn delete(pool: &PgPool, id: &Id) -> Result<bool> {
let result = sqlx::query!("DELETE FROM modelle WHERE id = $1", id)
.execute(pool)
.await?;

57
src/models/rolle.rs Normal file
View File

@@ -0,0 +1,57 @@
use async_graphql::{Context, FieldResult, Object};
use sqlx::PgPool;
use crate::scalar::{Id, Time};
use super::gruppe::Gruppe;
#[derive(Debug)]
pub struct Rolle {
pub id: Id,
pub rollenname: String,
pub erstellt_am: Time,
pub geaendert_am: Time,
}
#[Object]
impl Rolle {
pub async fn id(&self) -> Id {
self.id
}
pub async fn rollename(&self) -> &str {
&self.rollenname
}
pub async fn erstellt_am(&self) -> Time {
self.erstellt_am
}
pub async fn geaendert_am(&self) -> Time {
self.geaendert_am
}
pub async fn gruppen<'ctx>(&self, ctx: &Context<'ctx>) -> FieldResult<Vec<Gruppe>> {
let pool = ctx.data::<PgPool>()?;
let rows = sqlx::query_as!(
Gruppe,
r#"
SELECT
g.id,
g.gruppenname,
g.erstellt_am,
g.geaendert_am
FROM gruppen AS g
LEFT JOIN rollen_gruppen AS rg ON g.id = rg.gruppe_id
WHERE rg.rolle_id = $1;
"#,
&self.id
)
.fetch_all(pool)
.await?;
Ok(rows)
}
}

View File

@@ -2,29 +2,32 @@ use anyhow::Result;
use async_graphql::{InputObject, SimpleObject};
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, PgPool, Type};
use ulid::Ulid;
use crate::scalar::Id;
#[derive(SimpleObject, Debug, FromRow, Deserialize, Serialize, Type)]
pub struct Typ {
/// Die ID eines Geräte-Typs
pub id: i32,
pub id: Id,
/// Der Name eines Geräte-Typs
pub name: String,
pub typname: String,
}
#[derive(InputObject, Debug)]
pub struct TypCreateInput {
pub name: String,
pub typname: String,
}
#[derive(InputObject, Debug)]
pub struct TypUpdateInput {
pub id: i32,
pub name: Option<String>,
pub id: Id,
pub typname: Option<String>,
}
impl Typ {
pub async fn read_one(pool: &PgPool, id: &i32) -> Result<Typ> {
pub async fn read_one(pool: &PgPool, id: &Id) -> Result<Typ> {
const QUERY: &str = "SELECT * FROM typen WHERE id = $1";
let row: Typ = sqlx::query_as(QUERY).bind(id).fetch_one(pool).await?;
@@ -32,7 +35,7 @@ impl Typ {
}
pub async fn read_all(pool: &PgPool) -> Result<Vec<Typ>> {
let rows = sqlx::query_as!(Typ, "SELECT id, name FROM typen")
let rows = sqlx::query_as!(Typ, "SELECT id, typname FROM typen")
.fetch_all(pool)
.await?;
@@ -40,10 +43,11 @@ impl Typ {
}
pub async fn create(pool: &PgPool, input: &TypCreateInput) -> Result<Typ> {
const QUERY: &str = "INSERT INTO typen (name) VALUES ($1) RETURNING id, name";
const QUERY: &str = "INSERT INTO typen (id, typname) VALUES ($1, $2) RETURNING id, typname";
let result: Typ = sqlx::query_as(QUERY)
.bind(&input.name)
let result: Typ = sqlx::query_as::<_, Typ>(QUERY)
.bind::<Id>(Ulid::new().into())
.bind(&input.typname)
.fetch_one(pool)
.await?;
@@ -52,14 +56,14 @@ impl Typ {
pub async fn create_many(pool: &PgPool, input: &[TypCreateInput]) -> Result<Vec<Typ>> {
let mut v1: Vec<&str> = Vec::new();
input.iter().for_each(|typ| v1.push(&typ.name));
input.iter().for_each(|typ| v1.push(&typ.typname));
let row = sqlx::query_as!(
Typ,
r#"
INSERT INTO typen(name)
INSERT INTO typen(typname)
SELECT * FROM UNNEST($1::text[])
RETURNING id, name"#,
RETURNING id, typname"#,
&v1 as _
)
.fetch_all(pool)
@@ -70,8 +74,8 @@ impl Typ {
pub async fn update(pool: &PgPool, input: &TypUpdateInput) -> Result<Typ> {
sqlx::query!(
"UPDATE typen SET name=$1 WHERE id = $2",
input.name,
"UPDATE typen SET typname=$1 WHERE id = $2",
input.typname,
input.id
)
.execute(pool)
@@ -81,7 +85,7 @@ impl Typ {
Ok(t)
}
pub async fn delete(pool: &PgPool, id: &i32) -> Result<bool> {
pub async fn delete(pool: &PgPool, id: &Id) -> Result<bool> {
let result = sqlx::query!("DELETE FROM typen WHERE id = $1", id)
.execute(pool)
.await?;