use crate::{ConversationSurface, SurfaceParseError};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "camelCase", deny_unknown_fields)]
pub enum ClientPrincipal {
User {
#[serde(rename = "userId")]
user_id: String,
},
Space {
#[serde(rename = "tenantId")]
tenant_id: String,
#[serde(rename = "scopeId")]
scope_id: String,
},
}
impl ClientPrincipal {
pub fn user_id(&self) -> Option<&str> {
match self {
Self::User { user_id } => Some(user_id),
Self::Space { .. } => None,
}
}
pub fn validate_for(&self, tenant_id: &str, scope_id: &str) -> bool {
if !valid_id(tenant_id) || !valid_id(scope_id) {
return false;
}
match self {
Self::User { user_id } => valid_id(user_id),
Self::Space {
tenant_id: tenant,
scope_id: scope,
} => tenant == tenant_id && scope == scope_id,
}
}
pub fn client_surface(
&self,
tenant_id: &str,
scope_id: &str,
) -> Result<ConversationSurface, SurfaceParseError> {
if !self.validate_for(tenant_id, scope_id) {
return Err(SurfaceParseError);
}
match self {
Self::User { user_id } => ConversationSurface::client_personal(user_id),
Self::Space { .. } => Ok(ConversationSurface::space_clients()),
}
}
}
fn valid_id(value: &str) -> bool {
!value.is_empty()
&& value.len() <= 256
&& value.trim() == value
&& !value.chars().any(char::is_control)
}