183 lines
5.3 KiB
Rust
183 lines
5.3 KiB
Rust
use crate::{database::DatabaseGuard, utils, ConduitResult, Error, Ruma};
|
|
use ruma::api::client::{
|
|
error::ErrorKind,
|
|
r0::{
|
|
device::{self, delete_device, delete_devices, get_device, get_devices, update_device},
|
|
uiaa::{AuthFlow, UiaaInfo},
|
|
},
|
|
};
|
|
|
|
use super::SESSION_ID_LENGTH;
|
|
#[cfg(feature = "conduit_bin")]
|
|
use rocket::{delete, get, post, put};
|
|
|
|
#[cfg_attr(
|
|
feature = "conduit_bin",
|
|
get("/_matrix/client/r0/devices", data = "<body>")
|
|
)]
|
|
#[tracing::instrument(skip(db, body))]
|
|
pub async fn get_devices_route(
|
|
db: DatabaseGuard,
|
|
body: Ruma<get_devices::Request>,
|
|
) -> ConduitResult<get_devices::Response> {
|
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
|
|
|
let devices = db
|
|
.users
|
|
.all_devices_metadata(sender_user)
|
|
.filter_map(|r| r.ok()) // Filter out buggy devices
|
|
.collect::<Vec<device::Device>>();
|
|
|
|
Ok(get_devices::Response { devices }.into())
|
|
}
|
|
|
|
#[cfg_attr(
|
|
feature = "conduit_bin",
|
|
get("/_matrix/client/r0/devices/<_>", data = "<body>")
|
|
)]
|
|
#[tracing::instrument(skip(db, body))]
|
|
pub async fn get_device_route(
|
|
db: DatabaseGuard,
|
|
body: Ruma<get_device::Request<'_>>,
|
|
) -> ConduitResult<get_device::Response> {
|
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
|
|
|
let device = db
|
|
.users
|
|
.get_device_metadata(&sender_user, &body.body.device_id)?
|
|
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Device not found."))?;
|
|
|
|
Ok(get_device::Response { device }.into())
|
|
}
|
|
|
|
#[cfg_attr(
|
|
feature = "conduit_bin",
|
|
put("/_matrix/client/r0/devices/<_>", data = "<body>")
|
|
)]
|
|
#[tracing::instrument(skip(db, body))]
|
|
pub async fn update_device_route(
|
|
db: DatabaseGuard,
|
|
body: Ruma<update_device::Request<'_>>,
|
|
) -> ConduitResult<update_device::Response> {
|
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
|
|
|
let mut device = db
|
|
.users
|
|
.get_device_metadata(&sender_user, &body.device_id)?
|
|
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Device not found."))?;
|
|
|
|
device.display_name = body.display_name.clone();
|
|
|
|
db.users
|
|
.update_device_metadata(&sender_user, &body.device_id, &device)?;
|
|
|
|
db.flush()?;
|
|
|
|
Ok(update_device::Response {}.into())
|
|
}
|
|
|
|
#[cfg_attr(
|
|
feature = "conduit_bin",
|
|
delete("/_matrix/client/r0/devices/<_>", data = "<body>")
|
|
)]
|
|
#[tracing::instrument(skip(db, body))]
|
|
pub async fn delete_device_route(
|
|
db: DatabaseGuard,
|
|
body: Ruma<delete_device::Request<'_>>,
|
|
) -> ConduitResult<delete_device::Response> {
|
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
|
|
|
// UIAA
|
|
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(
|
|
&sender_user,
|
|
&sender_device,
|
|
auth,
|
|
&uiaainfo,
|
|
&db.users,
|
|
&db.globals,
|
|
)?;
|
|
if !worked {
|
|
return Err(Error::Uiaa(uiaainfo));
|
|
}
|
|
// Success!
|
|
} else if let Some(json) = body.json_body {
|
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
|
db.uiaa
|
|
.create(&sender_user, &sender_device, &uiaainfo, &json)?;
|
|
return Err(Error::Uiaa(uiaainfo));
|
|
} else {
|
|
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
|
}
|
|
|
|
db.users.remove_device(&sender_user, &body.device_id)?;
|
|
|
|
db.flush()?;
|
|
|
|
Ok(delete_device::Response {}.into())
|
|
}
|
|
|
|
#[cfg_attr(
|
|
feature = "conduit_bin",
|
|
post("/_matrix/client/r0/delete_devices", data = "<body>")
|
|
)]
|
|
#[tracing::instrument(skip(db, body))]
|
|
pub async fn delete_devices_route(
|
|
db: DatabaseGuard,
|
|
body: Ruma<delete_devices::Request<'_>>,
|
|
) -> ConduitResult<delete_devices::Response> {
|
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
|
|
|
// UIAA
|
|
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(
|
|
&sender_user,
|
|
&sender_device,
|
|
auth,
|
|
&uiaainfo,
|
|
&db.users,
|
|
&db.globals,
|
|
)?;
|
|
if !worked {
|
|
return Err(Error::Uiaa(uiaainfo));
|
|
}
|
|
// Success!
|
|
} else if let Some(json) = body.json_body {
|
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
|
db.uiaa
|
|
.create(&sender_user, &sender_device, &uiaainfo, &json)?;
|
|
return Err(Error::Uiaa(uiaainfo));
|
|
} else {
|
|
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
|
}
|
|
|
|
for device_id in &body.devices {
|
|
db.users.remove_device(&sender_user, &device_id)?
|
|
}
|
|
|
|
db.flush()?;
|
|
|
|
Ok(delete_devices::Response {}.into())
|
|
}
|