诚实性修复: API限流Retry-After(wait=60s)+断言 / purge定时接线(04:00 cron+actor+测试) / Channel表单校验(ref+rules+validate) / README PG数字513
This commit is contained in:
@@ -42,6 +42,11 @@ class APIKeyAuthentication(authentication.BaseAuthentication):
|
||||
if not key_obj.verify_key(raw_key):
|
||||
raise exceptions.AuthenticationFailed("API Key 签名无效")
|
||||
|
||||
# P0-5:把纸面的 rate_limit 接进认证链(分钟窗口,超限 429)。
|
||||
from apps.core.ratelimit import check_apikey_rate_limit
|
||||
|
||||
check_apikey_rate_limit(key_obj.prefix, key_obj.rate_limit)
|
||||
|
||||
# 记录调用时间并绑定 tenant
|
||||
key_obj.last_used_at = timezone.now()
|
||||
key_obj.save(update_fields=["last_used_at"])
|
||||
|
||||
@@ -18,6 +18,7 @@ class APIKeyCreateInputSerializer(serializers.Serializer):
|
||||
name = serializers.CharField(max_length=128)
|
||||
scopes = serializers.ListField(child=serializers.CharField(), required=False)
|
||||
expires_at = serializers.DateTimeField(required=False, allow_null=True)
|
||||
rate_limit = serializers.IntegerField(required=False, min_value=1)
|
||||
|
||||
|
||||
class ExternalOrderLineInputSerializer(serializers.Serializer):
|
||||
|
||||
@@ -52,6 +52,10 @@ class APIKeyViewSet(BaseTenantViewSet):
|
||||
expires_at=data.get("expires_at"),
|
||||
created_by=user,
|
||||
)
|
||||
# P0-5:允许创建时指定 rate_limit(下界 1 由 serializer 保证)。
|
||||
if data.get("rate_limit") is not None:
|
||||
key_obj.rate_limit = data["rate_limit"]
|
||||
await sync_to_async(key_obj.save)(update_fields=["rate_limit"])
|
||||
|
||||
res_data = APIKeySerializer(key_obj).data
|
||||
res_data["raw_key"] = raw_key # 仅在创建时返回一次明文密钥!
|
||||
|
||||
Reference in New Issue
Block a user