1+ import { mainDb } from "./connection.js" ;
2+ import { encrypt , decrypt } from "../utils/encryption.js" ; // Assuming decrypt function exists
3+ import { sql } from "kysely" ;
4+
5+ export interface FlightLogData {
6+ userId : string ;
7+ username : string ;
8+ sessionId : string ;
9+ action : 'add' | 'update' | 'delete' ;
10+ flightId : string ;
11+ oldData ?: object | null ;
12+ newData ?: object | null ;
13+ ipAddress ?: string | null ;
14+ }
15+
16+ export async function logFlightAction ( logData : FlightLogData ) {
17+ const {
18+ userId,
19+ username,
20+ sessionId,
21+ action,
22+ flightId,
23+ oldData = null ,
24+ newData = null ,
25+ ipAddress = null
26+ } = logData ;
27+
28+ try {
29+ const encryptedIP = ipAddress ? JSON . stringify ( encrypt ( ipAddress ) ) : null ;
30+ await mainDb
31+ . insertInto ( 'flight_logs' )
32+ . values ( {
33+ id : sql `DEFAULT` ,
34+ user_id : userId ,
35+ username,
36+ session_id : sessionId ,
37+ action,
38+ flight_id : flightId ,
39+ old_data : oldData ,
40+ new_data : newData ,
41+ ip_address : encryptedIP ,
42+ timestamp : sql `NOW()`
43+ } )
44+ . execute ( ) ;
45+ } catch ( error ) {
46+ console . error ( 'Error logging flight action:' , error ) ;
47+ // Non-blocking: don't throw, just log
48+ }
49+ }
50+
51+ export async function cleanupOldFlightLogs ( daysToKeep = 30 ) {
52+ try {
53+ const result = await mainDb
54+ . deleteFrom ( 'flight_logs' )
55+ . where ( 'timestamp' , '<' , new Date ( Date . now ( ) - daysToKeep * 24 * 60 * 60 * 1000 ) )
56+ . executeTakeFirst ( ) ;
57+
58+ return Number ( result ?. numDeletedRows ?? 0 ) ;
59+ } catch ( error ) {
60+ console . error ( 'Error cleaning up flight logs:' , error ) ;
61+ throw error ;
62+ }
63+ }
64+
65+ let cleanupInterval : NodeJS . Timeout | null = null ;
66+
67+ export function startFlightLogsCleanup ( ) {
68+ const CLEANUP_INTERVAL = 24 * 60 * 60 * 1000 ; // Daily
69+
70+ // Initial cleanup after 1 minute
71+ setTimeout ( async ( ) => {
72+ try {
73+ await cleanupOldFlightLogs ( 30 ) ;
74+ } catch ( error ) {
75+ console . error ( 'Initial flight logs cleanup failed:' , error ) ;
76+ }
77+ } , 60 * 1000 ) ;
78+
79+ // Recurring cleanup
80+ cleanupInterval = setInterval ( async ( ) => {
81+ try {
82+ await cleanupOldFlightLogs ( 30 ) ;
83+ } catch ( error ) {
84+ console . error ( 'Scheduled flight logs cleanup failed:' , error ) ;
85+ }
86+ } , CLEANUP_INTERVAL ) ;
87+ }
88+
89+ export function stopFlightLogsCleanup ( ) {
90+ if ( cleanupInterval ) {
91+ clearInterval ( cleanupInterval ) ;
92+ cleanupInterval = null ;
93+ }
94+ }
95+
96+ export interface FlightLogFilters {
97+ user ?: string ;
98+ action ?: 'add' | 'update' | 'delete' ;
99+ session ?: string ;
100+ flightId ?: string ;
101+ dateFrom ?: string ;
102+ dateTo ?: string ;
103+ }
104+
105+ export async function getFlightLogs (
106+ page = 1 ,
107+ limit = 50 ,
108+ filters : FlightLogFilters = { }
109+ ) {
110+ try {
111+ let query = mainDb
112+ . selectFrom ( 'flight_logs' )
113+ . selectAll ( )
114+ . orderBy ( 'timestamp' , 'desc' )
115+ . limit ( limit )
116+ . offset ( ( page - 1 ) * limit ) ;
117+
118+ if ( filters . user ) {
119+ query = query . where ( 'username' , 'ilike' , `%${ filters . user } %` ) ;
120+ }
121+ if ( filters . action ) {
122+ query = query . where ( 'action' , '=' , filters . action ) ;
123+ }
124+ if ( filters . session ) {
125+ query = query . where ( 'session_id' , '=' , filters . session ) ;
126+ }
127+ if ( filters . flightId ) {
128+ query = query . where ( 'flight_id' , '=' , filters . flightId ) ;
129+ }
130+ if ( filters . dateFrom ) {
131+ query = query . where ( 'timestamp' , '>=' , new Date ( filters . dateFrom ) ) ;
132+ }
133+ if ( filters . dateTo ) {
134+ query = query . where ( 'timestamp' , '<=' , new Date ( filters . dateTo ) ) ;
135+ }
136+
137+ const logs = await query . execute ( ) ;
138+ const total = await mainDb
139+ . selectFrom ( 'flight_logs' )
140+ . select ( ( eb ) => eb . fn . count ( 'id' ) . as ( 'count' ) )
141+ . executeTakeFirst ( ) ;
142+
143+ return {
144+ logs : logs . map ( log => ( {
145+ ...log ,
146+ ip_address : log . ip_address ? decrypt ( JSON . parse ( log . ip_address ) ) : null ,
147+ } ) ) ,
148+ pagination : {
149+ page,
150+ limit,
151+ total : Number ( total ?. count || 0 ) ,
152+ pages : Math . ceil ( Number ( total ?. count || 0 ) / limit ) ,
153+ } ,
154+ } ;
155+ } catch ( error ) {
156+ console . error ( 'Error fetching flight logs:' , error ) ;
157+ throw error ;
158+ }
159+ }
160+
161+ export async function getFlightLogById ( logId : string | number ) {
162+ try {
163+ const log = await mainDb
164+ . selectFrom ( 'flight_logs' )
165+ . selectAll ( )
166+ . where ( 'id' , '=' , Number ( logId ) )
167+ . executeTakeFirst ( ) ;
168+
169+ if ( ! log ) return null ;
170+
171+ return {
172+ ...log ,
173+ ip_address : log . ip_address ? decrypt ( JSON . parse ( log . ip_address ) ) : null ,
174+ } ;
175+ } catch ( error ) {
176+ console . error ( 'Error fetching flight log by ID:' , error ) ;
177+ throw error ;
178+ }
179+ }
0 commit comments