Add tests for authentication and security features

- Implement unit tests for password handling in `auth_test.ts`, covering bcrypt and legacy password hashes.
- Create a fake database for user management to facilitate testing of the `AdminHandler`.
- Validate JWT-based identity verification against database records.
- Introduce tests for credential encryption and registry management in `security_test.ts`.
- Ensure registry passwords are securely stored and can be decrypted correctly, including legacy support.
- Add utility functions for password hashing and verification in `auth.ts`.
This commit is contained in:
2026-04-19 01:30:54 +00:00
parent 0c9eb0653d
commit 618d4d674f
34 changed files with 585 additions and 255 deletions
+15 -8
View File
@@ -1,7 +1,7 @@
import * as plugins from '../../plugins.ts';
import type { OpsServer } from '../classes.opsserver.ts';
import * as interfaces from '../../../ts_interfaces/index.ts';
import { requireValidIdentity } from '../helpers/guards.ts';
import { requireAdminIdentity } from '../helpers/guards.ts';
export class SettingsHandler {
public typedrouter = new plugins.typedrequest.TypedRouter();
@@ -16,7 +16,7 @@ export class SettingsHandler {
const settingsMap = db.getAllSettings(); // Returns Record<string, string>
return {
cloudflareToken: settingsMap['cloudflareToken'] || '',
cloudflareToken: settingsMap['cloudflareToken'] || settingsMap['cloudflareAPIKey'] || '',
cloudflareZoneId: settingsMap['cloudflareZoneId'] || '',
autoRenewCerts: settingsMap['autoRenewCerts'] === 'true',
renewalThreshold: parseInt(settingsMap['renewalThreshold'] || '30', 10),
@@ -32,7 +32,7 @@ export class SettingsHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetSettings>(
'getSettings',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const settings = this.getSettingsObject();
return { settings };
},
@@ -43,14 +43,19 @@ export class SettingsHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateSettings>(
'updateSettings',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const db = this.opsServerRef.oneboxRef.database;
const updates = dataArg.settings;
// Store each setting as key-value pair
for (const [key, value] of Object.entries(updates)) {
if (value !== undefined) {
db.setSetting(key, String(value));
if (key === 'cloudflareToken') {
db.setSetting('cloudflareToken', String(value));
db.setSetting('cloudflareAPIKey', String(value));
} else {
db.setSetting(key, String(value));
}
}
}
@@ -64,7 +69,8 @@ export class SettingsHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_SetBackupPassword>(
'setBackupPassword',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
this.opsServerRef.oneboxRef.database.setSetting('backup_encryption_password', dataArg.password);
this.opsServerRef.oneboxRef.database.setSetting('backupPassword', dataArg.password);
return { ok: true };
},
@@ -75,8 +81,9 @@ export class SettingsHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetBackupPasswordStatus>(
'getBackupPasswordStatus',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
const backupPassword = this.opsServerRef.oneboxRef.database.getSetting('backupPassword');
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const backupPassword = this.opsServerRef.oneboxRef.database.getSetting('backupPassword')
|| this.opsServerRef.oneboxRef.database.getSetting('backup_encryption_password');
const isConfigured = !!backupPassword;
return { status: { isConfigured } };
},