1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2024-06-26 15:38:18 +02:00
conduit/src/client_server/device.rs

213 lines
6.2 KiB
Rust
Raw Normal View History

2021-07-14 09:07:08 +02:00
use crate::{database::DatabaseGuard, utils, ConduitResult, Error, Ruma};
2020-07-30 18:14:47 +02:00
use ruma::api::client::{
error::ErrorKind,
r0::{
device::{self, delete_device, delete_devices, get_device, get_devices, update_device},
uiaa::{AuthFlow, AuthType, UiaaInfo},
2020-07-30 18:14:47 +02:00
},
};
use super::SESSION_ID_LENGTH;
#[cfg(feature = "conduit_bin")]
use rocket::{delete, get, post, put};
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/client/r0/devices`
///
/// Get metadata on all devices of the sender user.
2020-07-30 18:14:47 +02:00
#[cfg_attr(
feature = "conduit_bin",
get("/_matrix/client/r0/devices", data = "<body>")
)]
2021-02-28 12:41:03 +01:00
#[tracing::instrument(skip(db, body))]
pub async fn get_devices_route(
2021-07-14 09:07:08 +02:00
db: DatabaseGuard,
2020-07-30 18:14:47 +02:00
body: Ruma<get_devices::Request>,
) -> ConduitResult<get_devices::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
2020-07-30 18:14:47 +02:00
let devices = db
.users
.all_devices_metadata(sender_user)
2020-07-30 18:14:47 +02:00
.filter_map(|r| r.ok()) // Filter out buggy devices
.collect::<Vec<device::Device>>();
Ok(get_devices::Response { devices }.into())
}
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/client/r0/devices/{deviceId}`
///
/// Get metadata on a single device of the sender user.
2020-07-30 18:14:47 +02:00
#[cfg_attr(
feature = "conduit_bin",
get("/_matrix/client/r0/devices/<_>", data = "<body>")
2020-07-30 18:14:47 +02:00
)]
2021-02-28 12:41:03 +01:00
#[tracing::instrument(skip(db, body))]
pub async fn get_device_route(
2021-07-14 09:07:08 +02:00
db: DatabaseGuard,
2020-09-08 17:32:03 +02:00
body: Ruma<get_device::Request<'_>>,
2020-07-30 18:14:47 +02:00
) -> ConduitResult<get_device::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
2020-07-30 18:14:47 +02:00
let device = db
.users
.get_device_metadata(sender_user, &body.body.device_id)?
2020-07-30 18:14:47 +02:00
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Device not found."))?;
Ok(get_device::Response { device }.into())
}
2021-08-31 19:14:37 +02:00
/// # `PUT /_matrix/client/r0/devices/{deviceId}`
///
/// Updates the metadata on a given device of the sender user.
2020-07-30 18:14:47 +02:00
#[cfg_attr(
feature = "conduit_bin",
put("/_matrix/client/r0/devices/<_>", data = "<body>")
2020-07-30 18:14:47 +02:00
)]
2021-02-28 12:41:03 +01:00
#[tracing::instrument(skip(db, body))]
pub async fn update_device_route(
2021-07-14 09:07:08 +02:00
db: DatabaseGuard,
2020-09-08 17:32:03 +02:00
body: Ruma<update_device::Request<'_>>,
2020-07-30 18:14:47 +02:00
) -> ConduitResult<update_device::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
2020-07-30 18:14:47 +02:00
let mut device = db
.users
.get_device_metadata(sender_user, &body.device_id)?
2020-07-30 18:14:47 +02:00
.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)?;
2020-07-30 18:14:47 +02:00
db.flush()?;
Ok(update_device::Response {}.into())
2020-07-30 18:14:47 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `PUT /_matrix/client/r0/devices/{deviceId}`
///
/// Deletes the given device.
///
/// - Requires UIAA to verify user password
/// - Invalidates access token
/// - Deletes device metadata (device id, device display name, last seen ip, last seen ts)
/// - Forgets to-device events
/// - Triggers device list updates
2020-07-30 18:14:47 +02:00
#[cfg_attr(
feature = "conduit_bin",
delete("/_matrix/client/r0/devices/<_>", data = "<body>")
2020-07-30 18:14:47 +02:00
)]
2021-02-28 12:41:03 +01:00
#[tracing::instrument(skip(db, body))]
pub async fn delete_device_route(
2021-07-14 09:07:08 +02:00
db: DatabaseGuard,
2020-09-08 17:32:03 +02:00
body: Ruma<delete_device::Request<'_>>,
2020-07-30 18:14:47 +02:00
) -> 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");
2020-07-30 18:14:47 +02:00
// UIAA
let mut uiaainfo = UiaaInfo {
flows: vec![AuthFlow {
stages: vec![AuthType::Password],
2020-07-30 18:14:47 +02:00
}],
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,
2020-07-30 18:14:47 +02:00
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));
2020-07-30 18:14:47 +02:00
} else {
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
2020-07-30 18:14:47 +02:00
}
db.users.remove_device(sender_user, &body.device_id)?;
2020-07-30 18:14:47 +02:00
db.flush()?;
Ok(delete_device::Response {}.into())
2020-07-30 18:14:47 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `PUT /_matrix/client/r0/devices/{deviceId}`
///
/// Deletes the given device.
///
/// - Requires UIAA to verify user password
///
/// For each device:
/// - Invalidates access token
/// - Deletes device metadata (device id, device display name, last seen ip, last seen ts)
/// - Forgets to-device events
/// - Triggers device list updates
2020-07-30 18:14:47 +02:00
#[cfg_attr(
feature = "conduit_bin",
post("/_matrix/client/r0/delete_devices", data = "<body>")
)]
2021-02-28 12:41:03 +01:00
#[tracing::instrument(skip(db, body))]
pub async fn delete_devices_route(
2021-07-14 09:07:08 +02:00
db: DatabaseGuard,
2020-09-08 17:32:03 +02:00
body: Ruma<delete_devices::Request<'_>>,
2020-07-30 18:14:47 +02:00
) -> 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");
2020-07-30 18:14:47 +02:00
// UIAA
let mut uiaainfo = UiaaInfo {
flows: vec![AuthFlow {
stages: vec![AuthType::Password],
2020-07-30 18:14:47 +02:00
}],
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,
2020-07-30 18:14:47 +02:00
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));
2020-07-30 18:14:47 +02:00
} else {
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
2020-07-30 18:14:47 +02:00
}
for device_id in &body.devices {
db.users.remove_device(sender_user, device_id)?
2020-07-30 18:14:47 +02:00
}
db.flush()?;
Ok(delete_devices::Response {}.into())
2020-07-30 18:14:47 +02:00
}