use crate::{
core::Serializer,
dx::access::{permissions::*, types::MetaValue, GrantTokenRequest},
lib::{
alloc::{
boxed::Box,
string::{String, ToString},
},
collections::HashMap,
},
};
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct GrantTokenResourcesPayload {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub channels: Option<HashMap<String, u8>>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub groups: Option<HashMap<String, u8>>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub uuids: Option<HashMap<String, u8>>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct GrantTokenPermissionsPayload<'request> {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub uuid: &'request Option<String>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub meta: &'request Option<HashMap<String, MetaValue>>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub resources: Option<GrantTokenResourcesPayload>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub patterns: Option<GrantTokenResourcesPayload>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct GrantTokenPayload<'request> {
pub ttl: usize,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub permissions: Option<GrantTokenPermissionsPayload<'request>>,
}
impl<'request> GrantTokenPayload<'request> {
pub(super) fn new<T, S, D>(request: &'request GrantTokenRequest<'_, T, S, D>) -> Self
where
S: for<'se, 'rq> Serializer<'se, GrantTokenPayload<'rq>>,
{
GrantTokenPayload {
ttl: request.ttl,
permissions: Some(GrantTokenPermissionsPayload {
patterns: resource_permissions(&request.patterns),
resources: resource_permissions(&request.resources),
uuid: &request.authorized_user_id,
meta: &request.meta,
}),
}
}
}
fn resource_permissions(
resources: &Option<&[Box<dyn Permission>]>,
) -> Option<GrantTokenResourcesPayload> {
resources.map(|res| {
let mut channels: HashMap<String, u8> = HashMap::new();
let mut groups: HashMap<String, u8> = HashMap::new();
let mut uuids: HashMap<String, u8> = HashMap::new();
res.iter().for_each(|perm| match perm.resource_type() {
ResourceType::Channel => {
channels.insert(perm.id().to_string(), *perm.value());
}
ResourceType::ChannelGroup => {
groups.insert(perm.id().to_string(), *perm.value());
}
ResourceType::UserId => {
uuids.insert(perm.id().to_string(), *perm.value());
}
});
GrantTokenResourcesPayload {
channels: (!channels.is_empty()).then_some(channels),
groups: (!groups.is_empty()).then_some(groups),
uuids: (!uuids.is_empty()).then_some(uuids),
}
})
}