feat: implement password changing (#138)
Password: Fixes Password: Implement logging out all devices except current Password: Implement password changing Co-authored-by: the0 <theo@localhost> Reviewed-on: https://git.koesters.xyz/timo/conduit/pulls/138 Reviewed-by: Timo Kösters <timo@koesters.xyz>next
parent
e809d819ac
commit
67a1f21f5d
|
@ -12,7 +12,7 @@ use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
r0::{
|
r0::{
|
||||||
account::{get_username_availability, register},
|
account::{change_password, get_username_availability, register},
|
||||||
alias::{create_alias, delete_alias, get_alias},
|
alias::{create_alias, delete_alias, get_alias},
|
||||||
backup::{
|
backup::{
|
||||||
add_backup_keys, create_backup, get_backup, get_backup_keys, get_latest_backup,
|
add_backup_keys, create_backup, get_backup, get_backup_keys, get_latest_backup,
|
||||||
|
@ -305,6 +305,58 @@ pub fn logout_route(
|
||||||
Ok(logout::Response.into())
|
Ok(logout::Response.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[post("/_matrix/client/r0/account/password", data = "<body>")]
|
||||||
|
pub fn change_password_route(
|
||||||
|
db: State<'_, Database>,
|
||||||
|
body: Ruma<change_password::Request>,
|
||||||
|
) -> ConduitResult<change_password::Response> {
|
||||||
|
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
||||||
|
let device_id = body.device_id.as_ref().expect("user is authenticated");
|
||||||
|
let mut uiaainfo = UiaaInfo {
|
||||||
|
flows: vec![AuthFlow {
|
||||||
|
stages: vec!["m.login.password".to_owned()],
|
||||||
|
}],
|
||||||
|
completed: Vec::new(),
|
||||||
|
params: Default::default(),
|
||||||
|
session: None,
|
||||||
|
auth_error: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(auth) = &body.auth {
|
||||||
|
let (worked, uiaainfo) = db.uiaa.try_auth(
|
||||||
|
&user_id,
|
||||||
|
&device_id,
|
||||||
|
auth,
|
||||||
|
&uiaainfo,
|
||||||
|
&db.users,
|
||||||
|
&db.globals,
|
||||||
|
)?;
|
||||||
|
if !worked {
|
||||||
|
return Err(Error::Uiaa(uiaainfo));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||||
|
db.uiaa.create(&user_id, &device_id, &uiaainfo)?;
|
||||||
|
return Err(Error::Uiaa(uiaainfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
db.users.set_password(&user_id, &body.new_password)?;
|
||||||
|
|
||||||
|
// TODO: Read logout_devices field when it's available and respect that, currently not supported in Ruma
|
||||||
|
// See: https://github.com/ruma/ruma/issues/107
|
||||||
|
// Logout all devices except the current one
|
||||||
|
for id in db
|
||||||
|
.users
|
||||||
|
.all_device_ids(&user_id)
|
||||||
|
.filter_map(|id| id.ok())
|
||||||
|
.filter(|id| id != device_id)
|
||||||
|
{
|
||||||
|
db.users.remove_device(&user_id, &id)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(change_password::Response.into())
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/_matrix/client/r0/capabilities")]
|
#[get("/_matrix/client/r0/capabilities")]
|
||||||
pub fn get_capabilities_route() -> ConduitResult<get_capabilities::Response> {
|
pub fn get_capabilities_route() -> ConduitResult<get_capabilities::Response> {
|
||||||
let mut available = BTreeMap::new();
|
let mut available = BTreeMap::new();
|
||||||
|
|
|
@ -93,6 +93,19 @@ impl Users {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Hash and set the user's password to the Argon2 hash
|
||||||
|
pub fn set_password(&self, user_id: &UserId, password: &str) -> Result<()> {
|
||||||
|
if let Ok(hash) = utils::calculate_hash(&password) {
|
||||||
|
self.userid_password.insert(user_id.to_string(), &*hash)?;
|
||||||
|
} else {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::InvalidParam,
|
||||||
|
"Password does not meet the requirements.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the displayname of a user on this homeserver.
|
/// Returns the displayname of a user on this homeserver.
|
||||||
pub fn displayname(&self, user_id: &UserId) -> Result<Option<String>> {
|
pub fn displayname(&self, user_id: &UserId) -> Result<Option<String>> {
|
||||||
self.userid_displayname
|
self.userid_displayname
|
||||||
|
|
|
@ -29,6 +29,7 @@ fn setup_rocket() -> rocket::Rocket {
|
||||||
client_server::get_login_route,
|
client_server::get_login_route,
|
||||||
client_server::login_route,
|
client_server::login_route,
|
||||||
client_server::logout_route,
|
client_server::logout_route,
|
||||||
|
client_server::change_password_route,
|
||||||
client_server::get_capabilities_route,
|
client_server::get_capabilities_route,
|
||||||
client_server::get_pushrules_all_route,
|
client_server::get_pushrules_all_route,
|
||||||
client_server::set_pushrule_route,
|
client_server::set_pushrule_route,
|
||||||
|
|
Loading…
Reference in New Issue