use super::JwtSignOptions;
use alibi_core::AuthRequest;
use alibi_core::AuthResult;
use alibi_core::CreateJwk;
use alibi_core::Jwk;
use alibi_core::wire::SessionView;
use alibi_core::wire::UserView;
use async_trait::async_trait;
use serde::Serialize;
use serde_json::Map;
use serde_json::Value;
#[derive(Clone, Debug, Serialize)]
pub struct JwtSession {
pub user: UserView,
pub session: SessionView,
#[serde(rename = "needsRefresh", skip_serializing_if = "Option::is_none")]
pub needs_refresh: Option<bool>,
#[serde(rename = "updatedAt", skip_serializing_if = "Option::is_none")]
pub updated_at: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
}
#[async_trait]
pub trait DefineJwtPayload: Send + Sync {
async fn define_payload(&self, session: &JwtSession) -> AuthResult<Map<String, Value>>;
}
#[async_trait]
pub trait DefineJwtSubject: Send + Sync {
async fn subject(&self, session: &JwtSession) -> AuthResult<Option<String>>;
}
#[async_trait]
pub trait JwtKeyring: Send + Sync {
async fn keys(&self, context: &JwtKeyringContext<'_>) -> AuthResult<Vec<Jwk>>;
async fn create_key(&self, key: CreateJwk, context: &JwtKeyringContext<'_>) -> AuthResult<Jwk>;
}
#[derive(Clone, Copy, Debug)]
pub struct JwtKeyringContext<'a> {
pub path: &'a str,
pub request: Option<&'a AuthRequest>,
pub endpoint: Option<&'a alibi_core::endpoint::EndpointCall>,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum RemoteJwtClaim<'a> {
Absent,
Undefined,
Value(&'a alibi_core::utils::json::JsValue),
}
#[derive(Clone, Debug)]
pub struct RemoteJwtPayload {
pub(in crate::jwt) raw_claims: alibi_core::utils::json::JsValue,
pub(in crate::jwt) own_keys: Vec<String>,
pub(in crate::jwt) undefined_claims: Vec<String>,
}
impl RemoteJwtPayload {
#[must_use]
pub const fn raw_claims(&self) -> &alibi_core::utils::json::JsValue {
&self.raw_claims
}
#[must_use]
pub fn own_keys(&self) -> &[String] {
&self.own_keys
}
#[must_use]
pub fn claim(&self, name: &str) -> RemoteJwtClaim<'_> {
if self.undefined_claims.iter().any(|key| key == name) {
RemoteJwtClaim::Undefined
} else if let Some(value) = self.raw_claims.get(name) {
RemoteJwtClaim::Value(value)
} else {
RemoteJwtClaim::Absent
}
}
}
#[async_trait]
pub trait SignRemoteJwt: Send + Sync {
async fn sign(
&self,
payload: &RemoteJwtPayload,
options: &JwtSignOptions,
) -> AuthResult<String>;
}