use proper timezone @ login information
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
				
			|||||||
use crate::{page, AppState};
 | 
					use crate::{AppState, page};
 | 
				
			||||||
use axum::{routing::get, Router};
 | 
					use axum::{Router, routing::get};
 | 
				
			||||||
use maud::{html, Markup};
 | 
					use maud::{Markup, html};
 | 
				
			||||||
use tower_sessions::Session;
 | 
					use tower_sessions::Session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) mod route;
 | 
					pub(crate) mod route;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    admin::{station::Station, team::Team},
 | 
					 | 
				
			||||||
    AppState,
 | 
					    AppState,
 | 
				
			||||||
 | 
					    admin::{station::Station, team::Team},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use axum::Router;
 | 
					use axum::Router;
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,12 @@
 | 
				
			|||||||
use super::Route;
 | 
					use super::Route;
 | 
				
			||||||
use crate::{admin::station::Station, err, page, succ, AppState};
 | 
					use crate::{AppState, admin::station::Station, err, page, succ};
 | 
				
			||||||
use axum::{
 | 
					use axum::{
 | 
				
			||||||
 | 
					    Form, Router,
 | 
				
			||||||
    extract::State,
 | 
					    extract::State,
 | 
				
			||||||
    response::{IntoResponse, Redirect},
 | 
					    response::{IntoResponse, Redirect},
 | 
				
			||||||
    routing::{get, post},
 | 
					    routing::{get, post},
 | 
				
			||||||
    Form, Router,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use maud::{html, Markup, PreEscaped};
 | 
					use maud::{Markup, PreEscaped, html};
 | 
				
			||||||
use serde::Deserialize;
 | 
					use serde::Deserialize;
 | 
				
			||||||
use sqlx::SqlitePool;
 | 
					use sqlx::SqlitePool;
 | 
				
			||||||
use std::sync::Arc;
 | 
					use std::sync::Arc;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
use crate::{admin::route::Route, AppState};
 | 
					use crate::{admin::route::Route, AppState};
 | 
				
			||||||
use axum::Router;
 | 
					use axum::Router;
 | 
				
			||||||
use chrono::NaiveDateTime;
 | 
					use chrono::{DateTime, Local, NaiveDateTime, Utc};
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
use sqlx::{FromRow, SqlitePool};
 | 
					use sqlx::{FromRow, SqlitePool};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,15 +39,27 @@ impl Station {
 | 
				
			|||||||
        .ok()
 | 
					        .ok()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub async fn find_by_id_and_code(db: &SqlitePool, id: i64, code: &str) -> Option<Self> {
 | 
					    pub async fn login(db: &SqlitePool, id: i64, code: &str) -> Option<Self> {
 | 
				
			||||||
        sqlx::query_as!(
 | 
					        let Some(station) =  sqlx::query_as!(
 | 
				
			||||||
            Self,
 | 
					            Self,
 | 
				
			||||||
            "SELECT id, name, notes, amount_people, last_login, pw, lat, lng FROM station WHERE id = ? AND pw = ?",
 | 
					            "SELECT id, name, notes, amount_people, last_login, pw, lat, lng FROM station WHERE id = ? AND pw = ?",
 | 
				
			||||||
            id, code
 | 
					            id, code
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .fetch_one(db)
 | 
					        .fetch_one(db)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .ok()
 | 
					        .ok() else {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sqlx::query!(
 | 
				
			||||||
 | 
					            "UPDATE station SET last_login = CURRENT_TIMESTAMP WHERE id = ?",
 | 
				
			||||||
 | 
					            station.id
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .execute(db)
 | 
				
			||||||
 | 
					        .await
 | 
				
			||||||
 | 
					        .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Some(station)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async fn create(db: &SqlitePool, name: &str) -> Result<(), String> {
 | 
					    async fn create(db: &SqlitePool, name: &str) -> Result<(), String> {
 | 
				
			||||||
@@ -147,6 +159,14 @@ impl Station {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        false
 | 
					        false
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub(crate) fn local_last_login(&self) -> Option<DateTime<Local>> {
 | 
				
			||||||
 | 
					        let Some(last_login) = &self.last_login else {
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        let datetime_utc = DateTime::<Utc>::from_naive_utc_and_offset(last_login.clone(), Utc);
 | 
				
			||||||
 | 
					        Some(datetime_utc.with_timezone(&Local))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(super) fn routes() -> Router<AppState> {
 | 
					pub(super) fn routes() -> Router<AppState> {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -98,7 +98,7 @@ async fn view(
 | 
				
			|||||||
                    th scope="row" { "Notizen" };
 | 
					                    th scope="row" { "Notizen" };
 | 
				
			||||||
                    td {
 | 
					                    td {
 | 
				
			||||||
                        @match station.notes {
 | 
					                        @match station.notes {
 | 
				
			||||||
                            Some(notes) => {
 | 
					                            Some(ref notes) => {
 | 
				
			||||||
                                (notes)
 | 
					                                (notes)
 | 
				
			||||||
                                details {
 | 
					                                details {
 | 
				
			||||||
                                summary { "✏️" }
 | 
					                                summary { "✏️" }
 | 
				
			||||||
@@ -119,11 +119,14 @@ async fn view(
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                tr {
 | 
					                tr {
 | 
				
			||||||
                    th scope="row" { "Stations-Code" };
 | 
					                    th scope="row" { "Stations-Link" };
 | 
				
			||||||
                    td {
 | 
					                    td {
 | 
				
			||||||
                        (station.pw)
 | 
					                        a href=(format!("/s/{}/{}", station.id, station.pw)) {
 | 
				
			||||||
 | 
					                            "Login-Link"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        article class="warning" {
 | 
					                        article class="warning" {
 | 
				
			||||||
                            (format!("Diesen Code nur Betreuern der Station {} geben! Mit diesem Code erhält man die Berechtigung, Teams zu bewerten.", station.name))
 | 
					                            (format!("Diesen Link nur Betreuern der Station {} geben! Mit diesem Link erhält man die Berechtigung, Teams zu bewerten.", station.name))
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -151,9 +154,9 @@ async fn view(
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                tr {
 | 
					                tr {
 | 
				
			||||||
                    th scope="row" { "Letzter Login eines Stationsbetreuers" };
 | 
					                    th scope="row" { "Letzter Zugriff eines Stationsbetreuers" };
 | 
				
			||||||
                    td {
 | 
					                    td {
 | 
				
			||||||
                        @match station.last_login {
 | 
					                        @match station.local_last_login() {
 | 
				
			||||||
                            Some(last_login) => (last_login),
 | 
					                            Some(last_login) => (last_login),
 | 
				
			||||||
                            None => "noch nicht eingeloggt :-(",
 | 
					                            None => "noch nicht eingeloggt :-(",
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    admin::{route::Route, station::Station},
 | 
					 | 
				
			||||||
    AppState,
 | 
					    AppState,
 | 
				
			||||||
 | 
					    admin::{route::Route, station::Station},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use axum::Router;
 | 
					use axum::Router;
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,18 @@
 | 
				
			|||||||
use super::{CreateError, Team};
 | 
					use super::{CreateError, Team};
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
 | 
					    AppState,
 | 
				
			||||||
    admin::{route::Route, station::Station},
 | 
					    admin::{route::Route, station::Station},
 | 
				
			||||||
    err,
 | 
					    err,
 | 
				
			||||||
    partials::page,
 | 
					    partials::page,
 | 
				
			||||||
    pl, succ, AppState,
 | 
					    pl, succ,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use axum::{
 | 
					use axum::{
 | 
				
			||||||
 | 
					    Form, Router,
 | 
				
			||||||
    extract::State,
 | 
					    extract::State,
 | 
				
			||||||
    response::{IntoResponse, Redirect},
 | 
					    response::{IntoResponse, Redirect},
 | 
				
			||||||
    routing::{get, post},
 | 
					    routing::{get, post},
 | 
				
			||||||
    Form, Router,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use maud::{html, Markup, PreEscaped};
 | 
					use maud::{Markup, PreEscaped, html};
 | 
				
			||||||
use serde::Deserialize;
 | 
					use serde::Deserialize;
 | 
				
			||||||
use sqlx::SqlitePool;
 | 
					use sqlx::SqlitePool;
 | 
				
			||||||
use std::sync::Arc;
 | 
					use std::sync::Arc;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ extern crate rust_i18n;
 | 
				
			|||||||
i18n!("locales", fallback = "de-AT");
 | 
					i18n!("locales", fallback = "de-AT");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use admin::station::Station;
 | 
					use admin::station::Station;
 | 
				
			||||||
use axum::{body::Body, extract::FromRef, response::Response, routing::get, Router};
 | 
					use axum::{Router, body::Body, extract::FromRef, response::Response, routing::get};
 | 
				
			||||||
use partials::page;
 | 
					use partials::page;
 | 
				
			||||||
use sqlx::SqlitePool;
 | 
					use sqlx::SqlitePool;
 | 
				
			||||||
use std::sync::Arc;
 | 
					use std::sync::Arc;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
use crate::{partials, AppState, Station};
 | 
					use crate::{AppState, Station, partials};
 | 
				
			||||||
use axum::{extract::State, routing::get, Router};
 | 
					use axum::{Router, extract::State, routing::get};
 | 
				
			||||||
use maud::{html, Markup};
 | 
					use maud::{Markup, html};
 | 
				
			||||||
use sqlx::SqlitePool;
 | 
					use sqlx::SqlitePool;
 | 
				
			||||||
use std::sync::Arc;
 | 
					use std::sync::Arc;
 | 
				
			||||||
use tower_sessions::Session;
 | 
					use tower_sessions::Session;
 | 
				
			||||||
@@ -76,7 +76,7 @@ async fn view(
 | 
				
			|||||||
    session: Session,
 | 
					    session: Session,
 | 
				
			||||||
    axum::extract::Path((id, code)): axum::extract::Path<(i64, String)>,
 | 
					    axum::extract::Path((id, code)): axum::extract::Path<(i64, String)>,
 | 
				
			||||||
) -> Markup {
 | 
					) -> Markup {
 | 
				
			||||||
    let Some(station) = Station::find_by_id_and_code(&db, id, &code).await else {
 | 
					    let Some(station) = Station::login(&db, id, &code).await else {
 | 
				
			||||||
        let content = html! {
 | 
					        let content = html! {
 | 
				
			||||||
            article class="error" {
 | 
					            article class="error" {
 | 
				
			||||||
                "Falscher Quick-Einlogg-Link. Bitte nochmal scannen oder neu eingeben."
 | 
					                "Falscher Quick-Einlogg-Link. Bitte nochmal scannen oder neu eingeben."
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user