use std::sync::Once;
use std::time::Duration;
use anyhow::{Result, bail};
use chrono::{Duration as ChronoDuration, Utc};
use jsonwebtoken::EncodingKey;
use crate::catalog;
use crate::err::Error;
pub(crate) fn config(alg: catalog::Algorithm, key: &str) -> Result<EncodingKey> {
match alg {
catalog::Algorithm::Hs256 => Ok(EncodingKey::from_secret(key.as_ref())),
catalog::Algorithm::Hs384 => Ok(EncodingKey::from_secret(key.as_ref())),
catalog::Algorithm::Hs512 => Ok(EncodingKey::from_secret(key.as_ref())),
catalog::Algorithm::EdDSA => Ok(EncodingKey::from_ed_pem(key.as_ref())?),
catalog::Algorithm::Es256 => Ok(EncodingKey::from_ec_pem(key.as_ref())?),
catalog::Algorithm::Es384 => Ok(EncodingKey::from_ec_pem(key.as_ref())?),
catalog::Algorithm::Es512 => {
static ES512_WARN: Once = Once::new();
ES512_WARN.call_once(|| {
warn!("ES512 is not currently supported by the underlying cryptography library and will fall back to ES384. Please update your access definition to use ES384 or another supported algorithm.");
});
Ok(EncodingKey::from_ec_pem(key.as_ref())?)
}
catalog::Algorithm::Ps256 => Ok(EncodingKey::from_rsa_pem(key.as_ref())?),
catalog::Algorithm::Ps384 => Ok(EncodingKey::from_rsa_pem(key.as_ref())?),
catalog::Algorithm::Ps512 => Ok(EncodingKey::from_rsa_pem(key.as_ref())?),
catalog::Algorithm::Rs256 => Ok(EncodingKey::from_rsa_pem(key.as_ref())?),
catalog::Algorithm::Rs384 => Ok(EncodingKey::from_rsa_pem(key.as_ref())?),
catalog::Algorithm::Rs512 => Ok(EncodingKey::from_rsa_pem(key.as_ref())?),
}
}
pub(crate) fn expiration(d: Option<Duration>) -> Result<Option<i64>> {
let exp = match d {
Some(v) => {
match ChronoDuration::from_std(v) {
Ok(d) => match Utc::now().checked_add_signed(d) {
Some(exp) => Some(exp.timestamp()),
None => bail!(Error::AccessInvalidExpiration),
},
Err(_) => bail!(Error::AccessInvalidDuration),
}
}
_ => None,
};
Ok(exp)
}