RJ75MX6YMJSXYKW2YK6ZJNG2SQMPCPKICMESMC4ZD4EB2SCVJ2KAC F5DMFQAO2IVQXQQ36Z5FRW5WNXKNTY2NAWMRR3VXIOWTPJ5UUDVAC W3M3C7CCWHJWRWHULDWO45D3OFD4NL3V4OTJVIJCYRQG57Z2JTWQC 5UNA2DEALCSRBINR27KSA6OMD6GQAXHYZ35ICQ7NB62G2XP4FT5QC DSWQKJRHGLKXUDXKMRXCIQZKEGXYV3H5LPUMGSV4HQ4HYPTI47GQC KULVODXDL6KFQDLXYAAM3YPYNUMTRWV3LP6NRTYUHU7XBM2OKYZAC T7TT5B4G3RBWVEG3BK6TPZQJJ3PSBBUZZCNBUM5KWYPVVPJ2VKAAC KFVJ3KMWXEGILN4NWIWPPX7AU65M4H4UEAUIAQL2QSXOW3B5RFGQC FS2NWBVN2SZB2FFPB3JSYT5URTVZEAZWMQ7QW4JUYPNJVDVAJTTQC 3E77DEMDLYBFJEGS2SLQKLQJQIXG2Y4TBDHAG3UKFLMKQ53CFOKQC S6TFYMRGWC4PSRLQ4OAKE2Z3JFEVGF3RZ5Z3MEN5XSA4INPQILOAC use rocket::{form::{Context, Form},response::{Flash, Redirect},};use rocket_dyn_templates::Template;use crate::database::Database;fn new() -> Template {Template::render("new_user", &Context::default())}#[derive(FromForm)]struct NewUser {// TODO validate against regexp: [a-z_][a-z0-9_-]*[$] - Needs a valid linux username#[field(validate = len(..20))]pub user_name: String,#[field(validate = len(3..))]pub email: String,#[field(validate = len(6..64))]pub password: String,}#[post("/", data = "<user>")]async fn create(db: &State<Database>,cookie: &CookieJar<'_>,user: Form<NewUser>,) -> Result<Flash<Redirect>, Flash<Redirect>> {// TODO When the form parsing fails, the users gets no feedbacklet mut new_user = User {id: -1,name: user.user_name.clone(),email: user.email.clone(),password: user.password.clone(),};match new_user.create(db).await {Ok(id) => {new_user.id = id;set_user_cookie(cookie, new_user);return Ok(Flash::success(Redirect::to("/"), "Signed up succesfully"));}Err(_e) => Err(Flash::error(Redirect::to("/users/new"),"Something went wrong",)), //TODO Show the error to the user in a flash message,}}#[derive(FromForm)]struct SignIn {#[field(validate = len(..20))]pub user_name: String,#[field(validate = len(6..64))]pub password: String,}#[get("/sign_in")]async fn get_sign_in() -> Template {Template::render("sign_in", &Context::default())}#[post("/sign_in", data = "<user>")]async fn sign_in(db: &State<Database>,jar: &CookieJar<'_>,user: Form<SignIn>,) -> Result<Flash<Redirect>, Flash<Redirect>> {// TODO figure out Rust and rewrite this without the nested matchingmatch User::authenticate(db, user.user_name.clone(), user.password.clone()).await {Ok(u) => match u {Some(u2) => {set_user_cookie(jar, u2);return Ok(Flash::success(Redirect::to("/"), "Signed in!"));}None => return Err(Flash::error(Redirect::to("./sign_in"), "Error signing in")),},Err(_e) => {return Err(Flash::error(Redirect::to("./sign_in"),"SQL Error signing in",))}}}static COOKIE_USER_ID_KEY: &str = "user_id";#[get("/sign_out")]fn sign_out(jar: &CookieJar<'_>) -> Flash<Redirect> {jar.remove_private(Cookie::named(COOKIE_USER_ID_KEY));Flash::success(Redirect::to("/"), "Signed out succesfully")}fn set_user_cookie(jar: &CookieJar<'_>, user: User) {jar.add_private(Cookie::new(COOKIE_USER_ID_KEY, user.id.to_string()))}pub fn routes() -> Vec<Route> {}routes![new,new_already_user,create,get_sign_in,sign_in,sign_out]}fn get_user_id_from_cookie(jar: &CookieJar) -> Option<i32> {match jar.get_private(COOKIE_USER_ID_KEY) {Some(id) => Some(id.value().parse::<i32>().ok()?),None => None,}#[get("/new", rank = 1)]fn new_already_user(_user: User) -> Redirect {Redirect::to("/")}// TODO decide if this routing file is the place for this guard to be at?#[rocket::async_trait]impl<'r> FromRequest<'r> for User {type Error = ();async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {let db = try_outcome!(request.guard::<&State<Database>>().await);// &State<Database>>().await);let cookies = request.cookies();let some_id = match get_user_id_from_cookie(cookies) {Some(id) => id,None => return Outcome::Failure((Status::Unauthorized, ())),};match User::find(db, some_id).await {Ok(u) => Outcome::Success(u),Err(_e) => Outcome::Failure((Status::Unauthorized, ())),}}}#[get("/new", rank = 2)]use crate::models::users::User;use rocket::outcome::try_outcome;Request, Route, State,http::{Cookie, CookieJar, Status},request,request::{FromRequest, Outcome},
use rocket::{form::{Context, Form},http::{Cookie, CookieJar, Status},request,request::{FromRequest, Outcome},response::{Flash, Redirect},Request, Route, State,};use rocket_dyn_templates::Template;use crate::database::Database;use crate::models::users::User;use rocket::outcome::try_outcome;// TODO decide if this routing file is the place for this guard to be at?#[rocket::async_trait]impl<'r> FromRequest<'r> for User {type Error = ();async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {let db = try_outcome!(request.guard::<&State<Database>>().await);// &State<Database>>().await);let cookies = request.cookies();let some_id = match get_user_id_from_cookie(cookies) {Some(id) => id,None => return Outcome::Failure((Status::Unauthorized, ())),};match User::find(db, some_id).await {Ok(u) => Outcome::Success(u),Err(_e) => Outcome::Failure((Status::Unauthorized, ())),}}}#[get("/users/new", rank = 2)]fn new() -> Template {Template::render("new_user", &Context::default())}#[get("/users/new", rank = 1)]fn new_already_user(_user: User) -> Redirect {Redirect::to("/")}#[derive(FromForm)]struct NewUser {// TODO validate against regexp: [a-z_][a-z0-9_-]*[$] - Needs a valid linux username#[field(validate = len(..20))]pub user_name: String,#[field(validate = len(3..))]pub email: String,#[field(validate = len(6..64))]pub password: String,}#[post("/users", data = "<user>")]async fn create(db: &State<Database>,cookie: &CookieJar<'_>,user: Form<NewUser>,) -> Result<Flash<Redirect>, Flash<Redirect>> {// TODO When the form parsing fails, the users gets no feedbacklet mut new_user = User {id: -1,name: user.user_name.clone(),email: user.email.clone(),password: user.password.clone(),};match new_user.create(db).await {Ok(id) => {new_user.id = id;set_user_cookie(cookie, new_user);return Ok(Flash::success(Redirect::to("/"), "Signed up succesfully"));}Err(_e) => Err(Flash::error(Redirect::to("/users/new"),"Something went wrong",)), //TODO Show the error to the user in a flash message,}}#[derive(FromForm)]struct SignIn {#[field(validate = len(..20))]pub user_name: String,#[field(validate = len(6..64))]pub password: String,}#[get("/users/sign_in")]async fn get_sign_in() -> Template {Template::render("sign_in", &Context::default())}#[post("/users/sign_in", data = "<user>")]async fn sign_in(db: &State<Database>,jar: &CookieJar<'_>,user: Form<SignIn>,) -> Result<Flash<Redirect>, Flash<Redirect>> {// TODO figure out Rust and rewrite this without the nested matchingmatch User::authenticate(db, user.user_name.clone(), user.password.clone()).await {Ok(u) => match u {Some(u2) => {set_user_cookie(jar, u2);return Ok(Flash::success(Redirect::to("/"), "Signed in!"));}None => return Err(Flash::error(Redirect::to("./sign_in"), "Error signing in")),},Err(_e) => {return Err(Flash::error(Redirect::to("./sign_in"),"SQL Error signing in",))}}}static COOKIE_USER_ID_KEY: &str = "user_id";#[get("/users/sign_out")]fn sign_out(jar: &CookieJar<'_>) -> Flash<Redirect> {jar.remove_private(Cookie::named(COOKIE_USER_ID_KEY));Flash::success(Redirect::to("/"), "Signed out succesfully")}fn set_user_cookie(jar: &CookieJar<'_>, user: User) {jar.add_private(Cookie::new(COOKIE_USER_ID_KEY, user.id.to_string()))}fn get_user_id_from_cookie(jar: &CookieJar) -> Option<i32> {match jar.get_private(COOKIE_USER_ID_KEY) {Some(id) => Some(id.value().parse::<i32>().ok()?),None => None,}}pub fn routes() -> Vec<Route> {routes![new,new_already_user,create,get_sign_in,sign_in,sign_out]}