diff options
| author | mo khan <mo@mokhan.ca> | 2025-06-11 17:11:39 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-06-11 17:11:39 -0600 |
| commit | 5ffc9b007ccbd8a4510b58de72aaee53291d7973 (patch) | |
| tree | f696a2a7599926d402c5456c434bd87e5e325c3a /src/repositories | |
| parent | dbd3c780f27bd5bee23adf6e280b84d669230e0d (diff) | |
refactor: apply SOLID principles
Diffstat (limited to 'src/repositories')
| -rw-r--r-- | src/repositories/mod.rs | 52 | ||||
| -rw-r--r-- | src/repositories/sqlite.rs | 164 |
2 files changed, 216 insertions, 0 deletions
diff --git a/src/repositories/mod.rs b/src/repositories/mod.rs new file mode 100644 index 0000000..1685fe0 --- /dev/null +++ b/src/repositories/mod.rs @@ -0,0 +1,52 @@ +use crate::database::{DbAccessToken, DbAuditLog, DbAuthCode, DbOAuthClient}; +use anyhow::Result; + +pub mod sqlite; + +pub use sqlite::{ + SqliteAuditRepository, SqliteAuthCodeRepository, SqliteClientRepository, SqliteRateRepository, + SqliteTokenRepository, +}; + +/// Repository trait for OAuth client operations +pub trait ClientRepository: Send + Sync { + fn get_client(&self, client_id: &str) -> Result<Option<DbOAuthClient>>; + fn create_client(&self, client: &DbOAuthClient) -> Result<()>; + fn update_client(&self, client: &DbOAuthClient) -> Result<()>; + fn delete_client(&self, client_id: &str) -> Result<()>; + fn list_clients(&self) -> Result<Vec<DbOAuthClient>>; +} + +/// Repository trait for authorization code operations +pub trait AuthCodeRepository: Send + Sync { + fn create_auth_code(&self, code: &DbAuthCode) -> Result<()>; + fn get_auth_code(&self, code: &str) -> Result<Option<DbAuthCode>>; + fn mark_auth_code_used(&self, code: &str) -> Result<()>; + fn cleanup_expired_codes(&self) -> Result<()>; +} + +/// Repository trait for access token operations +pub trait TokenRepository: Send + Sync { + fn create_access_token(&self, token: &DbAccessToken) -> Result<()>; + fn get_access_token(&self, token_hash: &str) -> Result<Option<DbAccessToken>>; + fn revoke_access_token(&self, token_hash: &str) -> Result<()>; + fn cleanup_expired_tokens(&self) -> Result<()>; +} + +/// Repository trait for audit log operations +pub trait AuditRepository: Send + Sync { + fn create_audit_log(&self, log: &DbAuditLog) -> Result<()>; + fn get_audit_logs(&self, limit: Option<i32>) -> Result<Vec<DbAuditLog>>; + fn cleanup_old_audit_logs(&self, days: i32) -> Result<()>; +} + +/// Repository trait for rate limiting operations +pub trait RateRepository: Send + Sync { + fn increment_rate_limit( + &self, + identifier: &str, + endpoint: &str, + window_size: i32, + ) -> Result<i32>; + fn cleanup_old_rate_limits(&self) -> Result<()>; +} diff --git a/src/repositories/sqlite.rs b/src/repositories/sqlite.rs new file mode 100644 index 0000000..79e6025 --- /dev/null +++ b/src/repositories/sqlite.rs @@ -0,0 +1,164 @@ +use super::*; +use crate::database::{Database, DbAccessToken, DbAuditLog, DbAuthCode, DbOAuthClient}; +use anyhow::Result; +use std::sync::{Arc, Mutex}; + +/// SQLite implementation of ClientRepository +pub struct SqliteClientRepository { + database: Arc<Mutex<Database>>, +} + +impl SqliteClientRepository { + pub fn new(database: Arc<Mutex<Database>>) -> Self { + Self { database } + } +} + +impl ClientRepository for SqliteClientRepository { + fn get_client(&self, client_id: &str) -> Result<Option<DbOAuthClient>> { + let db = self.database.lock().unwrap(); + db.get_oauth_client(client_id) + } + + fn create_client(&self, client: &DbOAuthClient) -> Result<()> { + let db = self.database.lock().unwrap(); + db.create_oauth_client(client).map(|_| ()) + } + + fn update_client(&self, client: &DbOAuthClient) -> Result<()> { + let db = self.database.lock().unwrap(); + db.update_oauth_client(client) + } + + fn delete_client(&self, client_id: &str) -> Result<()> { + let db = self.database.lock().unwrap(); + db.delete_oauth_client(client_id) + } + + fn list_clients(&self) -> Result<Vec<DbOAuthClient>> { + let db = self.database.lock().unwrap(); + db.list_oauth_clients() + } +} + +/// SQLite implementation of AuthCodeRepository +pub struct SqliteAuthCodeRepository { + database: Arc<Mutex<Database>>, +} + +impl SqliteAuthCodeRepository { + pub fn new(database: Arc<Mutex<Database>>) -> Self { + Self { database } + } +} + +impl AuthCodeRepository for SqliteAuthCodeRepository { + fn create_auth_code(&self, code: &DbAuthCode) -> Result<()> { + let db = self.database.lock().unwrap(); + db.create_auth_code(code).map(|_| ()) + } + + fn get_auth_code(&self, code: &str) -> Result<Option<DbAuthCode>> { + let db = self.database.lock().unwrap(); + db.get_auth_code(code) + } + + fn mark_auth_code_used(&self, code: &str) -> Result<()> { + let db = self.database.lock().unwrap(); + db.mark_auth_code_used(code) + } + + fn cleanup_expired_codes(&self) -> Result<()> { + let db = self.database.lock().unwrap(); + db.cleanup_expired_codes().map(|_| ()) + } +} + +/// SQLite implementation of TokenRepository +pub struct SqliteTokenRepository { + database: Arc<Mutex<Database>>, +} + +impl SqliteTokenRepository { + pub fn new(database: Arc<Mutex<Database>>) -> Self { + Self { database } + } +} + +impl TokenRepository for SqliteTokenRepository { + fn create_access_token(&self, token: &DbAccessToken) -> Result<()> { + let db = self.database.lock().unwrap(); + db.create_access_token(token).map(|_| ()) + } + + fn get_access_token(&self, token_hash: &str) -> Result<Option<DbAccessToken>> { + let db = self.database.lock().unwrap(); + db.get_access_token(token_hash) + } + + fn revoke_access_token(&self, token_hash: &str) -> Result<()> { + let db = self.database.lock().unwrap(); + db.revoke_access_token(token_hash) + } + + fn cleanup_expired_tokens(&self) -> Result<()> { + let db = self.database.lock().unwrap(); + db.cleanup_expired_tokens().map(|_| ()) + } +} + +/// SQLite implementation of AuditRepository +pub struct SqliteAuditRepository { + database: Arc<Mutex<Database>>, +} + +impl SqliteAuditRepository { + pub fn new(database: Arc<Mutex<Database>>) -> Self { + Self { database } + } +} + +impl AuditRepository for SqliteAuditRepository { + fn create_audit_log(&self, log: &DbAuditLog) -> Result<()> { + let db = self.database.lock().unwrap(); + db.create_audit_log(log).map(|_| ()) + } + + fn get_audit_logs(&self, limit: Option<i32>) -> Result<Vec<DbAuditLog>> { + let db = self.database.lock().unwrap(); + db.get_audit_logs(limit.unwrap_or(100)) + } + + fn cleanup_old_audit_logs(&self, days: i32) -> Result<()> { + let db = self.database.lock().unwrap(); + db.cleanup_old_audit_logs(days).map(|_| ()) + } +} + +/// SQLite implementation of RateRepository +pub struct SqliteRateRepository { + database: Arc<Mutex<Database>>, +} + +impl SqliteRateRepository { + pub fn new(database: Arc<Mutex<Database>>) -> Self { + Self { database } + } +} + +impl RateRepository for SqliteRateRepository { + fn increment_rate_limit( + &self, + identifier: &str, + endpoint: &str, + window_size: i32, + ) -> Result<i32> { + let db = self.database.lock().unwrap(); + db.increment_rate_limit(identifier, endpoint, window_size) + } + + fn cleanup_old_rate_limits(&self) -> Result<()> { + let db = self.database.lock().unwrap(); + db.cleanup_old_rate_limits() + } +} |
