use crate::{database::DatabaseGuard, ConduitResult, Error, Ruma}; use ruma::api::client::{ error::ErrorKind, r0::backup::{ add_backup_key_session, add_backup_key_sessions, add_backup_keys, create_backup, delete_backup, delete_backup_key_session, delete_backup_key_sessions, delete_backup_keys, get_backup, get_backup_key_session, get_backup_key_sessions, get_backup_keys, get_latest_backup, update_backup, }, }; #[cfg(feature = "conduit_bin")] use rocket::{delete, get, post, put}; #[cfg_attr( feature = "conduit_bin", post("/_matrix/client/unstable/room_keys/version", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn create_backup_route( db: DatabaseGuard, body: Ruma, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let version = db .key_backups .create_backup(&sender_user, &body.algorithm, &db.globals)?; db.flush().await?; Ok(create_backup::Response { version }.into()) } #[cfg_attr( feature = "conduit_bin", put("/_matrix/client/unstable/room_keys/version/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn update_backup_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); db.key_backups .update_backup(&sender_user, &body.version, &body.algorithm, &db.globals)?; db.flush().await?; Ok(update_backup::Response.into()) } #[cfg_attr( feature = "conduit_bin", get("/_matrix/client/unstable/room_keys/version", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn get_latest_backup_route( db: DatabaseGuard, body: Ruma, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let (version, algorithm) = db.key_backups .get_latest_backup(&sender_user)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "Key backup does not exist.", ))?; Ok(get_latest_backup::Response { algorithm, count: (db.key_backups.count_keys(sender_user, &version)? as u32).into(), etag: db.key_backups.get_etag(sender_user, &version)?, version, } .into()) } #[cfg_attr( feature = "conduit_bin", get("/_matrix/client/unstable/room_keys/version/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn get_backup_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let algorithm = db .key_backups .get_backup(&sender_user, &body.version)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "Key backup does not exist.", ))?; Ok(get_backup::Response { algorithm, count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(), etag: db.key_backups.get_etag(sender_user, &body.version)?, version: body.version.to_owned(), } .into()) } #[cfg_attr( feature = "conduit_bin", delete("/_matrix/client/unstable/room_keys/version/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn delete_backup_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); db.key_backups.delete_backup(&sender_user, &body.version)?; db.flush().await?; Ok(delete_backup::Response.into()) } /// Add the received backup keys to the database. #[cfg_attr( feature = "conduit_bin", put("/_matrix/client/unstable/room_keys/keys", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn add_backup_keys_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); for (room_id, room) in &body.rooms { for (session_id, key_data) in &room.sessions { db.key_backups.add_key( &sender_user, &body.version, &room_id, &session_id, &key_data, &db.globals, )? } } db.flush().await?; Ok(add_backup_keys::Response { count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(), etag: db.key_backups.get_etag(sender_user, &body.version)?, } .into()) } /// Add the received backup keys to the database. #[cfg_attr( feature = "conduit_bin", put("/_matrix/client/unstable/room_keys/keys/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn add_backup_key_sessions_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); for (session_id, key_data) in &body.sessions { db.key_backups.add_key( &sender_user, &body.version, &body.room_id, &session_id, &key_data, &db.globals, )? } db.flush().await?; Ok(add_backup_key_sessions::Response { count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(), etag: db.key_backups.get_etag(sender_user, &body.version)?, } .into()) } /// Add the received backup key to the database. #[cfg_attr( feature = "conduit_bin", put("/_matrix/client/unstable/room_keys/keys/<_>/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn add_backup_key_session_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); db.key_backups.add_key( &sender_user, &body.version, &body.room_id, &body.session_id, &body.session_data, &db.globals, )?; db.flush().await?; Ok(add_backup_key_session::Response { count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(), etag: db.key_backups.get_etag(sender_user, &body.version)?, } .into()) } #[cfg_attr( feature = "conduit_bin", get("/_matrix/client/unstable/room_keys/keys", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn get_backup_keys_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let rooms = db.key_backups.get_all(&sender_user, &body.version)?; Ok(get_backup_keys::Response { rooms }.into()) } #[cfg_attr( feature = "conduit_bin", get("/_matrix/client/unstable/room_keys/keys/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn get_backup_key_sessions_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sessions = db .key_backups .get_room(&sender_user, &body.version, &body.room_id)?; Ok(get_backup_key_sessions::Response { sessions }.into()) } #[cfg_attr( feature = "conduit_bin", get("/_matrix/client/unstable/room_keys/keys/<_>/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn get_backup_key_session_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let key_data = db .key_backups .get_session(&sender_user, &body.version, &body.room_id, &body.session_id)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "Backup key not found for this user's session.", ))?; Ok(get_backup_key_session::Response { key_data }.into()) } #[cfg_attr( feature = "conduit_bin", delete("/_matrix/client/unstable/room_keys/keys", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn delete_backup_keys_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); db.key_backups .delete_all_keys(&sender_user, &body.version)?; db.flush().await?; Ok(delete_backup_keys::Response { count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(), etag: db.key_backups.get_etag(sender_user, &body.version)?, } .into()) } #[cfg_attr( feature = "conduit_bin", delete("/_matrix/client/unstable/room_keys/keys/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn delete_backup_key_sessions_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); db.key_backups .delete_room_keys(&sender_user, &body.version, &body.room_id)?; db.flush().await?; Ok(delete_backup_key_sessions::Response { count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(), etag: db.key_backups.get_etag(sender_user, &body.version)?, } .into()) } #[cfg_attr( feature = "conduit_bin", delete("/_matrix/client/unstable/room_keys/keys/<_>/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn delete_backup_key_session_route( db: DatabaseGuard, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); db.key_backups .delete_room_key(&sender_user, &body.version, &body.room_id, &body.session_id)?; db.flush().await?; Ok(delete_backup_key_session::Response { count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(), etag: db.key_backups.get_etag(sender_user, &body.version)?, } .into()) }