fix: remove default dcrouter admin password

This commit is contained in:
2026-05-08 16:24:45 +00:00
parent 7bb6559748
commit 7e3b89d9b4
10 changed files with 1575 additions and 1917 deletions
+23 -23
View File
@@ -23,12 +23,12 @@
}, },
"devDependencies": { "devDependencies": {
"@git.zone/tsbuild": "^4.4.0", "@git.zone/tsbuild": "^4.4.0",
"@git.zone/tsbundle": "^2.10.0", "@git.zone/tsbundle": "^2.10.1",
"@git.zone/tsdocker": "^2.2.4", "@git.zone/tsdocker": "^2.2.5",
"@git.zone/tsrun": "^2.0.2", "@git.zone/tsrun": "^2.0.3",
"@git.zone/tstest": "^3.6.3", "@git.zone/tstest": "^3.6.3",
"@git.zone/tswatch": "^3.3.2", "@git.zone/tswatch": "^3.3.3",
"@types/node": "^25.6.0" "@types/node": "^25.6.1"
}, },
"dependencies": { "dependencies": {
"@api.global/typedrequest": "^3.3.0", "@api.global/typedrequest": "^3.3.0",
@@ -36,41 +36,41 @@
"@api.global/typedserver": "^8.4.6", "@api.global/typedserver": "^8.4.6",
"@api.global/typedsocket": "^4.1.2", "@api.global/typedsocket": "^4.1.2",
"@apiclient.xyz/cloudflare": "^7.1.0", "@apiclient.xyz/cloudflare": "^7.1.0",
"@design.estate/dees-catalog": "^3.78.2", "@design.estate/dees-catalog": "^3.81.0",
"@design.estate/dees-element": "^2.2.4", "@design.estate/dees-element": "^2.2.4",
"@push.rocks/lik": "^6.4.0", "@push.rocks/lik": "^6.4.1",
"@push.rocks/projectinfo": "^5.1.0", "@push.rocks/projectinfo": "^5.1.0",
"@push.rocks/qenv": "^6.1.3", "@push.rocks/qenv": "^6.1.4",
"@push.rocks/smartacme": "^9.5.0", "@push.rocks/smartacme": "^9.5.0",
"@push.rocks/smartdata": "^7.1.7", "@push.rocks/smartdata": "^7.1.7",
"@push.rocks/smartdb": "^2.6.2", "@push.rocks/smartdb": "^2.10.0",
"@push.rocks/smartdns": "^7.9.0", "@push.rocks/smartdns": "^7.9.2",
"@push.rocks/smartfs": "^1.5.0", "@push.rocks/smartfs": "^1.5.1",
"@push.rocks/smartguard": "^3.1.0", "@push.rocks/smartguard": "^3.1.0",
"@push.rocks/smartjwt": "^2.2.1", "@push.rocks/smartjwt": "^2.2.2",
"@push.rocks/smartlog": "^3.2.2", "@push.rocks/smartlog": "^3.2.2",
"@push.rocks/smartmetrics": "^3.0.3", "@push.rocks/smartmetrics": "^3.0.3",
"@push.rocks/smartmigration": "1.2.0", "@push.rocks/smartmigration": "1.3.1",
"@push.rocks/smartmta": "^5.3.3", "@push.rocks/smartmta": "^5.3.3",
"@push.rocks/smartnetwork": "^4.7.0", "@push.rocks/smartnetwork": "^4.7.1",
"@push.rocks/smartpath": "^6.0.0", "@push.rocks/smartpath": "^6.0.0",
"@push.rocks/smartpromise": "^4.2.3", "@push.rocks/smartpromise": "^4.2.4",
"@push.rocks/smartproxy": "^27.9.0", "@push.rocks/smartproxy": "^27.10.0",
"@push.rocks/smartradius": "^1.1.1", "@push.rocks/smartradius": "^1.1.2",
"@push.rocks/smartrequest": "^5.0.1", "@push.rocks/smartrequest": "^5.0.3",
"@push.rocks/smartrx": "^3.0.10", "@push.rocks/smartrx": "^3.0.10",
"@push.rocks/smartstate": "^2.3.0", "@push.rocks/smartstate": "^2.3.1",
"@push.rocks/smartunique": "^3.0.9", "@push.rocks/smartunique": "^3.0.9",
"@push.rocks/smartvpn": "1.19.2", "@push.rocks/smartvpn": "1.19.2",
"@push.rocks/taskbuffer": "^8.0.2", "@push.rocks/taskbuffer": "^8.0.2",
"@serve.zone/catalog": "^2.12.4", "@serve.zone/catalog": "^2.12.4",
"@serve.zone/interfaces": "^5.4.6", "@serve.zone/interfaces": "^5.5.0",
"@serve.zone/remoteingress": "^4.17.1", "@serve.zone/remoteingress": "^4.17.1",
"@tsclass/tsclass": "^9.5.0", "@tsclass/tsclass": "^9.5.1",
"@types/qrcode": "^1.5.6", "@types/qrcode": "^1.5.6",
"lru-cache": "^11.3.5", "lru-cache": "^11.3.6",
"qrcode": "^1.5.4", "qrcode": "^1.5.4",
"uuid": "^13.0.0" "uuid": "^14.0.0"
}, },
"keywords": [ "keywords": [
"mail service", "mail service",
+1523 -1883
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -5,6 +5,7 @@ import * as interfaces from '../ts_interfaces/index.js';
const TEST_PORT = 3201; const TEST_PORT = 3201;
const BASE_URL = `http://localhost:${TEST_PORT}/typedrequest`; const BASE_URL = `http://localhost:${TEST_PORT}/typedrequest`;
const TEST_ADMIN_PASSWORD = 'test-admin-password';
let testDcRouter: DcRouter; let testDcRouter: DcRouter;
let adminIdentity: interfaces.data.IIdentity; let adminIdentity: interfaces.data.IIdentity;
@@ -56,6 +57,7 @@ const queueItems = [
]; ];
tap.test('should start DCRouter with OpsServer for email API tests', async () => { tap.test('should start DCRouter with OpsServer for email API tests', async () => {
process.env.DCROUTER_ADMIN_PASSWORD = TEST_ADMIN_PASSWORD;
testDcRouter = new DcRouter({ testDcRouter = new DcRouter({
opsServerPort: TEST_PORT, opsServerPort: TEST_PORT,
dbConfig: { enabled: false }, dbConfig: { enabled: false },
@@ -98,7 +100,7 @@ tap.test('should login as admin for email API tests', async () => {
const response = await loginRequest.fire({ const response = await loginRequest.fire({
username: 'admin', username: 'admin',
password: 'admin', password: TEST_ADMIN_PASSWORD,
}); });
const responseIdentity = response.identity; const responseIdentity = response.identity;
+3 -1
View File
@@ -5,8 +5,10 @@ import * as interfaces from '../ts_interfaces/index.js';
let testDcRouter: DcRouter; let testDcRouter: DcRouter;
let identity: interfaces.data.IIdentity; let identity: interfaces.data.IIdentity;
const testAdminPassword = 'test-admin-password';
tap.test('should start DCRouter with OpsServer', async () => { tap.test('should start DCRouter with OpsServer', async () => {
process.env.DCROUTER_ADMIN_PASSWORD = testAdminPassword;
testDcRouter = new DcRouter({ testDcRouter = new DcRouter({
// Minimal config for testing // Minimal config for testing
opsServerPort: 3102, opsServerPort: 3102,
@@ -25,7 +27,7 @@ tap.test('should login with admin credentials and receive JWT', async () => {
const response = await loginRequest.fire({ const response = await loginRequest.fire({
username: 'admin', username: 'admin',
password: 'admin' password: testAdminPassword
}); });
expect(response).toHaveProperty('identity'); expect(response).toHaveProperty('identity');
+3 -1
View File
@@ -5,8 +5,10 @@ import * as interfaces from '../ts_interfaces/index.js';
let testDcRouter: DcRouter; let testDcRouter: DcRouter;
let adminIdentity: interfaces.data.IIdentity; let adminIdentity: interfaces.data.IIdentity;
const testAdminPassword = 'test-admin-password';
tap.test('should start DCRouter with OpsServer', async () => { tap.test('should start DCRouter with OpsServer', async () => {
process.env.DCROUTER_ADMIN_PASSWORD = testAdminPassword;
testDcRouter = new DcRouter({ testDcRouter = new DcRouter({
// Minimal config for testing // Minimal config for testing
opsServerPort: 3101, opsServerPort: 3101,
@@ -25,7 +27,7 @@ tap.test('should login as admin', async () => {
const response = await loginRequest.fire({ const response = await loginRequest.fire({
username: 'admin', username: 'admin',
password: 'admin', password: testAdminPassword,
}); });
expect(response).toHaveProperty('identity'); expect(response).toHaveProperty('identity');
+3 -1
View File
@@ -5,8 +5,10 @@ import * as interfaces from '../ts_interfaces/index.js';
let testDcRouter: DcRouter; let testDcRouter: DcRouter;
let adminIdentity: interfaces.data.IIdentity; let adminIdentity: interfaces.data.IIdentity;
const testAdminPassword = 'test-admin-password';
tap.test('should start DCRouter with OpsServer', async () => { tap.test('should start DCRouter with OpsServer', async () => {
process.env.DCROUTER_ADMIN_PASSWORD = testAdminPassword;
testDcRouter = new DcRouter({ testDcRouter = new DcRouter({
// Minimal config for testing // Minimal config for testing
opsServerPort: 3103, opsServerPort: 3103,
@@ -25,7 +27,7 @@ tap.test('should login as admin', async () => {
const response = await loginRequest.fire({ const response = await loginRequest.fire({
username: 'admin', username: 'admin',
password: 'admin' password: testAdminPassword
}); });
expect(response).toHaveProperty('identity'); expect(response).toHaveProperty('identity');
+3 -1
View File
@@ -5,6 +5,7 @@ import * as interfaces from '../ts_interfaces/index.js';
const TEST_PORT = 3200; const TEST_PORT = 3200;
const TEST_URL = `http://localhost:${TEST_PORT}/typedrequest`; const TEST_URL = `http://localhost:${TEST_PORT}/typedrequest`;
const TEST_ADMIN_PASSWORD = 'test-admin-password';
let testDcRouter: DcRouter; let testDcRouter: DcRouter;
let adminIdentity: interfaces.data.IIdentity; let adminIdentity: interfaces.data.IIdentity;
@@ -14,6 +15,7 @@ let adminIdentity: interfaces.data.IIdentity;
// ============================================================================ // ============================================================================
tap.test('should start DCRouter with OpsServer', async () => { tap.test('should start DCRouter with OpsServer', async () => {
process.env.DCROUTER_ADMIN_PASSWORD = TEST_ADMIN_PASSWORD;
testDcRouter = new DcRouter({ testDcRouter = new DcRouter({
opsServerPort: TEST_PORT, opsServerPort: TEST_PORT,
dbConfig: { enabled: false }, dbConfig: { enabled: false },
@@ -31,7 +33,7 @@ tap.test('should login as admin', async () => {
const response = await loginRequest.fire({ const response = await loginRequest.fire({
username: 'admin', username: 'admin',
password: 'admin', password: TEST_ADMIN_PASSWORD,
}); });
expect(response).toHaveProperty('identity'); expect(response).toHaveProperty('identity');
+11 -4
View File
@@ -43,14 +43,21 @@ export class AdminHandler {
} }
private initializeDefaultUsers(): void { private initializeDefaultUsers(): void {
// Add default admin user const username = process.env.DCROUTER_ADMIN_USERNAME || 'admin';
const configuredPassword = process.env.DCROUTER_ADMIN_PASSWORD;
const password = configuredPassword || plugins.crypto.randomBytes(24).toString('base64url');
const adminId = plugins.uuid.v4(); const adminId = plugins.uuid.v4();
this.users.set(adminId, { this.users.set(adminId, {
id: adminId, id: adminId,
username: 'admin', username,
password: 'admin', password,
role: 'admin', role: 'admin',
}); });
if (!configuredPassword) {
console.warn(`DCRouter generated one-time admin password for ${username}: ${password}`);
}
} }
/** /**
@@ -249,4 +256,4 @@ export class AdminHandler {
name: 'adminIdentityGuard', name: 'adminIdentityGuard',
} }
); );
} }
-2
View File
@@ -1,5 +1,3 @@
/// <reference types="node" />
/** /**
* dcrouter migration runner. * dcrouter migration runner.
* *
+3
View File
@@ -3,6 +3,9 @@
"target": "ES2022", "target": "ES2022",
"module": "NodeNext", "module": "NodeNext",
"moduleResolution": "NodeNext", "moduleResolution": "NodeNext",
"types": [
"node"
],
"esModuleInterop": true, "esModuleInterop": true,
"verbatimModuleSyntax": true "verbatimModuleSyntax": true
}, },