Skip to main content

tuwunel_api/client/session/
appservice.rs

1use 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	let user_id = extract!(
26		identifier,
27		x in Some(uiaa::UserIdentifier::Matrix(uiaa::MatrixUserIdentifier { user: x, .. }))
28	)
29	.or(user.as_ref())
30	.ok_or_else(|| {
31		err!(Request(Unknown(debug_warn!(
32			?body.login_info,
33			"Valid identifier or username was not provided (invalid or unsupported login type?)"
34		))))
35	})?;
36
37	let user_id = UserId::parse_with_server_name(user_id, &services.config.server_name)
38		.map_err(|e| err!(Request(InvalidUsername(warn!("Username is invalid: {e}")))))?;
39
40	if !services.globals.user_is_local(&user_id) {
41		return Err!(Request(Unknown("User ID does not belong to this homeserver")));
42	}
43
44	let emergency_mode_enabled = services.config.emergency_password.is_some();
45
46	if !info.is_user_match(&user_id) && !emergency_mode_enabled {
47		return Err!(Request(Exclusive("Username is not in an appservice namespace.")));
48	}
49
50	Ok(user_id)
51}