v4.0.10: 관리자 계정 변경 안전장치와 접속시간 지표 추가
역할 변경은 명시적으로 버튼을 눌렀을 때만 가능하게 제한하고, 마지막 접속시간과 비밀번호 분실 안내를 추가해 운영 관리성을 높인다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -28,6 +28,7 @@ export function initDb(dbPath) {
|
||||
avatar_url TEXT,
|
||||
role TEXT NOT NULL DEFAULT 'user',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
last_login_at TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
@@ -77,6 +78,9 @@ export function initDb(dbPath) {
|
||||
if (!userCols.some((c) => c.name === 'skip_deck_public_prompt')) {
|
||||
db.exec('ALTER TABLE users ADD COLUMN skip_deck_public_prompt INTEGER NOT NULL DEFAULT 0');
|
||||
}
|
||||
if (!userCols.some((c) => c.name === 'last_login_at')) {
|
||||
db.exec('ALTER TABLE users ADD COLUMN last_login_at TEXT');
|
||||
}
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,8 @@ export function createAdminRouter(db) {
|
||||
`).get(like, like, like).c;
|
||||
rows = db.prepare(`
|
||||
SELECT id, email, username, display_name AS displayName, avatar_url AS avatarUrl,
|
||||
role, is_active AS isActive, created_at AS createdAt, updated_at AS updatedAt
|
||||
role, is_active AS isActive, last_login_at AS lastLoginAt,
|
||||
created_at AS createdAt, updated_at AS updatedAt
|
||||
FROM users
|
||||
WHERE email LIKE ? OR username LIKE ? OR display_name LIKE ?
|
||||
ORDER BY created_at DESC LIMIT ? OFFSET ?
|
||||
@@ -78,7 +79,8 @@ export function createAdminRouter(db) {
|
||||
total = db.prepare('SELECT COUNT(*) AS c FROM users').get().c;
|
||||
rows = db.prepare(`
|
||||
SELECT id, email, username, display_name AS displayName, avatar_url AS avatarUrl,
|
||||
role, is_active AS isActive, created_at AS createdAt, updated_at AS updatedAt
|
||||
role, is_active AS isActive, last_login_at AS lastLoginAt,
|
||||
created_at AS createdAt, updated_at AS updatedAt
|
||||
FROM users ORDER BY created_at DESC LIMIT ? OFFSET ?
|
||||
`).all(Number(limit), offset);
|
||||
}
|
||||
@@ -100,7 +102,8 @@ export function createAdminRouter(db) {
|
||||
router.get('/users/:id', (req, res) => {
|
||||
const user = db.prepare(`
|
||||
SELECT id, email, username, display_name AS displayName, avatar_url AS avatarUrl,
|
||||
role, is_active AS isActive, created_at AS createdAt, updated_at AS updatedAt
|
||||
role, is_active AS isActive, last_login_at AS lastLoginAt,
|
||||
created_at AS createdAt, updated_at AS updatedAt
|
||||
FROM users WHERE id = ?
|
||||
`).get(req.params.id);
|
||||
|
||||
@@ -188,7 +191,8 @@ export function createAdminRouter(db) {
|
||||
|
||||
const updated = db.prepare(`
|
||||
SELECT id, email, username, display_name AS displayName, avatar_url AS avatarUrl,
|
||||
role, is_active AS isActive, created_at AS createdAt, updated_at AS updatedAt
|
||||
role, is_active AS isActive, last_login_at AS lastLoginAt,
|
||||
created_at AS createdAt, updated_at AS updatedAt
|
||||
FROM users WHERE id = ?
|
||||
`).get(targetId);
|
||||
updated.avatarUrl = getAvatarUrl(updated.id) || updated.avatarUrl;
|
||||
|
||||
@@ -97,8 +97,9 @@ export function createAuthRouter(db) {
|
||||
return res.status(401).json({ error: '이메일 또는 비밀번호가 올바르지 않습니다.' });
|
||||
}
|
||||
|
||||
db.prepare('UPDATE users SET last_login_at = ? WHERE id = ?').run(nowIso(), user.id);
|
||||
const row = db.prepare(`
|
||||
SELECT id, email, username, avatar_url, role, updated_at AS updatedAt
|
||||
SELECT id, email, username, avatar_url, role, updated_at AS updatedAt, last_login_at AS lastLoginAt
|
||||
FROM users WHERE id = ?
|
||||
`).get(user.id);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user