refactor(users): Add V2 user_roles data support (#5763)

Co-authored-by: Apoorv Dixit <apoorv.dixit@juspay.in>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Mani Chandra
2024-09-01 19:09:25 +05:30
committed by GitHub
parent 379831932a
commit 6b410505da
31 changed files with 768 additions and 2042 deletions

View File

@ -121,42 +121,10 @@ pub async fn get_user_details(
))
}
pub async fn signup(
state: SessionState,
request: user_api::SignUpRequest,
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignUpResponse>> {
let new_user = domain::NewUser::try_from(request)?;
new_user
.get_new_merchant()
.get_new_organization()
.insert_org_in_db(state.clone())
.await?;
let user_from_db = new_user
.insert_user_and_merchant_in_db(state.clone())
.await?;
let user_role = new_user
.insert_org_level_user_role_in_db(
state.clone(),
common_utils::consts::ROLE_ID_ORGANIZATION_ADMIN.to_string(),
UserStatus::Active,
None,
)
.await?;
utils::user_role::set_role_permissions_in_cache_by_user_role(&state, &user_role).await;
let token =
utils::user::generate_jwt_auth_token_without_profile(&state, &user_from_db, &user_role)
.await?;
let response =
utils::user::get_dashboard_entry_response(&state, user_from_db, user_role, token.clone())?;
auth::cookies::set_cookie_response(user_api::TokenOrPayloadResponse::Payload(response), token)
}
pub async fn signup_token_only_flow(
state: SessionState,
request: user_api::SignUpRequest,
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignUpResponse>> {
) -> UserResponse<user_api::TokenResponse> {
let new_user = domain::NewUser::try_from(request)?;
new_user
.get_new_merchant()
@ -182,61 +150,17 @@ pub async fn signup_token_only_flow(
.get_token_with_user_role(&state, &user_role)
.await?;
let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
let response = user_api::TokenResponse {
token: token.clone(),
token_type: next_flow.get_flow().into(),
});
};
auth::cookies::set_cookie_response(response, token)
}
pub async fn signin(
state: SessionState,
request: user_api::SignInRequest,
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignInResponse>> {
let user_from_db: domain::UserFromStorage = state
.global_store
.find_user_by_email(&request.email)
.await
.map_err(|e| {
if e.current_context().is_db_not_found() {
e.change_context(UserErrors::InvalidCredentials)
} else {
e.change_context(UserErrors::InternalServerError)
}
})?
.into();
user_from_db.compare_password(&request.password)?;
let signin_strategy =
if let Some(preferred_merchant_id) = user_from_db.get_preferred_merchant_id() {
let preferred_role = user_from_db
.get_role_from_db_by_merchant_id(&state, &preferred_merchant_id)
.await
.to_not_found_response(UserErrors::InternalServerError)
.attach_printable("User role with preferred_merchant_id not found")?;
domain::SignInWithRoleStrategyType::SingleRole(domain::SignInWithSingleRoleStrategy {
user: user_from_db,
user_role: Box::new(preferred_role),
})
} else {
let user_roles = user_from_db.get_roles_from_db(&state).await?;
domain::SignInWithRoleStrategyType::decide_signin_strategy_by_user_roles(
user_from_db,
user_roles,
)
.await?
};
let response = signin_strategy.get_signin_response(&state).await?;
let token = utils::user::get_token_from_signin_response(&response);
auth::cookies::set_cookie_response(user_api::TokenOrPayloadResponse::Payload(response), token)
}
pub async fn signin_token_only_flow(
state: SessionState,
request: user_api::SignInRequest,
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignInResponse>> {
) -> UserResponse<user_api::TokenResponse> {
let user_from_db: domain::UserFromStorage = state
.global_store
.find_user_by_email(&request.email)
@ -251,10 +175,10 @@ pub async fn signin_token_only_flow(
let token = next_flow.get_token(&state).await?;
let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
let response = user_api::TokenResponse {
token: token.clone(),
token_type: next_flow.get_flow().into(),
});
};
auth::cookies::set_cookie_response(response, token)
}
@ -573,105 +497,11 @@ pub async fn reset_password_token_only_flow(
auth::cookies::remove_cookie_response()
}
#[cfg(feature = "email")]
pub async fn reset_password(
state: SessionState,
request: user_api::ResetPasswordRequest,
) -> UserResponse<()> {
let token = request.token.expose();
let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
.await
.change_context(UserErrors::LinkInvalid)?;
auth::blacklist::check_email_token_in_blacklist(&state, &token).await?;
let password = domain::UserPassword::new(request.password)?;
let hash_password = utils::user::password::generate_password_hash(password.get_secret())?;
let user = state
.global_store
.update_user_by_email(
&email_token
.get_email()
.change_context(UserErrors::InternalServerError)?,
storage_user::UserUpdate::PasswordUpdate {
password: hash_password,
},
)
.await
.change_context(UserErrors::InternalServerError)?;
if let Some(inviter_merchant_id) = email_token.get_merchant_id() {
let key_manager_state = &(&state).into();
let key_store = state
.store
.get_merchant_key_store_by_merchant_id(
key_manager_state,
inviter_merchant_id,
&state.store.get_master_key().to_vec().into(),
)
.await
.change_context(UserErrors::InternalServerError)
.attach_printable("merchant_key_store not found")?;
let merchant_account = state
.store
.find_merchant_account_by_merchant_id(
key_manager_state,
inviter_merchant_id,
&key_store,
)
.await
.change_context(UserErrors::InternalServerError)
.attach_printable("merchant_account not found")?;
let (update_v1_result, update_v2_result) =
utils::user_role::update_v1_and_v2_user_roles_in_db(
&state,
user.user_id.clone().as_str(),
&merchant_account.organization_id,
inviter_merchant_id,
None,
UserRoleUpdate::UpdateStatus {
status: UserStatus::Active,
modified_by: user.user_id.clone(),
},
)
.await;
if update_v1_result
.as_ref()
.is_err_and(|err| !err.current_context().is_db_not_found())
|| update_v2_result
.as_ref()
.is_err_and(|err| !err.current_context().is_db_not_found())
{
return Err(report!(UserErrors::InternalServerError));
}
if update_v1_result.is_err() && update_v2_result.is_err() {
return Err(report!(UserErrors::InvalidRoleOperation))
.attach_printable("User not found in the organization")?;
}
}
let _ = auth::blacklist::insert_email_token_in_blacklist(&state, &token)
.await
.map_err(|error| logger::error!(?error));
let _ = auth::blacklist::insert_user_in_blacklist(&state, &user.user_id)
.await
.map_err(|error| logger::error!(?error));
auth::cookies::remove_cookie_response()
}
pub async fn invite_multiple_user(
state: SessionState,
user_from_token: auth::UserFromToken,
requests: Vec<user_api::InviteUserRequest>,
req_state: ReqState,
is_token_only: Option<bool>,
auth_id: Option<String>,
) -> UserResponse<Vec<InviteMultipleUserResponse>> {
if requests.len() > 10 {
@ -680,16 +510,7 @@ pub async fn invite_multiple_user(
}
let responses = futures::future::join_all(requests.iter().map(|request| async {
match handle_invitation(
&state,
&user_from_token,
request,
&req_state,
is_token_only,
&auth_id,
)
.await
{
match handle_invitation(&state, &user_from_token, request, &req_state, &auth_id).await {
Ok(response) => response,
Err(error) => InviteMultipleUserResponse {
email: request.email.clone(),
@ -709,7 +530,6 @@ async fn handle_invitation(
user_from_token: &auth::UserFromToken,
request: &user_api::InviteUserRequest,
req_state: &ReqState,
is_token_only: Option<bool>,
auth_id: &Option<String>,
) -> UserResult<InviteMultipleUserResponse> {
let inviter_user = user_from_token.get_user_from_db(state).await?;
@ -756,15 +576,8 @@ async fn handle_invitation(
.err()
.unwrap_or(false)
{
handle_new_user_invitation(
state,
user_from_token,
request,
req_state.clone(),
is_token_only,
auth_id,
)
.await
handle_new_user_invitation(state, user_from_token, request, req_state.clone(), auth_id)
.await
} else {
Err(UserErrors::InternalServerError.into())
}
@ -877,7 +690,6 @@ async fn handle_new_user_invitation(
user_from_token: &auth::UserFromToken,
request: &user_api::InviteUserRequest,
req_state: ReqState,
is_token_only: Option<bool>,
auth_id: &Option<String>,
) -> UserResult<InviteMultipleUserResponse> {
let new_user = domain::NewUser::try_from((request.clone(), user_from_token.clone()))?;
@ -912,8 +724,6 @@ async fn handle_new_user_invitation(
.await?;
let is_email_sent;
// TODO: Adding this to avoid clippy lints, remove this once the token only flow is being used
let _ = is_token_only;
#[cfg(feature = "email")]
{
@ -921,8 +731,7 @@ async fn handle_new_user_invitation(
// Will be adding actual usage for this variable later
let _ = req_state.clone();
let invitee_email = domain::UserEmail::from_pii_email(request.email.clone())?;
let email_contents: Box<dyn EmailData + Send + 'static> = if let Some(true) = is_token_only
{
let email_contents: Box<dyn EmailData + Send + 'static> =
Box::new(email_types::InviteRegisteredUser {
recipient_email: invitee_email,
user_name: domain::UserName::new(new_user.get_name())?,
@ -930,17 +739,7 @@ async fn handle_new_user_invitation(
subject: "You have been invited to join Hyperswitch Community!",
merchant_id: user_from_token.merchant_id.clone(),
auth_id: auth_id.clone(),
})
} else {
Box::new(email_types::InviteUser {
recipient_email: invitee_email,
user_name: domain::UserName::new(new_user.get_name())?,
settings: state.conf.clone(),
subject: "You have been invited to join Hyperswitch Community!",
merchant_id: user_from_token.merchant_id.clone(),
auth_id: auth_id.clone(),
})
};
});
let send_email_result = state
.email_client
.compose_and_send_email(email_contents, state.conf.proxy.https_url.as_ref())
@ -1047,115 +846,12 @@ pub async fn resend_invite(
Ok(ApplicationResponse::StatusOk)
}
#[cfg(feature = "email")]
pub async fn accept_invite_from_email(
state: SessionState,
request: user_api::AcceptInviteFromEmailRequest,
) -> UserResponse<user_api::DashboardEntryResponse> {
let token = request.token.expose();
let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
.await
.change_context(UserErrors::LinkInvalid)?;
auth::blacklist::check_email_token_in_blacklist(&state, &token).await?;
let user: domain::UserFromStorage = state
.global_store
.find_user_by_email(
&email_token
.get_email()
.change_context(UserErrors::InternalServerError)?,
)
.await
.change_context(UserErrors::InternalServerError)?
.into();
let merchant_id = email_token
.get_merchant_id()
.ok_or(UserErrors::InternalServerError)?;
let key_manager_state = &(&state).into();
let key_store = state
.store
.get_merchant_key_store_by_merchant_id(
key_manager_state,
merchant_id,
&state.store.get_master_key().to_vec().into(),
)
.await
.change_context(UserErrors::InternalServerError)
.attach_printable("merchant_key_store not found")?;
let merchant_account = state
.store
.find_merchant_account_by_merchant_id(key_manager_state, merchant_id, &key_store)
.await
.change_context(UserErrors::InternalServerError)
.attach_printable("merchant_account not found")?;
let (update_v1_result, update_v2_result) = utils::user_role::update_v1_and_v2_user_roles_in_db(
&state,
user.get_user_id(),
&merchant_account.organization_id,
merchant_id,
None,
UserRoleUpdate::UpdateStatus {
status: UserStatus::Active,
modified_by: user.get_user_id().to_string(),
},
)
.await;
if update_v1_result
.as_ref()
.is_err_and(|err| !err.current_context().is_db_not_found())
|| update_v2_result
.as_ref()
.is_err_and(|err| !err.current_context().is_db_not_found())
{
return Err(report!(UserErrors::InternalServerError));
}
if update_v1_result.is_err() && update_v2_result.is_err() {
return Err(report!(UserErrors::InvalidRoleOperation))
.attach_printable("User not found in the organization")?;
}
let _ = auth::blacklist::insert_email_token_in_blacklist(&state, &token)
.await
.map_err(|error| logger::error!(?error));
let user_from_db: domain::UserFromStorage = state
.global_store
.update_user_by_user_id(user.get_user_id(), storage_user::UserUpdate::VerifyUser)
.await
.change_context(UserErrors::InternalServerError)?
.into();
let user_role = user_from_db
.get_preferred_or_active_user_role_from_db(&state)
.await
.change_context(UserErrors::InternalServerError)?;
let token =
utils::user::generate_jwt_auth_token_without_profile(&state, &user_from_db, &user_role)
.await?;
utils::user_role::set_role_permissions_in_cache_by_user_role(&state, &user_role).await;
let response =
utils::user::get_dashboard_entry_response(&state, user_from_db, user_role, token.clone())?;
auth::cookies::set_cookie_response(response, token)
}
#[cfg(feature = "email")]
pub async fn accept_invite_from_email_token_only_flow(
state: SessionState,
user_token: auth::UserFromSinglePurposeToken,
request: user_api::AcceptInviteFromEmailRequest,
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::DashboardEntryResponse>> {
) -> UserResponse<user_api::TokenResponse> {
let token = request.token.expose();
let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
@ -1261,10 +957,10 @@ pub async fn accept_invite_from_email_token_only_flow(
.get_token_with_user_role(&state, &user_role)
.await?;
let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
let response = user_api::TokenResponse {
token: token.clone(),
token_type: next_flow.get_flow().into(),
});
};
auth::cookies::set_cookie_response(response, token)
}
@ -1503,7 +1199,7 @@ pub async fn list_merchants_for_user(
.await
.change_context(UserErrors::InternalServerError)?;
let merchant_accounts = state
let merchant_accounts_map = state
.store
.list_multiple_merchant_accounts(
&(&state).into(),
@ -1517,17 +1213,62 @@ pub async fn list_merchants_for_user(
.collect::<Result<Vec<_>, _>>()?,
)
.await
.change_context(UserErrors::InternalServerError)?;
.change_context(UserErrors::InternalServerError)?
.into_iter()
.map(|merchant_account| (merchant_account.get_id().clone(), merchant_account))
.collect::<HashMap<_, _>>();
let roles =
utils::user_role::get_multiple_role_info_for_user_roles(&state, &user_roles).await?;
let roles_map = futures::future::try_join_all(user_roles.iter().map(|user_role| async {
let Some(merchant_id) = &user_role.merchant_id else {
return Err(report!(UserErrors::InternalServerError))
.attach_printable("merchant_id not found for user_role");
};
let Some(org_id) = &user_role.org_id else {
return Err(report!(UserErrors::InternalServerError)
.attach_printable("org_id not found in user_role"));
};
roles::RoleInfo::from_role_id(&state, &user_role.role_id, merchant_id, org_id)
.await
.change_context(UserErrors::InternalServerError)
.attach_printable("Unable to find role info for user role")
}))
.await?
.into_iter()
.map(|role_info| (role_info.get_role_id().to_owned(), role_info))
.collect::<HashMap<_, _>>();
Ok(ApplicationResponse::Json(
utils::user::get_multiple_merchant_details_with_status(
user_roles,
merchant_accounts,
roles,
)?,
user_roles
.into_iter()
.map(|user_role| {
let Some(merchant_id) = &user_role.merchant_id else {
return Err(report!(UserErrors::InternalServerError))
.attach_printable("merchant_id not found for user_role");
};
let Some(org_id) = &user_role.org_id else {
return Err(report!(UserErrors::InternalServerError)
.attach_printable("org_id not found in user_role"));
};
let merchant_account = merchant_accounts_map
.get(merchant_id)
.ok_or(UserErrors::InternalServerError)
.attach_printable("Merchant account for user role doesn't exist")?;
let role_info = roles_map
.get(&user_role.role_id)
.ok_or(UserErrors::InternalServerError)
.attach_printable("Role info for user role doesn't exist")?;
Ok(user_api::UserMerchantAccount {
merchant_id: merchant_id.to_owned(),
merchant_name: merchant_account.merchant_name.clone(),
is_active: user_role.status == UserStatus::Active,
role_id: user_role.role_id,
role_name: role_info.get_role_name().to_string(),
org_id: org_id.to_owned(),
})
})
.collect::<Result<Vec<_>, _>>()?,
))
}
@ -1650,71 +1391,12 @@ pub async fn list_users_for_merchant_account(
)))
}
#[cfg(feature = "email")]
pub async fn verify_email(
state: SessionState,
req: user_api::VerifyEmailRequest,
) -> UserResponse<user_api::SignInResponse> {
let token = req.token.clone().expose();
let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
.await
.change_context(UserErrors::LinkInvalid)?;
auth::blacklist::check_email_token_in_blacklist(&state, &token).await?;
let user = state
.global_store
.find_user_by_email(
&email_token
.get_email()
.change_context(UserErrors::InternalServerError)?,
)
.await
.change_context(UserErrors::InternalServerError)?;
let user = state
.global_store
.update_user_by_user_id(user.user_id.as_str(), storage_user::UserUpdate::VerifyUser)
.await
.change_context(UserErrors::InternalServerError)?;
let user_from_db: domain::UserFromStorage = user.into();
let signin_strategy =
if let Some(preferred_merchant_id) = user_from_db.get_preferred_merchant_id() {
let preferred_role = user_from_db
.get_role_from_db_by_merchant_id(&state, &preferred_merchant_id)
.await
.change_context(UserErrors::InternalServerError)
.attach_printable("User role with preferred_merchant_id not found")?;
domain::SignInWithRoleStrategyType::SingleRole(domain::SignInWithSingleRoleStrategy {
user: user_from_db,
user_role: Box::new(preferred_role),
})
} else {
let user_roles = user_from_db.get_roles_from_db(&state).await?;
domain::SignInWithRoleStrategyType::decide_signin_strategy_by_user_roles(
user_from_db,
user_roles,
)
.await?
};
let _ = auth::blacklist::insert_email_token_in_blacklist(&state, &token)
.await
.map_err(|error| logger::error!(?error));
let response = signin_strategy.get_signin_response(&state).await?;
let token = utils::user::get_token_from_signin_response(&response);
auth::cookies::set_cookie_response(response, token)
}
#[cfg(feature = "email")]
pub async fn verify_email_token_only_flow(
state: SessionState,
user_token: auth::UserFromSinglePurposeToken,
req: user_api::VerifyEmailRequest,
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignInResponse>> {
) -> UserResponse<user_api::TokenResponse> {
let token = req.token.clone().expose();
let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
.await
@ -1754,10 +1436,10 @@ pub async fn verify_email_token_only_flow(
let next_flow = current_flow.next(user_from_db, &state).await?;
let token = next_flow.get_token(&state).await?;
let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
let response = user_api::TokenResponse {
token: token.clone(),
token_type: next_flow.get_flow().into(),
});
};
auth::cookies::set_cookie_response(response, token)
}
@ -2839,24 +2521,7 @@ pub async fn switch_org_for_user(
))?
.to_owned();
let merchant_id = if let Some(merchant_id) = &user_role.merchant_id {
merchant_id.clone()
} else {
state
.store
.list_merchant_accounts_by_organization_id(
key_manager_state,
request.org_id.get_string_repr(),
)
.await
.change_context(UserErrors::InternalServerError)
.attach_printable("Failed to list merchant accounts by organization_id")?
.first()
.ok_or(UserErrors::InternalServerError)
.attach_printable("No merchant account found for the given organization_id")?
.get_id()
.clone()
};
let merchant_id = utils::user_role::get_single_merchant_id(&state, &user_role).await?;
let profile_id = if let Some(profile_id) = &user_role.profile_id {
profile_id.clone()

View File

@ -24,20 +24,6 @@ pub mod role;
use common_enums::{EntityType, PermissionGroup};
use strum::IntoEnumIterator;
// TODO: To be deprecated once groups are stable
pub async fn get_authorization_info_with_modules(
_state: SessionState,
) -> UserResponse<user_role_api::AuthorizationInfoResponse> {
Ok(ApplicationResponse::Json(
user_role_api::AuthorizationInfoResponse(
info::get_module_authorization_info()
.into_iter()
.map(|module_info| user_role_api::AuthorizationInfo::Module(module_info.into()))
.collect(),
),
))
}
pub async fn get_authorization_info_with_groups(
_state: SessionState,
) -> UserResponse<user_role_api::AuthorizationInfoResponse> {
@ -50,6 +36,7 @@ pub async fn get_authorization_info_with_groups(
),
))
}
pub async fn get_authorization_info_with_group_tag(
) -> UserResponse<user_role_api::AuthorizationInfoResponse> {
static GROUPS_WITH_PARENT_TAGS: Lazy<Vec<user_role_api::ParentInfo>> = Lazy::new(|| {
@ -309,85 +296,11 @@ pub async fn accept_invitation(
Ok(ApplicationResponse::StatusOk)
}
pub async fn merchant_select(
state: SessionState,
user_token: auth::UserFromSinglePurposeToken,
req: user_role_api::MerchantSelectRequest,
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::DashboardEntryResponse>> {
let merchant_accounts = state
.store
.list_multiple_merchant_accounts(&(&state).into(), req.merchant_ids)
.await
.change_context(UserErrors::InternalServerError)?;
let update_result =
futures::future::join_all(merchant_accounts.iter().map(|merchant_account| async {
let (update_v1_result, update_v2_result) =
utils::user_role::update_v1_and_v2_user_roles_in_db(
&state,
user_token.user_id.as_str(),
&merchant_account.organization_id,
merchant_account.get_id(),
None,
UserRoleUpdate::UpdateStatus {
status: UserStatus::Active,
modified_by: user_token.user_id.clone(),
},
)
.await;
if update_v1_result.is_err_and(|err| !err.current_context().is_db_not_found())
|| update_v2_result.is_err_and(|err| !err.current_context().is_db_not_found())
{
Err(report!(UserErrors::InternalServerError))
} else {
Ok(())
}
}))
.await;
if update_result.iter().all(Result::is_err) {
return Err(UserErrors::MerchantIdNotFound.into());
}
if let Some(true) = req.need_dashboard_entry_response {
let user_from_db: domain::UserFromStorage = state
.global_store
.find_user_by_id(user_token.user_id.as_str())
.await
.change_context(UserErrors::InternalServerError)?
.into();
let user_role = user_from_db
.get_preferred_or_active_user_role_from_db(&state)
.await
.change_context(UserErrors::InternalServerError)?;
utils::user_role::set_role_permissions_in_cache_by_user_role(&state, &user_role).await;
let token =
utils::user::generate_jwt_auth_token_without_profile(&state, &user_from_db, &user_role)
.await?;
let response = utils::user::get_dashboard_entry_response(
&state,
user_from_db,
user_role,
token.clone(),
)?;
return auth::cookies::set_cookie_response(
user_api::TokenOrPayloadResponse::Payload(response),
token,
);
}
Ok(ApplicationResponse::StatusOk)
}
pub async fn merchant_select_token_only_flow(
state: SessionState,
user_token: auth::UserFromSinglePurposeToken,
req: user_role_api::MerchantSelectRequest,
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::DashboardEntryResponse>> {
) -> UserResponse<user_api::TokenResponse> {
let merchant_accounts = state
.store
.list_multiple_merchant_accounts(&(&state).into(), req.merchant_ids)
@ -444,10 +357,10 @@ pub async fn merchant_select_token_only_flow(
.get_token_with_user_role(&state, &user_role)
.await?;
let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
let response = user_api::TokenResponse {
token: token.clone(),
token_type: next_flow.get_flow().into(),
});
};
auth::cookies::set_cookie_response(response, token)
}

View File

@ -16,30 +16,10 @@ use crate::{
utils,
};
pub async fn get_role_from_token_with_permissions(
state: SessionState,
user_from_token: UserFromToken,
) -> UserResponse<role_api::GetRoleFromTokenResponse> {
let role_info = user_from_token
.get_role_info_from_db(&state)
.await
.attach_printable("Invalid role_id in JWT")?;
let permissions = role_info
.get_permissions_set()
.into_iter()
.map(Into::into)
.collect();
Ok(ApplicationResponse::Json(
role_api::GetRoleFromTokenResponse::Permissions(permissions),
))
}
pub async fn get_role_from_token_with_groups(
state: SessionState,
user_from_token: UserFromToken,
) -> UserResponse<role_api::GetRoleFromTokenResponse> {
) -> UserResponse<Vec<role_api::PermissionGroup>> {
let role_info = user_from_token
.get_role_info_from_db(&state)
.await
@ -47,9 +27,7 @@ pub async fn get_role_from_token_with_groups(
let permissions = role_info.get_permission_groups().to_vec();
Ok(ApplicationResponse::Json(
role_api::GetRoleFromTokenResponse::Groups(permissions),
))
Ok(ApplicationResponse::Json(permissions))
}
pub async fn create_role(
@ -105,56 +83,6 @@ pub async fn create_role(
))
}
// TODO: To be deprecated once groups are stable
pub async fn list_invitable_roles_with_permissions(
state: SessionState,
user_from_token: UserFromToken,
) -> UserResponse<role_api::ListRolesResponse> {
let predefined_roles_map = PREDEFINED_ROLES
.iter()
.filter(|(_, role_info)| role_info.is_invitable())
.map(|(role_id, role_info)| {
role_api::RoleInfoResponse::Permissions(role_api::RoleInfoWithPermissionsResponse {
permissions: role_info
.get_permissions_set()
.into_iter()
.map(Into::into)
.collect(),
role_id: role_id.to_string(),
role_name: role_info.get_role_name().to_string(),
role_scope: role_info.get_scope(),
})
});
let custom_roles_map = state
.store
.list_all_roles(&user_from_token.merchant_id, &user_from_token.org_id)
.await
.change_context(UserErrors::InternalServerError)?
.into_iter()
.filter_map(|role| {
let role_info = roles::RoleInfo::from(role);
role_info
.is_invitable()
.then_some(role_api::RoleInfoResponse::Permissions(
role_api::RoleInfoWithPermissionsResponse {
permissions: role_info
.get_permissions_set()
.into_iter()
.map(Into::into)
.collect(),
role_id: role_info.get_role_id().to_string(),
role_name: role_info.get_role_name().to_string(),
role_scope: role_info.get_scope(),
},
))
});
Ok(ApplicationResponse::Json(role_api::ListRolesResponse(
predefined_roles_map.chain(custom_roles_map).collect(),
)))
}
pub async fn list_invitable_roles_with_groups(
state: SessionState,
user_from_token: UserFromToken,
@ -162,14 +90,14 @@ pub async fn list_invitable_roles_with_groups(
let predefined_roles_map = PREDEFINED_ROLES
.iter()
.filter(|(_, role_info)| role_info.is_invitable())
.map(|(role_id, role_info)| {
role_api::RoleInfoResponse::Groups(role_api::RoleInfoWithGroupsResponse {
.map(
|(role_id, role_info)| role_api::RoleInfoWithGroupsResponse {
groups: role_info.get_permission_groups().to_vec(),
role_id: role_id.to_string(),
role_name: role_info.get_role_name().to_string(),
role_scope: role_info.get_scope(),
})
});
},
);
let custom_roles_map = state
.store
@ -181,14 +109,12 @@ pub async fn list_invitable_roles_with_groups(
let role_info = roles::RoleInfo::from(role);
role_info
.is_invitable()
.then_some(role_api::RoleInfoResponse::Groups(
role_api::RoleInfoWithGroupsResponse {
groups: role_info.get_permission_groups().to_vec(),
role_id: role_info.get_role_id().to_string(),
role_name: role_info.get_role_name().to_string(),
role_scope: role_info.get_scope(),
},
))
.then_some(role_api::RoleInfoWithGroupsResponse {
groups: role_info.get_permission_groups().to_vec(),
role_id: role_info.get_role_id().to_string(),
role_name: role_info.get_role_name().to_string(),
role_scope: role_info.get_scope(),
})
});
Ok(ApplicationResponse::Json(role_api::ListRolesResponse(
@ -196,46 +122,11 @@ pub async fn list_invitable_roles_with_groups(
)))
}
// TODO: To be deprecated once groups are stable
pub async fn get_role_with_permissions(
state: SessionState,
user_from_token: UserFromToken,
role: role_api::GetRoleRequest,
) -> UserResponse<role_api::RoleInfoResponse> {
let role_info = roles::RoleInfo::from_role_id(
&state,
&role.role_id,
&user_from_token.merchant_id,
&user_from_token.org_id,
)
.await
.to_not_found_response(UserErrors::InvalidRoleId)?;
if role_info.is_internal() {
return Err(UserErrors::InvalidRoleId.into());
}
let permissions = role_info
.get_permissions_set()
.into_iter()
.map(Into::into)
.collect();
Ok(ApplicationResponse::Json(
role_api::RoleInfoResponse::Permissions(role_api::RoleInfoWithPermissionsResponse {
permissions,
role_id: role.role_id,
role_name: role_info.get_role_name().to_string(),
role_scope: role_info.get_scope(),
}),
))
}
pub async fn get_role_with_groups(
state: SessionState,
user_from_token: UserFromToken,
role: role_api::GetRoleRequest,
) -> UserResponse<role_api::RoleInfoResponse> {
) -> UserResponse<role_api::RoleInfoWithGroupsResponse> {
let role_info = roles::RoleInfo::from_role_id(
&state,
&role.role_id,
@ -250,12 +141,12 @@ pub async fn get_role_with_groups(
}
Ok(ApplicationResponse::Json(
role_api::RoleInfoResponse::Groups(role_api::RoleInfoWithGroupsResponse {
role_api::RoleInfoWithGroupsResponse {
groups: role_info.get_permission_groups().to_vec(),
role_id: role.role_id,
role_name: role_info.get_role_name().to_string(),
role_scope: role_info.get_scope(),
}),
},
))
}