mod authority;
mod exception;
mod log;
pub use authority::*;
pub use exception::*;
pub use log::*;
use crate::error::CoolError;
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
use salvo::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JwtClaims {
pub user_id: i64,
pub username: Option<String>,
pub role_ids: Vec<i64>,
pub is_admin: bool,
pub tenant_id: Option<i64>,
pub exp: i64,
pub iat: i64,
}
impl JwtClaims {
pub fn new(
user_id: i64,
username: Option<String>,
role_ids: Vec<i64>,
is_admin: bool,
tenant_id: Option<i64>,
expire_secs: u64,
) -> Self {
let now = chrono::Utc::now().timestamp();
Self {
user_id,
username,
role_ids,
is_admin,
tenant_id,
exp: now + expire_secs as i64,
iat: now,
}
}
pub fn generate_token(&self, secret: &str) -> Result<String, CoolError> {
encode(
&Header::default(),
&self,
&EncodingKey::from_secret(secret.as_bytes()),
)
.map_err(CoolError::from)
}
pub fn verify_token(token: &str, secret: &str) -> Result<Self, CoolError> {
let token_data = decode::<Self>(
token,
&DecodingKey::from_secret(secret.as_bytes()),
&Validation::default(),
)
.map_err(CoolError::from)?;
Ok(token_data.claims)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdminInfo {
pub user_id: i64,
pub username: Option<String>,
pub role_ids: Vec<i64>,
pub is_admin: bool,
pub tenant_id: Option<i64>,
}
impl From<JwtClaims> for AdminInfo {
fn from(claims: JwtClaims) -> Self {
Self {
user_id: claims.user_id,
username: claims.username,
role_ids: claims.role_ids,
is_admin: claims.is_admin,
tenant_id: claims.tenant_id,
}
}
}
pub trait DepotExt {
fn admin(&self) -> Option<&AdminInfo>;
fn set_admin(&mut self, admin: AdminInfo);
}
impl DepotExt for Depot {
fn admin(&self) -> Option<&AdminInfo> {
self.get::<AdminInfo>("admin").ok()
}
fn set_admin(&mut self, admin: AdminInfo) {
self.insert("admin", admin);
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppUserInfo {
pub id: i64,
pub username: Option<String>,
pub phone: Option<String>,
pub tenant_id: Option<i64>,
}
pub trait DepotAppUserExt {
fn app_user(&self) -> Option<&AppUserInfo>;
fn set_app_user(&mut self, user: AppUserInfo);
}
impl DepotAppUserExt for Depot {
fn app_user(&self) -> Option<&AppUserInfo> {
self.get::<AppUserInfo>("app_user").ok()
}
fn set_app_user(&mut self, user: AppUserInfo) {
self.insert("app_user", user);
}
}