mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-12 23:33:43 +08:00
fix: sync managed admin password from environment
This commit is contained in:
@@ -177,6 +177,14 @@ export async function verifyPassword(password: string, salt: string, expectedHas
|
||||
return actual.hash === expectedHash;
|
||||
}
|
||||
|
||||
export function isBootstrapAdminCredential(
|
||||
username: string,
|
||||
password: string,
|
||||
adminPassword: string
|
||||
): boolean {
|
||||
return normalizeUsername(username) === 'admin' && !!adminPassword && password === adminPassword;
|
||||
}
|
||||
|
||||
export async function signSessionPayload(payload: SessionPayload, secret: string): Promise<string> {
|
||||
const payloadBytes = encodeText(JSON.stringify(payload));
|
||||
const encodedPayload = encodeBase64Url(payloadBytes);
|
||||
|
||||
+35
-4
@@ -5,6 +5,7 @@ import {
|
||||
createStoredAccount,
|
||||
ensureUniqueUsername,
|
||||
hashPassword,
|
||||
isBootstrapAdminCredential,
|
||||
normalizeUsername,
|
||||
parseBootstrapAccounts,
|
||||
resolveLoginMode,
|
||||
@@ -350,11 +351,41 @@ async function authenticateManagedLogin(username: string, password: string): Pro
|
||||
if (!normalizedUsername || !password) return null;
|
||||
|
||||
const accounts = await ensureManagedAccountsBootstrapped();
|
||||
const account = accounts.find((item) => item.username === normalizedUsername);
|
||||
if (!account) return null;
|
||||
let account = accounts.find((item) => item.username === normalizedUsername);
|
||||
const usesBootstrapAdminCredential = isBootstrapAdminCredential(
|
||||
normalizedUsername,
|
||||
password,
|
||||
effectiveAdminPassword
|
||||
);
|
||||
|
||||
const valid = await verifyPassword(password, account.passwordSalt, account.passwordHash);
|
||||
if (!valid) return null;
|
||||
if (!account) {
|
||||
if (!usesBootstrapAdminCredential) return null;
|
||||
|
||||
account = await createStoredAccount({
|
||||
username: 'admin',
|
||||
password,
|
||||
name: '超级管理员',
|
||||
role: 'super_admin',
|
||||
customPermissions: [],
|
||||
});
|
||||
await saveManagedAccounts([...accounts, account]);
|
||||
} else {
|
||||
const valid = await verifyPassword(password, account.passwordSalt, account.passwordHash);
|
||||
if (!valid) {
|
||||
if (!usesBootstrapAdminCredential) return null;
|
||||
|
||||
const nextPassword = await hashPassword(password);
|
||||
account = {
|
||||
...account,
|
||||
passwordHash: nextPassword.hash,
|
||||
passwordSalt: nextPassword.salt,
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
await saveManagedAccounts(
|
||||
accounts.map((item) => item.id === account?.id ? account : item)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
accountId: account.id,
|
||||
|
||||
@@ -3,6 +3,7 @@ import assert from 'node:assert/strict';
|
||||
import {
|
||||
createStoredAccount,
|
||||
hashPassword,
|
||||
isBootstrapAdminCredential,
|
||||
parseBootstrapAccounts,
|
||||
resolveLoginMode,
|
||||
shouldUseSecureSessionCookie,
|
||||
@@ -73,6 +74,13 @@ test('hashPassword and verifyPassword round-trip correctly', async () => {
|
||||
assert.equal(await verifyPassword('wrong-password', password.salt, password.hash), false);
|
||||
});
|
||||
|
||||
test('bootstrap admin credential only accepts the configured admin password', () => {
|
||||
assert.equal(isBootstrapAdminCredential('ADMIN', 'current-secret', 'current-secret'), true);
|
||||
assert.equal(isBootstrapAdminCredential('admin', 'old-secret', 'current-secret'), false);
|
||||
assert.equal(isBootstrapAdminCredential('viewer', 'current-secret', 'current-secret'), false);
|
||||
assert.equal(isBootstrapAdminCredential('admin', '', ''), false);
|
||||
});
|
||||
|
||||
test('signSessionPayload and verifySessionToken reject tampering', async () => {
|
||||
const token = await signSessionPayload({
|
||||
accountId: 'account-1',
|
||||
|
||||
Reference in New Issue
Block a user