use super::fetch_connection_string_from_request;
use crate::{
dtos::MyceliumProfileData,
middleware::recovery_profile_from_storage_engines,
};
use actix_web::HttpRequest;
use myc_core::domain::dtos::{
security_group::PermissionedRole, token::UserAccountConnectionString,
};
use myc_http_tools::{responses::GatewayError, Permission};
use tracing::Instrument;
use uuid::Uuid;
#[tracing::instrument(
name = "fetch_profile_from_request_connection_string",
skip(req)
)]
pub(crate) async fn fetch_profile_from_request_connection_string(
req: HttpRequest,
tenant: Option<Uuid>,
required_roles: Option<Vec<PermissionedRole>>,
) -> Result<MyceliumProfileData, GatewayError> {
let span: tracing::Span = tracing::Span::current();
tracing::trace!("Fetching profile from request connection string");
let connection_string: UserAccountConnectionString =
fetch_connection_string_from_request(req.clone())
.instrument(span.to_owned())
.await?
.connection_string()
.to_owned();
let updated_tenant = filter_tenant(
connection_string.get_tenant_id().to_owned(),
tenant.to_owned(),
);
let updated_roles = filter_roles(
required_roles.to_owned(),
connection_string.get_roles().to_owned(),
);
let profile = recovery_profile_from_storage_engines(
req.clone(),
connection_string.email.to_owned(),
updated_tenant.to_owned(),
updated_roles.to_owned(),
)
.instrument(span)
.await?;
tracing::trace!("Profile: {:?}", profile.profile_redacted());
Ok(MyceliumProfileData::from_profile(profile))
}
fn filter_tenant(
connection_string_tenant: Option<Uuid>,
request_tenant: Option<Uuid>,
) -> Option<Uuid> {
if let Some(tenant) = connection_string_tenant {
return Some(tenant);
}
if let Some(request_tenant) = request_tenant {
return Some(request_tenant);
}
None
}
fn filter_roles(
profile_roles: Option<Vec<PermissionedRole>>,
connection_string_roles: Option<Vec<PermissionedRole>>,
) -> Option<Vec<PermissionedRole>> {
if let (Some(profile_roles), Some(connection_string_roles)) =
(profile_roles.to_owned(), connection_string_roles.to_owned())
{
let connection_string_roles_binding = connection_string_roles
.iter()
.map(|role| (role.name.clone(), role.permission.clone()))
.collect::<Vec<_>>();
let filtered_roles = profile_roles
.iter()
.filter(|profile_role| {
if connection_string_roles.is_empty() {
return true;
}
let profile_perm =
profile_role.permission.clone().unwrap_or(Permission::Read);
connection_string_roles_binding.iter().any(
|(name, permission)| {
let conn_str_perm =
permission.clone().unwrap_or(Permission::Read);
let name_match = name.to_lowercase()
== profile_role.name.to_lowercase();
let perm_match =
profile_perm.to_i32() == conn_str_perm.to_i32();
name_match && perm_match
},
)
})
.map(|i| i.to_owned())
.collect::<Vec<_>>();
return match filtered_roles.is_empty() {
true => None,
false => Some(filtered_roles),
};
}
if let (Some(profile_roles), None) =
(profile_roles.to_owned(), connection_string_roles.to_owned())
{
return Some(profile_roles);
}
if let (None, Some(connection_string_roles)) =
(profile_roles, connection_string_roles)
{
return Some(connection_string_roles);
}
None
}