175 lines
5.0 KiB
Python
175 lines
5.0 KiB
Python
from flask import Blueprint, request, jsonify, render_template
|
||
from flask_login import login_required, current_user
|
||
from models import db, UserApiKey, ApiKeyDailyStat
|
||
from datetime import datetime, date
|
||
import secrets
|
||
|
||
apikey_bp = Blueprint('apikey', __name__, url_prefix='/user/apikey')
|
||
|
||
|
||
def generate_api_key():
|
||
"""生成 API Key"""
|
||
return f"sk_{secrets.token_hex(24)}"
|
||
|
||
|
||
@apikey_bp.route('/')
|
||
@login_required
|
||
def manage_page():
|
||
"""API Key 管理页面"""
|
||
return render_template('apikey/manage.html')
|
||
|
||
|
||
@apikey_bp.route('/list', methods=['GET'])
|
||
@login_required
|
||
def list_keys():
|
||
"""获取用户的 API Key 列表"""
|
||
keys = UserApiKey.query.filter_by(user_id=current_user.id).order_by(UserApiKey.created_at.desc()).all()
|
||
|
||
result = []
|
||
for key in keys:
|
||
# 获取今日调用次数
|
||
today_stat = ApiKeyDailyStat.query.filter_by(
|
||
api_key_id=key.id,
|
||
date=date.today()
|
||
).first()
|
||
|
||
result.append({
|
||
'id': key.id,
|
||
'name': key.name,
|
||
'api_key': key.api_key[:12] + '...' + key.api_key[-4:], # 隐藏中间部分
|
||
'is_active': key.is_active,
|
||
'daily_limit': key.daily_limit,
|
||
'total_calls': key.total_calls,
|
||
'today_calls': today_stat.call_count if today_stat else 0,
|
||
'last_used_at': key.last_used_at.strftime('%Y-%m-%d %H:%M:%S') if key.last_used_at else None,
|
||
'created_at': key.created_at.strftime('%Y-%m-%d %H:%M:%S')
|
||
})
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'data': result
|
||
})
|
||
|
||
|
||
@apikey_bp.route('/create', methods=['POST'])
|
||
@login_required
|
||
def create_key():
|
||
"""创建新的 API Key"""
|
||
data = request.get_json()
|
||
name = data.get('name', '').strip()
|
||
|
||
if not name:
|
||
return jsonify({'success': False, 'message': '请输入 Key 名称'}), 400
|
||
|
||
if len(name) > 100:
|
||
return jsonify({'success': False, 'message': 'Key 名称不能超过100个字符'}), 400
|
||
|
||
# 检查用户已有的 Key 数量(限制每个用户最多5个)
|
||
key_count = UserApiKey.query.filter_by(user_id=current_user.id).count()
|
||
if key_count >= 5:
|
||
return jsonify({'success': False, 'message': '每个用户最多创建5个 API Key'}), 400
|
||
|
||
# 生成新的 API Key
|
||
api_key = generate_api_key()
|
||
|
||
# 根据用户等级设置每日限制
|
||
daily_limit = 100 # 默认
|
||
if current_user.group:
|
||
if current_user.group.id == 3: # VIP
|
||
daily_limit = 500
|
||
elif current_user.group.id == 4: # SVIP
|
||
daily_limit = 2000
|
||
|
||
new_key = UserApiKey(
|
||
user_id=current_user.id,
|
||
name=name,
|
||
api_key=api_key,
|
||
daily_limit=daily_limit
|
||
)
|
||
|
||
db.session.add(new_key)
|
||
db.session.commit()
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'message': 'API Key 创建成功',
|
||
'data': {
|
||
'id': new_key.id,
|
||
'name': new_key.name,
|
||
'api_key': api_key, # 只在创建时返回完整的 Key
|
||
'daily_limit': new_key.daily_limit
|
||
}
|
||
})
|
||
|
||
|
||
@apikey_bp.route('/delete/<int:key_id>', methods=['DELETE'])
|
||
@login_required
|
||
def delete_key(key_id):
|
||
"""删除 API Key"""
|
||
key = UserApiKey.query.filter_by(id=key_id, user_id=current_user.id).first()
|
||
|
||
if not key:
|
||
return jsonify({'success': False, 'message': 'API Key 不存在'}), 404
|
||
|
||
db.session.delete(key)
|
||
db.session.commit()
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'message': 'API Key 已删除'
|
||
})
|
||
|
||
|
||
@apikey_bp.route('/toggle/<int:key_id>', methods=['POST'])
|
||
@login_required
|
||
def toggle_key(key_id):
|
||
"""启用/禁用 API Key"""
|
||
key = UserApiKey.query.filter_by(id=key_id, user_id=current_user.id).first()
|
||
|
||
if not key:
|
||
return jsonify({'success': False, 'message': 'API Key 不存在'}), 404
|
||
|
||
key.is_active = not key.is_active
|
||
db.session.commit()
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'message': f"API Key 已{'启用' if key.is_active else '禁用'}",
|
||
'is_active': key.is_active
|
||
})
|
||
|
||
|
||
@apikey_bp.route('/stats/<int:key_id>', methods=['GET'])
|
||
@login_required
|
||
def get_stats(key_id):
|
||
"""获取 API Key 统计数据"""
|
||
key = UserApiKey.query.filter_by(id=key_id, user_id=current_user.id).first()
|
||
|
||
if not key:
|
||
return jsonify({'success': False, 'message': 'API Key 不存在'}), 404
|
||
|
||
# 获取最近7天的统计
|
||
from datetime import timedelta
|
||
stats = ApiKeyDailyStat.query.filter(
|
||
ApiKeyDailyStat.api_key_id == key_id,
|
||
ApiKeyDailyStat.date >= date.today() - timedelta(days=6)
|
||
).order_by(ApiKeyDailyStat.date.asc()).all()
|
||
|
||
result = []
|
||
for stat in stats:
|
||
result.append({
|
||
'date': stat.date.strftime('%Y-%m-%d'),
|
||
'call_count': stat.call_count,
|
||
'success_count': stat.success_count,
|
||
'fail_count': stat.fail_count
|
||
})
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'data': {
|
||
'key_name': key.name,
|
||
'total_calls': key.total_calls,
|
||
'daily_stats': result
|
||
}
|
||
})
|