authnz-common 0.2.1

Authnz common library (types and utils).
Documentation
//! Light MPAAT module.

#[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};

#[derive(Deserialize, Serialize, PartialEq, Eq, Hash, Clone, Debug)]
#[cfg_attr(any(feature = "app-server-types", feature = "authnz-server-types"), derive(ToSchema))]
/// Access, refresh and client tokens.
pub struct TokenBundle {
  pub(crate) access: String,
  pub(crate) refresh: String,
  pub(crate) client: Option<String>,
}

impl TokenBundle {
  /// Creates new basic serialized token bundle.
  pub fn new_basic(act: impl ToString, rft: impl ToString) -> Self {
    Self {
      access: act.to_string(),
      refresh: rft.to_string(),
      client: None,
    }
  }

  /// Creates new basic serialized token bundle with client token.
  pub fn new_with_cba(act: impl ToString, rft: impl ToString, cba: impl ToString) -> Self {
    Self {
      access: act.to_string(),
      refresh: rft.to_string(),
      client: Some(cba.to_string()),
    }
  }

  /// Returns the access token.
  pub fn act(&self) -> &str {
    self.access.as_str()
  }

  /// Returns the refresh token.
  pub fn rft(&self) -> &str {
    self.refresh.as_str()
  }

  /// Returns the client token.
  pub fn cba(&self) -> Option<&str> {
    self.client.as_deref()
  }

  /// Splits bundle into parts.
  pub fn into_parts(self) -> (String, String, Option<String>) {
    (self.access, self.refresh, self.client)
  }

  /// Packs token triple in a single string.
  pub fn pack(&self) -> String {
    format!(
      "{}:::{}:::{}",
      self.access,
      self.refresh,
      self.client.as_deref().unwrap_or_default()
    )
  }

  /// Set new access token.
  pub fn set_act(&mut self, act: impl ToString) {
    self.access = act.to_string();
  }

  /// Set new refresh token.
  pub fn set_rft(&mut self, rft: impl ToString) {
    self.refresh = rft.to_string();
  }

  /// Set new client token.
  pub fn set_cba(&mut self, cba: Option<impl ToString>) {
    self.client = cba.map(|token| token.to_string());
  }

  #[allow(clippy::unwrap_used)]
  /// Unpacks token triple from a string.
  pub fn unpack(tokens: impl AsRef<str>) -> Option<Self> {
    let parts = tokens.as_ref().split(":::").collect::<Vec<_>>();
    if parts.len() != 3 {
      return None;
    }

    let access = parts.first().unwrap().to_string();
    let refresh = parts.get(1).unwrap().to_string();
    let client = if let Some(client) = parts.last()
      && !client.is_empty()
    {
      Some(client.to_string())
    } else {
      None
    };

    Some(Self { access, refresh, client })
  }
}