tuwunel_api/client/session/
appservice.rs1use ruma::{
2 OwnedUserId, UserId,
3 api::client::{
4 session::login::v3::{ApplicationService, Request},
5 uiaa,
6 },
7};
8use tuwunel_core::{Err, Result, err, extract};
9use tuwunel_service::Services;
10
11use crate::Ruma;
12
13pub(super) fn handle_login(
14 services: &Services,
15 body: &Ruma<Request>,
16 info: &ApplicationService,
17) -> Result<OwnedUserId> {
18 #[expect(deprecated)]
19 let ApplicationService { identifier, user } = info;
20
21 let Some(ref info) = body.appservice_info else {
22 return Err!(Request(MissingToken("Missing appservice token.")));
23 };
24
25 if info.registration.device_management {
28 return Err!(Request(AppserviceLoginUnsupported(
29 "Appservice has MSC4190 device management enabled; appservice login is unsupported."
30 )));
31 }
32
33 let user_id = extract!(
34 identifier,
35 x in Some(uiaa::UserIdentifier::Matrix(uiaa::MatrixUserIdentifier { user: x, .. }))
36 )
37 .or(user.as_ref())
38 .ok_or_else(|| {
39 err!(Request(Unknown(debug_warn!(
40 ?body.login_info,
41 "Valid identifier or username was not provided (invalid or unsupported login type?)"
42 ))))
43 })?;
44
45 let user_id = UserId::parse_with_server_name(user_id, &services.config.server_name)
46 .map_err(|e| err!(Request(InvalidUsername(warn!("Username is invalid: {e}")))))?;
47
48 if !services.globals.user_is_local(&user_id) {
49 return Err!(Request(Unknown("User ID does not belong to this homeserver")));
50 }
51
52 let emergency_mode_enabled = services.config.emergency_password.is_some();
53
54 if !info.is_user_match(&user_id) && !emergency_mode_enabled {
55 return Err!(Request(Exclusive("Username is not in an appservice namespace.")));
56 }
57
58 Ok(user_id)
59}