fix: resolve password migration crash and schema constraints
- Login bcrypt migration: write password_salt = '' instead of NULL, which violated the NOT NULL constraint and caused 500 errors - Schema: widen password_hash from CHAR(64) to VARCHAR(100) for bcrypt compatibility, add DEFAULT '' to password_salt - init-db: add ALTER TABLE migrations for existing databases - app.js: enrich error logging with method, path, SQL error details
这个提交包含在:
@@ -20,6 +20,8 @@ async function main() {
|
|||||||
await conn.query(schema)
|
await conn.query(schema)
|
||||||
|
|
||||||
await conn.query("ALTER TABLE devices MODIFY product_id VARCHAR(64) NOT NULL DEFAULT 'HOX_LIGHT_MASK'").catch(() => {})
|
await conn.query("ALTER TABLE devices MODIFY product_id VARCHAR(64) NOT NULL DEFAULT 'HOX_LIGHT_MASK'").catch(() => {})
|
||||||
|
await conn.query("ALTER TABLE admin_accounts MODIFY password_hash VARCHAR(100) NOT NULL").catch(() => {})
|
||||||
|
await conn.query("ALTER TABLE admin_accounts MODIFY password_salt VARCHAR(32) NOT NULL DEFAULT ''").catch(() => {})
|
||||||
|
|
||||||
const [rows] = await conn.execute('SELECT admin_id FROM admin_accounts WHERE username = ?', [config.admin.username])
|
const [rows] = await conn.execute('SELECT admin_id FROM admin_accounts WHERE username = ?', [config.admin.username])
|
||||||
if (rows.length === 0) {
|
if (rows.length === 0) {
|
||||||
|
|||||||
+2
-2
@@ -128,8 +128,8 @@ CREATE TABLE IF NOT EXISTS operation_logs (
|
|||||||
CREATE TABLE IF NOT EXISTS admin_accounts (
|
CREATE TABLE IF NOT EXISTS admin_accounts (
|
||||||
admin_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
admin_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
username VARCHAR(64) NOT NULL,
|
username VARCHAR(64) NOT NULL,
|
||||||
password_hash CHAR(64) NOT NULL,
|
password_hash VARCHAR(100) NOT NULL,
|
||||||
password_salt CHAR(32) NOT NULL,
|
password_salt VARCHAR(32) NOT NULL DEFAULT '',
|
||||||
real_name VARCHAR(100) NOT NULL DEFAULT '',
|
real_name VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
role VARCHAR(32) NOT NULL DEFAULT 'admin',
|
role VARCHAR(32) NOT NULL DEFAULT 'admin',
|
||||||
status TINYINT NOT NULL DEFAULT 1,
|
status TINYINT NOT NULL DEFAULT 1,
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ async function handle(event) {
|
|||||||
const body = await match.handler(ctx)
|
const body = await match.handler(ctx)
|
||||||
return http(200, body)
|
return http(200, body)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error('[ERROR]', ctx.method, ctx.path, err.code || '', err.sqlMessage || err.message, err.stack)
|
||||||
return http(500, fail(3001, 'server_error'))
|
return http(500, fail(3001, 'server_error'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ function register(router) {
|
|||||||
// Try legacy SHA-256 verification for migration
|
// Try legacy SHA-256 verification for migration
|
||||||
if (admin.password_salt && hashPasswordLegacy(password, admin.password_salt) === admin.password_hash) {
|
if (admin.password_salt && hashPasswordLegacy(password, admin.password_salt) === admin.password_hash) {
|
||||||
// Auto-migrate to bcrypt
|
// Auto-migrate to bcrypt
|
||||||
const newHash = await hashPassword(password)
|
const newHash = hashPassword(password)
|
||||||
await query('UPDATE admin_accounts SET password_hash = :password_hash, password_salt = NULL WHERE admin_id = :admin_id', { password_hash: newHash, admin_id: admin.admin_id })
|
await query('UPDATE admin_accounts SET password_hash = :password_hash, password_salt = :password_salt WHERE admin_id = :admin_id', { password_hash: newHash, password_salt: '', admin_id: admin.admin_id })
|
||||||
matched = true
|
matched = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户