conversation_api/
principal.rs1use crate::{ConversationSurface, SurfaceParseError};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[serde(tag = "kind", rename_all = "camelCase", deny_unknown_fields)]
11pub enum ClientPrincipal {
12 User {
13 #[serde(rename = "userId")]
14 user_id: String,
15 },
16 Space {
17 #[serde(rename = "tenantId")]
18 tenant_id: String,
19 #[serde(rename = "scopeId")]
20 scope_id: String,
21 },
22}
23
24impl ClientPrincipal {
25 pub fn user_id(&self) -> Option<&str> {
27 match self {
28 Self::User { user_id } => Some(user_id),
29 Self::Space { .. } => None,
30 }
31 }
32
33 pub fn validate_for(&self, tenant_id: &str, scope_id: &str) -> bool {
34 if !valid_id(tenant_id) || !valid_id(scope_id) {
35 return false;
36 }
37 match self {
38 Self::User { user_id } => valid_id(user_id),
39 Self::Space {
40 tenant_id: tenant,
41 scope_id: scope,
42 } => tenant == tenant_id && scope == scope_id,
43 }
44 }
45
46 pub fn client_surface(
49 &self,
50 tenant_id: &str,
51 scope_id: &str,
52 ) -> Result<ConversationSurface, SurfaceParseError> {
53 if !self.validate_for(tenant_id, scope_id) {
54 return Err(SurfaceParseError);
55 }
56 match self {
57 Self::User { user_id } => ConversationSurface::client_personal(user_id),
58 Self::Space { .. } => Ok(ConversationSurface::space_clients()),
59 }
60 }
61}
62
63fn valid_id(value: &str) -> bool {
64 !value.is_empty()
65 && value.len() <= 256
66 && value.trim() == value
67 && !value.chars().any(char::is_control)
68}