feature/authentication service #9
11
.vscode/settings.json
vendored
11
.vscode/settings.json
vendored
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ pub mod login;
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::{
|
use axum::{Router, routing::post};
|
||||||
Router,
|
|
||||||
routing::{get, post},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::routes::AppState;
|
use crate::routes::AppState;
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ pub async fn login(State(state): State<Arc<AppState>>, Json(payload): Json<Value
|
|||||||
Ok(resp) => resp,
|
Ok(resp) => resp,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error building response: {}", e);
|
error!("Error building response: {}", e);
|
||||||
return (StatusCode::INTERNAL_SERVER_ERROR).into_response();
|
(StatusCode::INTERNAL_SERVER_ERROR).into_response()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::{Router, routing::get};
|
use axum::Router;
|
||||||
|
|
||||||
use crate::{middlewares::require_auth::require_auth, routes::AppState};
|
use crate::{middlewares::require_auth::require_auth, routes::AppState};
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use tokio::sync::RwLock;
|
|||||||
use crate::errors::service_error::ServiceError;
|
use crate::errors::service_error::ServiceError;
|
||||||
|
|
||||||
// Number of requests between invalidation cache cleanups
|
// 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
|
const INVALIDATE_CACHE_CLEANUP_INTERVAL_REQUESTS: usize = 100; // Cleanup every 100 for invalidation checks
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
@@ -38,10 +39,15 @@ pub trait AuthenticationService: Send + Sync {
|
|||||||
token: &str,
|
token: &str,
|
||||||
target_sub: Option<String>,
|
target_sub: Option<String>,
|
||||||
) -> Result<Option<Claims>, ServiceError>;
|
) -> Result<Option<Claims>, ServiceError>;
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
async fn parse_jwt(&self, token: &str) -> Result<Claims, ServiceError>;
|
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>;
|
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>;
|
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>;
|
async fn logout(&self, token: &str) -> Result<(), ServiceError>;
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
async fn cleanup_invalidation_cache(&self);
|
async fn cleanup_invalidation_cache(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +60,9 @@ struct InvalidationEntry {
|
|||||||
|
|
||||||
pub struct AuthenticationServiceImpl {
|
pub struct AuthenticationServiceImpl {
|
||||||
secret: String,
|
secret: String,
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
invalidation_cache: Arc<RwLock<HashSet<InvalidationEntry>>>,
|
invalidation_cache: Arc<RwLock<HashSet<InvalidationEntry>>>,
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
cache_cleanup_counter: Arc<RwLock<usize>>,
|
cache_cleanup_counter: Arc<RwLock<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ impl PasswordStrategy {
|
|||||||
|
|
||||||
Ok(user.id)
|
Ok(user.id)
|
||||||
}
|
}
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
pub async fn revoke_identity(
|
pub async fn revoke_identity(
|
||||||
&self,
|
&self,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
@@ -126,7 +126,7 @@ impl PasswordStrategy {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
pub async fn update_password(
|
pub async fn update_password(
|
||||||
&self,
|
&self,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
@@ -368,7 +368,7 @@ mod test {
|
|||||||
user_id: Uuid::new_v4(),
|
user_id: Uuid::new_v4(),
|
||||||
email: None,
|
email: None,
|
||||||
provider: PASSWORD_PROVIDER.to_string(),
|
provider: PASSWORD_PROVIDER.to_string(),
|
||||||
password_hash: Some("somehash".to_string()),
|
password_hash: Some("some_hash".to_string()),
|
||||||
metadata: None,
|
metadata: None,
|
||||||
is_revoked: false,
|
is_revoked: false,
|
||||||
revoked_at: None,
|
revoked_at: None,
|
||||||
@@ -413,7 +413,7 @@ mod test {
|
|||||||
user_id,
|
user_id,
|
||||||
email: None,
|
email: None,
|
||||||
provider: PASSWORD_PROVIDER.to_string(),
|
provider: PASSWORD_PROVIDER.to_string(),
|
||||||
password_hash: Some("oldhash".to_string()),
|
password_hash: Some("old_hash".to_string()),
|
||||||
metadata: None,
|
metadata: None,
|
||||||
is_revoked: false,
|
is_revoked: false,
|
||||||
revoked_at: None,
|
revoked_at: None,
|
||||||
@@ -430,7 +430,7 @@ mod test {
|
|||||||
user_id,
|
user_id,
|
||||||
email: None,
|
email: None,
|
||||||
provider: PASSWORD_PROVIDER.to_string(),
|
provider: PASSWORD_PROVIDER.to_string(),
|
||||||
password_hash: Some("newhash".to_string()),
|
password_hash: Some("new_hash".to_string()),
|
||||||
metadata: None,
|
metadata: None,
|
||||||
is_revoked: false,
|
is_revoked: false,
|
||||||
revoked_at: None,
|
revoked_at: None,
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ pub trait UserService: Send + Sync {
|
|||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
tx: Option<&mut DatabaseTransaction>,
|
tx: Option<&mut DatabaseTransaction>,
|
||||||
) -> Result<User, ServiceError>;
|
) -> Result<User, ServiceError>;
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
async fn is_admin(
|
async fn is_admin(
|
||||||
&self,
|
&self,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
tx: Option<&mut DatabaseTransaction>,
|
tx: Option<&mut DatabaseTransaction>,
|
||||||
) -> Result<bool, ServiceError>;
|
) -> Result<bool, ServiceError>;
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
async fn user_exists(
|
async fn user_exists(
|
||||||
&self,
|
&self,
|
||||||
username: &str,
|
username: &str,
|
||||||
@@ -32,12 +34,14 @@ pub trait UserService: Send + Sync {
|
|||||||
user: NewUser,
|
user: NewUser,
|
||||||
tx: Option<&mut DatabaseTransaction>,
|
tx: Option<&mut DatabaseTransaction>,
|
||||||
) -> Result<User, ServiceError>;
|
) -> Result<User, ServiceError>;
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
async fn update_user(
|
async fn update_user(
|
||||||
&self,
|
&self,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
user: UpdateUser,
|
user: UpdateUser,
|
||||||
tx: Option<&mut DatabaseTransaction>,
|
tx: Option<&mut DatabaseTransaction>,
|
||||||
) -> Result<User, ServiceError>;
|
) -> Result<User, ServiceError>;
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
async fn delete_user(
|
async fn delete_user(
|
||||||
&self,
|
&self,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
@@ -47,7 +51,9 @@ pub trait UserService: Send + Sync {
|
|||||||
|
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: Uuid,
|
pub id: Uuid,
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
pub username: String,
|
pub username: String,
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
pub is_admin: bool,
|
pub is_admin: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,12 +73,16 @@ pub struct NewUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct UpdateUser {
|
pub struct UpdateUser {
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
pub is_admin: Option<bool>,
|
pub is_admin: Option<bool>,
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
pub is_active: Option<bool>,
|
pub is_active: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpdateUser {
|
impl UpdateUser {
|
||||||
|
#[allow(dead_code)] // TODO: remove when used
|
||||||
fn apply_to_active_model(&self, model: &mut UserActiveModel) {
|
fn apply_to_active_model(&self, model: &mut UserActiveModel) {
|
||||||
if let Some(username) = &self.username {
|
if let Some(username) = &self.username {
|
||||||
model.name = ActiveValue::Set(username.clone());
|
model.name = ActiveValue::Set(username.clone());
|
||||||
|
|||||||
Reference in New Issue
Block a user