From 598335b756fbc4b5ea62f9cf999a91b7751bdbbb Mon Sep 17 00:00:00 2001 From: Sxyntheon <jakob_kannenberg@icloud.com> Date: Wed, 20 Nov 2024 18:54:03 +0100 Subject: [PATCH] fix http response codes --- backend/src/api/change_email.rs | 25 +- backend/src/api/change_password.rs | 35 ++- backend/src/api/change_untis_data.rs | 19 +- backend/src/api/check_session.rs | 12 +- backend/src/api/delete.rs | 18 +- backend/src/api/forgot_password.rs | 21 +- backend/src/api/gdpr_data_compliance.rs | 28 +- backend/src/api/get_free_rooms.rs | 34 +-- backend/src/api/get_lernbueros.rs | 32 +-- backend/src/api/get_timetable.rs | 33 +-- .../src/api/get_timetable_serviceworker.rs | 33 +-- backend/src/api/link/check_uuid.rs | 14 +- backend/src/api/link/email_change.rs | 42 +-- backend/src/api/link/email_reset.rs | 28 +- backend/src/api/link/password.rs | 28 +- backend/src/api/link/verify.rs | 20 +- backend/src/api/login.rs | 16 +- backend/src/api/logout.rs | 9 +- backend/src/api/logout_all.rs | 11 +- backend/src/api/mod.rs | 3 +- backend/src/api/register.rs | 24 +- backend/src/api/resend_mail.rs | 27 +- backend/src/api/response.rs | 65 ----- backend/src/api/verified.rs | 19 +- backend/src/api_wrapper/untis_client.rs | 4 +- backend/src/api_wrapper/utils.rs | 5 + backend/src/database/sessions.rs | 2 +- backend/src/mail/mailing.rs | 2 +- backend/src/main.rs | 7 +- backend/src/models/links_model.rs | 2 +- backend/src/models/manual_lb_model.rs | 2 +- backend/src/models/model.rs | 2 +- backend/src/models/room_model.rs | 2 +- backend/src/models/sessions_model.rs | 2 +- backend/src/models/teacher_model.rs | 2 +- backend/src/models/user_model.rs | 2 +- backend/src/prelude.rs | 22 -- frontend/compileServiceWorker.ts | 7 +- frontend/public/manifest.webmanifest | 3 +- frontend/src/api/dateHandling.ts | 4 +- frontend/src/api/frontmatter.ts | 18 +- frontend/src/api/main.ts | 39 ++- frontend/src/api/theBackend.ts | 26 +- frontend/src/components/RegisterForm.tsx | 15 +- .../components/plan-components/FreeRooms.tsx | 2 +- .../components/plan-components/Lernbueros.tsx | 38 +-- .../components/plan-components/Settings.tsx | 8 +- .../plan-components/Stundenplan.tsx | 4 +- .../settings-components/ChangeEmail.tsx | 1 + .../settings-components/DeleteAccount.tsx | 2 +- .../settings-components/ResetEmail.tsx | 2 +- frontend/src/layouts/PlanLayout.astro | 16 +- frontend/src/layouts/RootLayout.astro | 258 +++++++++--------- frontend/src/pwa/cachingStrategies.ts | 12 +- frontend/src/pwa/serviceWorker.ts | 39 ++- frontend/src/styles/Stundenplan.scss | 1 - 56 files changed, 525 insertions(+), 622 deletions(-) delete mode 100644 backend/src/api/response.rs delete mode 100644 backend/src/prelude.rs diff --git a/backend/src/api/change_email.rs b/backend/src/api/change_email.rs index e387863..38608f7 100644 --- a/backend/src/api/change_email.rs +++ b/backend/src/api/change_email.rs @@ -1,13 +1,13 @@ use actix_identity::Identity; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use chrono::{DateTime, Days, Utc}; use lettre::message::header::ContentType; use log::error; use surrealdb::sql::Thing; -use super::response::Response; + use crate::{ - mail::{ + api_wrapper::utils::TextResponse, mail::{ mailing::{build_mail, send_mail}, utils::{load_template, Mailer} }, models::{ links_model::{Link, LinkType}, model::{ConnectionData, CRUD}, user_model::User @@ -18,7 +18,7 @@ pub async fn change_email_get( id: Option<Identity>, db: ConnectionData, mailer: web::Data<Mailer>, ) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in".into()))); + return Err(error::ErrorForbidden( "Not logged in")); } let id = id.unwrap(); @@ -26,7 +26,7 @@ pub async fn change_email_get( Ok(a) => a, Err(e) => { error!("Error trying to get id.id()\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; @@ -35,12 +35,12 @@ pub async fn change_email_get( Some(a) => a, None => { error!("User not found?"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }, Err(e) => { error!("Error getting user from id\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; @@ -52,7 +52,7 @@ pub async fn change_email_get( Ok(a) => a.construct_link(), Err(e) => { error!("Error creating link\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; @@ -60,7 +60,7 @@ pub async fn change_email_get( Ok(a) => a.replace("${{CHANGE_URL}}", &link), Err(e) => { error!("Error loading template\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; @@ -68,14 +68,15 @@ pub async fn change_email_get( Ok(a) => a, Err(e) => { error!("Error building message\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; if let Err(e) = send_mail(mailer, message).await { error!("Error sending mail\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); }; - Ok(web::Json(Response::new_success("Sent E-Mail, check your inbox".to_string()))) + Ok(web::Json(TextResponse { message: "Sent E-Mail, check your inbox".to_string()})) } + diff --git a/backend/src/api/change_password.rs b/backend/src/api/change_password.rs index 6645d08..61c2b6c 100644 --- a/backend/src/api/change_password.rs +++ b/backend/src/api/change_password.rs @@ -1,6 +1,6 @@ use actix_identity::Identity; use actix_web::{ - web::{self, Json}, Responder, Result + error, web::{self, Json}, Responder, Result }; use argon2::{password_hash::SaltString, Argon2, PasswordHasher}; use chrono::{Days, Utc}; @@ -10,13 +10,12 @@ use rand_core::OsRng; use serde::Deserialize; use surrealdb::sql::Thing; -use super::response::Response; use crate::{ - database::sessions::delete_user_sessions, mail::{ + api_wrapper::utils::TextResponse, database::sessions::delete_user_sessions, error::Error, mail::{ mailing::{build_mail, send_mail}, utils::{load_template, Mailer} }, models::{ links_model::{Link, LinkType}, model::{ConnectionData, CRUD}, user_model::User - }, prelude::Error, utils::password::valid_password + }, utils::password::valid_password }; #[derive(Debug, Deserialize)] @@ -30,7 +29,7 @@ pub async fn change_password_post( body: Json<PasswordChange>, id: Option<Identity>, db: ConnectionData, mailer: web::Data<Mailer>, ) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in".into()))); + return Err(error::ErrorForbidden( "Not logged in")); } let id = id.unwrap(); @@ -38,7 +37,7 @@ pub async fn change_password_post( Ok(a) => a, Err(e) => { error!("Error trying to get id\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; @@ -47,12 +46,12 @@ pub async fn change_password_post( Some(a) => a, None => { error!("User not found?"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }, Err(e) => { error!("Error trying to get user\n{e}"); - return Ok(Response::new_error(500, "Interal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Interal Server Error")); } }; @@ -61,12 +60,12 @@ pub async fn change_password_post( }; if body.old_password == body.new_password { - return Ok(Response::new_error(400, "New Password can't be Old Password".into()).into()); + return Err(error::ErrorUnprocessableEntity( "New Password can't be Old Password")); } if user.verify_password(body.old_password.clone()).is_err() { debug!("Wrong password"); - return Ok(Response::new_error(403, "Wrong password".into()).into()); + return Err(error::ErrorForbidden( "Wrong password")); } let argon2 = Argon2::default(); @@ -76,7 +75,7 @@ pub async fn change_password_post( Ok(a) => a, Err(e) => { error!("Error hashing password\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; @@ -93,12 +92,12 @@ pub async fn change_password_post( if let Err(e) = User::update_replace(db.clone(), old_user.id, new_user.clone()).await { error!("Error updating user\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } if let Err(e) = delete_user_sessions(db.clone(), new_user.clone().id.to_string()).await { error!("Error logging user out\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } let expiry_time = Utc::now().checked_add_days(Days::new(2)).unwrap(); @@ -107,7 +106,7 @@ pub async fn change_password_post( Ok(a) => a.construct_link(), Err(e) => { error!("Error creating link\n{e}"); - return Ok(Response::new_error(500, "Error sending mail".into()).into()); + return Err(error::ErrorInternalServerError( "Error sending mail")); } }; @@ -115,7 +114,7 @@ pub async fn change_password_post( Ok(a) => a.replace("${{RESET_URL}}", &reset_link), Err(e) => { error!("Error loading template\n{e}"); - return Ok(Response::new_error(500, "Error sending mail".into()).into()); + return Err(error::ErrorInternalServerError( "Error sending mail")); } }; @@ -124,14 +123,14 @@ pub async fn change_password_post( Ok(a) => a, Err(e) => { error!("Error building mail\n{e}"); - return Ok(Response::new_error(500, "Error sending mail".into()).into()); + return Err(error::ErrorInternalServerError( "Error sending mail")); } }; if let Err(e) = send_mail(mailer, message).await { error!("Error sending mail\n{e}"); - return Ok(Response::new_error(500, "Error sending mail".into()).into()); + return Err(error::ErrorInternalServerError( "Error sending mail")); } - Ok(web::Json(Response::new_success("Successfully changed Password".to_string()))) + Ok(web::Json(TextResponse { message: "Successfully changed Password".to_string()})) } diff --git a/backend/src/api/change_untis_data.rs b/backend/src/api/change_untis_data.rs index 5fa2ccb..0456019 100644 --- a/backend/src/api/change_untis_data.rs +++ b/backend/src/api/change_untis_data.rs @@ -1,12 +1,11 @@ use actix_identity::Identity; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use log::{error, warn}; use serde::Deserialize; use surrealdb::sql::Thing; -use super::response::Response; use crate::{ - database::sessions::delete_user_sessions, internalError, models::{ + api_wrapper::utils::TextResponse, database::sessions::delete_user_sessions, models::{ model::{ConnectionData, CRUD}, user_model::User } }; @@ -22,7 +21,7 @@ pub async fn change_untis_data_post( body: web::Json<UntisData>, db: ConnectionData, id: Option<Identity>, ) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in".into()))); + return Err(error::ErrorForbidden( "Not logged in")); } let id = id.unwrap(); @@ -30,7 +29,7 @@ pub async fn change_untis_data_post( Ok(a) => Thing::from(a.split_once(':').unwrap()), Err(e) => { error!("Error trying to get id\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -39,17 +38,17 @@ pub async fn change_untis_data_post( Some(a) => a, None => { error!("User not found?"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }, Err(e) => { error!("Error trying to get user\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; if user.verify_password(body.password.clone()).is_err() { - return Ok(web::Json(Response::new_error(403, "Incorrect Password".to_string()))); + return Err(error::ErrorForbidden( "Incorrect Password".to_string())); } let new_user = User { @@ -63,12 +62,12 @@ pub async fn change_untis_data_post( if let Err(e) = User::update_replace(db.clone(), id.clone(), new_user).await { error!("Error updating user\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } if let Err(e) = delete_user_sessions(db, id.to_string()).await { warn!("Error deleting user sessions, ignoring\n{e}"); } - Ok(web::Json(Response::new_success("Successfully changed Untis Data".to_string()))) + Ok(web::Json(TextResponse { message: "Successfully changed Untis Data".to_string()})) } diff --git a/backend/src/api/check_session.rs b/backend/src/api/check_session.rs index 8f8e7fb..652a4be 100644 --- a/backend/src/api/check_session.rs +++ b/backend/src/api/check_session.rs @@ -1,19 +1,21 @@ use actix_identity::Identity; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use log::error; -use crate::api::response::Response; +use crate::api_wrapper::utils::TextResponse; + + pub async fn check_session_get(id: Option<Identity>) -> Result<impl Responder> { if let Some(id) = id { match id.id() { - Ok(_) => Ok(web::Json(Response::new_success("Authenticated".to_string()))), + Ok(_) => Ok(web::Json(TextResponse { message: "Authenticated".to_string()})), Err(e) => { error!("Error trying to get id.id()\n{}", e); - Ok(Response::new_error(500, "NOPE Server Error".to_string()).into()) + Err(error::ErrorInternalServerError( "NOPE Server Error".to_string()).into()) } } } else { - Ok(Response::new_error(403, "Not Authenticated".to_string()).into()) + Err(error::ErrorForbidden( "Not Authenticated".to_string()).into()) } } diff --git a/backend/src/api/delete.rs b/backend/src/api/delete.rs index 6db005a..a31b277 100644 --- a/backend/src/api/delete.rs +++ b/backend/src/api/delete.rs @@ -1,11 +1,11 @@ use actix_identity::Identity; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use log::{error, warn}; use serde::Deserialize; use surrealdb::sql::Thing; use crate::{ - api::response::Response, database::sessions::delete_user_sessions, internalError, models::{ + api_wrapper::utils::TextResponse, database::sessions::delete_user_sessions, models::{ model::{ConnectionData, CRUD}, user_model::User } }; @@ -19,7 +19,7 @@ pub async fn delete_post( body: web::Json<DeleteBody>, id: Option<Identity>, db: ConnectionData, ) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in".into()))); + return Err(error::ErrorForbidden( "Not logged in")); } let id = id.unwrap(); @@ -27,7 +27,7 @@ pub async fn delete_post( Ok(a) => Thing::from(a.split_once(':').unwrap()), Err(e) => { error!("Error trying to get id\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -36,18 +36,18 @@ pub async fn delete_post( Some(a) => a, None => { error!("User not found?"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }, Err(e) => { error!("Error trying to get user\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; if user.verify_password(body.password.clone()).is_err() { warn!("Incorrect password"); - return Ok(web::Json(Response::new_error(403, "Incorrect Password".into()))); + return Err(error::ErrorForbidden( "Incorrect Password")); } if let Err(e) = delete_user_sessions(db.clone(), id.to_string()).await { @@ -56,8 +56,8 @@ pub async fn delete_post( if let Err(e) = User::delete(db, id).await { error!("Failed to delete account\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); }; - Ok(web::Json(Response::new_success("Deleted your Account, bye-bye!".to_string()))) + Ok(web::Json(TextResponse { message: "Deleted your Account, bye-bye!".to_string()})) } diff --git a/backend/src/api/forgot_password.rs b/backend/src/api/forgot_password.rs index 58f7d04..a6497fa 100644 --- a/backend/src/api/forgot_password.rs +++ b/backend/src/api/forgot_password.rs @@ -1,12 +1,11 @@ -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use chrono::{Days, Utc}; use lettre::{message::header::ContentType, Address}; use log::error; use serde::Deserialize; -use super::response::Response; use crate::{ - mail::{ + api_wrapper::utils::TextResponse, mail::{ mailing::{build_mail, send_mail}, utils::{load_template, Mailer} }, models::{ links_model::{Link, LinkType}, model::ConnectionData, user_model::User @@ -22,19 +21,19 @@ pub async fn forgot_password_post( body: web::Json<ForgotPassword>, db: ConnectionData, mailer: web::Data<Mailer>, ) -> Result<impl Responder> { if body.mail.parse::<Address>().is_err() { - return Ok(web::Json(Response::new_error(400, "Not a valid e-mail".into()))); + return Err(error::ErrorUnprocessableEntity( "Not a valid e-mail")); } let user = match User::get_from_email(db.clone(), body.mail.clone()).await { Ok(a) => match a { Some(a) => a, None => { - return Ok(Response::new_error(404, "No account associated with e-mail".into()).into()); + return Err(error::ErrorNotFound( "No account associated with e-mail")); } }, Err(e) => { error!("Error getting user from mail\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; @@ -44,7 +43,7 @@ pub async fn forgot_password_post( Ok(a) => a.construct_link(), Err(e) => { error!("Error creating link\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; @@ -52,7 +51,7 @@ pub async fn forgot_password_post( Ok(a) => a.replace("${{RESET_URL}}", &link), Err(e) => { error!("Error loading template\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; @@ -60,14 +59,14 @@ pub async fn forgot_password_post( Ok(a) => a, Err(e) => { error!("Error building mail\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; if let Err(e) = send_mail(mailer, message).await { error!("Error sending mail\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } - Ok(web::Json(Response::new_success("Sent E-Mail, check your Inbox".to_string()))) + Ok(web::Json(TextResponse { message: "Sent E-Mail, check your Inbox".to_string()})) } diff --git a/backend/src/api/gdpr_data_compliance.rs b/backend/src/api/gdpr_data_compliance.rs index f2bbffa..29e3395 100644 --- a/backend/src/api/gdpr_data_compliance.rs +++ b/backend/src/api/gdpr_data_compliance.rs @@ -1,5 +1,5 @@ use actix_identity::Identity; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use chrono::Local; use lettre::{ message::{header::ContentType, Attachment, Mailbox, MultiPart, SinglePart}, Message @@ -9,7 +9,7 @@ use serde::Serialize; use surrealdb::sql::Thing; use crate::{ - api::response::Response, internalError, mail::{ + api_wrapper::utils::TextResponse, mail::{ mailing::send_mail, utils::{load_template, Mailer} }, models::{ links_model::Link, model::{ConnectionData, CRUD}, sessions_model::Session, user_model::User @@ -27,7 +27,7 @@ pub async fn gdpr_data_compliance_get( id: Option<Identity>, db: ConnectionData, mailer: web::Data<Mailer>, ) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in".into()))); + return Err(error::ErrorForbidden( "Not logged in")); } let id = id.unwrap(); @@ -35,7 +35,7 @@ pub async fn gdpr_data_compliance_get( Ok(a) => Thing::from(a.split_once(':').unwrap()), Err(e) => { error!("Error trying to get id\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -44,12 +44,12 @@ pub async fn gdpr_data_compliance_get( Some(a) => a, None => { error!("User not found?"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }, Err(e) => { error!("Error trying to get user\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -57,7 +57,7 @@ pub async fn gdpr_data_compliance_get( Ok(a) => a, Err(e) => { error!("Error trying to get links\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -65,7 +65,7 @@ pub async fn gdpr_data_compliance_get( Ok(a) => a, Err(e) => { error!("Error trying to get sessions\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -83,7 +83,7 @@ pub async fn gdpr_data_compliance_get( Ok(a) => a.replace("${{TIMESTAMP}}", ×tamp), Err(e) => { error!("Error loading template\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; @@ -91,7 +91,7 @@ pub async fn gdpr_data_compliance_get( Ok(a) => a, Err(e) => { error!("Error parsing mail\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -99,7 +99,7 @@ pub async fn gdpr_data_compliance_get( Ok(a) => a, Err(e) => { error!("Error Serializing data to json\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -120,14 +120,14 @@ pub async fn gdpr_data_compliance_get( Ok(a) => a, Err(e) => { error!("Error constructing message\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; if let Err(e) = send_mail(mailer, message).await { error!("Error sending mail\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); }; - Ok(web::Json(Response::new_success("Sent E-Mail, check your inbox".to_string()))) + Ok(web::Json(TextResponse { message: "Sent E-Mail, check your inbox".to_string()})) } diff --git a/backend/src/api/get_free_rooms.rs b/backend/src/api/get_free_rooms.rs index 966098c..61cca64 100644 --- a/backend/src/api/get_free_rooms.rs +++ b/backend/src/api/get_free_rooms.rs @@ -1,15 +1,15 @@ use actix_identity::Identity; -use actix_web::{web, HttpRequest, Responder, Result}; +use actix_web::{error, web, HttpRequest, Responder, Result}; use log::{debug, error}; use serde::{Deserialize, Serialize}; use surrealdb::sql::Thing; use crate::{ - api::response::Response, api_wrapper::{ + api_wrapper::{ untis_client::UntisClient, utils::{FormattedFreeRoom, TimetableParameter} - }, models::{ + }, error::Error, models::{ model::{DBConnection, CRUD}, user_model::User - }, prelude::Error, utils::time::{format_for_untis, get_this_friday, get_this_monday}, GlobalUntisData + }, utils::time::{format_for_untis, get_this_friday, get_this_monday}, GlobalUntisData }; #[derive(Serialize)] @@ -28,13 +28,13 @@ pub async fn get_free_rooms( db: web::Data<DBConnection>, ) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in".to_string()))); + return Err(error::ErrorForbidden( "Not logged in".to_string())); } let jsessionid = if let Some(session_cookie) = req.cookie("JSESSIONID") { session_cookie.value().to_string() } else { - return Ok(Response::new_error(403, "No JSESSIONID provided".to_string()).into()); + return Err(error::ErrorForbidden( "No JSESSIONID provided".to_string()).into()); }; let pot_user: Option<User> = User::get_from_id( @@ -46,12 +46,12 @@ pub async fn get_free_rooms( Thing::from(split.unwrap()) } else { error!("ID in session_cookie is wrong???"); - return Ok(Response::new_error(500, "There was an error trying to get your id".to_string()).into()); + return Err(error::ErrorInternalServerError( "There was an error trying to get your id".to_string()).into()); } } Err(e) => { error!("Error getting Identity id\n{e}"); - return Ok(Response::new_error(500, "There was an error trying to get your id".to_string()).into()); + return Err(error::ErrorInternalServerError( "There was an error trying to get your id".to_string()).into()); } }, ) @@ -61,16 +61,12 @@ pub async fn get_free_rooms( Some(u) => u, None => { debug!("Deleted(?) User tried to log in with old session token"); - return Ok(Response::new_error(404, "This account doesn't exist!".to_string()).into()); + return Err(error::ErrorNotFound( "This account doesn't exist!".to_string()).into()); } }; if !user.verified { - return Ok(Response::new_error( - 403, - "Account not verified! Check your E-Mails for a verification link".to_string(), - ) - .into()); + return Err(error::ErrorUnauthorized("Account not verified! Check your E-Mails for a verification link")); } let untis = match UntisClient::unsafe_init( @@ -87,9 +83,9 @@ pub async fn get_free_rooms( Ok(u) => u, Err(e) => { if let Error::Reqwest(_) = e { - return Ok(Response::new_error(400, "You done fucked up".into()).into()); + return Err(error::ErrorUnprocessableEntity( "You done fucked up")); } else { - return Ok(Response::new_error(500, "Untis done fucked up ".to_string() + &e.to_string()).into()); + return Err(error::ErrorInternalServerError( "Untis done fucked up ".to_string() + &e.to_string()).into()); } } }; @@ -105,9 +101,9 @@ pub async fn get_free_rooms( let rooms = match untis.clone().get_free_rooms(TimetableParameter::default(untis, from, until)).await { Ok(rooms) => rooms, - Err(err) => { - return Ok(Response::from(Error::UntisError(err.to_string())).into()); + Err(_err) => { + return Err(error::ErrorInternalServerError("Error while fetching rooms")); } }; - Ok(Response::new_success(TimetableResponse { rooms }).into()) + Ok(web::Json(TimetableResponse { rooms })) } diff --git a/backend/src/api/get_lernbueros.rs b/backend/src/api/get_lernbueros.rs index ebd61fb..6e3c15d 100644 --- a/backend/src/api/get_lernbueros.rs +++ b/backend/src/api/get_lernbueros.rs @@ -1,15 +1,15 @@ use actix_identity::Identity; -use actix_web::{web, HttpRequest, Responder, Result}; +use actix_web::{error, web, HttpRequest, Responder, Result}; use log::{debug, error}; use serde::{Deserialize, Serialize}; use surrealdb::sql::Thing; use crate::{ - api::response::Response, api_wrapper::{ + api_wrapper::{ untis_client::UntisClient, utils::{FormattedLesson, TimetableParameter} }, models::{ model::{DBConnection, CRUD}, user_model::User - }, prelude::Error, utils::time::{format_for_untis, get_this_friday, get_this_monday}, GlobalUntisData + }, error::Error, utils::time::{format_for_untis, get_this_friday, get_this_monday}, GlobalUntisData }; #[derive(Serialize)] @@ -28,13 +28,13 @@ pub async fn get_lernbueros( db: web::Data<DBConnection>, ) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in".to_string()))); + return Err(error::ErrorForbidden( "Not logged in".to_string())); } let jsessionid = if let Some(session_cookie) = req.cookie("JSESSIONID") { session_cookie.value().to_string() } else { - return Ok(Response::new_error(403, "No JSESSIONID provided".to_string()).into()); + return Err(error::ErrorForbidden( "No JSESSIONID provided".to_string()).into()); }; let pot_user: Option<User> = User::get_from_id( @@ -46,12 +46,12 @@ pub async fn get_lernbueros( Thing::from(split.unwrap()) } else { error!("ID in session_cookie is wrong???"); - return Ok(Response::new_error(500, "There was an error trying to get your id".to_string()).into()); + return Err(error::ErrorInternalServerError( "There was an error trying to get your id".to_string()).into()); } } Err(e) => { error!("Error getting Identity id\n{e}"); - return Ok(Response::new_error(500, "There was an error trying to get your id".to_string()).into()); + return Err(error::ErrorInternalServerError( "There was an error trying to get your id".to_string()).into()); } }, ) @@ -61,16 +61,12 @@ pub async fn get_lernbueros( Some(u) => u, None => { debug!("Deleted(?) User tried to log in with old session token"); - return Ok(Response::new_error(404, "This account doesn't exist!".to_string()).into()); + return Err(error::ErrorNotFound( "This account doesn't exist!".to_string()).into()); } }; if !user.verified { - return Ok(Response::new_error( - 403, - "Account not verified! Check your E-Mails for a verification link".to_string(), - ) - .into()); + return Err(error::ErrorForbidden( "Account not verified! Check your E-Mails for a verification link")); } let untis = match UntisClient::unsafe_init( @@ -87,9 +83,9 @@ pub async fn get_lernbueros( Ok(u) => u, Err(e) => { if let Error::Reqwest(_) = e { - return Ok(Response::new_error(400, "You done fucked up".into()).into()); + return Err(error::ErrorUnprocessableEntity( "You done fucked up")); } else { - return Ok(Response::new_error(500, "Untis done fucked up ".to_string() + &e.to_string()).into()); + return Err(error::ErrorInternalServerError( "Untis done fucked up ".to_string() + &e.to_string()).into()); } } }; @@ -105,9 +101,9 @@ pub async fn get_lernbueros( let lernbueros = match untis.clone().get_lernbueros(TimetableParameter::default(untis, from, until)).await { Ok(lernbueros) => lernbueros, - Err(err) => { - return Ok(Response::from(Error::UntisError(err.to_string())).into()); + Err(_err) => { + return Err(error::ErrorInternalServerError("Error while fetching lbs")); } }; - Ok(Response::new_success(TimetableResponse { lessons: lernbueros }).into()) + Ok(web::Json(TimetableResponse { lessons: lernbueros })) } diff --git a/backend/src/api/get_timetable.rs b/backend/src/api/get_timetable.rs index fc30a41..249cc2f 100644 --- a/backend/src/api/get_timetable.rs +++ b/backend/src/api/get_timetable.rs @@ -1,17 +1,18 @@ use actix_identity::Identity; -use actix_web::{web, HttpRequest, Responder, Result}; +use actix_web::{error, web::{self}, HttpRequest, Responder, Result}; use log::{debug, error}; use serde::{Deserialize, Serialize}; use surrealdb::sql::Thing; use crate::{ - api::response::Response, api_wrapper::{ + api_wrapper::{ untis_client::UntisClient, utils::{FormattedLesson, TimetableParameter} }, models::{ model::{DBConnection, CRUD}, user_model::User - }, prelude::Error, utils::time::{format_for_untis, get_this_friday, get_this_monday}, GlobalUntisData + }, error::Error, utils::time::{format_for_untis, get_this_friday, get_this_monday}, GlobalUntisData }; + #[derive(Serialize)] struct TimetableResponse { lessons: Vec<FormattedLesson>, @@ -29,13 +30,13 @@ pub async fn get_timetable( db: web::Data<DBConnection>, ) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in".to_string()))); + return Err(error::ErrorForbidden("Not logged in")); } let jsessionid = if let Some(session_cookie) = req.cookie("JSESSIONID") { session_cookie.value().to_string() } else { - return Ok(Response::new_error(403, "No JSESSIONID provided".to_string()).into()); + return Err(error::ErrorForbidden( "No JSESSIONID provided".to_string())); }; let pot_user: Option<User> = User::get_from_id( @@ -47,12 +48,12 @@ pub async fn get_timetable( Thing::from(split.unwrap()) } else { error!("ID in session_cookie is wrong???"); - return Ok(Response::new_error(500, "There was an error trying to get your id".to_string()).into()); + return Err(error::ErrorInternalServerError( "There was an error trying to get your id".to_string())); } } Err(e) => { error!("Error getting Identity id\n{e}"); - return Ok(Response::new_error(500, "There was an error trying to get your id".to_string()).into()); + return Err(error::ErrorInternalServerError( "There was an error trying to get your id".to_string())); } }, ) @@ -62,16 +63,12 @@ pub async fn get_timetable( Some(u) => u, None => { debug!("Deleted(?) User tried to log in with old session token"); - return Ok(Response::new_error(404, "This account doesn't exist!".to_string()).into()); + return Err(error::ErrorNotFound( "This account doesn't exist!".to_string())); } }; if !user.verified { - return Ok(Response::new_error( - 403, - "Account not verified! Check your E-Mails for a verification link".to_string(), - ) - .into()); + return Err(error::ErrorUnauthorized("Account not verified! Check your E-Mails for a verification link".to_string())); } let untis = match UntisClient::unsafe_init( @@ -88,12 +85,12 @@ pub async fn get_timetable( Ok(u) => u, Err(e) => { if let Error::Reqwest(_) = e { - return Ok(Response::new_error(400, "You done fucked up".into()).into()); + return Err(error::ErrorUnprocessableEntity( "You done fucked up")); } else if let Error::UntisError(body) = e { - return Ok(Response::new_error(500, "Untis done fucked up ".to_string() + &body).into()); + return Err(error::ErrorInternalServerError( "Untis done fucked up ".to_string() + &body)); } else { - return Ok(Response::new_error(500, "Some mysterious guy done fucked up".into()).into()); + return Err(error::ErrorInternalServerError( "Some mysterious guy done fucked up")); } } }; @@ -110,8 +107,8 @@ pub async fn get_timetable( let timetable = match untis.clone().get_timetable(TimetableParameter::default(untis, from, until), class_name).await { Ok(timetable) => timetable, Err(err) => { - return Ok(Response::new_error(500, "Untis done fucked up ".to_string() + &err.to_string()).into()); + return Err(error::ErrorInternalServerError( "Untis done fucked up ".to_string() + &err.to_string()).into()); } }; - Ok(Response::new_success(TimetableResponse { lessons: timetable }).into()) + Ok(web::Json(TimetableResponse { lessons: timetable })) } diff --git a/backend/src/api/get_timetable_serviceworker.rs b/backend/src/api/get_timetable_serviceworker.rs index 6a00412..ca864a5 100644 --- a/backend/src/api/get_timetable_serviceworker.rs +++ b/backend/src/api/get_timetable_serviceworker.rs @@ -1,15 +1,15 @@ use actix_identity::Identity; -use actix_web::{web::{self}, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use log::{debug, error}; use serde::{Deserialize, Serialize}; use surrealdb::sql::Thing; use crate::{ - api::response::Response, api_wrapper::{ + api_wrapper::{ untis_client::UntisClient, utils::{FormattedLesson, TimetableParameter} }, models::{ model::{DBConnection, CRUD}, user_model::User - }, prelude::Error, utils::time::{format_for_untis, get_this_friday, get_this_monday}, GlobalUntisData + }, error::Error, utils::time::{format_for_untis, get_this_friday, get_this_monday}, GlobalUntisData }; #[derive(Serialize)] @@ -34,12 +34,12 @@ pub async fn get_timetable_serviceworker( db: web::Data<DBConnection>, ) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in".to_string()))); + return Err(error::ErrorForbidden( "Not logged in").into()); } let jsessionid = match data.jsessionid.clone() { Some(session_cookie) => session_cookie, - None => return Ok(Response::new_error(403, "No JSESSIONID provided".to_string()).into()), + None => return Err(error::ErrorForbidden( "No JSESSIONID provided".to_string()).into()), }; let pot_user: Option<User> = User::get_from_id( @@ -51,12 +51,12 @@ pub async fn get_timetable_serviceworker( Thing::from(split.unwrap()) } else { error!("ID in session_cookie is wrong???"); - return Ok(Response::new_error(500, "There was an error trying to get your id".to_string()).into()); + return Err(error::ErrorInternalServerError( "There was an error trying to get your id".to_string()).into()); } } Err(e) => { error!("Error getting Identity id\n{e}"); - return Ok(Response::new_error(500, "There was an error trying to get your id".to_string()).into()); + return Err(error::ErrorInternalServerError( "There was an error trying to get your id".to_string()).into()); } }, ) @@ -66,15 +66,12 @@ pub async fn get_timetable_serviceworker( Some(u) => u, None => { debug!("Deleted(?) User tried to log in with old session token"); - return Ok(Response::new_error(404, "This account doesn't exist!".to_string()).into()); + return Err(error::ErrorNotFound( "This account doesn't exist!".to_string()).into()); } }; if !user.verified { - return Ok(Response::new_error( - 403, - "Account not verified! Check your E-Mails for a verification link".to_string(), - ) + return Err(error::ErrorForbidden("Account not verified! Check your E-Mails for a verification link".to_string(),) .into()); } @@ -92,12 +89,12 @@ pub async fn get_timetable_serviceworker( Ok(u) => u, Err(e) => { if let Error::Reqwest(_) = e { - return Ok(Response::new_error(400, "You done fucked up".into()).into()); + return Err(error::ErrorUnprocessableEntity( "You done fucked up")); } else if let Error::UntisError(body) = e { - return Ok(Response::new_error(500, "Untis done fucked up ".to_string() + &body).into()); + return Err(error::ErrorInternalServerError( "Untis done fucked up ".to_string() + &body).into()); } else { - return Ok(Response::new_error(500, "Some mysterious guy done fucked up".into()).into()); + return Err(error::ErrorInternalServerError( "Some mysterious guy done fucked up")); } } }; @@ -114,8 +111,8 @@ pub async fn get_timetable_serviceworker( let timetable = match untis.clone().get_timetable(TimetableParameter::default(untis, from, until), class_name).await { Ok(timetable) => timetable, Err(err) => { - return Ok(Response::new_error(500, "Untis done fucked up ".to_string() + &err.to_string()).into()); + return Err(error::ErrorInternalServerError( "Untis done fucked up ".to_string() + &err.to_string()).into()); } }; - Ok(Response::new_success(TimetableResponse { lessons: timetable }).into()) -} + Ok(web::Json(TimetableResponse { lessons: timetable }).into()) +} \ No newline at end of file diff --git a/backend/src/api/link/check_uuid.rs b/backend/src/api/link/check_uuid.rs index 5007bcb..dd78f62 100644 --- a/backend/src/api/link/check_uuid.rs +++ b/backend/src/api/link/check_uuid.rs @@ -1,13 +1,13 @@ use std::str::FromStr; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use log::{error, warn}; use serde::Deserialize; use surrealdb::sql::Thing; use uuid::Uuid; use crate::{ - api::response::Response, internalError, models::{ + api_wrapper::utils::TextResponse, models::{ links_model::{Link, LinkType}, model::{ConnectionData, CRUD} } }; @@ -23,7 +23,7 @@ pub async fn check_uuid_get( path: web::Path<String>, typequery: web::Query<UuidQuery>, db: ConnectionData, ) -> Result<impl Responder> { if Uuid::from_str(&path).is_err() { - return Ok(Response::new_error(400, "UUID is not a valid uuid".into()).into()); + return Err(error::ErrorUnprocessableEntity( "UUID is not a valid uuid")); } let pot_link = match Link::get_from_id( @@ -38,20 +38,20 @@ pub async fn check_uuid_get( Ok(a) => a, Err(e) => { error!("There was an error getting a link from the database\n{e}"); - internalError!("There was a database error") + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; if pot_link.is_none() { - return Ok(Response::new_error(404, "Link not found".into()).into()); + return Err(error::ErrorNotFound( "Link not found")); } let link = pot_link.unwrap(); if link.link_type != typequery.link_type { warn!("Link found but wrong type"); - return Ok(Response::new_error(404, "Link not found".into()).into()); + return Err(error::ErrorNotFound( "Link not found")); } - Ok(web::Json(Response::new_success("Link found".to_string()))) + Ok(web::Json(TextResponse { message: "Link found".to_string()})) } diff --git a/backend/src/api/link/email_change.rs b/backend/src/api/link/email_change.rs index a475209..718fd93 100644 --- a/backend/src/api/link/email_change.rs +++ b/backend/src/api/link/email_change.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use chrono::{Days, Utc}; use lettre::{message::header::ContentType, Address}; use log::{debug, error, warn}; @@ -9,7 +9,7 @@ use surrealdb::sql::Thing; use uuid::Uuid; use crate::{ - api::response::Response, database::sessions::delete_user_sessions, mail::{ + api_wrapper::utils::TextResponse, database::sessions::delete_user_sessions, mail::{ mailing::{build_mail, send_mail}, utils::{load_template, Mailer} }, models::{ links_model::{Link, LinkType}, model::{ConnectionData, CRUD}, user_model::User @@ -31,10 +31,10 @@ pub async fn email_change_post( path: web::Path<String>, body: web::Json<NewMail>, db: ConnectionData, mailer: web::Data<Mailer>, ) -> Result<impl Responder> { if body.mail.parse::<Address>().is_err() { - return Ok(web::Json(Response::new_error(400, "Not a valid e-mail".into()))); + return Err(error::ErrorUnprocessableEntity( "Not a valid e-mail")); } if Uuid::from_str(&path).is_err() { - return Ok(Response::new_error(400, "UUID is not a valid uuid".into()).into()); + return Err(error::ErrorUnprocessableEntity( "UUID is not a valid uuid")); } let pot_link = match Link::get_from_id( @@ -49,12 +49,12 @@ pub async fn email_change_post( Ok(a) => a, Err(e) => { error!("There was an error getting a link from the database\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }; if pot_link.is_none() { - return Ok(Response::new_error(404, "Link not found".into()).into()); + return Err(error::ErrorNotFound( "Link not found")); } let link = pot_link.unwrap(); @@ -65,7 +65,7 @@ pub async fn email_change_post( // Potential Attacker really shouldn't know if there's a link of another type with the // provided UUID warn!("Link found but wrong type"); - return Ok(Response::new_error(404, "Link not found".into()).into()); + return Err(error::ErrorNotFound( "Link not found")); } } @@ -76,29 +76,29 @@ pub async fn email_change_post( Some(a) => a, None => { error!("User ID in link is not valid"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }, Err(e) => { error!("Database error trying to get user from link\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }; if user.verify_password(body.password.clone()).is_err() { debug!("Client sent wrong password"); - return Ok(Response::new_error(403, "Wrong Password".into()).into()); + return Err(error::ErrorForbidden( "Wrong Password")); }; if match User::get_from_email(db.clone(), body.mail.clone()).await { Ok(a) => a.is_some(), Err(e) => { error!("Getting potential user from mail failed\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } } { warn!("E-mail is already in use"); - return Ok(Response::new_error(403, "Mail already in use".into()).into()); + return Err(error::ErrorForbidden( "Mail already in use")); } let new_user = User { @@ -112,7 +112,7 @@ pub async fn email_change_post( if let Err(e) = User::update_replace(db.clone(), user_id.clone(), new_user).await { error!("Error updating user email\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } if let Err(e) = Link::delete(db.clone(), link.id).await { @@ -124,19 +124,19 @@ pub async fn email_change_post( Some(a) => a, None => { error!("Updated e-mail isn't found in the database?"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }, Err(e) => { error!("Error trying to get updated user from database\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }; // Logout user from all devices if let Err(e) = delete_user_sessions(db.clone(), user_id.to_string()).await { error!("Error deleting user sessions\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); }; let expiry = Utc::now().checked_add_days(Days::new(2)).unwrap(); @@ -145,7 +145,7 @@ pub async fn email_change_post( Ok(a) => a.construct_link(), Err(e) => { error!("Error creating reset link\n{e}"); - return Ok(Response::new_error(500, "There was an error sending out an e-mail".into()).into()); + return Err(error::ErrorInternalServerError( "There was an error sending out an e-mail")); } }; @@ -153,7 +153,7 @@ pub async fn email_change_post( Ok(a) => a.replace("${{RESET_URL}}", &reset_link).replace("${{NEW_MAIL}}", &body.mail), Err(e) => { error!("Error loading mail template\n{e}"); - return Ok(Response::new_error(500, "There was an error sending out an e-mail".into()).into()); + return Err(error::ErrorInternalServerError( "There was an error sending out an e-mail")); } }; @@ -162,7 +162,7 @@ pub async fn email_change_post( Ok(a) => a, Err(e) => { error!("Error constructing message\n{e}"); - return Ok(Response::new_error(500, "There was an error sending out an e-mail".into()).into()); + return Err(error::ErrorInternalServerError( "There was an error sending out an e-mail")); } }; @@ -170,9 +170,9 @@ pub async fn email_change_post( Ok(_) => {} Err(e) => { error!("Error sending mail\n{e}"); - return Ok(Response::new_error(500, "There was an error sending out an e-mail".into()).into()); + return Err(error::ErrorInternalServerError( "There was an error sending out an e-mail")); } }; - Ok(web::Json(Response::new_success("Successfully updated e-mail".to_string()))) + Ok(web::Json(TextResponse { message: "Successfully updated e-mail".to_string()})) } diff --git a/backend/src/api/link/email_reset.rs b/backend/src/api/link/email_reset.rs index b7751e1..d14ace9 100644 --- a/backend/src/api/link/email_reset.rs +++ b/backend/src/api/link/email_reset.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use lettre::Address; use log::{error, warn}; use serde::Deserialize; @@ -8,7 +8,7 @@ use surrealdb::sql::Thing; use uuid::Uuid; use crate::{ - api::response::Response, database::sessions::delete_user_sessions, models::{ + api_wrapper::utils::TextResponse, database::sessions::delete_user_sessions, models::{ links_model::{Link, LinkType}, model::{ConnectionData, CRUD}, user_model::User } }; @@ -23,10 +23,10 @@ pub async fn email_reset_post( path: web::Path<String>, body: web::Json<NewMail>, db: ConnectionData, ) -> Result<impl Responder> { if body.mail.parse::<Address>().is_err() { - return Ok(web::Json(Response::new_error(400, "Not a valid e-mail".into()))); + return Err(error::ErrorUnprocessableEntity( "Not a valid e-mail")); } if Uuid::from_str(&path).is_err() { - return Ok(Response::new_error(400, "UUID is not a valid uuid".into()).into()); + return Err(error::ErrorUnprocessableEntity( "UUID is not a valid uuid")); } let pot_link = match Link::get_from_id( @@ -41,12 +41,12 @@ pub async fn email_reset_post( Ok(a) => a, Err(e) => { error!("There was an error getting a link from the database\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }; if pot_link.is_none() { - return Ok(Response::new_error(404, "Link not found".into()).into()); + return Err(error::ErrorNotFound( "Link not found")); } let link = pot_link.unwrap(); @@ -57,7 +57,7 @@ pub async fn email_reset_post( // Potential Attacker really shouldn't know if there's a link of another type with the // provided UUID warn!("Link found but wrong type"); - return Ok(Response::new_error(404, "Link not found".into()).into()); + return Err(error::ErrorNotFound( "Link not found")); } } @@ -68,12 +68,12 @@ pub async fn email_reset_post( Some(a) => a, None => { error!("User ID in link is not valid"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }, Err(e) => { error!("Database error trying to get user from link\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }; @@ -81,11 +81,11 @@ pub async fn email_reset_post( Ok(a) => a.is_some(), Err(e) => { error!("Getting potential user from mail failed\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } } { warn!("E-mail is already in use"); - return Ok(Response::new_error(403, "Mail already in use".into()).into()); + return Err(error::ErrorForbidden( "Mail already in use")); } let new_user = User { @@ -99,7 +99,7 @@ pub async fn email_reset_post( if User::update_replace(db.clone(), user_id.clone(), new_user).await.is_err() { error!("Error updating user email"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } if let Err(e) = Link::delete(db.clone(), link.id).await { @@ -109,8 +109,8 @@ pub async fn email_reset_post( // Logout user from all devices if let Err(e) = delete_user_sessions(db.clone(), user_id.to_string()).await { error!("Error deleting user sessions\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); }; - Ok(web::Json(Response::new_success("Successfully updated e-mail".to_string()))) + Ok(web::Json(TextResponse { message: "Successfully updated e-mail".to_string()})) } diff --git a/backend/src/api/link/password.rs b/backend/src/api/link/password.rs index 8ef2744..f80d6f4 100644 --- a/backend/src/api/link/password.rs +++ b/backend/src/api/link/password.rs @@ -4,7 +4,7 @@ // 3. Passwort über link in E-Mail zurücksetzen: /link/password/{uuid} use std::str::FromStr; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use argon2::{password_hash::SaltString, Argon2, PasswordHasher}; use log::{error, warn}; use rand_core::OsRng; @@ -13,9 +13,9 @@ use surrealdb::sql::Thing; use uuid::Uuid; use crate::{ - api::response::Response, database::sessions::delete_user_sessions, models::{ + api_wrapper::utils::TextResponse, database::sessions::delete_user_sessions, error::Error, models::{ links_model::{Link, LinkType}, model::{ConnectionData, CRUD}, user_model::User - }, prelude::Error, utils::password::valid_password + }, utils::password::valid_password }; #[derive(Debug, Deserialize)] @@ -30,7 +30,7 @@ pub async fn reset_password_post( path: web::Path<String>, db: ConnectionData, body: web::Json<PasswordChange>, ) -> Result<impl Responder> { if Uuid::from_str(&path).is_err() { - return Ok(Response::new_error(400, "UUID is not a valid uuid".into()).into()); + return Err(error::ErrorUnprocessableEntity( "UUID is not a valid uuid")); } if let Err(e) = valid_password(&body.new_password) { return Err(Error::from(e).into()); @@ -48,12 +48,12 @@ pub async fn reset_password_post( Ok(a) => a, Err(e) => { error!("There was an error getting a link from the database\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }; if pot_link.is_none() { - return Ok(Response::new_error(404, "Link not found".into()).into()); + return Err(error::ErrorNotFound( "Link not found")); } let link = pot_link.unwrap(); @@ -64,7 +64,7 @@ pub async fn reset_password_post( // Potential Attacker really shouldn't know if there's a link of another type with the // provided UUID warn!("Link found but wrong type"); - return Ok(Response::new_error(404, "Link not found".into()).into()); + return Err(error::ErrorNotFound( "Link not found")); } } @@ -75,19 +75,19 @@ pub async fn reset_password_post( Some(a) => a, None => { error!("User ID in link is not valid"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }, Err(e) => { error!("Database error trying to get user from link\n{e}"); - return Ok(Response::new_error(500, "There was a database error".into()).into()); + return Err(error::ErrorInternalServerError( "There was a database error")); } }; let argon2 = Argon2::default(); if user.verify_password(body.new_password.clone()).is_ok() { - return Ok(Response::new_error(400, "New Password can't be Old Password".into()).into()); + return Err(error::ErrorUnprocessableEntity( "New Password can't be Old Password")); } let salt = SaltString::generate(OsRng); @@ -95,7 +95,7 @@ pub async fn reset_password_post( Ok(a) => a.to_string(), Err(e) => { error!("Error trying to hash password\n{e}"); - return Ok(Response::new_error(500, "Unknown error trying to hash password".to_string()).into()); + return Err(error::ErrorInternalServerError( "Unknown error trying to hash password".to_string()).into()); } }; @@ -111,7 +111,7 @@ pub async fn reset_password_post( if let Err(e) = User::update_replace(db.clone(), new_user.clone().id, new_user.clone()).await { error!("Error updating user\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } if let Err(e) = Link::delete(db.clone(), link.id).await { @@ -120,8 +120,8 @@ pub async fn reset_password_post( if let Err(e) = delete_user_sessions(db.clone(), new_user.id.to_string()).await { error!("Error logging user out\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } - Ok(web::Json(Response::new_success("Successfully updated Password".to_string()))) + Ok(web::Json(TextResponse { message: "Successfully updated Password".to_string()})) } diff --git a/backend/src/api/link/verify.rs b/backend/src/api/link/verify.rs index 52234a4..d3aa2ed 100644 --- a/backend/src/api/link/verify.rs +++ b/backend/src/api/link/verify.rs @@ -1,12 +1,12 @@ use std::str::FromStr; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use log::{error, warn}; use surrealdb::sql::Thing; use uuid::Uuid; use crate::{ - api::response::Response, internalError, models::{ + api_wrapper::utils::TextResponse, models::{ links_model::{Link, LinkType}, model::{ConnectionData, CRUD}, user_model::User } }; @@ -14,7 +14,7 @@ use crate::{ pub async fn verify_get(path: web::Path<String>, db: ConnectionData) -> Result<impl Responder> { if Uuid::from_str(&path).is_err() { - return Ok(web::Json(Response::new_error(400, "UUID is not a valid uuid".into()))); + return Err(error::ErrorUnprocessableEntity( "UUID is not a valid uuid")); } let pot_link = match Link::get_from_id( @@ -29,12 +29,12 @@ pub async fn verify_get(path: web::Path<String>, db: ConnectionData) -> Result<i Ok(a) => a, Err(e) => { error!("There was an error getting a link from the database\n{e}"); - internalError!("There was a database error") + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; if pot_link.is_none() { - return Ok(Response::new_error(404, "Link not found".into()).into()); + return Err(error::ErrorNotFound( "Link not found")); } let link = pot_link.unwrap(); @@ -45,7 +45,7 @@ pub async fn verify_get(path: web::Path<String>, db: ConnectionData) -> Result<i // Potential Attacker really shouldn't know if there's a link of another type with the // provided UUID warn!("Link found but wrong type"); - return Ok(Response::new_error(404, "Link not found".into()).into()); + return Err(error::ErrorNotFound( "Link not found")); } } @@ -54,12 +54,12 @@ pub async fn verify_get(path: web::Path<String>, db: ConnectionData) -> Result<i Some(a) => a, None => { error!("User not found?"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }, Err(e) => { error!("Error getting user from id\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -74,12 +74,12 @@ pub async fn verify_get(path: web::Path<String>, db: ConnectionData) -> Result<i if let Err(e) = User::update_replace(db.clone(), link.user, new_user).await { error!("Updating user failed\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } if let Err(e) = Link::delete(db, link.id).await { warn!("Failed to delete link, ignoring\n{e}"); } - Ok(web::Json(Response::new_success("Successfully verified!".to_string()))) + Ok(web::Json(TextResponse { message: "Successfully verified!".to_string()})) } diff --git a/backend/src/api/login.rs b/backend/src/api/login.rs index 7dfbe37..35405b5 100644 --- a/backend/src/api/login.rs +++ b/backend/src/api/login.rs @@ -1,9 +1,8 @@ use actix_identity::Identity; -use actix_web::{web, HttpMessage, HttpRequest, Responder, Result}; +use actix_web::{error, web, HttpMessage, HttpRequest, Responder, Result}; use log::error; use serde::{Deserialize, Serialize}; -use super::response::Response; use crate::models::{model::DBConnection, user_model::User}; #[derive(Deserialize)] @@ -26,27 +25,26 @@ pub async fn login_post( Ok(n) => n, Err(e) => { error!("Unknown error occured when trying to get user.\n{}", e); - return Ok(web::Json(Response::new_error(500, "Internal Server Error".to_owned()))); + return Err(error::ErrorInternalServerError( "Internal Server Error".to_owned())); } } { Some(u) => u, None => { - return Ok(Response::new_error(403, "E-Mail or Password is incorrect!".to_owned()).into()); + return Err(error::ErrorForbidden( "E-Mail or Password is incorrect!".to_owned()).into()); } } }; match db_user.verify_password(data.password.clone()) { Ok(_) => match Identity::login(&req.extensions(), db_user.id.to_string()) { - Ok(_) => Ok(Response::<LoginResponse>::new_success(LoginResponse { + Ok(_) => Ok(web::Json(LoginResponse { untis_cypher: db_user.untis_cypher, - }) - .into()), + })), Err(e) => { error!("Error: Unknown error trying to login to Identity\n{}", e); - Ok(Response::new_error(500, "Internal Server Error".to_owned()).into()) + Err(error::ErrorInternalServerError( "Internal Server Error".to_owned()).into()) } }, - Err(_) => Ok(Response::new_error(403, "E-Mail or Password is incorrect!".to_owned()).into()), + Err(_) => Err(error::ErrorForbidden( "E-Mail or Password is incorrect!".to_owned()).into()), } } diff --git a/backend/src/api/logout.rs b/backend/src/api/logout.rs index 634148e..8b731c3 100644 --- a/backend/src/api/logout.rs +++ b/backend/src/api/logout.rs @@ -1,13 +1,14 @@ use actix_identity::Identity; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; + +use crate::api_wrapper::utils::TextResponse; -use super::response::Response; pub async fn logout_post(id: Option<Identity>) -> Result<impl Responder> { if let Some(id) = id { id.logout(); - Ok(Response::new_success("Logout successful!").into()) + Ok(web::Json(TextResponse { message: "Logout successful!".to_string()})) } else { - Ok(web::Json(Response::new_error(403, "Not logged in!".into()))) + Err(error::ErrorForbidden( "Not logged in!")) } } diff --git a/backend/src/api/logout_all.rs b/backend/src/api/logout_all.rs index 5f4925c..0041b6f 100644 --- a/backend/src/api/logout_all.rs +++ b/backend/src/api/logout_all.rs @@ -1,9 +1,8 @@ use actix_identity::Identity; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use log::error; -use super::response::Response; -use crate::{database::sessions::delete_user_sessions, models::model::DBConnection}; +use crate::{api_wrapper::utils::TextResponse, database::sessions::delete_user_sessions, models::model::DBConnection}; pub async fn logout_all_post(id: Option<Identity>, db: web::Data<DBConnection>) -> Result<impl Responder> { if let Some(identity) = id { @@ -11,12 +10,12 @@ pub async fn logout_all_post(id: Option<Identity>, db: web::Data<DBConnection>) Ok(a) => a, Err(e) => { error!("There was an error trying to get id.id()\n{e}"); - return Ok(Response::new_error(500, "Internal Server Error".into()).into()); + return Err(error::ErrorInternalServerError( "Internal Server Error")); } }; delete_user_sessions(db, id).await?; - Ok(Response::new_success("Logged out on all devices!").into()) + Ok(web::Json(TextResponse { message: "Logged out on all devices!".to_string()})) } else { - Ok(web::Json(Response::new_error(403, "Not logged in!".into()))) + Err(error::ErrorForbidden( "Not logged in!")) } } diff --git a/backend/src/api/mod.rs b/backend/src/api/mod.rs index 6806f29..3521d8b 100644 --- a/backend/src/api/mod.rs +++ b/backend/src/api/mod.rs @@ -14,6 +14,5 @@ pub mod logout; pub mod logout_all; pub mod register; pub mod resend_mail; -pub mod response; pub mod verified; -pub mod get_timetable_serviceworker; \ No newline at end of file +//pub mod get_timetable_serviceworker; \ No newline at end of file diff --git a/backend/src/api/register.rs b/backend/src/api/register.rs index fe9a9c1..5874555 100644 --- a/backend/src/api/register.rs +++ b/backend/src/api/register.rs @@ -1,5 +1,5 @@ use actix_identity::Identity; -use actix_web::{web, HttpMessage, HttpRequest, Responder, Result}; +use actix_web::{error, web, HttpMessage, HttpRequest, Responder, Result}; use argon2::{password_hash::SaltString, Argon2, PasswordHasher}; use chrono::{Months, Utc}; use lettre::{message::header::ContentType, Address}; @@ -8,11 +8,11 @@ use rand_core::OsRng; use serde::Deserialize; use crate::{ - api::response::Response, internalError, mail::{ + api_wrapper::utils::TextResponse, error::Error, mail::{ mailing::{build_mail, send_mail}, utils::{load_template, Mailer} }, models::{ links_model::{Link, LinkType}, model::{DBConnection, CRUD}, user_model::{User, UserCreate} - }, prelude::Error, utils::password::valid_password + }, utils::password::valid_password }; #[derive(Deserialize)] @@ -27,12 +27,12 @@ pub async fn register_post( data: web::Json<RegisterData>, db: web::Data<DBConnection>, request: HttpRequest, mailer: web::Data<Mailer>, ) -> Result<impl Responder> { if data.email.clone().parse::<Address>().is_err() { - return Ok(Response::new_error(400, "Not a valid email address".into()).into()); + return Err(error::ErrorUnprocessableEntity( "Not a valid email address")); } let pot_user = User::get_from_email(db.clone(), data.email.clone()).await; if pot_user.is_ok() && pot_user.unwrap().is_some() { - return Ok(web::Json(Response::new_error(403, "E-mail already associated to account!".to_string()))); + return Err(error::ErrorForbidden( "E-mail already associated to account!".to_string())); } if let Err(e) = valid_password(&data.password) { return Err(Error::from(e).into()); @@ -45,7 +45,7 @@ pub async fn register_post( Ok(str) => str.to_string(), Err(e) => { error!("Error: Unknown error trying to hash password\n{}", e); - internalError!("Error trying to hash password") + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -68,7 +68,7 @@ pub async fn register_post( Ok(a) => a.construct_link(), Err(e) => { error!("Error creating link\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -76,7 +76,7 @@ pub async fn register_post( Ok(a) => a.replace("${{VERIFY_URL}}", &link), Err(e) => { error!("Error loading template\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -85,19 +85,19 @@ pub async fn register_post( Err(e) => { error!("Error building message\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; if let Err(e) = send_mail(mailer, message).await { error!("Error sending mail\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } if let Err(e) = Identity::login(&request.extensions(), ret_user.id.to_string()) { error!("Error trying to log into Identity\n{}", e); - internalError!("Error trying to log in, please try again") + return Err(error::ErrorInternalServerError("Internal Server Error")); }; - Ok(Response::new_success("Account successfully registered".to_string()).into()) + Ok(web::Json(TextResponse { message: "Account successfully registered".to_string()})) } diff --git a/backend/src/api/resend_mail.rs b/backend/src/api/resend_mail.rs index b2222dc..da71b09 100644 --- a/backend/src/api/resend_mail.rs +++ b/backend/src/api/resend_mail.rs @@ -1,13 +1,12 @@ use actix_identity::Identity; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use chrono::{Months, Utc}; use lettre::message::header::ContentType; use log::error; use surrealdb::sql::Thing; -use super::response::Response; use crate::{ - internalError, mail::{ + api_wrapper::utils::TextResponse, mail::{ mailing::{build_mail, send_mail}, utils::{load_template, Mailer} }, models::{ links_model::{Link, LinkType}, model::{ConnectionData, CRUD}, user_model::User @@ -19,7 +18,7 @@ pub async fn resend_mail_get( db: ConnectionData, mailer: web::Data<Mailer>, id: Option<Identity>, ) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in".to_string()))); + return Err(error::ErrorForbidden( "Not logged in".to_string())); } let id = id.unwrap(); @@ -27,7 +26,7 @@ pub async fn resend_mail_get( Ok(a) => Thing::from(a.split_once(':').unwrap()), Err(e) => { error!("Error trying to get id\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -36,22 +35,22 @@ pub async fn resend_mail_get( Some(a) => a, None => { error!("User not found?"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }, Err(e) => { error!("Error trying to get user\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; if user.clone().verified { - return Ok(web::Json(Response::new_error(400, "You're already verified".to_string()))); + return Err(error::ErrorUnprocessableEntity( "You're already verified".to_string())); } if let Err(e) = Link::delete_from_user_type(db.clone(), user.clone(), LinkType::VerifyAccount).await { error!("Error deleting verification links\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } let expiry_time = Utc::now().checked_add_months(Months::new(1)).unwrap(); @@ -60,7 +59,7 @@ pub async fn resend_mail_get( Ok(a) => a.construct_link(), Err(e) => { error!("Error creating link\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -68,7 +67,7 @@ pub async fn resend_mail_get( Ok(a) => a.replace("${{VERIFY_URL}}", &link), Err(e) => { error!("Error loading template\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -76,14 +75,14 @@ pub async fn resend_mail_get( Ok(a) => a, Err(e) => { error!("Error building message\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; if let Err(e) = send_mail(mailer, message).await { error!("Error sending mail\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } - Ok(web::Json(Response::new_success("Sent E-Mail, check your inbox".to_string()))) + Ok(web::Json(TextResponse { message: "Sent E-Mail, check your inbox".to_string()})) } diff --git a/backend/src/api/response.rs b/backend/src/api/response.rs deleted file mode 100644 index c735cc1..0000000 --- a/backend/src/api/response.rs +++ /dev/null @@ -1,65 +0,0 @@ -use actix_web::{web::Json, ResponseError as actixResponseError}; -use serde::Serialize; - -use crate::prelude::Error; - -#[derive(Serialize)] -pub struct Response<T> { - pub success: bool, - pub body: ResponseResult<T>, -} - -impl<ResponseError> Response<ResponseError> { - pub fn new_error(code: u16, message: String) -> Self { - Self { - success: false, - body: ResponseResult::Err(crate::api::response::ResponseError { code, message }), - } - } -} - -impl<ResponseError> From<Error> for Response<ResponseError> { - fn from(value: Error) -> Self { - Response { - success: false, - body: ResponseResult::Err(value.into()), - } - } -} - -impl<T> Response<T> { - pub fn new_success(body: T) -> Self { - Self { - success: true, - body: ResponseResult::Ok(body), - } - } -} - -impl<T> From<Response<T>> for Json<Response<T>> { - fn from(val: Response<T>) -> Self { - Json(val) - } -} - -#[derive(Serialize)] -#[serde(untagged)] -pub enum ResponseResult<T> { - Ok(T), - Err(ResponseError), -} - -#[derive(Serialize)] -pub struct ResponseError { - code: u16, - message: String, -} - -impl From<Error> for ResponseError { - fn from(value: Error) -> Self { - Self { - code: value.status_code().into(), - message: value.to_string(), - } - } -} diff --git a/backend/src/api/verified.rs b/backend/src/api/verified.rs index dd46981..8868030 100644 --- a/backend/src/api/verified.rs +++ b/backend/src/api/verified.rs @@ -1,25 +1,22 @@ use actix_identity::Identity; -use actix_web::{web, Responder, Result}; +use actix_web::{error, web, Responder, Result}; use log::error; use surrealdb::sql::Thing; -use super::response::Response; -use crate::{ - internalError, models::{ +use crate::models::{ model::{ConnectionData, CRUD}, user_model::User - } -}; + }; pub async fn verified_get(id: Option<Identity>, db: ConnectionData) -> Result<impl Responder> { if id.is_none() { - return Ok(web::Json(Response::new_error(403, "Not logged in!".to_string()))); + return Err(error::ErrorForbidden( "Not logged in!".to_string())); } let id = match id.unwrap().id() { Ok(a) => Thing::from(a.split_once(':').unwrap()), Err(e) => { error!("Error getting id.id()\n{e}"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; @@ -28,14 +25,14 @@ pub async fn verified_get(id: Option<Identity>, db: ConnectionData) -> Result<im Some(a) => a, None => { error!("User not found?"); - internalError!() + return Err(error::ErrorInternalServerError("Internal Server Error")); } }, Err(e) => { error!("Error getting user from id\n{e}"); - internalError!("There was a database error") + return Err(error::ErrorInternalServerError("Internal Server Error")); } }; - Ok(web::Json(Response::new_success(user.verified))) + Ok(web::Json(user.verified)) } diff --git a/backend/src/api_wrapper/untis_client.rs b/backend/src/api_wrapper/untis_client.rs index 8b1bc52..111ea46 100644 --- a/backend/src/api_wrapper/untis_client.rs +++ b/backend/src/api_wrapper/untis_client.rs @@ -10,7 +10,7 @@ use super::utils::{ self, day_of_week, DetailedSubject, FormattedFreeRoom, FormattedLesson, Holidays, Klasse, LoginResults, PeriodObject, Schoolyear, Substitution, TimegridUnits, TimetableParameter, UntisArrayResponse }; use crate::{ - api_wrapper::utils::UntisResponse, models::{manual_lb_model::ManualLB, model::DBConnection, room_model::Room, teacher_model::Teacher}, prelude::Error + api_wrapper::utils::UntisResponse, models::{manual_lb_model::ManualLB, model::DBConnection, room_model::Room, teacher_model::Teacher}, error::Error }; #[derive(Clone)] @@ -684,7 +684,7 @@ impl UntisClient { Ok(every_lb) } - /// . + /// fn manual_overwrite_lbs(lb: &FormattedLesson) -> bool { matches! ( (lb.day, lb.start, lb.teacher.as_str()), diff --git a/backend/src/api_wrapper/utils.rs b/backend/src/api_wrapper/utils.rs index c0a6c37..0c46499 100644 --- a/backend/src/api_wrapper/utils.rs +++ b/backend/src/api_wrapper/utils.rs @@ -328,3 +328,8 @@ pub fn day_of_week(date: u32) -> u8 { let h = (d + (13 * (m + 1)) / 5 + k + k / 4 + j / 4 + 5 * j) % 7; ((h + 5) % 7) as u8 } + +#[derive(Serialize)] +pub struct TextResponse { + pub message: String +} \ No newline at end of file diff --git a/backend/src/database/sessions.rs b/backend/src/database/sessions.rs index 0780f69..71ae787 100644 --- a/backend/src/database/sessions.rs +++ b/backend/src/database/sessions.rs @@ -1,4 +1,4 @@ -use crate::{models::model::ConnectionData, prelude::Error}; +use crate::{models::model::ConnectionData, error::Error}; // This is very hacky but it works /// NEXER EXPOSE THIS FUNCTION TO USER INPUT, IT WILL ALLOW THEM TO SQL INJECT diff --git a/backend/src/mail/mailing.rs b/backend/src/mail/mailing.rs index 4e1395e..6dca44a 100644 --- a/backend/src/mail/mailing.rs +++ b/backend/src/mail/mailing.rs @@ -3,7 +3,7 @@ use lettre::{ }; use super::{error::MailError, utils::Mailer}; -use crate::prelude::Error; +use crate::error::Error; pub fn build_mail<T>(to: &str, subject: &str, content_type: ContentType, body: T) -> Result<Message, Error> where diff --git a/backend/src/main.rs b/backend/src/main.rs index 9833e4d..7392f18 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -7,7 +7,6 @@ mod error; mod governor; mod mail; mod models; -mod prelude; mod utils; use std::{ @@ -26,7 +25,7 @@ use actix_web::{ cookie::{time::Duration, Key}, middleware::Logger, middleware::Compress, web::{self, Data}, App, HttpResponse, HttpServer }; use api::{ - change_email::change_email_get, get_free_rooms::get_free_rooms, get_timetable_serviceworker::get_timetable_serviceworker, change_password::change_password_post, change_untis_data::change_untis_data_post, check_session::check_session_get, delete::delete_post, forgot_password::forgot_password_post, gdpr_data_compliance::gdpr_data_compliance_get, get_lernbueros::get_lernbueros, get_timetable::get_timetable, link::{ + change_email::change_email_get, get_free_rooms::get_free_rooms, /* get_timetable_serviceworker::get_timetable_serviceworker ,*/ change_password::change_password_post, change_untis_data::change_untis_data_post, check_session::check_session_get, delete::delete_post, forgot_password::forgot_password_post, gdpr_data_compliance::gdpr_data_compliance_get, get_lernbueros::get_lernbueros, get_timetable::get_timetable, link::{ check_uuid::check_uuid_get, email_change::email_change_post, email_reset::email_reset_post, password::reset_password_post, verify::verify_get }, login::login_post, logout::logout_post, logout_all::logout_all_post, register::register_post, resend_mail::resend_mail_get, verified::verified_get }; @@ -160,7 +159,7 @@ async fn main() -> io::Result<()> { #[cfg(feature = "proxy")] let governor_config = GovernorConfigBuilder::default() .key_extractor(NginxIpKeyExctrator) - .per_second(10) + .seconds_per_request(10) .burst_size(20) .use_headers() .finish() @@ -207,7 +206,7 @@ async fn main() -> io::Result<()> { .service(web::resource("/delete").route(web::post().to(delete_post))) .service(web::resource("/check_session").route(web::get().to(check_session_get))) .service(web::resource("/get_timetable").route(web::get().to(get_timetable))) - .service(web::resource("/get_timetable_serviceworker").route(web::post().to(get_timetable_serviceworker))) + //.service(web::resource("/get_timetable_serviceworker").route(web::post().to(get_timetable_serviceworker))) .service(web::resource("/get_lernbueros").route(web::get().to(get_lernbueros))) .service(web::resource("/get_free_rooms").route(web::get().to(get_free_rooms))) .service(web::resource("/change_email").route(web::get().to(change_email_get))) diff --git a/backend/src/models/links_model.rs b/backend/src/models/links_model.rs index e619c6d..ee643ac 100644 --- a/backend/src/models/links_model.rs +++ b/backend/src/models/links_model.rs @@ -6,7 +6,7 @@ use surrealdb::sql::{Id, Thing}; use super::{ model::{ConnectionData, DBConnection, CRUD}, user_model::User }; -use crate::{prelude::Error, utils::uuid::random_id}; +use crate::{error::Error, utils::uuid::random_id}; #[derive(Debug, Serialize, Deserialize)] pub struct Link { diff --git a/backend/src/models/manual_lb_model.rs b/backend/src/models/manual_lb_model.rs index e4f164d..f4a7d88 100644 --- a/backend/src/models/manual_lb_model.rs +++ b/backend/src/models/manual_lb_model.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use surrealdb::sql::Thing; -use crate::prelude::Error; +use crate::error::Error; use super::model::{ConnectionData, DBConnection, CRUD}; diff --git a/backend/src/models/model.rs b/backend/src/models/model.rs index c8cb917..083d962 100644 --- a/backend/src/models/model.rs +++ b/backend/src/models/model.rs @@ -2,7 +2,7 @@ use async_trait::async_trait; use serde::{Deserialize, Serialize}; use surrealdb::{engine::remote::ws::Client, sql::Thing, Surreal}; -use crate::prelude::Error; +use crate::error::Error; pub type DBConnection = Surreal<Client>; pub type ConnectionData = actix_web::web::Data<DBConnection>; diff --git a/backend/src/models/room_model.rs b/backend/src/models/room_model.rs index 0dcfd5e..78dc92f 100644 --- a/backend/src/models/room_model.rs +++ b/backend/src/models/room_model.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use surrealdb::sql::Thing; use super::model::{ConnectionData, DBConnection, CRUD}; -use crate::prelude::Error; +use crate::error::Error; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Room { diff --git a/backend/src/models/sessions_model.rs b/backend/src/models/sessions_model.rs index 2d07ad1..93d369b 100644 --- a/backend/src/models/sessions_model.rs +++ b/backend/src/models/sessions_model.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use surrealdb::sql::{Datetime, Thing}; use super::model::ConnectionData; -use crate::prelude::Error; +use crate::error::Error; #[derive(Debug, Serialize, Deserialize)] diff --git a/backend/src/models/teacher_model.rs b/backend/src/models/teacher_model.rs index 9b1b510..f451aae 100644 --- a/backend/src/models/teacher_model.rs +++ b/backend/src/models/teacher_model.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use surrealdb::sql::{Array, Thing}; use super::model::{ConnectionData, DBConnection, CRUD}; -use crate::prelude::Error; +use crate::error::Error; #[derive(Debug, Serialize, Deserialize)] pub struct Teacher { diff --git a/backend/src/models/user_model.rs b/backend/src/models/user_model.rs index 4b000aa..4647fb9 100644 --- a/backend/src/models/user_model.rs +++ b/backend/src/models/user_model.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use surrealdb::sql::Thing; use super::model::{ConnectionData, DBConnection, CRUD}; -use crate::prelude::Error; +use crate::error::Error; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct User { diff --git a/backend/src/prelude.rs b/backend/src/prelude.rs deleted file mode 100644 index 52f1303..0000000 --- a/backend/src/prelude.rs +++ /dev/null @@ -1,22 +0,0 @@ -pub use crate::error::Error; - -/// Macro that returns a 500 Internal Server Error JSON Response -/// Can take a string literal as an argument to change the error message -/// -/// ## Usage -/// ```no_run -/// internalError!() // Returns a "Internal Server Error" with code 500 -/// internalError!("Database Error") // Returns a "Database Error" with code 500 -/// ``` -#[macro_export] -macro_rules! internalError { - ($l:literal) => {{ - return Ok(actix_web::web::Json($crate::api::response::Response::new_error(500, $l.to_string()))); - }}; - () => {{ - return Ok(actix_web::web::Json($crate::api::response::Response::new_error( - 500, - "Internal Server Error".to_string(), - ))); - }}; -} diff --git a/frontend/compileServiceWorker.ts b/frontend/compileServiceWorker.ts index 00fe797..a09f71f 100644 --- a/frontend/compileServiceWorker.ts +++ b/frontend/compileServiceWorker.ts @@ -1,7 +1,6 @@ import { rollup, InputOptions, OutputOptions } from "rollup"; import typescript from "@rollup/plugin-typescript"; -import terser from "@rollup/plugin-terser" - +import terser from "@rollup/plugin-terser"; const compileServiceWorker = () => ({ name: "compile-typescript-service-worker", @@ -17,7 +16,7 @@ const compileServiceWorker = () => ({ }; const bundle = await rollup(inputOptions); await bundle.write(outputOptions); - await bundle.close() + await bundle.close(); } }); -export default compileServiceWorker \ No newline at end of file +export default compileServiceWorker; diff --git a/frontend/public/manifest.webmanifest b/frontend/public/manifest.webmanifest index 3f5053f..efb7e8b 100644 --- a/frontend/public/manifest.webmanifest +++ b/frontend/public/manifest.webmanifest @@ -8,7 +8,6 @@ "background_color": "#24273a", "theme_color": "#24273a", - "icons": [ { "src": "/AppImages/windows11/SmallTile.scale-100.png", @@ -459,4 +458,4 @@ "sizes": "1024x1024" } ] -} \ No newline at end of file +} diff --git a/frontend/src/api/dateHandling.ts b/frontend/src/api/dateHandling.ts index d084841..563c84c 100644 --- a/frontend/src/api/dateHandling.ts +++ b/frontend/src/api/dateHandling.ts @@ -1,8 +1,8 @@ -export function getMondayAndFridayDates(strMonday? : string): { currentMonday: string; currentFriday: string } { +export function getMondayAndFridayDates(strMonday?: string): { currentMonday: string; currentFriday: string } { let now = new Date(); let currentDayOfWeek = now.getDay(); // 0 = Sunday, 1 = Monday, ..., 6 = Saturday - if(strMonday){ + if (strMonday) { currentDayOfWeek = 0; now = createDate(strMonday); } diff --git a/frontend/src/api/frontmatter.ts b/frontend/src/api/frontmatter.ts index 183fd67..127c1aa 100644 --- a/frontend/src/api/frontmatter.ts +++ b/frontend/src/api/frontmatter.ts @@ -12,6 +12,9 @@ class Request { credentials: "include", body: JSON.stringify(data) }); + if (!result.ok) { + return Promise.reject(result.status); + } if (!result.body) { return Promise.reject({ status: 500, message: "Server Connection Failed" }); } @@ -20,10 +23,7 @@ class Request { } let stream = await Request.readStream(result.body); let body = JSON.parse(stream); - if (!body.success) { - return Promise.reject(body.body); - } - return body.body; + return body; } catch (error) { return Promise.reject(error); } @@ -36,14 +36,13 @@ class Request { method: "GET", credentials: "include" }); + if (!result.ok) { + return Promise.reject(result.status); + } if (result.status == 429) { return Promise.reject(new Error("Too many requests. Try again later")); } - const body = await result.json(); - if (!body.success) { - return Promise.reject(body.body); - } - return body.body; + return result.body; } catch (error) { return Promise.reject(error); } @@ -65,6 +64,7 @@ class Request { export async function checkSessionIdAstro(id: string): Promise<any> { try { let result = await Request.Get("check_session", { Cookie: `id=${id}` }); + console.log(result); return result; } catch (error) { return Promise.reject(error); diff --git a/frontend/src/api/main.ts b/frontend/src/api/main.ts index d8606ee..ce55f38 100644 --- a/frontend/src/api/main.ts +++ b/frontend/src/api/main.ts @@ -15,10 +15,10 @@ export interface TheScheduleObject { } | null; } export interface FreeRoom { - start: number, - length: number, - day: number, - room: string + start: number; + length: number; + day: number; + room: string; } export const SubjectColor: { [key: string]: string } = { M: "#dba402", @@ -68,26 +68,25 @@ export function JSESSIONIDCookieString(JSESSIONID: string): string { return `JSESSIONID=${JSESSIONID}; max-age=600; secure; samesite=none; domain=${import.meta.env.PUBLIC_COOKIE_DOMAIN}`; } export async function getCommitHash(): Promise<string> { - const result = await fetch("https://api.github.com/repos/ixhbinphoenix/bne/commits/master", { + const result = (await fetch("https://api.github.com/repos/ixhbinphoenix/bne/commits/master", { method: "GET" - }) as unknown as Array<any> + })) as unknown as Array<any>; try { - return JSON.parse(await readStream(result.body)).sha.substring(0, 7) - } - catch (error) { - return Promise.reject(error) + return JSON.parse(await readStream(result.body)).sha.substring(0, 7); + } catch (error) { + return Promise.reject(error); } } async function readStream(stream: ReadableStream<Uint8Array>) { - const textDecode = new TextDecoder(); - const chunks = []; - const reader = stream.getReader(); - while (true) { - const { done, value } = await reader.read(); - if (done) { - break; - } - chunks.push(textDecode.decode(value)); + const textDecode = new TextDecoder(); + const chunks = []; + const reader = stream.getReader(); + while (true) { + const { done, value } = await reader.read(); + if (done) { + break; } - return chunks.join(""); + chunks.push(textDecode.decode(value)); + } + return chunks.join(""); } diff --git a/frontend/src/api/theBackend.ts b/frontend/src/api/theBackend.ts index 93ac9a6..3a1a1c3 100644 --- a/frontend/src/api/theBackend.ts +++ b/frontend/src/api/theBackend.ts @@ -15,18 +15,16 @@ class Request { credentials: "include", body: JSON.stringify(data) }); + if (!result.ok) { + return Promise.reject({ status: result.status, message: await result.text() }); + } if (!result.body) { return Promise.reject({ status: 500, message: "Server Connection Failed" }); } if (result.status == 429) { return Promise.reject(new Error("Too many requests. Try again later")); } - let stream = await Request.readStream(result.body); - let body = JSON.parse(stream); - if (!body.success) { - return Promise.reject(body.body); - } - return body.body; + return result.json(); } catch (error) { return Promise.reject(error); } @@ -42,11 +40,10 @@ class Request { if (result.status == 429) { return Promise.reject(new Error("Too many requests. Try again later")); } - const body = await result.json(); - if (!body.success) { - return Promise.reject(body.body); + if (result.headers.get("Content-Type") === "application/json") { + return await result.json(); } - return body.body; + return await result.text(); } catch (error) { return Promise.reject(error); } @@ -104,7 +101,7 @@ export async function getTimetable(monday: string, friday: string, className?: s const untisCredentials = getLocalUntisCredentials(); if (!storedJSessionId && getLocalUntisCredentials()) { const result = await fetchJSessionId(untisCredentials.username, untisCredentials.password); - document.cookie = JSESSIONIDCookieString(result.JSessionId) + document.cookie = JSESSIONIDCookieString(result.JSessionId); body = await Request.Get<{ lessons: TheScheduleObject[] }>("get_timetable" + searchQuery); } else { body = await Request.Get<{ lessons: TheScheduleObject[] }>("get_timetable" + searchQuery); @@ -114,7 +111,12 @@ export async function getTimetable(monday: string, friday: string, className?: s return Promise.reject(error); } } -export async function getTimetableServiceWorker(monday: string, friday: string, JSessionId: string, className?: string): Promise<TheScheduleObject[]> { +export async function getTimetableServiceWorker( + monday: string, + friday: string, + JSessionId: string, + className?: string +): Promise<TheScheduleObject[]> { try { let body: { lessons: TheScheduleObject[] }; let searchQuery = `?from=${monday}&until=${friday}`; diff --git a/frontend/src/components/RegisterForm.tsx b/frontend/src/components/RegisterForm.tsx index 7e07f31..f0f3b6d 100644 --- a/frontend/src/components/RegisterForm.tsx +++ b/frontend/src/components/RegisterForm.tsx @@ -20,7 +20,7 @@ export default function LoginForm(): JSX.Element { fetchJSessionId(event.target[3].value, event.target[4].value).then( (result) => { if (result.JSessionId && result.personId) { - document.cookie = JSESSIONIDCookieString(result.JSessionId); + document.cookie = JSESSIONIDCookieString(result.JSessionId); sendRegister( event.target[0].value, event.target[1].value, @@ -117,8 +117,17 @@ export default function LoginForm(): JSX.Element { required /> <div class="checkbox-div"> - <input type="checkbox" id="checkbox" required/> - <label htmlFor="checkbox">Ich akzeptiere die <a href="/datenschutz" style="color: var(--highlight-blue);">Datenschutzbestimmung</a> und <a href="/nutzungsbedingungen" style="color: var(--highlight-blue);">Nutzungsbedingungen</a></label> + <input type="checkbox" id="checkbox" required /> + <label htmlFor="checkbox"> + Ich akzeptiere die{" "} + <a href="/datenschutz" style="color: var(--highlight-blue);"> + Datenschutzbestimmung + </a>{" "} + und{" "} + <a href="/nutzungsbedingungen" style="color: var(--highlight-blue);"> + Nutzungsbedingungen + </a> + </label> </div> <div className="button-container"> <input type="submit" id="submit-button" value="Absenden" /> diff --git a/frontend/src/components/plan-components/FreeRooms.tsx b/frontend/src/components/plan-components/FreeRooms.tsx index ea10c3b..320854a 100644 --- a/frontend/src/components/plan-components/FreeRooms.tsx +++ b/frontend/src/components/plan-components/FreeRooms.tsx @@ -2,7 +2,7 @@ import { JSESSIONIDCookieString, type FreeRoom } from "../../api/main"; import { getFreeRooms } from "../../api/theBackend"; -import Loading from "../Loading" +import Loading from "../Loading"; import Popup from "./Popup"; import type { JSX } from "preact"; import "../../styles/Stundenplan.scss"; diff --git a/frontend/src/components/plan-components/Lernbueros.tsx b/frontend/src/components/plan-components/Lernbueros.tsx index 8a30937..1bf6c5d 100644 --- a/frontend/src/components/plan-components/Lernbueros.tsx +++ b/frontend/src/components/plan-components/Lernbueros.tsx @@ -107,11 +107,10 @@ export default function Lernbueros(): JSX.Element { tableDaysTemp.push(<div className="table-day">{tableElements[i]}</div>); } setTableDays(tableDaysTemp); - } - else { + } else { openPopup(); } - } + }; useEffect(() => { onSwipe(".table-layout", { direction: "left" }, nextWeek); @@ -304,21 +303,22 @@ export default function Lernbueros(): JSX.Element { const FilterItems = []; for (const item in SubjectNames) { if (item != "SP") { - FilterItems.push( - <label htmlFor={item}> - {SubjectNames[item]} - <input - type="checkbox" - id={item} - defaultChecked={filterItems[item]} - onClick={() => { - filterItems[item] = !filterItems[item]; - changeFilter(filterItems); - }} - /> - <span className="checkbox"></span> - </label> - );} + FilterItems.push( + <label htmlFor={item}> + {SubjectNames[item]} + <input + type="checkbox" + id={item} + defaultChecked={filterItems[item]} + onClick={() => { + filterItems[item] = !filterItems[item]; + changeFilter(filterItems); + }} + /> + <span className="checkbox"></span> + </label> + ); + } } setFilterContent( <div class="filter-background"> @@ -421,7 +421,7 @@ export default function Lernbueros(): JSX.Element { } if (lessons[k].substitution?.cancelled) { roomStyle = { textDecoration: "line-through" }; - teacherStyle = { textDecoration: "line-through"}; + teacherStyle = { textDecoration: "line-through" }; } if (lessons[k].substitution?.substitution_text) { substitutionTextStyle = { display: "block" }; diff --git a/frontend/src/components/plan-components/Settings.tsx b/frontend/src/components/plan-components/Settings.tsx index fa1aab5..081ada0 100644 --- a/frontend/src/components/plan-components/Settings.tsx +++ b/frontend/src/components/plan-components/Settings.tsx @@ -76,11 +76,9 @@ export default function Settings(): JSX.Element { const [pageContent, setPageContent] = useState<JSX.Element>(Menu); const [username, setUsername] = useState(""); useEffect(() => { - getCommitHash().then( - (result) => { - setCommitHash(result) - } - ) + getCommitHash().then((result) => { + setCommitHash(result); + }); showNotVerifiedMessage(); const usernameRaw = localStorage.getItem("untis_username"); const nameParts = usernameRaw?.split("_"); diff --git a/frontend/src/components/plan-components/Stundenplan.tsx b/frontend/src/components/plan-components/Stundenplan.tsx index 72f8a8a..022f8e3 100644 --- a/frontend/src/components/plan-components/Stundenplan.tsx +++ b/frontend/src/components/plan-components/Stundenplan.tsx @@ -59,7 +59,7 @@ export default function Stundenplan(): JSX.Element { if (error.message == "Untis done fucked up Fetching from Untis failed") { fetchJSessionId(getLocalUntisCredentials().username, getLocalUntisCredentials().password).then((result) => { if (result.JSessionId) { - closePopup() + closePopup(); document.cookie = JSESSIONIDCookieString(result.JSessionId); getTimetable(currentWeek.currentMonday, currentWeek.currentFriday).then( (lessons) => { @@ -196,7 +196,7 @@ export default function Stundenplan(): JSX.Element { if (error.message == "Untis done fucked up Fetching from Untis failed") { fetchJSessionId(getLocalUntisCredentials().username, getLocalUntisCredentials().password).then((result) => { if (result.JSessionId) { - document.cookie = JSESSIONIDCookieString(result.JSessionId) + document.cookie = JSESSIONIDCookieString(result.JSessionId); previousWeek(); } }); diff --git a/frontend/src/components/plan-components/settings-components/ChangeEmail.tsx b/frontend/src/components/plan-components/settings-components/ChangeEmail.tsx index 6616030..e58d054 100644 --- a/frontend/src/components/plan-components/settings-components/ChangeEmail.tsx +++ b/frontend/src/components/plan-components/settings-components/ChangeEmail.tsx @@ -17,6 +17,7 @@ export default function ChangeEmail(props: IProps): JSX.Element { setErrorMessage(<p>Deine E-Mail-Adresse wurde geändert</p>); }, (error) => { + console.log(error); setErrorMessage(<p>Etwas ist schief gegangen: {error.message}</p>); } ); diff --git a/frontend/src/components/plan-components/settings-components/DeleteAccount.tsx b/frontend/src/components/plan-components/settings-components/DeleteAccount.tsx index 06f2110..1561c50 100644 --- a/frontend/src/components/plan-components/settings-components/DeleteAccount.tsx +++ b/frontend/src/components/plan-components/settings-components/DeleteAccount.tsx @@ -39,4 +39,4 @@ export default function DeleteAccount(): JSX.Element { </div> </div> ); -} \ No newline at end of file +} diff --git a/frontend/src/components/plan-components/settings-components/ResetEmail.tsx b/frontend/src/components/plan-components/settings-components/ResetEmail.tsx index 3597bce..b5db811 100644 --- a/frontend/src/components/plan-components/settings-components/ResetEmail.tsx +++ b/frontend/src/components/plan-components/settings-components/ResetEmail.tsx @@ -17,7 +17,7 @@ export default function ResetEmail(props: IProps): JSX.Element { setErrorMessage(<p>Deine E-Mail-Adresse wurde geändert</p>); }, (error) => { - setErrorMessage(<p>Etwas ist schief gelaufen: {error.message}</p>); + setErrorMessage(<p>Etwas ist schief gelaufen: {error}</p>); } ); }; diff --git a/frontend/src/layouts/PlanLayout.astro b/frontend/src/layouts/PlanLayout.astro index 9df8f5f..f69a971 100644 --- a/frontend/src/layouts/PlanLayout.astro +++ b/frontend/src/layouts/PlanLayout.astro @@ -13,18 +13,16 @@ const { title } = Astro.props; </RootLayout> <script> -import { getLocalUntisCredentials } from "../api/untisAPI"; + import { getLocalUntisCredentials } from "../api/untisAPI"; if ("serviceWorker" in navigator) { - if(Notification.permission == "granted") { - navigator.serviceWorker.register("/serviceWorker.js", { scope: "/home" }).then((worker) => { - }); + if (Notification.permission == "granted") { + navigator.serviceWorker.register("/serviceWorker.js", { scope: "/home" }).then((worker) => {}); navigator.serviceWorker.ready.then((worker) => { - worker.active?.postMessage(getLocalUntisCredentials()) - }) - } - else { - console.log("permission denied") + worker.active?.postMessage(getLocalUntisCredentials()); + }); + } else { + console.log("permission denied"); } } </script> diff --git a/frontend/src/layouts/RootLayout.astro b/frontend/src/layouts/RootLayout.astro index 61ff714..868e64a 100644 --- a/frontend/src/layouts/RootLayout.astro +++ b/frontend/src/layouts/RootLayout.astro @@ -9,211 +9,211 @@ export interface Props { const { title } = Astro.props; --- -<html lang='de'> +<html lang="de"> <head> - <meta charset='UTF-8' /> + <meta charset="UTF-8" /> <meta - name='description' - content='Mit TheSchedule kannst du deinen Stundenplan individuell anpassen und dir Änderungen übersichtlich anzeigen lassen.' + name="description" + content="Mit TheSchedule kannst du deinen Stundenplan individuell anpassen und dir Änderungen übersichtlich anzeigen lassen." /> - <meta name='apple-mobile-web-app-capable' content='yes' /> - <link rel='apple-touch-icon' href='icons/apple-icon-180.png' /> + <meta name="apple-mobile-web-app-capable" content="yes" /> + <link rel="apple-touch-icon" href="icons/apple-icon-180.png" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2048-2732.png' - media='(prefers-color-scheme: dark) and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2048-2732.png" + media="(prefers-color-scheme: dark) and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2732-2048.png' - media='(prefers-color-scheme: dark) and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2732-2048.png" + media="(prefers-color-scheme: dark) and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1668-2388.png' - media='(prefers-color-scheme: dark) and (device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1668-2388.png" + media="(prefers-color-scheme: dark) and (device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2388-1668.png' - media='(prefers-color-scheme: dark) and (device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2388-1668.png" + media="(prefers-color-scheme: dark) and (device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1536-2048.png' - media='(prefers-color-scheme: dark) and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1536-2048.png" + media="(prefers-color-scheme: dark) and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2048-1536.png' - media='(prefers-color-scheme: dark) and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2048-1536.png" + media="(prefers-color-scheme: dark) and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1488-2266.png' - media='(prefers-color-scheme: dark) and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1488-2266.png" + media="(prefers-color-scheme: dark) and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2266-1488.png' - media='(prefers-color-scheme: dark) and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2266-1488.png" + media="(prefers-color-scheme: dark) and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1640-2360.png' - media='(prefers-color-scheme: dark) and (device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1640-2360.png" + media="(prefers-color-scheme: dark) and (device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2360-1640.png' - media='(prefers-color-scheme: dark) and (device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2360-1640.png" + media="(prefers-color-scheme: dark) and (device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1668-2224.png' - media='(prefers-color-scheme: dark) and (device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1668-2224.png" + media="(prefers-color-scheme: dark) and (device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2224-1668.png' - media='(prefers-color-scheme: dark) and (device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2224-1668.png" + media="(prefers-color-scheme: dark) and (device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1620-2160.png' - media='(prefers-color-scheme: dark) and (device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1620-2160.png" + media="(prefers-color-scheme: dark) and (device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2160-1620.png' - media='(prefers-color-scheme: dark) and (device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2160-1620.png" + media="(prefers-color-scheme: dark) and (device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1290-2796.png' - media='(prefers-color-scheme: dark) and (device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1290-2796.png" + media="(prefers-color-scheme: dark) and (device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2796-1290.png' - media='(prefers-color-scheme: dark) and (device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2796-1290.png" + media="(prefers-color-scheme: dark) and (device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1179-2556.png' - media='(prefers-color-scheme: dark) and (device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1179-2556.png" + media="(prefers-color-scheme: dark) and (device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2556-1179.png' - media='(prefers-color-scheme: dark) and (device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2556-1179.png" + media="(prefers-color-scheme: dark) and (device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1284-2778.png' - media='(prefers-color-scheme: dark) and (device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1284-2778.png" + media="(prefers-color-scheme: dark) and (device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2778-1284.png' - media='(prefers-color-scheme: dark) and (device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2778-1284.png" + media="(prefers-color-scheme: dark) and (device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1170-2532.png' - media='(prefers-color-scheme: dark) and (device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1170-2532.png" + media="(prefers-color-scheme: dark) and (device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2532-1170.png' - media='(prefers-color-scheme: dark) and (device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2532-1170.png" + media="(prefers-color-scheme: dark) and (device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1125-2436.png' - media='(prefers-color-scheme: dark) and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1125-2436.png" + media="(prefers-color-scheme: dark) and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2436-1125.png' - media='(prefers-color-scheme: dark) and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2436-1125.png" + media="(prefers-color-scheme: dark) and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1242-2688.png' - media='(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1242-2688.png" + media="(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2688-1242.png' - media='(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2688-1242.png" + media="(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-828-1792.png' - media='(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-828-1792.png" + media="(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1792-828.png' - media='(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1792-828.png" + media="(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1242-2208.png' - media='(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1242-2208.png" + media="(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-2208-1242.png' - media='(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-2208-1242.png" + media="(prefers-color-scheme: dark) and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-750-1334.png' - media='(prefers-color-scheme: dark) and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-750-1334.png" + media="(prefers-color-scheme: dark) and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1334-750.png' - media='(prefers-color-scheme: dark) and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1334-750.png" + media="(prefers-color-scheme: dark) and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-640-1136.png' - media='(prefers-color-scheme: dark) and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-640-1136.png" + media="(prefers-color-scheme: dark) and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" /> <link - rel='apple-touch-startup-image' - href='AppImages/ios/splash-screens/apple-splash-dark-1136-640.png' - media='(prefers-color-scheme: dark) and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)' + rel="apple-touch-startup-image" + href="AppImages/ios/splash-screens/apple-splash-dark-1136-640.png" + media="(prefers-color-scheme: dark) and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" /> - <link rel='icon' href={favicon} /> - <link rel='manifest' href='/manifest.webmanifest' /> - <meta name='viewport' content='width=device-width, initial-scale=1' /> - <meta name='theme-color' content='#1e2030' /> + <link rel="icon" href={favicon} /> + <link rel="manifest" href="/manifest.webmanifest" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta name="theme-color" content="#1e2030" /> <title>{title}</title> </head> <body> <CookieBanner client:load /> <slot /> </body> - <style is:global> - :root { - --background-color: #24273a; - --text-color: #cad3f5; - --text-gradient: linear-gradient( - 90deg, - rgba(198, 160, 246, 1) 0%, - rgba(237, 135, 150, 1) 50%, - rgba(238, 212, 159, 1) 100% - ); - --highlight-blue: #5974e2; - --highlight-red: #e44040; - } - ::selection { - background: #1a1d2f; - color: #b8c0e0; - } + <style is:global> + :root { + --background-color: #24273a; + --text-color: #cad3f5; + --text-gradient: linear-gradient( + 90deg, + rgba(198, 160, 246, 1) 0%, + rgba(237, 135, 150, 1) 50%, + rgba(238, 212, 159, 1) 100% + ); + --highlight-blue: #5974e2; + --highlight-red: #e44040; + } + ::selection { + background: #1a1d2f; + color: #b8c0e0; + } </style> </html> diff --git a/frontend/src/pwa/cachingStrategies.ts b/frontend/src/pwa/cachingStrategies.ts index 2fa4f76..a1a1699 100644 --- a/frontend/src/pwa/cachingStrategies.ts +++ b/frontend/src/pwa/cachingStrategies.ts @@ -19,8 +19,10 @@ export class Strategies { return ( response || fetch(event.request).then(async (response): Promise<Response> => { - const cache = await caches.open(cacheName); - cache.put(event.request, response.clone()); + if (response.ok) { + const cache = await caches.open(cacheName); + cache.put(event.request, response.clone()); + } return response; }) ); @@ -40,8 +42,10 @@ export class Strategies { public static async StaleWhileRevalidate(event: FetchEvent, cacheName: string = "generic"): Promise<Response> { return caches.match(event.request).then((cacheResponse: Response | undefined) => { let fetchResponse = fetch(event.request).then(async (response): Promise<Response> => { - const cache = await caches.open(cacheName); - cache.put(event.request, response.clone()); + if (response.ok) { + const cache = await caches.open(cacheName); + cache.put(event.request, response.clone()); + } return response; }); return cacheResponse || fetchResponse || this.ErrorMessage(); diff --git a/frontend/src/pwa/serviceWorker.ts b/frontend/src/pwa/serviceWorker.ts index e8a738d..b3ffa93 100644 --- a/frontend/src/pwa/serviceWorker.ts +++ b/frontend/src/pwa/serviceWorker.ts @@ -2,12 +2,11 @@ * @author Sxyntheon * * @description Service Worker for enabling offline experience with TheSchedule -**/ -import { Strategies } from "./cachingStrategies" + **/ +import { Strategies } from "./cachingStrategies"; const cache: string = "v1"; - async function cacheFonts(event: FetchEvent): Promise<Response> { return Strategies.CacheFirst(event); } @@ -18,7 +17,7 @@ async function cacheScripts(event: FetchEvent): Promise<Response> { return Strategies.CacheFirst(event); } async function cacheComponents(event: FetchEvent): Promise<Response> { - return Strategies.StaleWhileRevalidate(event) + return Strategies.StaleWhileRevalidate(event); } async function handleFetch(event: FetchEvent): Promise<Response> { const url = new URL(event.request.url); @@ -26,23 +25,23 @@ async function handleFetch(event: FetchEvent): Promise<Response> { const backend_url = "https://api.theschedule.de"; const untis_domain = "https://borys.webuntis.com"; if (url.href.startsWith(untis_domain) || event.request.method != "GET") { - return Strategies.NetworkOnly(event) + return Strategies.NetworkOnly(event); } if (url.href.startsWith(backend_url)) { - console.log(url, " is blacklisted") + console.log(url, " is blacklisted"); switch (url.pathname) { case "/get_timetable": - console.log("Timetable is network first") - return Strategies.StaleWhileRevalidate(event) + console.log("Timetable is network first"); + return Strategies.StaleWhileRevalidate(event); case "/get_lernbueros": - console.log("LBs is Cache first") - return Strategies.StaleWhileRevalidate(event) + console.log("LBs is Cache first"); + return Strategies.StaleWhileRevalidate(event); case "/get_free_rooms": - console.log("Free Rooms is Cache first") - return Strategies.StaleWhileRevalidate(event) + console.log("Free Rooms is Cache first"); + return Strategies.StaleWhileRevalidate(event); } - return Strategies.NetworkOnly(event) + return Strategies.NetworkOnly(event); } if (!fileExtension) { return Strategies.NetworkRevalidateAndCache(event); @@ -54,21 +53,21 @@ async function handleFetch(event: FetchEvent): Promise<Response> { return cacheFonts(event); case ".css": console.log(url); - console.count("css from cache") + console.count("css from cache"); return cacheStyles(event); case ".js": - console.log(url) - console.count("Script from Cache") - return cacheScripts(event) + console.log(url); + console.count("Script from Cache"); + return cacheScripts(event); case ".svg": - return cacheStyles(event) + return cacheStyles(event); default: console.log(url); - console.count("default caching") + console.count("default caching"); return Strategies.NetworkOnly(event); } } } self.addEventListener("fetch", (event: FetchEvent) => { event.respondWith(handleFetch(event)); -}); \ No newline at end of file +}); diff --git a/frontend/src/styles/Stundenplan.scss b/frontend/src/styles/Stundenplan.scss index 57c35b6..e7daa40 100644 --- a/frontend/src/styles/Stundenplan.scss +++ b/frontend/src/styles/Stundenplan.scss @@ -58,7 +58,6 @@ font-size: clamp(0rem, 100%, 2vh); } & > select option { - background-color: #24273a; } }