tuwunel_admin/user/
set_profile_key.rs1use ruma::{OwnedUserId, profile::ProfileFieldValue};
2use serde_json::Value;
3use tuwunel_core::{Err, Result, err};
4use tuwunel_service::{Services, profile::Propagation};
5
6use super::PropagateTo;
7use crate::{
8 admin_command,
9 utils::{check_known_remote_user, parse_active_local_user_id, parse_user_id},
10};
11
12#[admin_command]
13pub(super) async fn set_profile_key(
14 &self,
15 user_id: String,
16 key: String,
17 value: Vec<String>,
18 clear: bool,
19 propagate_to: Option<PropagateTo>,
20) -> Result {
21 let user_id = profile_owner(self.services, &user_id, clear, propagate_to.is_some()).await?;
22
23 let propagation = propagate_to
24 .map(Into::into)
25 .unwrap_or(Propagation::All);
26
27 let profile_value = if clear {
28 (key.as_str().into(), None)
29 } else {
30 let value = value.join(" ");
31
32 let value = serde_json::from_str(&value).unwrap_or(Value::String(value));
33
34 let profile_value = ProfileFieldValue::new(&key, value)
35 .map_err(|e| err!("Invalid value for profile key {key:?}: {e}"))?;
36
37 (profile_value.field_name(), Some(profile_value.value().into_owned()))
38 };
39
40 self.services
41 .profile
42 .set_profile_keys(&user_id, &[profile_value], Some(propagation))
43 .await?;
44
45 if clear {
46 write!(self, "Cleared profile key {key:?} for {user_id}").await
47 } else {
48 write!(self, "Set profile key {key:?} for {user_id}").await
49 }
50}
51
52async fn profile_owner(
59 services: &Services,
60 user_id: &str,
61 clear: bool,
62 propagate: bool,
63) -> Result<OwnedUserId> {
64 let local = parse_user_id(services, user_id)
65 .is_ok_and(|user_id| services.globals.user_is_local(&user_id));
66
67 let remote = OwnedUserId::parse(user_id)
68 .ok()
69 .filter(|_| !local);
70
71 match remote {
72 | None => parse_active_local_user_id(services, user_id).await,
73 | Some(_) if !clear => Err!("A remote user's profile key can only be cleared."),
74 | Some(_) if propagate => Err!("Propagation applies only to a local user's profile."),
75 | Some(user_id) => check_known_remote_user(services, &user_id)
76 .await
77 .map(|()| user_id),
78 }
79}