mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 13:00:39 +00:00
feat: added logging system
This commit is contained in:
+87
-12
@@ -2,6 +2,7 @@ import { Env, User, ProfileResponse, DEFAULT_DEV_SECRET } from '../types';
|
||||
import { StorageService } from '../services/storage';
|
||||
import { AuthService } from '../services/auth';
|
||||
import { RateLimitService, getClientIdentifier } from '../services/ratelimit';
|
||||
import { auditRequestMetadata, writeAuditEvent, safeWriteAuditEvent } from '../services/audit-events';
|
||||
import { jsonResponse, errorResponse } from '../utils/response';
|
||||
import { generateUUID } from '../utils/uuid';
|
||||
import { LIMITS } from '../config/limits';
|
||||
@@ -227,14 +228,14 @@ export async function handleRegister(request: Request, env: Env): Promise<Respon
|
||||
return errorResponse('Registration is temporarily unavailable, retry once', 409);
|
||||
}
|
||||
await storage.setRegistered();
|
||||
await storage.createAuditLog({
|
||||
id: generateUUID(),
|
||||
await writeAuditEvent(storage, {
|
||||
actorUserId: user.id,
|
||||
action: 'user.register.first_admin',
|
||||
targetType: 'user',
|
||||
targetId: user.id,
|
||||
metadata: JSON.stringify({ email: user.email }),
|
||||
createdAt: now,
|
||||
category: 'security',
|
||||
level: 'security',
|
||||
metadata: { email: user.email, ...auditRequestMetadata(request) },
|
||||
});
|
||||
return jsonResponse({ success: true, role: user.role }, 200);
|
||||
}
|
||||
@@ -259,14 +260,14 @@ export async function handleRegister(request: Request, env: Env): Promise<Respon
|
||||
return errorResponse('Invite code is invalid or expired', 403);
|
||||
}
|
||||
|
||||
await storage.createAuditLog({
|
||||
id: generateUUID(),
|
||||
await writeAuditEvent(storage, {
|
||||
actorUserId: user.id,
|
||||
action: 'user.register.invite',
|
||||
targetType: 'user',
|
||||
targetId: user.id,
|
||||
metadata: JSON.stringify({ email: user.email, inviteCode }),
|
||||
createdAt: now,
|
||||
category: 'security',
|
||||
level: 'info',
|
||||
metadata: { email: user.email, inviteCode, ...auditRequestMetadata(request) },
|
||||
});
|
||||
|
||||
return jsonResponse({ success: true, role: user.role }, 200);
|
||||
@@ -378,6 +379,18 @@ export async function handleUpdateProfile(request: Request, env: Env, userId: st
|
||||
user.masterPasswordHint = masterPasswordHint;
|
||||
user.updatedAt = new Date().toISOString();
|
||||
await storage.saveUser(user);
|
||||
await writeAuditEvent(storage, {
|
||||
actorUserId: user.id,
|
||||
action: 'account.profile.update',
|
||||
category: 'security',
|
||||
level: 'info',
|
||||
targetType: 'user',
|
||||
targetId: user.id,
|
||||
metadata: {
|
||||
updatedMasterPasswordHint: true,
|
||||
...auditRequestMetadata(request),
|
||||
},
|
||||
});
|
||||
|
||||
return jsonResponse(toProfile(user, env));
|
||||
}
|
||||
@@ -412,6 +425,18 @@ export async function handleSetVerifyDevices(request: Request, env: Env, userId:
|
||||
user.verifyDevices = body.verifyDevices;
|
||||
user.updatedAt = new Date().toISOString();
|
||||
await storage.saveUser(user);
|
||||
await writeAuditEvent(storage, {
|
||||
actorUserId: user.id,
|
||||
action: 'account.verify_devices.update',
|
||||
category: 'security',
|
||||
level: 'security',
|
||||
targetType: 'user',
|
||||
targetId: user.id,
|
||||
metadata: {
|
||||
verifyDevices: user.verifyDevices,
|
||||
...auditRequestMetadata(request),
|
||||
},
|
||||
});
|
||||
|
||||
return new Response(null, { status: 200 });
|
||||
}
|
||||
@@ -461,6 +486,20 @@ export async function handleSetKeys(request: Request, env: Env, userId: string):
|
||||
user.updatedAt = new Date().toISOString();
|
||||
|
||||
await storage.saveUser(user);
|
||||
await writeAuditEvent(storage, {
|
||||
actorUserId: user.id,
|
||||
action: 'account.keys.update',
|
||||
category: 'security',
|
||||
level: 'security',
|
||||
targetType: 'user',
|
||||
targetId: user.id,
|
||||
metadata: {
|
||||
updatedKey: !!body.key,
|
||||
updatedPrivateKey: !!body.encryptedPrivateKey,
|
||||
updatedPublicKey: !!body.publicKey,
|
||||
...auditRequestMetadata(request),
|
||||
},
|
||||
});
|
||||
|
||||
return handleGetProfile(request, env, userId);
|
||||
}
|
||||
@@ -527,14 +566,14 @@ export async function handleChangePassword(request: Request, env: Env, userId: s
|
||||
await storage.saveUser(user);
|
||||
await storage.deleteRefreshTokensByUserId(user.id);
|
||||
AuthService.invalidateUserCache(user.id);
|
||||
await storage.createAuditLog({
|
||||
id: generateUUID(),
|
||||
await writeAuditEvent(storage, {
|
||||
actorUserId: user.id,
|
||||
action: 'user.password.change',
|
||||
targetType: 'user',
|
||||
targetId: user.id,
|
||||
metadata: JSON.stringify({ email: user.email }),
|
||||
createdAt: user.updatedAt,
|
||||
category: 'security',
|
||||
level: 'security',
|
||||
metadata: { email: user.email, ...auditRequestMetadata(request) },
|
||||
});
|
||||
|
||||
return new Response(null, { status: 200 });
|
||||
@@ -589,6 +628,15 @@ export async function handleSetTotpStatus(request: Request, env: Env, userId: st
|
||||
await storage.saveUser(user);
|
||||
await storage.deleteRefreshTokensByUserId(user.id);
|
||||
AuthService.invalidateUserCache(user.id);
|
||||
await writeAuditEvent(storage, {
|
||||
actorUserId: user.id,
|
||||
action: 'account.totp.enable',
|
||||
category: 'security',
|
||||
level: 'security',
|
||||
targetType: 'user',
|
||||
targetId: user.id,
|
||||
metadata: auditRequestMetadata(request),
|
||||
});
|
||||
return jsonResponse({ enabled: true, recoveryCode: user.totpRecoveryCode, object: 'twoFactor' });
|
||||
}
|
||||
|
||||
@@ -604,6 +652,15 @@ export async function handleSetTotpStatus(request: Request, env: Env, userId: st
|
||||
await storage.saveUser(user);
|
||||
await storage.deleteRefreshTokensByUserId(user.id);
|
||||
AuthService.invalidateUserCache(user.id);
|
||||
await writeAuditEvent(storage, {
|
||||
actorUserId: user.id,
|
||||
action: 'account.totp.disable',
|
||||
category: 'security',
|
||||
level: 'security',
|
||||
targetType: 'user',
|
||||
targetId: user.id,
|
||||
metadata: auditRequestMetadata(request),
|
||||
});
|
||||
return jsonResponse({ enabled: false, object: 'twoFactor' });
|
||||
}
|
||||
|
||||
@@ -713,6 +770,15 @@ export async function handleRecoverTwoFactor(request: Request, env: Env): Promis
|
||||
await storage.deleteRefreshTokensByUserId(user.id);
|
||||
AuthService.invalidateUserCache(user.id);
|
||||
await rateLimit.clearLoginAttempts(recoverLimitKey);
|
||||
await safeWriteAuditEvent(env, {
|
||||
actorUserId: user.id,
|
||||
action: 'account.totp.recover',
|
||||
category: 'security',
|
||||
level: 'security',
|
||||
targetType: 'user',
|
||||
targetId: user.id,
|
||||
metadata: auditRequestMetadata(request),
|
||||
});
|
||||
|
||||
return jsonResponse({
|
||||
success: true,
|
||||
@@ -806,6 +872,15 @@ async function apiKey(request: Request, env: Env, userId: string, rotate: boolea
|
||||
user.updatedAt = new Date().toISOString();
|
||||
await storage.saveUser(user);
|
||||
AuthService.invalidateUserCache(user.id);
|
||||
await writeAuditEvent(storage, {
|
||||
actorUserId: user.id,
|
||||
action: rotate ? 'account.api_key.rotate' : 'account.api_key.create',
|
||||
category: 'security',
|
||||
level: rotate ? 'security' : 'info',
|
||||
targetType: 'user',
|
||||
targetId: user.id,
|
||||
metadata: auditRequestMetadata(request),
|
||||
});
|
||||
}
|
||||
|
||||
return jsonResponse({
|
||||
|
||||
Reference in New Issue
Block a user