use crate::{
dtos::{MyceliumProfileData, TenantData},
rest::shared::PaginationParams,
};
use actix_web::{delete, get, patch, post, web, HttpResponse, Responder};
use myc_core::{
domain::dtos::{
email::Email, guest_user::GuestUser, profile::LicensedResources,
security_group::PermissionedRole,
},
models::AccountLifeCycle,
use_cases::role_scoped::subscriptions_manager::guest::{
guest_user_to_subscription_account, list_guest_on_subscription_account,
list_licensed_accounts_of_email,
revoke_user_guest_to_subscription_account,
update_flags_from_subscription_account,
},
};
use myc_diesel::repositories::SqlAppModule;
use myc_http_tools::{
utils::HttpJsonResponse,
wrappers::default_response_to_http_response::{
delete_response_kind, fetch_many_response_kind,
get_or_create_response_kind, handle_mapped_error,
updating_response_kind,
},
};
use mycelium_base::dtos::PaginatedRecord;
use serde::Deserialize;
use shaku::HasComponent;
use utoipa::{IntoParams, ToSchema};
use uuid::Uuid;
pub fn configure(config: &mut web::ServiceConfig) {
config
.service(list_licensed_accounts_of_email_url)
.service(guest_user_url)
.service(update_flags_from_subscription_account_url)
.service(uninvite_guest_url)
.service(list_guest_on_subscription_account_url);
}
#[derive(Deserialize, ToSchema, IntoParams)]
#[serde(rename_all = "camelCase")]
pub struct GuestUserBody {
email: String,
}
#[derive(Deserialize, ToSchema, IntoParams)]
#[serde(rename_all = "camelCase")]
pub struct UpdateFlagsFromSubscriptionAccountBody {
permit_flags: Option<Vec<String>>,
deny_flags: Option<Vec<String>>,
}
#[derive(Deserialize, ToSchema, IntoParams)]
#[serde(rename_all = "camelCase")]
pub struct ListLicensedAccountsOfEmailParams {
email: String,
roles: Option<Vec<PermissionedRole>>,
was_verified: Option<bool>,
}
#[utoipa::path(
get,
operation_id = "list_licensed_accounts_of_email",
params(
(
"x-mycelium-tenant-id" = Uuid,
Header,
description = "The tenant unique id."
),
ListLicensedAccountsOfEmailParams,
),
responses(
(
status = 500,
description = "Unknown internal server error.",
body = HttpJsonResponse,
),
(
status = 204,
description = "Not found.",
),
(
status = 403,
description = "Forbidden.",
body = HttpJsonResponse,
),
(
status = 401,
description = "Unauthorized.",
body = HttpJsonResponse,
),
(
status = 200,
description = "Fetching success.",
body = [LicensedResources],
),
),
)]
#[get("")]
pub async fn list_licensed_accounts_of_email_url(
tenant: TenantData,
query: web::Query<ListLicensedAccountsOfEmailParams>,
profile: MyceliumProfileData,
app_module: web::Data<SqlAppModule>,
) -> impl Responder {
let email = match Email::from_string(query.email.to_owned()) {
Err(err) => {
return HttpResponse::BadRequest().json(
HttpJsonResponse::new_message(format!("Invalid email: {err}")),
)
}
Ok(res) => res,
};
match list_licensed_accounts_of_email(
profile.to_profile(),
tenant.tenant_id().to_owned(),
email.to_owned(),
query.roles.to_owned(),
query.was_verified.to_owned(),
Box::new(&*app_module.resolve_ref()),
)
.await
{
Ok(res) => fetch_many_response_kind(res),
Err(err) => handle_mapped_error(err),
}
}
#[utoipa::path(
post,
operation_id = "guest_user",
params(
(
"x-mycelium-tenant-id" = Uuid,
Header,
description = "The tenant unique id."
),
("account_id" = Uuid, Path, description = "The account primary key."),
("role_id" = Uuid, Path, description = "The guest-role unique id."),
),
request_body = GuestUserBody,
responses(
(
status = 500,
description = "Unknown internal server error.",
body = HttpJsonResponse,
),
(
status = 403,
description = "Forbidden.",
body = HttpJsonResponse,
),
(
status = 401,
description = "Unauthorized.",
body = HttpJsonResponse,
),
(
status = 400,
description = "Bad request.",
body = HttpJsonResponse,
),
(
status = 201,
description = "Guesting done.",
body = GuestUser,
),
(
status = 200,
description = "Guest already exist.",
body = GuestUser,
),
),
)]
#[post("/accounts/{account_id}/roles/{role_id}")]
pub async fn guest_user_url(
tenant: TenantData,
path: web::Path<(Uuid, Uuid)>,
body: web::Json<GuestUserBody>,
profile: MyceliumProfileData,
life_cycle_settings: web::Data<AccountLifeCycle>,
sql_app_module: web::Data<SqlAppModule>,
) -> impl Responder {
let (account_id, role_id) = path.to_owned();
let email = match Email::from_string(body.email.to_owned()) {
Err(err) => {
return HttpResponse::BadRequest()
.json(HttpJsonResponse::new_message(err.to_string()))
}
Ok(res) => res,
};
match guest_user_to_subscription_account(
profile.to_profile(),
tenant.tenant_id().to_owned(),
email,
role_id,
account_id,
life_cycle_settings.get_ref().to_owned(),
Box::new(&*sql_app_module.resolve_ref()),
Box::new(&*sql_app_module.resolve_ref()),
Box::new(&*sql_app_module.resolve_ref()),
Box::new(&*sql_app_module.resolve_ref()),
Box::new(&*sql_app_module.resolve_ref()),
)
.await
{
Ok(res) => get_or_create_response_kind(res),
Err(err) => handle_mapped_error(err),
}
}
#[utoipa::path(
patch,
operation_id = "update_flags_from_subscription_account",
params(
(
"x-mycelium-tenant-id" = Uuid,
Header,
description = "The tenant unique id."
),
("account_id" = Uuid, Path, description = "The account primary key."),
("role_id" = Uuid, Path, description = "The guest-role unique id."),
),
request_body = UpdateFlagsFromSubscriptionAccountBody,
responses(
(
status = 500,
description = "Unknown internal server error.",
body = HttpJsonResponse,
),
(
status = 403,
description = "Forbidden.",
body = HttpJsonResponse,
),
(
status = 401,
description = "Unauthorized.",
body = HttpJsonResponse,
),
(
status = 400,
description = "Bad request.",
body = HttpJsonResponse,
),
(
status = 201,
description = "Flags updated.",
body = GuestUser,
),
(
status = 200,
description = "Flags already updated.",
body = GuestUser,
),
),
)]
#[patch("/accounts/{account_id}/roles/{role_id}")]
pub async fn update_flags_from_subscription_account_url(
tenant: TenantData,
path: web::Path<(Uuid, Uuid)>,
body: web::Json<UpdateFlagsFromSubscriptionAccountBody>,
profile: MyceliumProfileData,
sql_app_module: web::Data<SqlAppModule>,
) -> impl Responder {
let (account_id, role_id) = path.to_owned();
let permit_flags = body.permit_flags.to_owned().unwrap_or_default();
let deny_flags = body.deny_flags.to_owned().unwrap_or_default();
match update_flags_from_subscription_account(
profile.to_profile(),
tenant.tenant_id().to_owned(),
role_id,
account_id,
permit_flags,
deny_flags,
Box::new(&*sql_app_module.resolve_ref()),
Box::new(&*sql_app_module.resolve_ref()),
Box::new(&*sql_app_module.resolve_ref()),
)
.await
{
Ok(res) => updating_response_kind(res),
Err(err) => handle_mapped_error(err),
}
}
#[utoipa::path(
delete,
operation_id = "uninvite_guest",
params(
(
"x-mycelium-tenant-id" = Uuid,
Header,
description = "The tenant unique id."
),
("account_id" = Uuid, Path, description = "The account primary key."),
("role_id" = Uuid, Path, description = "The guest-role unique id."),
GuestUserBody,
),
responses(
(
status = 500,
description = "Unknown internal server error.",
body = HttpJsonResponse,
),
(
status = 403,
description = "Forbidden.",
body = HttpJsonResponse,
),
(
status = 401,
description = "Unauthorized.",
body = HttpJsonResponse,
),
(
status = 400,
description = "Guest User not uninvited.",
body = HttpJsonResponse,
),
(
status = 204,
description = "Guest User uninvited.",
),
),
)]
#[delete("/accounts/{account_id}/roles/{role_id}")]
pub async fn uninvite_guest_url(
tenant: TenantData,
path: web::Path<(Uuid, Uuid)>,
query: web::Query<GuestUserBody>,
profile: MyceliumProfileData,
app_module: web::Data<SqlAppModule>,
) -> impl Responder {
let (account_id, role_id) = path.to_owned();
match revoke_user_guest_to_subscription_account(
profile.to_profile(),
tenant.tenant_id().to_owned(),
account_id,
role_id,
query.email.to_owned(),
Box::new(&*app_module.resolve_ref()),
)
.await
{
Ok(res) => delete_response_kind(res),
Err(err) => handle_mapped_error(err),
}
}
#[utoipa::path(
get,
operation_id = "list_guest_on_subscription_account",
params(
(
"x-mycelium-tenant-id" = Uuid,
Header,
description = "The tenant unique id."
),
("account_id" = Uuid, Path, description = "The account primary key."),
),
responses(
(
status = 500,
description = "Unknown internal server error.",
body = HttpJsonResponse,
),
(
status = 204,
description = "Not found.",
),
(
status = 403,
description = "Forbidden.",
body = HttpJsonResponse,
),
(
status = 401,
description = "Unauthorized.",
body = HttpJsonResponse,
),
(
status = 200,
description = "Fetching success.",
body = PaginatedRecord<GuestUser>,
),
),
)]
#[get("/accounts/{account_id}")]
pub async fn list_guest_on_subscription_account_url(
tenant: TenantData,
path: web::Path<Uuid>,
page: web::Query<PaginationParams>,
profile: MyceliumProfileData,
app_module: web::Data<SqlAppModule>,
) -> impl Responder {
match list_guest_on_subscription_account(
profile.to_profile(),
tenant.tenant_id().to_owned(),
path.to_owned(),
page.page_size.to_owned(),
page.skip.to_owned(),
Box::new(&*app_module.resolve_ref()),
Box::new(&*app_module.resolve_ref()),
)
.await
{
Ok(res) => fetch_many_response_kind(res),
Err(err) => handle_mapped_error(err),
}
}