use cedar_policy::{ContextJsonError, ParseErrors, RequestValidationError};
use serde_json::Error as SerdeJsonError;
use crate::entity_builder::MultiIssuerEntityError;
use crate::entity_builder::{BuildEntityError, BuildUnsignedEntityError};
use crate::jwt::JwtProcessingError;
use cedar_policy::entities_errors::EntitiesError;
#[derive(Debug, thiserror::Error)]
pub enum MultiIssuerValidationError {
#[error("Token input validation failed: {0}")]
TokenInput(#[from] TokenInputError),
#[error("Empty token array")]
EmptyTokenArray,
#[error("Could not validate tokens.")]
TokenValidationFailed,
#[error("Invalid JSON in context field")]
InvalidContextJson,
#[error("Missing issuer claim in JWT")]
MissingIssuer,
#[error("JWT claims are not a JSON object: {0}")]
InvalidClaims(&'static str),
}
#[derive(Debug, thiserror::Error)]
pub enum TokenInputError {
#[error("Empty mapping string")]
EmptyMapping,
#[error("Empty payload")]
EmptyPayload,
}
#[derive(thiserror::Error, Debug)]
pub enum AuthorizeError {
#[error(transparent)]
ProcessTokens(#[from] JwtProcessingError),
#[error("could not parse action: {0}")]
Action(Box<ParseErrors>),
#[error("could not parse identifier: {0}")]
IdentifierParsing(Box<ParseErrors>),
#[error("could not create context: {0}")]
CreateContext(#[from] Box<ContextJsonError>),
#[error(transparent)]
InvalidPrincipal(#[from] Box<InvalidPrincipalError>),
#[error("request validation error: {0}")]
RequestValidation(#[from] Box<RequestValidationError>),
#[error("failed to validate Cedar entities: {0:?}")]
ValidateEntities(#[from] Box<EntitiesError>),
#[error("could not convert entities to json: {0}")]
EntitiesToJson(SerdeJsonError),
#[error("Failed to build context: {0}")]
BuildContext(#[from] BuildContextError),
#[error(transparent)]
BuildEntity(#[from] BuildEntityError),
#[error("failed to build role entities for unsigned request: {0}")]
BuildUnsignedRoleEntity(#[from] BuildUnsignedEntityError),
#[error(transparent)]
MultiIssuerValidation(#[from] MultiIssuerValidationError),
#[error("Multi-issuer entity building failed: {0}")]
MultiIssuerEntity(MultiIssuerEntityError),
}
impl From<ParseErrors> for AuthorizeError {
fn from(err: ParseErrors) -> Self {
Self::Action(Box::new(err))
}
}
impl From<InvalidPrincipalError> for AuthorizeError {
fn from(err: InvalidPrincipalError) -> Self {
Self::InvalidPrincipal(Box::new(err))
}
}
#[derive(Debug, thiserror::Error)]
pub enum BuildContextError {
#[error("failed to merge JSON objects due to conflicting keys: {0}")]
KeyConflict(String),
#[error(transparent)]
DeserializeFromJson(#[from] Box<ContextJsonError>),
#[error("failed to find the action `{0}` in the schema")]
UnknownAction(String),
#[error("failed to build entity reference for `{0}` since an entity id was not provided")]
MissingEntityId(String),
#[error("invalid action context type: {0}. expected: {1}")]
InvalidKind(String, String),
#[error("failed to parse the entity name `{0}`: {1}")]
ParseEntityName(String, Box<ParseErrors>),
#[error("failed to create Cedar context: {0}")]
ContextCreation(String),
}
impl From<ContextJsonError> for BuildContextError {
fn from(err: ContextJsonError) -> Self {
BuildContextError::DeserializeFromJson(Box::new(err))
}
}
#[derive(Debug, derive_more::Error, derive_more::Display)]
#[display("The request for `{principal}` does not conform to the schema: {err}")]
pub struct InvalidPrincipalError {
pub principal: cedar_policy::EntityUid,
pub err: RequestValidationError,
}
impl InvalidPrincipalError {
pub fn new(principal: &cedar_policy::EntityUid, err: RequestValidationError) -> Self {
InvalidPrincipalError {
principal: principal.clone(),
err,
}
}
}