mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 20:23:43 +08:00
feat(users): Create Token only support for pre-login user flow APIs (#4558)
This commit is contained in:
@ -14,8 +14,8 @@ use crate::user::{
|
||||
CreateInternalUserRequest, DashboardEntryResponse, ForgotPasswordRequest,
|
||||
GetUserDetailsResponse, GetUserRoleDetailsRequest, GetUserRoleDetailsResponse,
|
||||
InviteUserRequest, ListUsersResponse, ReInviteUserRequest, ResetPasswordRequest,
|
||||
SendVerifyEmailRequest, SignInResponse, SignInWithTokenResponse, SignUpRequest,
|
||||
SignUpWithMerchantIdRequest, SwitchMerchantIdRequest, TokenResponse,
|
||||
SendVerifyEmailRequest, SignInResponse, SignUpRequest, SignUpWithMerchantIdRequest,
|
||||
SwitchMerchantIdRequest, TokenOrPayloadResponse, TokenResponse,
|
||||
UpdateUserAccountDetailsRequest, UserFromEmailRequest, UserMerchantCreate, VerifyEmailRequest,
|
||||
};
|
||||
|
||||
@ -38,6 +38,12 @@ impl ApiEventMetric for VerifyTokenResponse {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ApiEventMetric for TokenOrPayloadResponse<T> {
|
||||
fn get_api_event_type(&self) -> Option<ApiEventsType> {
|
||||
Some(ApiEventsType::Miscellaneous)
|
||||
}
|
||||
}
|
||||
|
||||
common_utils::impl_misc_api_event_type!(
|
||||
SignUpRequest,
|
||||
SignUpWithMerchantIdRequest,
|
||||
@ -62,7 +68,6 @@ common_utils::impl_misc_api_event_type!(
|
||||
SignInResponse,
|
||||
UpdateUserAccountDetailsRequest,
|
||||
GetUserDetailsResponse,
|
||||
SignInWithTokenResponse,
|
||||
GetUserRoleDetailsRequest,
|
||||
GetUserRoleDetailsResponse,
|
||||
TokenResponse,
|
||||
|
||||
@ -227,9 +227,9 @@ pub struct TokenResponse {
|
||||
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum SignInWithTokenResponse {
|
||||
pub enum TokenOrPayloadResponse<T> {
|
||||
Token(TokenResponse),
|
||||
SignInResponse(SignInResponse),
|
||||
Payload(T),
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||
|
||||
@ -99,6 +99,7 @@ pub enum UserStatus {
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||
pub struct AcceptInvitationRequest {
|
||||
pub merchant_ids: Vec<String>,
|
||||
// TODO: Remove this once the token only api is being used
|
||||
pub need_dashboard_entry_response: Option<bool>,
|
||||
}
|
||||
|
||||
|
||||
@ -94,7 +94,7 @@ pub async fn get_user_details(
|
||||
pub async fn signup(
|
||||
state: AppState,
|
||||
request: user_api::SignUpRequest,
|
||||
) -> UserResponse<user_api::SignUpResponse> {
|
||||
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignUpResponse>> {
|
||||
let new_user = domain::NewUser::try_from(request)?;
|
||||
new_user
|
||||
.get_new_merchant()
|
||||
@ -117,13 +117,48 @@ pub async fn signup(
|
||||
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: AppState,
|
||||
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_user_role_in_db(
|
||||
state.clone(),
|
||||
consts::user_role::ROLE_ID_ORGANIZATION_ADMIN.to_string(),
|
||||
UserStatus::Active,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let next_flow =
|
||||
domain::NextFlow::from_origin(domain::Origin::SignUp, user_from_db.clone(), &state).await?;
|
||||
|
||||
let token = next_flow
|
||||
.get_token_with_user_role(&state, &user_role)
|
||||
.await?;
|
||||
|
||||
let response = user_api::TokenOrPayloadResponse::Token(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: AppState,
|
||||
request: user_api::SignInRequest,
|
||||
) -> UserResponse<user_api::SignInWithTokenResponse> {
|
||||
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignInResponse>> {
|
||||
let user_from_db: domain::UserFromStorage = state
|
||||
.store
|
||||
.find_user_by_email(&request.email)
|
||||
@ -161,16 +196,13 @@ pub async fn signin(
|
||||
|
||||
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::SignInWithTokenResponse::SignInResponse(response),
|
||||
token,
|
||||
)
|
||||
auth::cookies::set_cookie_response(user_api::TokenOrPayloadResponse::Payload(response), token)
|
||||
}
|
||||
|
||||
pub async fn signin_token_only_flow(
|
||||
state: AppState,
|
||||
request: user_api::SignInRequest,
|
||||
) -> UserResponse<user_api::SignInWithTokenResponse> {
|
||||
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignInResponse>> {
|
||||
let user_from_db: domain::UserFromStorage = state
|
||||
.store
|
||||
.find_user_by_email(&request.email)
|
||||
@ -185,7 +217,7 @@ pub async fn signin_token_only_flow(
|
||||
|
||||
let token = next_flow.get_token(&state).await?;
|
||||
|
||||
let response = user_api::SignInWithTokenResponse::Token(user_api::TokenResponse {
|
||||
let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
|
||||
token: token.clone(),
|
||||
token_type: next_flow.get_flow().into(),
|
||||
});
|
||||
@ -820,6 +852,73 @@ pub async fn accept_invite_from_email(
|
||||
auth::cookies::set_cookie_response(response, token)
|
||||
}
|
||||
|
||||
#[cfg(feature = "email")]
|
||||
pub async fn accept_invite_from_email_token_only_flow(
|
||||
state: AppState,
|
||||
user_token: auth::UserFromSinglePurposeToken,
|
||||
request: user_api::AcceptInviteFromEmailRequest,
|
||||
) -> UserResponse<user_api::TokenOrPayloadResponse<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_from_db: domain::UserFromStorage = state
|
||||
.store
|
||||
.find_user_by_email(
|
||||
&email_token
|
||||
.get_email()
|
||||
.change_context(UserErrors::InternalServerError)?,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?
|
||||
.into();
|
||||
|
||||
if user_from_db.get_user_id() != user_token.user_id {
|
||||
return Err(UserErrors::LinkInvalid.into());
|
||||
}
|
||||
|
||||
let merchant_id = email_token
|
||||
.get_merchant_id()
|
||||
.ok_or(UserErrors::LinkInvalid)?;
|
||||
|
||||
let user_role = state
|
||||
.store
|
||||
.update_user_role_by_user_id_merchant_id(
|
||||
user_from_db.get_user_id(),
|
||||
merchant_id,
|
||||
UserRoleUpdate::UpdateStatus {
|
||||
status: UserStatus::Active,
|
||||
modified_by: user_from_db.get_user_id().to_string(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?;
|
||||
|
||||
let _ = auth::blacklist::insert_email_token_in_blacklist(&state, &token)
|
||||
.await
|
||||
.map_err(|e| logger::error!(?e));
|
||||
|
||||
let current_flow = domain::CurrentFlow::new(
|
||||
user_token.origin,
|
||||
domain::SPTFlow::AcceptInvitationFromEmail.into(),
|
||||
)?;
|
||||
let next_flow = current_flow.next(user_from_db.clone(), &state).await?;
|
||||
|
||||
let token = next_flow
|
||||
.get_token_with_user_role(&state, &user_role)
|
||||
.await?;
|
||||
|
||||
let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
|
||||
token: token.clone(),
|
||||
token_type: next_flow.get_flow().into(),
|
||||
});
|
||||
auth::cookies::set_cookie_response(response, token)
|
||||
}
|
||||
|
||||
pub async fn create_internal_user(
|
||||
state: AppState,
|
||||
request: user_api::CreateInternalUserRequest,
|
||||
@ -1196,6 +1295,60 @@ pub async fn verify_email(
|
||||
auth::cookies::set_cookie_response(response, token)
|
||||
}
|
||||
|
||||
#[cfg(feature = "email")]
|
||||
pub async fn verify_email_token_only_flow(
|
||||
state: AppState,
|
||||
user_token: auth::UserFromSinglePurposeToken,
|
||||
req: user_api::VerifyEmailRequest,
|
||||
) -> UserResponse<user_api::TokenOrPayloadResponse<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_from_email = state
|
||||
.store
|
||||
.find_user_by_email(
|
||||
&email_token
|
||||
.get_email()
|
||||
.change_context(UserErrors::InternalServerError)?,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?;
|
||||
|
||||
if user_from_email.user_id != user_token.user_id {
|
||||
return Err(UserErrors::LinkInvalid.into());
|
||||
}
|
||||
|
||||
let user_from_db: domain::UserFromStorage = state
|
||||
.store
|
||||
.update_user_by_user_id(
|
||||
user_from_email.user_id.as_str(),
|
||||
storage_user::UserUpdate::VerifyUser,
|
||||
)
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?
|
||||
.into();
|
||||
|
||||
let _ = auth::blacklist::insert_email_token_in_blacklist(&state, &token)
|
||||
.await
|
||||
.map_err(|e| logger::error!(?e));
|
||||
|
||||
let current_flow =
|
||||
domain::CurrentFlow::new(user_token.origin, domain::SPTFlow::VerifyEmail.into())?;
|
||||
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 {
|
||||
token: token.clone(),
|
||||
token_type: next_flow.get_flow().into(),
|
||||
});
|
||||
|
||||
auth::cookies::set_cookie_response(response, token)
|
||||
}
|
||||
|
||||
#[cfg(feature = "email")]
|
||||
pub async fn send_verification_mail(
|
||||
state: AppState,
|
||||
|
||||
@ -172,8 +172,7 @@ pub async fn accept_invitation(
|
||||
state: AppState,
|
||||
user_token: auth::UserFromSinglePurposeToken,
|
||||
req: user_role_api::AcceptInvitationRequest,
|
||||
_req_state: ReqState,
|
||||
) -> UserResponse<user_api::DashboardEntryResponse> {
|
||||
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::DashboardEntryResponse>> {
|
||||
let user_role = futures::future::join_all(req.merchant_ids.iter().map(|merchant_id| async {
|
||||
state
|
||||
.store
|
||||
@ -215,12 +214,65 @@ pub async fn accept_invitation(
|
||||
user_role,
|
||||
token.clone(),
|
||||
)?;
|
||||
return auth::cookies::set_cookie_response(response, token);
|
||||
return auth::cookies::set_cookie_response(
|
||||
user_api::TokenOrPayloadResponse::Payload(response),
|
||||
token,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(ApplicationResponse::StatusOk)
|
||||
}
|
||||
|
||||
pub async fn accept_invitation_token_only_flow(
|
||||
state: AppState,
|
||||
user_token: auth::UserFromSinglePurposeToken,
|
||||
req: user_role_api::AcceptInvitationRequest,
|
||||
) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::DashboardEntryResponse>> {
|
||||
let user_role = futures::future::join_all(req.merchant_ids.iter().map(|merchant_id| async {
|
||||
state
|
||||
.store
|
||||
.update_user_role_by_user_id_merchant_id(
|
||||
user_token.user_id.as_str(),
|
||||
merchant_id,
|
||||
UserRoleUpdate::UpdateStatus {
|
||||
status: UserStatus::Active,
|
||||
modified_by: user_token.user_id.clone(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
logger::error!("Error while accepting invitation {}", e);
|
||||
})
|
||||
.ok()
|
||||
}))
|
||||
.await
|
||||
.into_iter()
|
||||
.reduce(Option::or)
|
||||
.flatten()
|
||||
.ok_or(UserErrors::MerchantIdNotFound)?;
|
||||
|
||||
let user_from_db: domain::UserFromStorage = state
|
||||
.store
|
||||
.find_user_by_id(user_token.user_id.as_str())
|
||||
.await
|
||||
.change_context(UserErrors::InternalServerError)?
|
||||
.into();
|
||||
|
||||
let current_flow =
|
||||
domain::CurrentFlow::new(user_token.origin, domain::SPTFlow::MerchantSelect.into())?;
|
||||
let next_flow = current_flow.next(user_from_db.clone(), &state).await?;
|
||||
|
||||
let token = next_flow
|
||||
.get_token_with_user_role(&state, &user_role)
|
||||
.await?;
|
||||
|
||||
let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
|
||||
token: token.clone(),
|
||||
token_type: next_flow.get_flow().into(),
|
||||
});
|
||||
auth::cookies::set_cookie_response(response, token)
|
||||
}
|
||||
|
||||
pub async fn delete_user_role(
|
||||
state: AppState,
|
||||
user_from_token: auth::UserFromToken,
|
||||
|
||||
@ -57,15 +57,23 @@ pub async fn user_signup(
|
||||
state: web::Data<AppState>,
|
||||
http_req: HttpRequest,
|
||||
json_payload: web::Json<user_api::SignUpRequest>,
|
||||
query: web::Query<user_api::TokenOnlyQueryParam>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::UserSignUp;
|
||||
let req_payload = json_payload.into_inner();
|
||||
let is_token_only = query.into_inner().token_only;
|
||||
Box::pin(api::server_wrap(
|
||||
flow.clone(),
|
||||
state,
|
||||
&http_req,
|
||||
req_payload.clone(),
|
||||
|state, _, req_body, _| user_core::signup(state, req_body),
|
||||
|state, _, req_body, _| async move {
|
||||
if let Some(true) = is_token_only {
|
||||
user_core::signup_token_only_flow(state, req_body).await
|
||||
} else {
|
||||
user_core::signup(state, req_body).await
|
||||
}
|
||||
},
|
||||
&auth::NoAuth,
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
@ -428,18 +436,37 @@ pub async fn accept_invite_from_email(
|
||||
state: web::Data<AppState>,
|
||||
req: HttpRequest,
|
||||
payload: web::Json<user_api::AcceptInviteFromEmailRequest>,
|
||||
query: web::Query<user_api::TokenOnlyQueryParam>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::AcceptInviteFromEmail;
|
||||
Box::pin(api::server_wrap(
|
||||
flow,
|
||||
state.clone(),
|
||||
&req,
|
||||
payload.into_inner(),
|
||||
|state, _, request_payload, _| user_core::accept_invite_from_email(state, request_payload),
|
||||
&auth::NoAuth,
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
.await
|
||||
let is_token_only = query.into_inner().token_only;
|
||||
if let Some(true) = is_token_only {
|
||||
Box::pin(api::server_wrap(
|
||||
flow.clone(),
|
||||
state,
|
||||
&req,
|
||||
payload.into_inner(),
|
||||
|state, user, req_payload, _| {
|
||||
user_core::accept_invite_from_email_token_only_flow(state, user, req_payload)
|
||||
},
|
||||
&auth::SinglePurposeJWTAuth(common_enums::TokenPurpose::AcceptInvitationFromEmail),
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
.await
|
||||
} else {
|
||||
Box::pin(api::server_wrap(
|
||||
flow,
|
||||
state.clone(),
|
||||
&req,
|
||||
payload.into_inner(),
|
||||
|state, _, request_payload, _| {
|
||||
user_core::accept_invite_from_email(state, request_payload)
|
||||
},
|
||||
&auth::NoAuth,
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "email")]
|
||||
@ -447,18 +474,35 @@ pub async fn verify_email(
|
||||
state: web::Data<AppState>,
|
||||
http_req: HttpRequest,
|
||||
json_payload: web::Json<user_api::VerifyEmailRequest>,
|
||||
query: web::Query<user_api::TokenOnlyQueryParam>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::VerifyEmail;
|
||||
Box::pin(api::server_wrap(
|
||||
flow.clone(),
|
||||
state,
|
||||
&http_req,
|
||||
json_payload.into_inner(),
|
||||
|state, _, req_payload, _| user_core::verify_email(state, req_payload),
|
||||
&auth::NoAuth,
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
.await
|
||||
let is_token_only = query.into_inner().token_only;
|
||||
if let Some(true) = is_token_only {
|
||||
Box::pin(api::server_wrap(
|
||||
flow.clone(),
|
||||
state,
|
||||
&http_req,
|
||||
json_payload.into_inner(),
|
||||
|state, user, req_payload, _| {
|
||||
user_core::verify_email_token_only_flow(state, user, req_payload)
|
||||
},
|
||||
&auth::SinglePurposeJWTAuth(common_enums::TokenPurpose::VerifyEmail),
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
.await
|
||||
} else {
|
||||
Box::pin(api::server_wrap(
|
||||
flow.clone(),
|
||||
state,
|
||||
&http_req,
|
||||
json_payload.into_inner(),
|
||||
|state, _, req_payload, _| user_core::verify_email(state, req_payload),
|
||||
&auth::NoAuth,
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "email")]
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use api_models::user_role::{self as user_role_api, role as role_api};
|
||||
use api_models::{
|
||||
user as user_api,
|
||||
user_role::{self as user_role_api, role as role_api},
|
||||
};
|
||||
use common_enums::TokenPurpose;
|
||||
use router_env::Flow;
|
||||
|
||||
@ -206,15 +209,23 @@ pub async fn accept_invitation(
|
||||
state: web::Data<AppState>,
|
||||
req: HttpRequest,
|
||||
json_payload: web::Json<user_role_api::AcceptInvitationRequest>,
|
||||
query: web::Query<user_api::TokenOnlyQueryParam>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::AcceptInvitation;
|
||||
let payload = json_payload.into_inner();
|
||||
let is_token_only = query.into_inner().token_only;
|
||||
Box::pin(api::server_wrap(
|
||||
flow,
|
||||
state.clone(),
|
||||
&req,
|
||||
payload,
|
||||
user_role_core::accept_invitation,
|
||||
|state, user, req_body, _| async move {
|
||||
if let Some(true) = is_token_only {
|
||||
user_role_core::accept_invitation_token_only_flow(state, user, req_body).await
|
||||
} else {
|
||||
user_role_core::accept_invitation(state, user, req_body).await
|
||||
}
|
||||
},
|
||||
&auth::SinglePurposeJWTAuth(TokenPurpose::AcceptInvite),
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
|
||||
@ -7,6 +7,7 @@ use crate::{
|
||||
core::errors::{StorageErrorExt, UserErrors, UserResult},
|
||||
routes::AppState,
|
||||
services::authentication as auth,
|
||||
utils,
|
||||
};
|
||||
|
||||
#[derive(Eq, PartialEq, Clone, Copy)]
|
||||
@ -150,8 +151,9 @@ const VERIFY_EMAIL_FLOW: [UserFlow; 5] = [
|
||||
UserFlow::JWTFlow(JWTFlow::UserInfo),
|
||||
];
|
||||
|
||||
const ACCEPT_INVITATION_FROM_EMAIL_FLOW: [UserFlow; 4] = [
|
||||
const ACCEPT_INVITATION_FROM_EMAIL_FLOW: [UserFlow; 5] = [
|
||||
UserFlow::SPTFlow(SPTFlow::TOTP),
|
||||
UserFlow::SPTFlow(SPTFlow::VerifyEmail),
|
||||
UserFlow::SPTFlow(SPTFlow::AcceptInvitationFromEmail),
|
||||
UserFlow::SPTFlow(SPTFlow::ForceSetPassword),
|
||||
UserFlow::JWTFlow(JWTFlow::UserInfo),
|
||||
@ -234,16 +236,38 @@ impl NextFlow {
|
||||
{
|
||||
self.user.get_verification_days_left(state)?;
|
||||
}
|
||||
|
||||
let user_role = self
|
||||
.user
|
||||
.get_preferred_or_active_user_role_from_db(state)
|
||||
.await
|
||||
.to_not_found_response(UserErrors::InternalServerError)?;
|
||||
utils::user_role::set_role_permissions_in_cache_by_user_role(state, &user_role)
|
||||
.await;
|
||||
|
||||
jwt_flow.generate_jwt(state, self, &user_role).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_token_with_user_role(
|
||||
&self,
|
||||
state: &AppState,
|
||||
user_role: &UserRole,
|
||||
) -> UserResult<Secret<String>> {
|
||||
match self.next_flow {
|
||||
UserFlow::SPTFlow(spt_flow) => spt_flow.generate_spt(state, self).await,
|
||||
UserFlow::JWTFlow(jwt_flow) => {
|
||||
#[cfg(feature = "email")]
|
||||
{
|
||||
self.user.get_verification_days_left(state)?;
|
||||
}
|
||||
utils::user_role::set_role_permissions_in_cache_by_user_role(state, user_role)
|
||||
.await;
|
||||
|
||||
jwt_flow.generate_jwt(state, self, user_role).await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UserFlow> for TokenPurpose {
|
||||
@ -274,3 +298,15 @@ impl From<JWTFlow> for TokenPurpose {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SPTFlow> for UserFlow {
|
||||
fn from(value: SPTFlow) -> Self {
|
||||
Self::SPTFlow(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<JWTFlow> for UserFlow {
|
||||
fn from(value: JWTFlow) -> Self {
|
||||
Self::JWTFlow(value)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user