Files
ai_api_web/backend/models/token.py
2026-01-22 18:26:47 +08:00

67 lines
3.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from models import db
from datetime import datetime
import secrets
import string
class Token(db.Model):
__tablename__ = 'tokens'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
name = db.Column(db.String(100), nullable=False)
key = db.Column(db.String(255), unique=True, nullable=False, index=True)
status = db.Column(db.String(20), default='enabled') # enabled, disabled
remaining_quota = db.Column(db.Numeric(15, 2), nullable=True) # None表示无限额度
total_quota = db.Column(db.Numeric(15, 2), nullable=True)
group = db.Column(db.String(100), default='Claude Code 官方编程模型')
available_models = db.Column(db.Text, nullable=True) # JSON字符串或None表示无限制
ip_restriction = db.Column(db.String(500), nullable=True) # IP白名单逗号分隔
expires_at = db.Column(db.DateTime, nullable=True) # None表示永不过期
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# 关系
usage_logs = db.relationship('UsageLog', backref='token', lazy=True)
@staticmethod
def generate_key():
"""生成API密钥"""
return 'sk-' + ''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(40))
def to_dict(self, show_key=False):
"""转换为字典"""
return {
'id': self.id,
'user_id': self.user_id,
'name': self.name,
'key': self.key if show_key else self.masked_key,
'status': self.status,
'remaining_quota': float(self.remaining_quota) if self.remaining_quota else None,
'total_quota': float(self.total_quota) if self.total_quota else None,
'quota_display': self.quota_display,
'group': self.group,
'available_models': self.available_models,
'ip_restriction': self.ip_restriction,
'expires_at': self.expires_at.isoformat() if self.expires_at else None,
'expires_display': '永不过期' if not self.expires_at else self.expires_at.strftime('%Y-%m-%d %H:%M:%S'),
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None,
}
@property
def masked_key(self):
"""掩码显示的密钥"""
if len(self.key) > 10:
return self.key[:5] + '*' * 10 + self.key[-5:]
return '*' * len(self.key)
@property
def quota_display(self):
"""额度显示文本"""
if self.remaining_quota is None and self.total_quota is None:
return '无限额度'
if self.remaining_quota is None:
return f'无限额度 / {float(self.total_quota):.2f}'
if self.total_quota is None:
return f'{float(self.remaining_quota):.2f} / 无限额度'
return f'{float(self.remaining_quota):.2f} / {float(self.total_quota):.2f}'