This commit is contained in:
2026-06-17 16:35:26 +02:00
parent a1d95f1ba2
commit c11309a3a5
5 changed files with 64 additions and 2 deletions
+4 -2
View File
@@ -32,8 +32,10 @@ use crate::env::Env;
/// - `db`: PostgreSQL connection pool for database access (via `sqlx::PgPool`) /// - `db`: PostgreSQL connection pool for database access (via `sqlx::PgPool`)
/// - `env`: [`Env`] configuration loaded from environment variables /// - `env`: [`Env`] configuration loaded from environment variables
pub struct AppState { pub struct AppState {
db: PgPool, /// PostgreSQL connection pool for all database operations
env: Env, pub db: PgPool,
/// Environment configuration with secrets and settings
pub env: Env,
} }
/// Main application entry point. /// Main application entry point.
+39
View File
@@ -33,15 +33,25 @@ use serde::{Deserialize, Serialize};
/// ``` /// ```
#[derive(Deserialize, Serialize, Debug, PartialEq)] #[derive(Deserialize, Serialize, Debug, PartialEq)]
pub struct TicketResponse { pub struct TicketResponse {
/// Unique ticket identifier
pub id: i32, pub id: i32,
/// Ticket category/type (e.g., "maintenance", "support")
pub category: String, pub category: String,
/// Ticket subject line
pub betreff: String, pub betreff: String,
/// Detailed ticket description
pub description: String, pub description: String,
/// Room number associated with the issue
pub room: i16, pub room: i16,
/// Current ticket status (e.g., "open", "in_progress", "resolved", "archived")
pub status: String, pub status: String,
/// When the ticket was created (UTC timestamp)
pub date: chrono::DateTime<chrono::Utc>, pub date: chrono::DateTime<chrono::Utc>,
/// ID of the user who created the ticket
pub user_id: i16, pub user_id: i16,
/// First name of the ticket creator (denormalized from `User`)
pub user_first_name: String, pub user_first_name: String,
/// Last name of the ticket creator (denormalized from `User`)
pub user_last_name: String, pub user_last_name: String,
} }
@@ -62,11 +72,17 @@ pub struct TicketResponse {
/// Use [`filter_user()`](`crate::handlers::auth::filter_user`) to convert to [`FilteredUser`] for responses. /// Use [`filter_user()`](`crate::handlers::auth::filter_user`) to convert to [`FilteredUser`] for responses.
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone, sqlx::FromRow)] #[derive(Deserialize, Serialize, PartialEq, Debug, Clone, sqlx::FromRow)]
pub struct User { pub struct User {
/// Unique user identifier
pub id: i16, pub id: i16,
/// User's last name
pub last_name: String, pub last_name: String,
/// User's first name
pub first_name: String, pub first_name: String,
/// Unique login username (must be unique in the database)
pub username: String, pub username: String,
/// Whether this user has administrator privileges
pub is_admin: bool, pub is_admin: bool,
/// Argon2 password hash (NEVER expose to clients)
pub pwd: String, pub pwd: String,
} }
@@ -82,9 +98,13 @@ pub struct User {
/// - `room`: Room number where the issue is located /// - `room`: Room number where the issue is located
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
pub struct TicketCreateScheme { pub struct TicketCreateScheme {
/// Ticket category/type
pub category: String, pub category: String,
/// Subject line for the ticket
pub betreff: String, pub betreff: String,
/// Detailed problem description
pub description: String, pub description: String,
/// Room number where the issue is located
pub room: i16, pub room: i16,
} }
@@ -97,6 +117,7 @@ pub struct TicketCreateScheme {
/// - `status`: New ticket status (e.g., "open", "in_progress", "resolved") /// - `status`: New ticket status (e.g., "open", "in_progress", "resolved")
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
pub struct TicketUpdateScheme { pub struct TicketUpdateScheme {
/// New ticket status (e.g., "open", "in_progress", "resolved", "archived")
pub status: String, pub status: String,
} }
@@ -113,11 +134,17 @@ pub struct TicketUpdateScheme {
/// - `new_pwd`: New password (empty string = keep existing password) /// - `new_pwd`: New password (empty string = keep existing password)
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
pub struct UserUpdateScheme { pub struct UserUpdateScheme {
/// User ID to update
pub id: i16, pub id: i16,
/// Updated user first name
pub first_name: String, pub first_name: String,
/// Updated user last name
pub last_name: String, pub last_name: String,
/// Updated login username
pub username: String, pub username: String,
/// New admin privilege status
pub make_admin: bool, pub make_admin: bool,
/// New password (empty string = keep existing password)
pub new_pwd: String, pub new_pwd: String,
} }
@@ -134,10 +161,15 @@ pub struct UserUpdateScheme {
/// - `pwd`: Plain text password (hashed on server) /// - `pwd`: Plain text password (hashed on server)
#[derive(Deserialize, Serialize, Debug, sqlx::FromRow)] #[derive(Deserialize, Serialize, Debug, sqlx::FromRow)]
pub struct UserCreateScheme { pub struct UserCreateScheme {
/// User's first name
pub first_name: String, pub first_name: String,
/// User's last name
pub last_name: String, pub last_name: String,
/// Unique username for login
pub username: String, pub username: String,
/// Whether to grant admin privileges
pub is_admin: bool, pub is_admin: bool,
/// Plain text password (hashed on server before storage)
pub pwd: String, pub pwd: String,
} }
@@ -150,7 +182,9 @@ pub struct UserCreateScheme {
/// The password is never stored in plain text - only the Argon2 hash is persisted. /// The password is never stored in plain text - only the Argon2 hash is persisted.
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
pub struct LoginScheme { pub struct LoginScheme {
/// Username for login
pub username: String, pub username: String,
/// Plain text password (verified against stored Argon2 hash)
pub pwd: String, pub pwd: String,
} }
@@ -161,10 +195,15 @@ pub struct LoginScheme {
/// to prevent leaking sensitive data. /// to prevent leaking sensitive data.
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct FilteredUser { pub struct FilteredUser {
/// Unique user identifier
pub id: i16, pub id: i16,
/// User's first name
pub first_name: String, pub first_name: String,
/// User's last name
pub last_name: String, pub last_name: String,
/// Login username
pub username: String, pub username: String,
/// Whether user has admin privileges
pub is_admin: bool, pub is_admin: bool,
} }
Binary file not shown.
+17
View File
@@ -1,5 +1,22 @@
use yew::prelude::*; use yew::prelude::*;
/// A button component that toggles between light and dark theme modes.
///
/// Clicking this button switches the application's theme by modifying the `data-theme` attribute
/// on the document element. The theme preference is applied via CSS variables for consistent styling.
///
/// # Behavior
/// - Reads the current `data-theme` attribute value from the HTML element
/// - Sets `data-theme="dark"` if currently in light mode
/// - Clears the attribute (light mode) if currently in dark mode
/// - Re-renders to reflect the visual changes (typically toggled via CSS)
///
/// # Example Usage
/// ```ignore
/// html! {
/// <ThemeToggle />
/// }
/// ```
#[function_component] #[function_component]
pub fn ThemeToggle() -> Html { pub fn ThemeToggle() -> Html {
let onclick = { let onclick = {
+4
View File
@@ -1,5 +1,9 @@
use frontend::App; use frontend::App;
/// Main entry point for the Yew frontend application.
///
/// Initializes the Yew framework and renders the root [`App`] component into the DOM.
/// This function is typically called automatically by the WebAssembly runtime.
fn main() { fn main() {
yew::Renderer::<App>::new().render(); yew::Renderer::<App>::new().render();
} }