use super::{Error, Result};
use axum_extra::headers::{authorization::Bearer, Authorization};
use sos_core::{decode, AccountId};
use sos_signer::ed25519::{self, BinaryEd25519Signature};
#[derive(Debug)]
pub struct BearerToken {
pub account_id: AccountId,
pub device_signature: ed25519::Signature,
}
impl BearerToken {
pub async fn new(
header_account_id: Option<AccountId>,
token: &str,
) -> Result<Self> {
let has_period_delimiter = token.contains('.');
#[allow(unused_assignments)]
let mut account_id: Option<AccountId> = None;
#[allow(unused_assignments)]
let mut device_signature: Option<ed25519::Signature> = None;
match (header_account_id, has_period_delimiter) {
(Some(id), false) => {
account_id = Some(id);
let value = bs58::decode(token).into_vec()?;
let buffer: BinaryEd25519Signature = decode(&value).await?;
let signature: ed25519::Signature = buffer.into();
device_signature = Some(signature);
}
(Some(_), true) => {
return Err(Error::Forbidden);
}
(None, true) => {
return Err(Error::Forbidden);
}
(None, false) => {
return Err(Error::Forbidden);
}
}
let account_id = account_id.ok_or_else(|| Error::BadRequest)?;
let device_signature =
device_signature.ok_or_else(|| Error::BadRequest)?;
Ok(Self {
account_id,
device_signature,
})
}
}
pub async fn bearer(
account_id: Option<AccountId>,
authorization: Authorization<Bearer>,
) -> Result<BearerToken> {
BearerToken::new(account_id, authorization.token()).await
}