2025-04-01 23:16:09 -04:00
use super ::* ;
use crate ::cache ::Cache ;
2025-04-03 13:52:29 -04:00
use crate ::model ::{ Error , Result , auth ::User , moderation ::AuditLogEntry , permissions ::FinePermission } ;
2025-04-03 15:07:57 -04:00
use crate ::{ auto_method , execute , get , params , query_row , query_rows } ;
2025-04-01 23:16:09 -04:00
#[ cfg(feature = " sqlite " ) ]
use rusqlite ::Row ;
#[ cfg(feature = " postgres " ) ]
use tokio_postgres ::Row ;
impl DataManager {
/// Get an [`AuditLogEntry`] from an SQL row.
2025-04-02 11:39:51 -04:00
pub ( crate ) fn get_audit_log_entry_from_row (
2025-04-01 23:16:09 -04:00
#[ cfg(feature = " sqlite " ) ] x : & Row < '_ > ,
#[ cfg(feature = " postgres " ) ] x : & Row ,
) -> AuditLogEntry {
AuditLogEntry {
2025-04-03 13:52:29 -04:00
id : get ! ( x ->0 ( i64 ) ) as usize ,
created : get ! ( x ->1 ( i64 ) ) as usize ,
moderator : get ! ( x ->2 ( i64 ) ) as usize ,
2025-04-01 23:16:09 -04:00
content : get ! ( x ->3 ( String ) ) ,
}
}
2025-04-03 15:07:57 -04:00
auto_method! ( get_audit_log_entry_by_id ( usize as i64 ) @ get_audit_log_entry_from_row -> " SELECT * FROM audit_log WHERE id = $1 " - - name = " audit log entry " - - returns = AuditLogEntry - - cache - key - tmpl = " atto.audit_log:{} " ) ;
2025-04-02 11:39:51 -04:00
/// Get all audit log entries (paginated).
///
/// # Arguments
/// * `batch` - the limit of items in each page
/// * `page` - the page number
pub async fn get_audit_log_entries (
& self ,
batch : usize ,
page : usize ,
) -> Result < Vec < AuditLogEntry > > {
let conn = match self . connect ( ) . await {
Ok ( c ) = > c ,
Err ( e ) = > return Err ( Error ::DatabaseConnection ( e . to_string ( ) ) ) ,
} ;
let res = query_rows! (
& conn ,
" SELECT * FROM audit_log ORDER BY created DESC LIMIT $1 OFFSET $2 " ,
2025-04-03 13:52:29 -04:00
& [ & ( batch as i64 ) , & ( ( page * batch ) as i64 ) ] ,
2025-04-02 11:39:51 -04:00
| x | { Self ::get_audit_log_entry_from_row ( x ) }
) ;
if res . is_err ( ) {
return Err ( Error ::GeneralNotFound ( " audit log entry " . to_string ( ) ) ) ;
}
Ok ( res . unwrap ( ) )
}
2025-04-01 23:16:09 -04:00
/// Create a new audit log entry in the database.
///
/// # Arguments
/// * `data` - a mock [`AuditLogEntry`] object to insert
2025-04-02 11:39:51 -04:00
pub async fn create_audit_log_entry ( & self , data : AuditLogEntry ) -> Result < ( ) > {
2025-04-01 23:16:09 -04:00
let conn = match self . connect ( ) . await {
Ok ( c ) = > c ,
Err ( e ) = > return Err ( Error ::DatabaseConnection ( e . to_string ( ) ) ) ,
} ;
let res = execute! (
& conn ,
2025-04-02 11:39:51 -04:00
" INSERT INTO audit_log VALUES ($1, $2, $3, $4) " ,
2025-04-03 15:07:57 -04:00
params! [
& ( data . id as i64 ) ,
& ( data . created as i64 ) ,
& ( data . moderator as i64 ) ,
2025-04-01 23:16:09 -04:00
& data . content . as_str ( ) ,
]
) ;
if let Err ( e ) = res {
return Err ( Error ::DatabaseError ( e . to_string ( ) ) ) ;
}
// return
Ok ( ( ) )
}
2025-04-02 11:39:51 -04:00
pub async fn delete_audit_log_entry ( & self , id : usize , user : User ) -> Result < ( ) > {
2025-04-01 23:16:09 -04:00
if ! user . permissions . check ( FinePermission ::MANAGE_AUDITLOG ) {
return Err ( Error ::NotAllowed ) ;
}
let conn = match self . connect ( ) . await {
Ok ( c ) = > c ,
Err ( e ) = > return Err ( Error ::DatabaseConnection ( e . to_string ( ) ) ) ,
} ;
let res = execute! (
& conn ,
2025-04-02 11:39:51 -04:00
" DELETE FROM audit_log WHERE id = $1 " ,
2025-04-03 15:07:57 -04:00
& [ & ( id as i64 ) ]
2025-04-01 23:16:09 -04:00
) ;
if let Err ( e ) = res {
return Err ( Error ::DatabaseError ( e . to_string ( ) ) ) ;
}
2025-04-02 11:39:51 -04:00
self . 2. remove ( format! ( " atto.audit_log: {} " , id ) ) . await ;
2025-04-01 23:16:09 -04:00
// return
Ok ( ( ) )
}
}