cc / scripts /migrate-apikey-expiry.js
hequ's picture
Upload 221 files
69b897d verified
#!/usr/bin/env node
/**
* 数据迁移脚本:为现有 API Key 设置默认有效期
*
* 使用方法:
* node scripts/migrate-apikey-expiry.js [--days=30] [--dry-run]
*
* 参数:
* --days: 设置默认有效期天数(默认30天)
* --dry-run: 仅模拟运行,不实际修改数据
*/
const redis = require('../src/models/redis')
const logger = require('../src/utils/logger')
const readline = require('readline')
// 解析命令行参数
const args = process.argv.slice(2)
const params = {}
args.forEach((arg) => {
const [key, value] = arg.split('=')
params[key.replace('--', '')] = value || true
})
const DEFAULT_DAYS = params.days ? parseInt(params.days) : 30
const DRY_RUN = params['dry-run'] === true
// 创建 readline 接口用于用户确认
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
async function askConfirmation(question) {
return new Promise((resolve) => {
rl.question(`${question} (yes/no): `, (answer) => {
resolve(answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y')
})
})
}
async function migrateApiKeys() {
try {
logger.info('🔄 Starting API Key expiry migration...')
logger.info(`📅 Default expiry period: ${DEFAULT_DAYS} days`)
logger.info(`🔍 Mode: ${DRY_RUN ? 'DRY RUN (no changes will be made)' : 'LIVE RUN'}`)
// 连接 Redis
await redis.connect()
logger.success('✅ Connected to Redis')
// 获取所有 API Keys
const apiKeys = await redis.getAllApiKeys()
logger.info(`📊 Found ${apiKeys.length} API Keys in total`)
// 统计信息
const stats = {
total: apiKeys.length,
needsMigration: 0,
alreadyHasExpiry: 0,
migrated: 0,
errors: 0
}
// 需要迁移的 Keys
const keysToMigrate = []
// 分析每个 API Key
for (const key of apiKeys) {
if (!key.expiresAt || key.expiresAt === 'null' || key.expiresAt === '') {
keysToMigrate.push(key)
stats.needsMigration++
logger.info(`📌 API Key "${key.name}" (${key.id}) needs migration`)
} else {
stats.alreadyHasExpiry++
const expiryDate = new Date(key.expiresAt)
logger.info(
`✓ API Key "${key.name}" (${key.id}) already has expiry: ${expiryDate.toLocaleString()}`
)
}
}
if (keysToMigrate.length === 0) {
logger.success('✨ No API Keys need migration!')
return
}
// 显示迁移摘要
console.log(`\n${'='.repeat(60)}`)
console.log('📋 Migration Summary:')
console.log('='.repeat(60))
console.log(`Total API Keys: ${stats.total}`)
console.log(`Already have expiry: ${stats.alreadyHasExpiry}`)
console.log(`Need migration: ${stats.needsMigration}`)
console.log(`Default expiry: ${DEFAULT_DAYS} days from now`)
console.log(`${'='.repeat(60)}\n`)
// 如果不是 dry run,请求确认
if (!DRY_RUN) {
const confirmed = await askConfirmation(
`⚠️ This will set expiry dates for ${keysToMigrate.length} API Keys. Continue?`
)
if (!confirmed) {
logger.warn('❌ Migration cancelled by user')
return
}
}
// 计算新的过期时间
const newExpiryDate = new Date()
newExpiryDate.setDate(newExpiryDate.getDate() + DEFAULT_DAYS)
const newExpiryISO = newExpiryDate.toISOString()
logger.info(`\n🚀 Starting migration... New expiry date: ${newExpiryDate.toLocaleString()}`)
// 执行迁移
for (const key of keysToMigrate) {
try {
if (!DRY_RUN) {
// 直接更新 Redis 中的数据
// 使用 hset 更新单个字段
await redis.client.hset(`apikey:${key.id}`, 'expiresAt', newExpiryISO)
logger.success(`✅ Migrated: "${key.name}" (${key.id})`)
} else {
logger.info(`[DRY RUN] Would migrate: "${key.name}" (${key.id})`)
}
stats.migrated++
} catch (error) {
logger.error(`❌ Error migrating "${key.name}" (${key.id}):`, error.message)
stats.errors++
}
}
// 显示最终结果
console.log(`\n${'='.repeat(60)}`)
console.log('✅ Migration Complete!')
console.log('='.repeat(60))
console.log(`Successfully migrated: ${stats.migrated}`)
console.log(`Errors: ${stats.errors}`)
console.log(`New expiry date: ${newExpiryDate.toLocaleString()}`)
console.log(`${'='.repeat(60)}\n`)
if (DRY_RUN) {
logger.warn('⚠️ This was a DRY RUN. No actual changes were made.')
logger.info('💡 Run without --dry-run flag to apply changes.')
}
} catch (error) {
logger.error('💥 Migration failed:', error)
process.exit(1)
} finally {
// 清理
rl.close()
await redis.disconnect()
logger.info('👋 Disconnected from Redis')
}
}
// 显示帮助信息
if (params.help) {
console.log(`
API Key Expiry Migration Script
This script adds expiry dates to existing API Keys that don't have one.
Usage:
node scripts/migrate-apikey-expiry.js [options]
Options:
--days=NUMBER Set default expiry days (default: 30)
--dry-run Simulate the migration without making changes
--help Show this help message
Examples:
# Set 30-day expiry for all API Keys without expiry
node scripts/migrate-apikey-expiry.js
# Set 90-day expiry
node scripts/migrate-apikey-expiry.js --days=90
# Test run without making changes
node scripts/migrate-apikey-expiry.js --dry-run
`)
process.exit(0)
}
// 运行迁移
migrateApiKeys().catch((error) => {
logger.error('💥 Unexpected error:', error)
process.exit(1)
})