204 lines
5.3 KiB
JavaScript
204 lines
5.3 KiB
JavaScript
/**
|
|
* 数据库清空脚本
|
|
* 这个脚本会清空所有表的数据,但保留表结构
|
|
*/
|
|
import { sql } from 'drizzle-orm'
|
|
import {
|
|
apiKeyPermissions,
|
|
apiKeys,
|
|
apiLogs,
|
|
cardCodeRedeemLogs,
|
|
cardCodes,
|
|
collaborationLogs,
|
|
db,
|
|
emailTemplates,
|
|
notifications,
|
|
notificationSettings,
|
|
passwordAuditLogs,
|
|
passwordRateLimits,
|
|
playTimes,
|
|
requestTimes,
|
|
scheduleSongPool,
|
|
schedules,
|
|
semesters,
|
|
songBlacklists,
|
|
songCollaborators,
|
|
songReplayRequests,
|
|
songs,
|
|
systemSettings,
|
|
userIdentities,
|
|
users,
|
|
userStatusLogs,
|
|
votes
|
|
} from '../app/drizzle/db.ts'
|
|
import bcrypt from 'bcryptjs'
|
|
import { closeConnection } from '../app/drizzle/db.ts'
|
|
|
|
function getFirstRow(result) {
|
|
return result?.rows?.[0] ?? result?.[0]
|
|
}
|
|
|
|
function quoteIdentifierPart(value) {
|
|
const normalized =
|
|
value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1).replace(/""/g, '"') : value
|
|
|
|
return `"${normalized.replace(/"/g, '""')}"`
|
|
}
|
|
|
|
function toQualifiedIdentifier(value) {
|
|
return sql.raw(value.split('.').map(quoteIdentifierPart).join('.'))
|
|
}
|
|
|
|
function toPgRelationName(value) {
|
|
return value.split('.').map(quoteIdentifierPart).join('.')
|
|
}
|
|
|
|
function toRegclass(value) {
|
|
return sql.raw(`'${value.replace(/'/g, "''")}'::regclass`)
|
|
}
|
|
|
|
// 重置所有表的自增序列
|
|
async function resetAutoIncrementSequences() {
|
|
const tables = [
|
|
'User',
|
|
'Song',
|
|
'Vote',
|
|
'Schedule',
|
|
'Notification',
|
|
'NotificationSettings',
|
|
'PlayTime',
|
|
'Semester',
|
|
'SystemSettings',
|
|
'SongBlacklist',
|
|
'CardCode',
|
|
'CardCodeRedeemLog',
|
|
'SongCollaborator',
|
|
'CollaborationLog',
|
|
'SongReplayRequest',
|
|
'RequestTime',
|
|
'ScheduleSongPool',
|
|
'UserIdentity',
|
|
'PasswordAuditLog',
|
|
'PasswordRateLimit',
|
|
'EmailTemplate',
|
|
'user_status_logs'
|
|
]
|
|
|
|
console.log('重置自增序列...')
|
|
|
|
for (const table of tables) {
|
|
try {
|
|
const maxIdResult = await db.execute(
|
|
sql`SELECT MAX(id) as max_id FROM ${toQualifiedIdentifier(table)}`
|
|
)
|
|
const maxId = Number(getFirstRow(maxIdResult)?.max_id || 0)
|
|
|
|
const sequenceNameResult = await db.execute(
|
|
sql`SELECT pg_get_serial_sequence(${toPgRelationName(table)}, 'id') as sequence_name`
|
|
)
|
|
const sequenceName = getFirstRow(sequenceNameResult)?.sequence_name
|
|
|
|
if (sequenceName) {
|
|
if (maxId === 0) {
|
|
await db.execute(sql`ALTER SEQUENCE ${toQualifiedIdentifier(sequenceName)} RESTART WITH 1`)
|
|
} else {
|
|
const newSequenceValue = maxId
|
|
await db.execute(sql`SELECT setval(${toRegclass(sequenceName)}, ${newSequenceValue})`)
|
|
}
|
|
} else {
|
|
console.warn(`未找到表 ${table} 的序列`)
|
|
}
|
|
} catch (error) {
|
|
console.warn(`重置 ${table} 表序列失败: ${error.message}`)
|
|
}
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
console.log('开始清空数据库...')
|
|
|
|
// 清空所有表数据
|
|
try {
|
|
// 按照关联关系顺序删除数据
|
|
await db.delete(notifications)
|
|
await db.delete(notificationSettings)
|
|
await db.delete(votes)
|
|
await db.delete(collaborationLogs)
|
|
await db.delete(schedules)
|
|
await db.delete(scheduleSongPool)
|
|
await db.delete(songCollaborators)
|
|
await db.delete(songReplayRequests)
|
|
await db.delete(requestTimes)
|
|
await db.delete(cardCodeRedeemLogs)
|
|
await db.delete(userIdentities)
|
|
await db.delete(passwordAuditLogs)
|
|
await db.delete(passwordRateLimits)
|
|
await db.delete(songs)
|
|
await db.delete(cardCodes)
|
|
await db.delete(playTimes)
|
|
await db.delete(semesters)
|
|
await db.delete(systemSettings)
|
|
await db.delete(songBlacklists)
|
|
await db.delete(apiLogs)
|
|
await db.delete(apiKeyPermissions)
|
|
await db.delete(apiKeys)
|
|
await db.delete(userStatusLogs)
|
|
await db.delete(emailTemplates)
|
|
await db.delete(users)
|
|
|
|
console.log('数据库已清空,开始重置自增序列...')
|
|
|
|
// 先重置所有自增序列
|
|
await resetAutoIncrementSequences()
|
|
|
|
console.log('开始创建默认超级管理员账户...')
|
|
|
|
// 创建默认管理员账户
|
|
const hashedPassword = await bcrypt.hash('admin123', 10)
|
|
|
|
// 创建超级管理员用户
|
|
const [admin] = await db
|
|
.insert(users)
|
|
.values({
|
|
name: '超级管理员',
|
|
username: 'admin',
|
|
password: hashedPassword,
|
|
role: 'SUPER_ADMIN',
|
|
forcePasswordChange: false
|
|
})
|
|
.returning()
|
|
|
|
console.log('默认超级管理员账户已创建:')
|
|
console.log('用户名: admin')
|
|
console.log('密码: admin123')
|
|
console.log(`管理员ID: ${admin.id}`)
|
|
|
|
// 调整User表的自增序列,确保下一个用户从admin.id + 1开始
|
|
try {
|
|
const sequenceNameResult = await db.execute(
|
|
sql`SELECT pg_get_serial_sequence(${toPgRelationName('User')}, 'id') as sequence_name`
|
|
)
|
|
const sequenceName = getFirstRow(sequenceNameResult)?.sequence_name
|
|
|
|
if (sequenceName) {
|
|
const nextId = admin.id
|
|
await db.execute(sql`SELECT setval(${toRegclass(sequenceName)}, ${nextId})`)
|
|
}
|
|
} catch (error) {
|
|
console.warn(`调整User表序列失败: ${error.message}`)
|
|
}
|
|
|
|
console.log('🎉 数据库清空、初始化和序列重置全部完成!')
|
|
} catch (error) {
|
|
console.error('清空数据库时出错:', error)
|
|
process.exit(1)
|
|
} finally {
|
|
await closeConnection()
|
|
}
|
|
}
|
|
|
|
main().catch((e) => {
|
|
console.error(e)
|
|
process.exit(1)
|
|
})
|