use chrono::NaiveDateTime;
use serde_derive::{Deserialize, Serialize};
use crate::utils::apierror::{error_forbidden, error_invalid_request, specialize, ApiError};
pub const ROLE_ADMIN: &str = "admin";
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Authentication {
pub principal: AuthenticationPrincipal,
#[serde(rename = "canWrite")]
pub can_write: bool,
#[serde(rename = "canAdmin")]
pub can_admin: bool,
}
impl Authentication {
#[must_use]
pub fn new_self() -> Self {
Self {
principal: AuthenticationPrincipal::SelfAuth,
can_write: false,
can_admin: false,
}
}
#[must_use]
pub fn new_service(token_id: String) -> Self {
Self {
principal: AuthenticationPrincipal::Service { token_id },
can_write: false,
can_admin: false,
}
}
#[must_use]
pub fn new_user(uid: i64, email: String) -> Self {
Self {
principal: AuthenticationPrincipal::User { uid, email },
can_write: true,
can_admin: true,
}
}
pub fn uid(&self) -> Result<i64, ApiError> {
if let AuthenticationPrincipal::User { uid, email: _ } = &self.principal {
Ok(*uid)
} else {
Err(specialize(
error_invalid_request(),
String::from("Expected a user to be authenticated"),
))
}
}
pub fn email(&self) -> Result<&str, ApiError> {
if let AuthenticationPrincipal::User { uid: _, email } = &self.principal {
Ok(email)
} else {
Err(specialize(
error_invalid_request(),
String::from("Expected a user to be authenticated"),
))
}
}
pub fn check_can_write(&self) -> Result<(), ApiError> {
if self.can_write {
Ok(())
} else {
Err(specialize(
error_forbidden(),
String::from("writing is forbidden for this authentication"),
))
}
}
pub fn check_can_admin(&self) -> Result<(), ApiError> {
if self.can_admin {
Ok(())
} else {
Err(specialize(
error_forbidden(),
String::from("administration is forbidden for this authentication"),
))
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum AuthenticationPrincipal {
User { uid: i64, email: String },
Service { token_id: String },
SelfAuth,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct RegistryUserToken {
pub id: i64,
pub name: String,
#[serde(rename = "lastUsed")]
pub last_used: NaiveDateTime,
#[serde(rename = "canWrite")]
pub can_write: bool,
#[serde(rename = "canAdmin")]
pub can_admin: bool,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct RegistryUserTokenWithSecret {
pub id: i64,
pub name: String,
pub secret: String,
#[serde(rename = "lastUsed")]
pub last_used: NaiveDateTime,
#[serde(rename = "canWrite")]
pub can_write: bool,
#[serde(rename = "canAdmin")]
pub can_admin: bool,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct OAuthToken {
pub access_token: String,
pub token_type: String,
pub expires_in: Option<i64>,
pub refresh_token: Option<String>,
pub scope: Option<String>,
}
#[must_use]
pub fn find_field_in_blob<'v>(blob: &'v serde_json::Value, path: &str) -> Option<&'v str> {
let mut last = blob;
for item in path.split('.') {
last = last.as_object()?.get(item)?;
}
last.as_str()
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TokenKind {
User,
Registry,
}
#[derive(Debug, Clone)]
pub struct TokenUsage {
pub kind: TokenKind,
pub token_id: i64,
pub timestamp: NaiveDateTime,
}