mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 08:59:16 +00:00
@@ -24,6 +24,51 @@ const ProxyHelper = require('../utils/proxyHelper')
|
||||
|
||||
const router = express.Router()
|
||||
|
||||
// 👥 用户管理
|
||||
|
||||
// 获取所有用户列表(用于API Key分配)
|
||||
router.get('/users', authenticateAdmin, async (req, res) => {
|
||||
try {
|
||||
const userService = require('../services/userService')
|
||||
const result = await userService.getAllUsers({ isActive: true, limit: 1000 }) // Get all active users
|
||||
|
||||
// Extract users array from the paginated result
|
||||
const allUsers = result.users || []
|
||||
|
||||
// Map to the format needed for the dropdown
|
||||
const activeUsers = allUsers.map((user) => ({
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
displayName: user.displayName || user.username,
|
||||
email: user.email,
|
||||
role: user.role
|
||||
}))
|
||||
|
||||
// 添加Admin选项作为第一个
|
||||
const usersWithAdmin = [
|
||||
{
|
||||
id: 'admin',
|
||||
username: 'admin',
|
||||
displayName: 'Admin',
|
||||
email: '',
|
||||
role: 'admin'
|
||||
},
|
||||
...activeUsers
|
||||
]
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: usersWithAdmin
|
||||
})
|
||||
} catch (error) {
|
||||
logger.error('❌ Failed to get users list:', error)
|
||||
return res.status(500).json({
|
||||
error: 'Failed to get users list',
|
||||
message: error.message
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 🔑 API Keys 管理
|
||||
|
||||
// 调试:获取API Key费用详情
|
||||
@@ -63,6 +108,9 @@ router.get('/api-keys', authenticateAdmin, async (req, res) => {
|
||||
const { timeRange = 'all' } = req.query // all, 7days, monthly
|
||||
const apiKeys = await apiKeyService.getAllApiKeys()
|
||||
|
||||
// 获取用户服务来补充owner信息
|
||||
const userService = require('../services/userService')
|
||||
|
||||
// 根据时间范围计算查询模式
|
||||
const now = new Date()
|
||||
const searchPatterns = []
|
||||
@@ -313,6 +361,28 @@ router.get('/api-keys', authenticateAdmin, async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 为每个API Key添加owner的displayName
|
||||
for (const apiKey of apiKeys) {
|
||||
// 如果API Key有关联的用户ID,获取用户信息
|
||||
if (apiKey.userId) {
|
||||
try {
|
||||
const user = await userService.getUserById(apiKey.userId, false)
|
||||
if (user) {
|
||||
apiKey.ownerDisplayName = user.displayName || user.username || 'Unknown User'
|
||||
} else {
|
||||
apiKey.ownerDisplayName = 'Unknown User'
|
||||
}
|
||||
} catch (error) {
|
||||
logger.debug(`无法获取用户 ${apiKey.userId} 的信息:`, error)
|
||||
apiKey.ownerDisplayName = 'Unknown User'
|
||||
}
|
||||
} else {
|
||||
// 如果没有userId,使用createdBy字段或默认为Admin
|
||||
apiKey.ownerDisplayName =
|
||||
apiKey.createdBy === 'admin' ? 'Admin' : apiKey.createdBy || 'Admin'
|
||||
}
|
||||
}
|
||||
|
||||
return res.json({ success: true, data: apiKeys })
|
||||
} catch (error) {
|
||||
logger.error('❌ Failed to get API keys:', error)
|
||||
@@ -822,7 +892,8 @@ router.put('/api-keys/:keyId', authenticateAdmin, async (req, res) => {
|
||||
expiresAt,
|
||||
dailyCostLimit,
|
||||
weeklyOpusCostLimit,
|
||||
tags
|
||||
tags,
|
||||
ownerId // 新增:所有者ID字段
|
||||
} = req.body
|
||||
|
||||
// 只允许更新指定字段
|
||||
@@ -992,6 +1063,45 @@ router.put('/api-keys/:keyId', authenticateAdmin, async (req, res) => {
|
||||
updates.isActive = isActive
|
||||
}
|
||||
|
||||
// 处理所有者变更
|
||||
if (ownerId !== undefined) {
|
||||
const userService = require('../services/userService')
|
||||
|
||||
if (ownerId === 'admin') {
|
||||
// 分配给Admin
|
||||
updates.userId = ''
|
||||
updates.userUsername = ''
|
||||
updates.createdBy = 'admin'
|
||||
} else if (ownerId) {
|
||||
// 分配给用户
|
||||
try {
|
||||
const user = await userService.getUserById(ownerId, false)
|
||||
if (!user) {
|
||||
return res.status(400).json({ error: 'Invalid owner: User not found' })
|
||||
}
|
||||
if (!user.isActive) {
|
||||
return res.status(400).json({ error: 'Cannot assign to inactive user' })
|
||||
}
|
||||
|
||||
// 设置新的所有者信息
|
||||
updates.userId = ownerId
|
||||
updates.userUsername = user.username
|
||||
updates.createdBy = user.username
|
||||
|
||||
// 管理员重新分配时,不检查用户的API Key数量限制
|
||||
logger.info(`🔄 Admin reassigning API key ${keyId} to user ${user.username}`)
|
||||
} catch (error) {
|
||||
logger.error('Error fetching user for owner reassignment:', error)
|
||||
return res.status(400).json({ error: 'Invalid owner ID' })
|
||||
}
|
||||
} else {
|
||||
// 清空所有者(分配给Admin)
|
||||
updates.userId = ''
|
||||
updates.userUsername = ''
|
||||
updates.createdBy = 'admin'
|
||||
}
|
||||
}
|
||||
|
||||
await apiKeyService.updateApiKey(keyId, updates)
|
||||
|
||||
logger.success(`📝 Admin updated API key: ${keyId}`)
|
||||
|
||||
@@ -208,7 +208,8 @@ router.get('/profile', authenticateUser, async (req, res) => {
|
||||
totalUsage: user.totalUsage
|
||||
},
|
||||
config: {
|
||||
maxApiKeysPerUser: config.userManagement.maxApiKeysPerUser
|
||||
maxApiKeysPerUser: config.userManagement.maxApiKeysPerUser,
|
||||
allowUserDeleteApiKeys: config.userManagement.allowUserDeleteApiKeys
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
@@ -352,6 +353,15 @@ router.delete('/api-keys/:keyId', authenticateUser, async (req, res) => {
|
||||
try {
|
||||
const { keyId } = req.params
|
||||
|
||||
// 检查是否允许用户删除自己的API Keys
|
||||
if (!config.userManagement.allowUserDeleteApiKeys) {
|
||||
return res.status(403).json({
|
||||
error: 'Operation not allowed',
|
||||
message:
|
||||
'Users are not allowed to delete their own API keys. Please contact an administrator.'
|
||||
})
|
||||
}
|
||||
|
||||
// 检查API Key是否属于当前用户
|
||||
const existingKey = await apiKeyService.getApiKeyById(keyId)
|
||||
if (!existingKey || existingKey.userId !== req.user.id) {
|
||||
|
||||
Reference in New Issue
Block a user