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
+16 -16
View File
@@ -2,7 +2,7 @@ import * as plugins from '../../plugins.ts';
import { logger } from '../../logging.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 ServicesHandler {
public typedrouter = new plugins.typedrequest.TypedRouter();
@@ -18,7 +18,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetServices>(
'getServices',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const services = this.opsServerRef.oneboxRef.services.listServices();
return { services };
},
@@ -30,7 +30,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetService>(
'getService',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const service = this.opsServerRef.oneboxRef.services.getService(dataArg.serviceName);
if (!service) {
throw new plugins.typedrequest.TypedResponseError('Service not found');
@@ -45,7 +45,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateService>(
'createService',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const service = await this.opsServerRef.oneboxRef.services.deployService(dataArg.serviceConfig);
return { service };
},
@@ -57,7 +57,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateService>(
'updateService',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const service = await this.opsServerRef.oneboxRef.services.updateService(
dataArg.serviceName,
dataArg.updates,
@@ -72,7 +72,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteService>(
'deleteService',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
await this.opsServerRef.oneboxRef.services.removeService(dataArg.serviceName);
return { ok: true };
},
@@ -84,7 +84,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_StartService>(
'startService',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
await this.opsServerRef.oneboxRef.services.startService(dataArg.serviceName);
const service = this.opsServerRef.oneboxRef.services.getService(dataArg.serviceName);
return { service: service! };
@@ -97,7 +97,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_StopService>(
'stopService',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
await this.opsServerRef.oneboxRef.services.stopService(dataArg.serviceName);
const service = this.opsServerRef.oneboxRef.services.getService(dataArg.serviceName);
return { service: service! };
@@ -110,7 +110,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_RestartService>(
'restartService',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
await this.opsServerRef.oneboxRef.services.restartService(dataArg.serviceName);
const service = this.opsServerRef.oneboxRef.services.getService(dataArg.serviceName);
return { service: service! };
@@ -123,7 +123,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetServiceLogs>(
'getServiceLogs',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const logs = await this.opsServerRef.oneboxRef.services.getServiceLogs(dataArg.serviceName);
return { logs: String(logs) };
},
@@ -135,7 +135,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetServiceStats>(
'getServiceStats',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const service = this.opsServerRef.oneboxRef.services.getService(dataArg.serviceName);
if (!service || !service.containerID) {
throw new plugins.typedrequest.TypedResponseError('Service has no container');
@@ -154,7 +154,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetServiceMetrics>(
'getServiceMetrics',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const service = this.opsServerRef.oneboxRef.services.getService(dataArg.serviceName);
if (!service || !service.id) {
throw new plugins.typedrequest.TypedResponseError('Service not found');
@@ -170,7 +170,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetServicePlatformResources>(
'getServicePlatformResources',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const rawResources = await this.opsServerRef.oneboxRef.services.getServicePlatformResources(
dataArg.serviceName,
);
@@ -204,7 +204,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetServiceBackups>(
'getServiceBackups',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const backups = this.opsServerRef.oneboxRef.backupManager.listBackups(dataArg.serviceName);
return { backups };
},
@@ -216,7 +216,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateServiceBackup>(
'createServiceBackup',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const result = await this.opsServerRef.oneboxRef.backupManager.createBackup(dataArg.serviceName);
return { backup: result.backup };
},
@@ -228,7 +228,7 @@ export class ServicesHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetServiceBackupSchedules>(
'getServiceBackupSchedules',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const service = this.opsServerRef.oneboxRef.services.getService(dataArg.serviceName);
if (!service) {
throw new plugins.typedrequest.TypedResponseError('Service not found');