api-tokens
This commit is contained in:
+72
-5
@@ -4,14 +4,18 @@ use diesel::pg::{Pg, PgValue};
|
||||
use diesel::prelude::*;
|
||||
use diesel::serialize::{IsNull, Output, ToSql};
|
||||
use diesel::{deserialize, serialize, AsExpression, FromSqlRow};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::fmt;
|
||||
use std::io::Write;
|
||||
use std::str;
|
||||
use uuid::Uuid;
|
||||
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::schema::sql_types::{
|
||||
MagicTokenKind as MagicTokenKindSql, TenantStatus as TenantStatusSql,
|
||||
ApiTokenCapability as ApiTokenCapabilitySql, MagicTokenKind as MagicTokenKindSql,
|
||||
TenantStatus as TenantStatusSql,
|
||||
};
|
||||
use crate::schema::*;
|
||||
|
||||
@@ -52,6 +56,16 @@ pub enum MagicTokenKind {
|
||||
DemoLogin,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Copy, PartialEq, Eq, AsExpression, FromSqlRow, Serialize, Deserialize, ToSchema,
|
||||
)]
|
||||
#[diesel(sql_type = ApiTokenCapabilitySql)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ApiTokenCapability {
|
||||
Api,
|
||||
Webdav,
|
||||
}
|
||||
|
||||
impl MagicTokenKind {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
@@ -65,12 +79,31 @@ impl MagicTokenKind {
|
||||
}
|
||||
}
|
||||
|
||||
impl ApiTokenCapability {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
ApiTokenCapability::Api => "api",
|
||||
ApiTokenCapability::Webdav => "webdav",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn variants() -> &'static [&'static str] {
|
||||
&["api", "webdav"]
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for MagicTokenKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ApiTokenCapability {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSql<MagicTokenKindSql, Pg> for MagicTokenKind {
|
||||
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
||||
out.write_all(self.as_str().as_bytes())?;
|
||||
@@ -78,6 +111,13 @@ impl ToSql<MagicTokenKindSql, Pg> for MagicTokenKind {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSql<ApiTokenCapabilitySql, Pg> for ApiTokenCapability {
|
||||
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
||||
out.write_all(self.as_str().as_bytes())?;
|
||||
Ok(IsNull::No)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql<MagicTokenKindSql, Pg> for MagicTokenKind {
|
||||
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
||||
match std::str::from_utf8(bytes.as_bytes())? {
|
||||
@@ -91,6 +131,19 @@ impl FromSql<MagicTokenKindSql, Pg> for MagicTokenKind {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql<ApiTokenCapabilitySql, Pg> for ApiTokenCapability {
|
||||
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
||||
match std::str::from_utf8(bytes.as_bytes())? {
|
||||
"api" => Ok(ApiTokenCapability::Api),
|
||||
"webdav" => Ok(ApiTokenCapability::Webdav),
|
||||
other => Err(Box::new(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
format!("invalid api_token_capability '{other}'"),
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for MagicTokenKind {
|
||||
type Err = &'static str;
|
||||
|
||||
@@ -103,6 +156,18 @@ impl str::FromStr for MagicTokenKind {
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for ApiTokenCapability {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"api" => Ok(ApiTokenCapability::Api),
|
||||
"webdav" => Ok(ApiTokenCapability::Webdav),
|
||||
_ => Err("unsupported api token capability"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TenantStatus {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
@@ -243,10 +308,10 @@ pub struct NewWebauthnChallenge {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Queryable, Identifiable, Associations)]
|
||||
#[diesel(table_name = webdav_tokens)]
|
||||
#[diesel(table_name = api_tokens)]
|
||||
#[diesel(belongs_to(User))]
|
||||
#[diesel(belongs_to(Tenant))]
|
||||
pub struct WebdavToken {
|
||||
pub struct ApiToken {
|
||||
pub id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub tenant_id: Uuid,
|
||||
@@ -257,11 +322,12 @@ pub struct WebdavToken {
|
||||
pub last_used_at: Option<NaiveDateTime>,
|
||||
pub expires_at: Option<NaiveDateTime>,
|
||||
pub revoked_at: Option<NaiveDateTime>,
|
||||
pub capabilities: Vec<ApiTokenCapability>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Insertable)]
|
||||
#[diesel(table_name = webdav_tokens)]
|
||||
pub struct NewWebdavToken {
|
||||
#[diesel(table_name = api_tokens)]
|
||||
pub struct NewApiToken {
|
||||
pub id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub tenant_id: Uuid,
|
||||
@@ -269,6 +335,7 @@ pub struct NewWebdavToken {
|
||||
pub token_hash: String,
|
||||
pub label: Option<String>,
|
||||
pub expires_at: Option<NaiveDateTime>,
|
||||
pub capabilities: Vec<ApiTokenCapability>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Queryable, Identifiable)]
|
||||
|
||||
Reference in New Issue
Block a user