fix: lazy DATA_DIR in sync db (multi-instance safe), demo never admin, first real user auto-promoted
This commit is contained in:
@@ -11,10 +11,12 @@ export function register({ username, password, device_name, invite_code, seed })
|
||||
if (cnt >= maxUsers) throw new Error('注册名额已满,请联系管理员');
|
||||
}
|
||||
const userCount = d.prepare('SELECT COUNT(*) AS c FROM users').get().c;
|
||||
const hasAdmin = d.prepare('SELECT COUNT(*) AS c FROM users WHERE is_admin=1').get().c;
|
||||
let isAdmin = 0;
|
||||
if (userCount === 0) {
|
||||
isAdmin = 1; // 首位注册者自动成为管理员
|
||||
} else if (seed) {
|
||||
if (username !== 'demo' && hasAdmin === 0) {
|
||||
isAdmin = 1; // 首个真实用户自动成为管理员(demo 只是演示账号,不占管理员席位)
|
||||
}
|
||||
if (seed) {
|
||||
// 内置演示账号播种:不要求邀请码
|
||||
} else {
|
||||
const code = String(invite_code || '').trim().toUpperCase();
|
||||
|
||||
+13
-6
@@ -3,15 +3,22 @@ import { DatabaseSync } from 'node:sqlite';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export const DATA_DIR = process.env.DATA_DIR || path.join(process.cwd(), 'data');
|
||||
export const BLOB_DIR = path.join(DATA_DIR, 'blobs');
|
||||
const DB_PATH = path.join(DATA_DIR, 'sync.db');
|
||||
|
||||
export function blobDirNow() { return path.join(dataDirNow(), 'blobs'); }
|
||||
export let BLOB_DIR = path.join(dataDirNow(), 'blobs');
|
||||
export function dataDirNow() {
|
||||
return process.env.DATA_DIR || path.join(process.cwd(), 'data');
|
||||
}
|
||||
let db = null;
|
||||
|
||||
export function getDb() {
|
||||
if (db) return db;
|
||||
fs.mkdirSync(BLOB_DIR, { recursive: true });
|
||||
const DATA_DIR = dataDirNow();
|
||||
const blobDir = path.join(DATA_DIR, 'blobs');
|
||||
const DB_PATH = path.join(DATA_DIR, 'sync.db');
|
||||
if (db && getDb._dir === DATA_DIR) return db;
|
||||
if (db) { try { db.close(); } catch {} }
|
||||
getDb._dir = DATA_DIR;
|
||||
BLOB_DIR = blobDir;
|
||||
fs.mkdirSync(blobDir, { recursive: true });
|
||||
db = new DatabaseSync(DB_PATH);
|
||||
db.exec('PRAGMA journal_mode = WAL;');
|
||||
db.exec('PRAGMA foreign_keys = ON;');
|
||||
|
||||
@@ -233,6 +233,7 @@ const server = http.createServer(async (req, res) => {
|
||||
if (existing && existing.id !== auth.user_id) await deleteUserCascade(db, existing);
|
||||
const { register } = await import('./auth.mjs');
|
||||
const uid = register({ username: 'demo', password: 'demo1234', device_name: 'seed-demo', seed: true }).user_id;
|
||||
db.prepare('UPDATE users SET is_admin=0 WHERE username=?').run('demo');
|
||||
const seeded = commandsFor(uid).handleCommand('demo_seed', {});
|
||||
console.log('[footprints-sync] demo 账号已重建:', JSON.stringify(seeded));
|
||||
return send(200, true, { ok: true, seeded });
|
||||
@@ -568,6 +569,8 @@ try {
|
||||
} else {
|
||||
console.log('[footprints-sync] demo 账号已存在 (demo / demo1234)');
|
||||
}
|
||||
// demo 永远不是管理员(历史库也一并纠正)
|
||||
d.prepare('UPDATE users SET is_admin=0 WHERE username=?').run('demo');
|
||||
const seeded = commandsFor(demoId).handleCommand('demo_seed', {});
|
||||
console.log('[footprints-sync] demo 演示数据:', JSON.stringify(seeded));
|
||||
} catch (e) { console.log('[footprints-sync] demo 种子跳过:', e.message); }
|
||||
|
||||
Reference in New Issue
Block a user