2023-04-03 16:11:26 +02:00
use rocket ::{
form ::Form ,
2023-04-03 17:32:41 +02:00
get ,
http ::{ Cookie , CookieJar } ,
post ,
2023-04-03 16:11:26 +02:00
request ::FlashMessage ,
2023-04-03 17:32:41 +02:00
response ::{ Flash , Redirect } ,
2023-06-07 00:07:11 +02:00
routes ,
time ::{ Duration , OffsetDateTime } ,
FromForm , Route , State ,
2023-04-03 16:11:26 +02:00
} ;
2023-04-04 10:44:14 +02:00
use rocket_dyn_templates ::{ context , tera , Template } ;
2023-04-03 17:32:41 +02:00
use serde_json ::json ;
2023-04-03 16:11:26 +02:00
use sqlx ::SqlitePool ;
2023-04-18 12:10:11 +02:00
use crate ::model ::{
log ::Log ,
user ::{ LoginError , User } ,
} ;
2023-04-03 16:11:26 +02:00
#[ get( " / " ) ]
2023-04-04 19:49:27 +02:00
fn index ( flash : Option < FlashMessage < '_ > > ) -> Template {
2023-04-03 16:11:26 +02:00
let mut context = tera ::Context ::new ( ) ;
if let Some ( msg ) = flash {
context . insert ( " flash " , & msg . into_inner ( ) ) ;
}
Template ::render ( " auth/login " , context . into_json ( ) )
}
#[ derive(FromForm) ]
2023-05-24 12:11:55 +02:00
struct LoginForm < ' r > {
name : & ' r str ,
password : & ' r str ,
2023-04-03 16:11:26 +02:00
}
#[ post( " / " , data = " <login> " ) ]
2023-04-03 17:32:41 +02:00
async fn login (
2023-05-24 12:11:55 +02:00
login : Form < LoginForm < '_ > > ,
2023-04-03 17:32:41 +02:00
db : & State < SqlitePool > ,
cookies : & CookieJar < '_ > ,
) -> Flash < Redirect > {
2023-05-24 12:11:55 +02:00
let user = User ::login ( db , login . name , login . password ) . await ;
2023-04-03 16:11:26 +02:00
let user = match user {
Ok ( user ) = > user ,
2023-04-04 10:44:14 +02:00
Err ( LoginError ::NoPasswordSet ( user ) ) = > {
return Flash ::warning (
Redirect ::to ( format! ( " /auth/set-pw/ {} " , user . id ) ) ,
" Setze ein neues Passwort " ,
) ;
}
2023-04-03 16:11:26 +02:00
Err ( _ ) = > {
2023-07-10 17:17:17 +02:00
return Flash ::error ( Redirect ::to ( " /auth " ) , " Falscher Benutzername/Passwort. Du bist Vereinsmitglied und der Login klappt nicht? Kontaktiere Philipp H. (Tel.nr. siehe Signalgruppe) oder schreibe eine Mail an rudern@gmx.at! " ) ;
2023-04-03 16:11:26 +02:00
}
} ;
2023-04-03 17:32:41 +02:00
let user_json : String = format! ( " {} " , json! ( user ) ) ;
2023-04-03 22:03:45 +02:00
cookies . add_private ( Cookie ::new ( " loggedin_user " , user_json ) ) ;
2023-04-03 17:32:41 +02:00
2023-04-03 16:11:26 +02:00
Flash ::success ( Redirect ::to ( " / " ) , " Login erfolgreich " )
}
2023-04-04 10:44:14 +02:00
#[ get( " /set-pw/<userid> " ) ]
2023-04-04 19:49:27 +02:00
fn setpw ( userid : i32 ) -> Template {
2023-04-04 10:44:14 +02:00
Template ::render ( " auth/set-pw " , context! ( userid ) )
}
#[ derive(FromForm) ]
2023-05-24 12:11:55 +02:00
struct UpdatePw < ' r > {
2023-04-04 10:44:14 +02:00
userid : i32 ,
2023-05-24 12:11:55 +02:00
password : & ' r str ,
password_confirm : & ' r str ,
2023-04-04 10:44:14 +02:00
}
#[ post( " /set-pw " , data = " <updatepw> " ) ]
async fn updatepw (
db : & State < SqlitePool > ,
2023-05-24 12:11:55 +02:00
updatepw : Form < UpdatePw < '_ > > ,
2023-04-04 10:44:14 +02:00
cookies : & CookieJar < '_ > ,
) -> Flash < Redirect > {
let user = User ::find_by_id ( db , updatepw . userid ) . await ;
2023-04-10 14:25:31 +02:00
let Some ( user ) = user else {
2023-04-04 10:44:14 +02:00
return Flash ::error (
Redirect ::to ( " /auth " ) ,
format! ( " User with ID {} does not exist! " , updatepw . userid ) ,
)
} ;
if updatepw . password ! = updatepw . password_confirm {
return Flash ::error (
Redirect ::to ( format! ( " /auth/set-pw/ {} " , updatepw . userid ) ) ,
" Passwörter stimmen nicht überein! Bitte probiere es nochmal " ,
) ;
}
2023-05-24 12:11:55 +02:00
user . update_pw ( db , updatepw . password ) . await ;
2023-04-04 10:44:14 +02:00
let user_json : String = format! ( " {} " , json! ( user ) ) ;
2023-06-07 00:07:11 +02:00
let mut cookie = Cookie ::new ( " loggedin_user " , user_json ) ;
cookie . set_expires ( OffsetDateTime ::now_utc ( ) + Duration ::weeks ( 12 ) ) ;
cookies . add_private ( cookie ) ;
2023-04-04 10:44:14 +02:00
2023-04-18 12:10:11 +02:00
Log ::create ( db , format! ( " User {} set her password. " , user . name ) ) . await ;
2023-04-04 10:44:14 +02:00
Flash ::success (
Redirect ::to ( " / " ) ,
" Passwort erfolgreich gesetzt. Du bist nun eingeloggt. " ,
)
}
2023-04-03 22:10:12 +02:00
#[ get( " /logout " ) ]
2023-04-04 19:49:27 +02:00
fn logout ( cookies : & CookieJar < '_ > , _user : User ) -> Flash < Redirect > {
2023-04-03 22:10:12 +02:00
cookies . remove_private ( Cookie ::named ( " loggedin_user " ) ) ;
Flash ::success ( Redirect ::to ( " /auth " ) , " Logout erfolgreich " )
}
2023-04-03 16:11:26 +02:00
pub fn routes ( ) -> Vec < Route > {
2023-04-04 10:44:14 +02:00
routes! [ index , login , logout , setpw , updatepw ]
2023-04-03 16:11:26 +02:00
}