133 lines
4.3 KiB
JavaScript
133 lines
4.3 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
require('../src/common');
|
|
|
|
const registerAccountRoutes = require('../src/web/routes/admin/account');
|
|
const pages = require('../src/web/pages');
|
|
const { validatePasswordStrength } = require('../src/auth');
|
|
|
|
test('required-password page shows only password controls and uses an inline warning', () => {
|
|
const html = pages.renderRequiredPasswordPage({ id: 5, username: 'demo' }, {
|
|
minimumLength: 12,
|
|
minimumCategories: 3,
|
|
requireLowercase: false,
|
|
requireUppercase: false,
|
|
requireNumber: false,
|
|
requireSymbol: false
|
|
}, 'Current password is incorrect.');
|
|
|
|
assert.match(html, /Password change required/);
|
|
assert.match(html, /Please change your password before continuing\./);
|
|
assert.match(html, /Current password is incorrect\./);
|
|
assert.match(html, /name="current_password"/);
|
|
assert.match(html, /name="new_password"/);
|
|
assert.match(html, /name="confirm_password"/);
|
|
assert.doesNotMatch(html, /account-profile-form|name="email"|Active sessions/);
|
|
assert.doesNotMatch(html, /id="app-toast"/);
|
|
});
|
|
|
|
test('required-password route renders the password-only page and redirects after the requirement clears', async () => {
|
|
const handlers = {};
|
|
const app = {
|
|
get(path, ...routeHandlers) { handlers[path] = routeHandlers; },
|
|
post() {}
|
|
};
|
|
const deps = {
|
|
pool: { async query() { return [[]]; } },
|
|
common: {},
|
|
pages: {
|
|
renderRequiredPasswordPage(user, requirements) {
|
|
return user.username + ':' + requirements.minimumLength;
|
|
}
|
|
},
|
|
formatDashboardDate: () => '',
|
|
getAuditUserId: () => 5,
|
|
verifyPassword: () => true,
|
|
validatePasswordStrength: validatePasswordStrength,
|
|
hashPassword: () => ({ hash: 'hash', salt: 'salt', iterations: 1 }),
|
|
createUserSession: async () => 'token',
|
|
setSessionCookie: () => {}
|
|
};
|
|
registerAccountRoutes(app, deps);
|
|
|
|
const forcedResponse = {
|
|
send(value) { this.body = value; },
|
|
redirect(url) { this.redirectedTo = url; }
|
|
};
|
|
await handlers['/account/password'][0]({ currentUser: { id: 5, username: 'demo', mustChangePassword: true } }, forcedResponse, (error) => { throw error; });
|
|
|
|
const regularResponse = {
|
|
send(value) { this.body = value; },
|
|
redirect(url) { this.redirectedTo = url; }
|
|
};
|
|
await handlers['/account/password'][0]({ currentUser: { id: 5, username: 'demo', mustChangePassword: false } }, regularResponse, (error) => { throw error; });
|
|
|
|
assert.equal(forcedResponse.body, 'demo:10');
|
|
assert.equal(regularResponse.redirectedTo, '/account');
|
|
});
|
|
|
|
test('account password update redirects back to the account page', async () => {
|
|
const handlers = {};
|
|
const app = {
|
|
post(path, ...routeHandlers) {
|
|
handlers[path] = routeHandlers;
|
|
},
|
|
get() {}
|
|
};
|
|
|
|
const deps = {
|
|
pool: {
|
|
async query(sql) {
|
|
if (sql.includes('SELECT id, name, username, password_hash, password_salt, password_iterations FROM a_users WHERE id = ? LIMIT 1')) {
|
|
return [[{ id: 5, password_hash: 'hash', password_salt: 'salt', password_iterations: 1 }]];
|
|
}
|
|
if (sql.includes('UPDATE a_users SET password_hash = ?, password_salt = ?, password_iterations = ?, modified_by = ? WHERE id = ?')) {
|
|
return [{ affectedRows: 1 }];
|
|
}
|
|
if (sql.includes('DELETE FROM a_sessions WHERE user_id = ?')) {
|
|
return [{ affectedRows: 1 }];
|
|
}
|
|
return [[]];
|
|
}
|
|
},
|
|
common: {},
|
|
pages: {},
|
|
formatDashboardDate: () => '',
|
|
getAuditUserId: () => 9,
|
|
verifyPassword: () => true,
|
|
validatePasswordStrength: validatePasswordStrength,
|
|
hashPassword: () => ({ hash: 'new-hash', salt: 'new-salt', iterations: 2 }),
|
|
createUserSession: async () => 'session-token',
|
|
setSessionCookie: () => {}
|
|
};
|
|
|
|
registerAccountRoutes(app, deps);
|
|
|
|
const routeHandlers = handlers['/account/password'];
|
|
assert.equal(Array.isArray(routeHandlers), true);
|
|
|
|
const req = {
|
|
body: {
|
|
current_password: 'current-password',
|
|
new_password: 'NewPassword!1',
|
|
confirm_password: 'NewPassword!1'
|
|
},
|
|
currentUser: { id: 5 }
|
|
};
|
|
const res = {
|
|
redirect(url) {
|
|
this.redirectedTo = url;
|
|
},
|
|
status() {
|
|
return this;
|
|
},
|
|
send() {
|
|
return this;
|
|
}
|
|
};
|
|
|
|
await routeHandlers[0](req, res, () => {});
|
|
|
|
assert.equal(res.redirectedTo, '/account?message=Password%20updated.');
|
|
}); |