Skip to content

Commit 1fdde48

Browse files
authored
Merge pull request #150 from cephie-studios/canary
Canary
2 parents 381059c + 2966f58 commit 1fdde48

File tree

18 files changed

+322
-93
lines changed

18 files changed

+322
-93
lines changed

server/db/apiLogs.ts

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,32 @@ import { decrypt } from '../utils/encryption.js';
33
import { redisConnection } from './connection.js';
44
import { sql } from 'kysely';
55

6+
// Decrypts the raw text field in the api_logs table
7+
function readApiLogTextField(raw: string | null): string | null {
8+
if (raw == null) return null;
9+
try {
10+
const parsed: unknown = JSON.parse(raw);
11+
if (
12+
parsed &&
13+
typeof parsed === 'object' &&
14+
'iv' in parsed &&
15+
'data' in parsed &&
16+
'authTag' in parsed
17+
) {
18+
const decrypted = decrypt(
19+
parsed as { iv: string; data: string; authTag: string }
20+
);
21+
if (decrypted == null) return null;
22+
return typeof decrypted === 'string'
23+
? decrypted
24+
: JSON.stringify(decrypted);
25+
}
26+
} catch {
27+
/* not legacy ciphertext JSON */
28+
}
29+
return raw;
30+
}
31+
632
export interface ApiLogFilters {
733
userId?: string;
834
username?: string;
@@ -157,16 +183,10 @@ export async function getApiLogs(
157183

158184
const decryptedLogs = logs.map((log) => ({
159185
...log,
160-
ip_address: log.ip_address ? decrypt(JSON.parse(log.ip_address)) : null,
161-
request_body: log.request_body
162-
? decrypt(JSON.parse(log.request_body))
163-
: null,
164-
response_body: log.response_body
165-
? decrypt(JSON.parse(log.response_body))
166-
: null,
167-
error_message: log.error_message
168-
? decrypt(JSON.parse(log.error_message))
169-
: null,
186+
ip_address: readApiLogTextField(log.ip_address),
187+
request_body: readApiLogTextField(log.request_body),
188+
response_body: readApiLogTextField(log.response_body),
189+
error_message: readApiLogTextField(log.error_message),
170190
}));
171191

172192
return {
@@ -194,19 +214,12 @@ export async function getApiLogById(logId: number | string) {
194214

195215
if (!log) return null;
196216

197-
// Decrypt sensitive fields
198217
return {
199218
...log,
200-
ip_address: log.ip_address ? decrypt(JSON.parse(log.ip_address)) : null,
201-
request_body: log.request_body
202-
? decrypt(JSON.parse(log.request_body))
203-
: null,
204-
response_body: log.response_body
205-
? decrypt(JSON.parse(log.response_body))
206-
: null,
207-
error_message: log.error_message
208-
? decrypt(JSON.parse(log.error_message))
209-
: null,
219+
ip_address: readApiLogTextField(log.ip_address),
220+
request_body: readApiLogTextField(log.request_body),
221+
response_body: readApiLogTextField(log.response_body),
222+
error_message: readApiLogTextField(log.error_message),
210223
};
211224
} catch (error) {
212225
console.error('Error fetching API log by ID:', error);

server/db/updateModals.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { mainDb } from './connection.js';
22
import { sql } from 'kysely';
33
import { redisConnection } from './connection.js';
4+
import { UPDATE_MODAL_REDIS_SEC } from '../utils/cacheTtl.js';
45

56
const ACTIVE_MODAL_CACHE_KEY = 'update_modal:active';
67

@@ -28,7 +29,7 @@ export async function getActiveUpdateModal() {
2829
ACTIVE_MODAL_CACHE_KEY,
2930
JSON.stringify(result),
3031
'EX',
31-
24 * 60 * 60
32+
UPDATE_MODAL_REDIS_SEC
3233
);
3334
} catch (error) {
3435
console.warn('[Redis] Failed to cache active modal:', error);

server/db/version.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { mainDb } from './connection.js';
2+
import { APP_VERSION_REDIS_SEC } from '../utils/cacheTtl.js';
23

34
export async function getAppVersion() {
45
const result = await mainDb
@@ -27,7 +28,12 @@ export async function getAppVersion() {
2728

2829
try {
2930
const { redisConnection } = await import('./connection.js');
30-
await redisConnection.set('app:version', JSON.stringify(defaultVersion));
31+
await redisConnection.set(
32+
'app:version',
33+
JSON.stringify(defaultVersion),
34+
'EX',
35+
APP_VERSION_REDIS_SEC
36+
);
3137
} catch (error) {
3238
console.warn('[Redis] Failed to set version cache:', error);
3339
}
@@ -42,7 +48,12 @@ export async function getAppVersion() {
4248

4349
try {
4450
const { redisConnection } = await import('./connection.js');
45-
await redisConnection.set('app:version', JSON.stringify(versionData));
51+
await redisConnection.set(
52+
'app:version',
53+
JSON.stringify(versionData),
54+
'EX',
55+
APP_VERSION_REDIS_SEC
56+
);
4657
} catch (error) {
4758
console.warn('[Redis] Failed to set version cache:', error);
4859
}

server/middleware/apiLogger.ts

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Request, Response, NextFunction } from 'express';
22
import { mainDb } from '../db/connection.js';
3-
import { encrypt } from '../utils/encryption.js';
43
import { getClientIp } from '../utils/getIpAddress.js';
54
import { JwtPayloadClient } from '../types/JwtPayload.js';
65
import { sql } from 'kysely';
@@ -89,20 +88,6 @@ export async function logApiCall(logEntry: ApiLogEntry): Promise<void> {
8988
? logEntry.ip_address.join(', ')
9089
: logEntry.ip_address;
9190

92-
const encryptedIpAddress = encrypt(ipAddress);
93-
94-
const encryptedRequestBody = logEntry.request_body
95-
? encrypt(logEntry.request_body)
96-
: null;
97-
98-
const encryptedResponseBody = logEntry.response_body
99-
? encrypt(logEntry.response_body)
100-
: null;
101-
102-
const encryptedErrorMessage = logEntry.error_message
103-
? encrypt(logEntry.error_message)
104-
: null;
105-
10691
await mainDb
10792
.insertInto('api_logs')
10893
.values({
@@ -113,17 +98,11 @@ export async function logApiCall(logEntry: ApiLogEntry): Promise<void> {
11398
path: logEntry.path,
11499
status_code: logEntry.status_code,
115100
response_time: logEntry.response_time,
116-
ip_address: JSON.stringify(encryptedIpAddress),
101+
ip_address: ipAddress,
117102
user_agent: logEntry.user_agent,
118-
request_body: encryptedRequestBody
119-
? JSON.stringify(encryptedRequestBody)
120-
: null,
121-
response_body: encryptedResponseBody
122-
? JSON.stringify(encryptedResponseBody)
123-
: null,
124-
error_message: encryptedErrorMessage
125-
? JSON.stringify(encryptedErrorMessage)
126-
: null,
103+
request_body: logEntry.request_body,
104+
response_body: logEntry.response_body,
105+
error_message: logEntry.error_message,
127106
timestamp: logEntry.timestamp,
128107
})
129108
.execute();

server/routes/admin/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { requirePermission } from '../../middleware/rolePermissions.js';
55
import { getDailyStatistics, getTotalStatistics } from '../../db/admin.js';
66
import { getAppVersion, updateAppVersion } from '../../db/version.js';
77
import { redisConnection } from '../../db/connection.js';
8+
import { APP_VERSION_REDIS_SEC } from '../../utils/cacheTtl.js';
89

910
import usersRouter from './users.js';
1011
import sessionsRouter from './sessions.js';
@@ -107,7 +108,7 @@ router.put(
107108
cacheKey,
108109
JSON.stringify(updatedVersion),
109110
'EX',
110-
86400
111+
APP_VERSION_REDIS_SEC
111112
);
112113
} catch (error) {
113114
if (error instanceof Error) {

0 commit comments

Comments
 (0)