#[cfg(any(feature = "app-server-types", feature = "authnz-server-types"))]
use impulse_server_kit::salvo;
#[cfg(any(feature = "app-server-types", feature = "authnz-server-types"))]
use salvo::oapi::ToSchema;
use serde::{Deserialize, Serialize};
use crate::{AccessTag, CBAChallengeSign, Id, TokenBundle};
use crate::{MResult, ServerError};
#[cfg_attr(any(feature = "app-server-types", feature = "authnz-server-types"), derive(ToSchema))]
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone, Debug)]
pub struct UserAuthorizeRequest {
pub access_token: String,
pub refresh_token: String,
pub client_token: Option<String>,
pub cba_challenge_sign: Option<CBAChallengeSign>,
pub requested_tags: Vec<AccessTag>,
}
impl UserAuthorizeRequest {
#[allow(clippy::new_ret_no_self)]
pub fn new() -> UserAuthorizeRequestBuilder {
Default::default()
}
pub fn into_parts(self) -> (TokenBundle, Vec<AccessTag>, Option<CBAChallengeSign>) {
(
TokenBundle {
access: self.access_token,
refresh: self.refresh_token,
client: self.client_token,
},
self.requested_tags,
self.cba_challenge_sign,
)
}
}
#[derive(Default)]
pub struct UserAuthorizeRequestBuilder {
access_token: Option<String>,
refresh_token: Option<String>,
client_token: Option<String>,
cba_challenge_sign: Option<CBAChallengeSign>,
requested_tags: Option<Vec<AccessTag>>,
}
impl UserAuthorizeRequestBuilder {
pub fn token_pair(mut self, act: impl ToString, rft: impl ToString) -> Self {
self.access_token = Some(act.to_string());
self.refresh_token = Some(rft.to_string());
self
}
pub fn token_triple(mut self, act: impl ToString, rft: impl ToString, cba: impl ToString) -> Self {
self.access_token = Some(act.to_string());
self.refresh_token = Some(rft.to_string());
self.client_token = Some(cba.to_string());
self
}
pub fn with_tags(mut self, tags: &[impl Into<AccessTag> + Clone]) -> Self {
let tags = tags.iter().map(|t| t.clone().into()).collect::<Vec<_>>();
self.requested_tags = Some(tags);
self
}
pub fn no_tags(mut self) -> Self {
self.requested_tags = Some(vec![]);
self
}
pub fn with_signed_challenge(mut self, sign: Vec<u8>) -> Self {
self.cba_challenge_sign = Some(CBAChallengeSign::new(sign));
self
}
#[allow(clippy::unwrap_used)]
pub fn build(self) -> MResult<UserAuthorizeRequest> {
if self.access_token.is_none() || self.refresh_token.is_none() {
ServerError::from_private_str("You must specify at least access & refresh tokens to perform authorization request!")
.with_500()
.bail()?;
}
if self.requested_tags.is_none() {
ServerError::from_private_str("You must specify requested tags (`.with_tags(...)`) or no tags at all (`.no_tags()`) explicitly!")
.with_500()
.bail()?;
}
let req = UserAuthorizeRequest {
access_token: unsafe { self.access_token.unwrap_unchecked() },
refresh_token: unsafe { self.refresh_token.unwrap_unchecked() },
client_token: self.client_token,
requested_tags: unsafe { self.requested_tags.unwrap_unchecked() },
cba_challenge_sign: self.cba_challenge_sign,
};
Ok(req)
}
}
#[cfg_attr(any(feature = "app-server-types", feature = "authnz-server-types"), derive(ToSchema))]
#[derive(Deserialize, Serialize, PartialEq, Eq, Hash, Clone, Debug)]
pub struct UserAuthorizeResponse {
pub approved: bool,
pub id: Option<Id>,
pub new_access_token: Option<String>,
pub new_cba_challenge: Option<Vec<u8>>,
pub new_cba_token: Option<String>,
}
#[derive(Deserialize, Serialize)]
pub struct ApplicationAuthorizeResponse {
pub authorized: bool,
pub user_id: Option<Id>,
}