#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] use models::{NewUser, User}; use rocket::{ request::{FlashMessage, Form}, response::{Flash, Redirect}, Route, }; use utils::{DbConn, Page}; #[derive(BartDisplay)] #[template = "templates/users.html"] pub struct UsersTemplate { users: Vec, } implement_responder_for!(UsersTemplate); #[get("/", format = "text/html")] fn index(flash: Option, conn: DbConn) -> Page { Page { title: String::from("Users"), flash, content: UsersTemplate { users: User::all(&conn).unwrap(), }, } } #[derive(BartDisplay)] #[template = "templates/edit_user.html"] pub struct EditUserTemplate { user: User, } implement_responder_for!(EditUserTemplate); #[get("//edit")] fn edit(id: i32, conn: DbConn) -> Page { Page { title: String::from("Edit users"), flash: None, content: EditUserTemplate { user: User::by_id(id, &conn).unwrap(), }, } } #[get("//delete")] fn delete(id: i32, route: &Route, conn: DbConn) -> Flash { match User::delete(id, &conn) { Ok(user) => Flash::success( Redirect::to(route.base.path()), format!("User {} was successfully deleted.", user.username), ), Err(msg) => Flash::error( Redirect::to(route.base.path()), format!("Error deleting user: {}", msg), ), } } #[derive(BartDisplay)] #[template = "templates/new_user.html"] pub struct NewUserTemplate { user: NewUser, } implement_responder_for!(NewUserTemplate); #[get("/new", format = "text/html")] fn new(flash: Option) -> Page { Page { title: String::from("New user"), flash, content: NewUserTemplate { user: Default::default(), }, } } #[derive(FromForm)] struct RegisterUserForm { username: String, realname: Option, email: Option, password: String, password_confirm: String, } impl RegisterUserForm { fn new_user(&self) -> Result { if self.password != self.password_confirm { Err("Passwords don't match") } else { Ok(NewUser { username: self.username.clone(), realname: self.realname.clone(), email: self.email.clone(), password: self.password.clone(), }) } } fn attrs(&self) -> Result { if self.password != self.password_confirm { Err("Passwords don't match") } else { Ok(User { id: Default::default(), username: self.username.clone(), realname: self.realname.clone(), email: self.email.clone(), password: self.password.clone(), }) } } } #[post("/create", data = "")] fn create(user: Form, route: &Route, conn: DbConn) -> Flash { match user.get().new_user() { Ok(new_user) => match User::create(&new_user, &conn) { Ok(_) => Flash::success( Redirect::to(route.base.path()), "User successfully created!", ), Err(_) => Flash::error(Redirect::to("/"), "Could not create user!"), }, Err(msg) => Flash::error(Redirect::to(&format!("{}/new", route.base.path())), &msg), } } #[post("//update", data = "")] fn update( id: i32, user_form: Form, route: &Route, conn: DbConn, ) -> Flash { match user_form.get().attrs() { Ok(attrs) => { if let Ok(mut user) = User::by_id(id, &conn) { if user.username != attrs.username { user.username = attrs.username.clone(); } if user.realname != attrs.realname { user.realname = attrs.realname.clone(); } if user.email != attrs.email { user.email = attrs.email.clone(); } if !attrs.password.is_empty() && user.password != attrs.password { user.password = attrs.password.clone(); } match User::update(&user, &conn) { Ok(user) => Flash::success( Redirect::to(route.base.path()), format!("User {} updated successfully", user.username), ), Err(msg) => Flash::error( Redirect::to(route.base.path()), format!("User {} was not updated! {}", user.username, msg), ), } } else { Flash::error( Redirect::to(route.base.path()), "Can't delete users which does not exist", ) } } Err(msg) => Flash::error( Redirect::to(route.base.path()), format!("Invalid form data: {}", msg), ), } } pub fn routes() -> Vec { routes![index, new, create, edit, update, delete] }