feature/authentication service #9

Merged
GW_MC merged 19 commits from feature/authentication into master 2025-12-19 12:24:49 +08:00
7 changed files with 36 additions and 12 deletions
Showing only changes of commit ec81d3228b - Show all commits

11
.vscode/settings.json vendored
View File

@@ -1,3 +1,12 @@
{
"cSpell.words": ["YANPM"]
"cSpell.words": ["chrono", "jsonwebtoken", "oneshot", "utoipa", "YANPM"],
"sqltools.useNodeRuntime": true,
"sqltools.connections": [
{
"previewLimit": 50,
"driver": "SQLite",
"database": "${workspaceFolder:yet-another-nginx-proxy-manager}/apps/container/generated/sqlite/sqlite.db",
"name": "YANPM"
}
]
}

View File

@@ -3,10 +3,7 @@ pub mod login;
use std::sync::Arc;
use axum::{
Router,
routing::{get, post},
};
use axum::{Router, routing::post};
use crate::routes::AppState;

View File

@@ -92,7 +92,7 @@ pub async fn login(State(state): State<Arc<AppState>>, Json(payload): Json<Value
Ok(resp) => resp,
Err(e) => {
error!("Error building response: {}", e);
return (StatusCode::INTERNAL_SERVER_ERROR).into_response();
(StatusCode::INTERNAL_SERVER_ERROR).into_response()
}
}
}

View File

@@ -1,6 +1,6 @@
use std::sync::Arc;
use axum::{Router, routing::get};
use axum::Router;
use crate::{middlewares::require_auth::require_auth, routes::AppState};

View File

@@ -14,6 +14,7 @@ use tokio::sync::RwLock;
use crate::errors::service_error::ServiceError;
// Number of requests between invalidation cache cleanups
#[allow(dead_code)] // TODO: remove when used
const INVALIDATE_CACHE_CLEANUP_INTERVAL_REQUESTS: usize = 100; // Cleanup every 100 for invalidation checks
#[derive(Serialize, Deserialize, Clone)]
@@ -38,10 +39,15 @@ pub trait AuthenticationService: Send + Sync {
token: &str,
target_sub: Option<String>,
) -> Result<Option<Claims>, ServiceError>;
#[allow(dead_code)] // TODO: remove when used
async fn parse_jwt(&self, token: &str) -> Result<Claims, ServiceError>;
#[allow(dead_code)] // TODO: remove when used
async fn invalidate_jwt(&self, token: &str) -> Result<(), ServiceError>;
#[allow(dead_code)] // TODO: remove when used
async fn refresh_jwt(&self, token: &str, duration_secs: u64) -> Result<String, ServiceError>;
#[allow(dead_code)] // TODO: remove when used
async fn logout(&self, token: &str) -> Result<(), ServiceError>;
#[allow(dead_code)] // TODO: remove when used
async fn cleanup_invalidation_cache(&self);
}
@@ -54,7 +60,9 @@ struct InvalidationEntry {
pub struct AuthenticationServiceImpl {
secret: String,
#[allow(dead_code)] // TODO: remove when used
invalidation_cache: Arc<RwLock<HashSet<InvalidationEntry>>>,
#[allow(dead_code)] // TODO: remove when used
cache_cleanup_counter: Arc<RwLock<usize>>,
}

View File

@@ -68,7 +68,7 @@ impl PasswordStrategy {
Ok(user.id)
}
#[allow(dead_code)] // TODO: remove when used
pub async fn revoke_identity(
&self,
user_id: Uuid,
@@ -126,7 +126,7 @@ impl PasswordStrategy {
Ok(())
}
#[allow(dead_code)] // TODO: remove when used
pub async fn update_password(
&self,
user_id: Uuid,
@@ -368,7 +368,7 @@ mod test {
user_id: Uuid::new_v4(),
email: None,
provider: PASSWORD_PROVIDER.to_string(),
password_hash: Some("somehash".to_string()),
password_hash: Some("some_hash".to_string()),
metadata: None,
is_revoked: false,
revoked_at: None,
@@ -413,7 +413,7 @@ mod test {
user_id,
email: None,
provider: PASSWORD_PROVIDER.to_string(),
password_hash: Some("oldhash".to_string()),
password_hash: Some("old_hash".to_string()),
metadata: None,
is_revoked: false,
revoked_at: None,
@@ -430,7 +430,7 @@ mod test {
user_id,
email: None,
provider: PASSWORD_PROVIDER.to_string(),
password_hash: Some("newhash".to_string()),
password_hash: Some("new_hash".to_string()),
metadata: None,
is_revoked: false,
revoked_at: None,

View File

@@ -17,11 +17,13 @@ pub trait UserService: Send + Sync {
user_id: Uuid,
tx: Option<&mut DatabaseTransaction>,
) -> Result<User, ServiceError>;
#[allow(dead_code)] // TODO: remove when used
async fn is_admin(
&self,
user_id: Uuid,
tx: Option<&mut DatabaseTransaction>,
) -> Result<bool, ServiceError>;
#[allow(dead_code)] // TODO: remove when used
async fn user_exists(
&self,
username: &str,
@@ -32,12 +34,14 @@ pub trait UserService: Send + Sync {
user: NewUser,
tx: Option<&mut DatabaseTransaction>,
) -> Result<User, ServiceError>;
#[allow(dead_code)] // TODO: remove when used
async fn update_user(
&self,
user_id: Uuid,
user: UpdateUser,
tx: Option<&mut DatabaseTransaction>,
) -> Result<User, ServiceError>;
#[allow(dead_code)] // TODO: remove when used
async fn delete_user(
&self,
user_id: Uuid,
@@ -47,7 +51,9 @@ pub trait UserService: Send + Sync {
pub struct User {
pub id: Uuid,
#[allow(dead_code)] // TODO: remove when used
pub username: String,
#[allow(dead_code)] // TODO: remove when used
pub is_admin: bool,
}
@@ -67,12 +73,16 @@ pub struct NewUser {
}
pub struct UpdateUser {
#[allow(dead_code)] // TODO: remove when used
pub username: Option<String>,
#[allow(dead_code)] // TODO: remove when used
pub is_admin: Option<bool>,
#[allow(dead_code)] // TODO: remove when used
pub is_active: Option<bool>,
}
impl UpdateUser {
#[allow(dead_code)] // TODO: remove when used
fn apply_to_active_model(&self, model: &mut UserActiveModel) {
if let Some(username) = &self.username {
model.name = ActiveValue::Set(username.clone());