diff --git a/src/api.rs b/src/api.rs index 83c53a9..6e96df1 100644 --- a/src/api.rs +++ b/src/api.rs @@ -9,6 +9,7 @@ use std::vec::Vec; pub fn routes() -> impl Into> { routes![ auth, + auth_change_pw, auth_sign_in, auth_params ] @@ -99,4 +100,23 @@ fn auth_params(db: DbConn, email: String) -> Custom> { Err(user::UserOpError(e)) => error_resp(Status::InternalServerError, vec![e]) } +} + +#[derive(Deserialize)] +struct ChangePwParams { + email: String, + password: String, + current_password: String +} + +#[post("/auth/change_pw", format = "json", data = "")] +fn auth_change_pw(db: DbConn, params: Json) -> Custom> { + let res = user::User::find_user_by_email(&db, ¶ms.email) + .and_then(|u| + u.change_pw(&db, ¶ms.current_password, ¶ms.password)); + match res { + Ok(_) => Custom(Status::NoContent, Json(Response::Success(()))), + Err(user::UserOpError(e)) => + error_resp(Status::InternalServerError, vec![e]) + } } \ No newline at end of file diff --git a/src/user.rs b/src/user.rs index 8c864f2..5484531 100644 --- a/src/user.rs +++ b/src/user.rs @@ -82,4 +82,21 @@ impl User { .map_err(|_| UserOpError::new("Failed to generate token")) } } + + // Change the password in database, if old password is provided + // The current instance of User model will not be mutated + pub fn change_pw(&self, db: &SqliteConnection, passwd: &str, new_passwd: &str) -> Result<(), UserOpError> { + if passwd != self.password { + Err(UserOpError::new("Password mismatch")) + } else { + // Update database + // TODO: Maybe we should revoke all JWTs somehow? + // maybe we can record when the user last changed? + diesel::update(users.find(self.id)) + .set(password.eq(new_passwd)) + .execute(db) + .map(|_| ()) + .map_err(|_| UserOpError::new("Database error")) + } + } } \ No newline at end of file