67 lines
3.0 KiB
Python
67 lines
3.0 KiB
Python
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}'
|