feat: add admin client policy control

This commit is contained in:
QiuSW
2026-07-28 15:42:23 +08:00
parent 9544aaf4cc
commit 2171968780
17 changed files with 558 additions and 21 deletions
+93
View File
@@ -7,6 +7,8 @@ from django.template.response import TemplateResponse
from django.urls import path, reverse
from .models import (
ClientSubscriptionPolicy,
ClientSubscriptionPolicyAudit,
ClientDevice,
DeviceCredential,
DeviceBindingAudit,
@@ -23,8 +25,10 @@ from .services import (
LicensingError,
grant_software_entitlement,
create_legacy_migration_grant,
get_subscription_mode,
renew_software_entitlement,
revoke_software_entitlement,
set_client_subscription_policy,
)
@@ -35,6 +39,95 @@ class HiddenFromAdminIndexMixin:
return {}
class ClientSubscriptionPolicyAdminForm(forms.ModelForm):
reason = forms.CharField(label="变更原因", widget=forms.Textarea(attrs={"rows": 3}))
class Meta:
model = ClientSubscriptionPolicy
fields = ("mode",)
def clean_mode(self):
mode = self.cleaned_data["mode"]
if not self.instance._state.adding and self.instance.mode == mode:
raise forms.ValidationError("请选择不同的客户端订阅策略。")
return mode
def clean_reason(self):
reason = self.cleaned_data["reason"].strip()
if not reason:
raise forms.ValidationError("必须填写操作原因。")
return reason
class ClientSubscriptionPolicyAuditInline(admin.TabularInline):
model = ClientSubscriptionPolicyAudit
extra = 0
can_delete = False
max_num = 0
ordering = ("-changed_at", "-id")
fields = ("previous_mode", "mode", "reason", "changed_by", "changed_at")
readonly_fields = fields
verbose_name = "策略变更审计"
verbose_name_plural = "策略变更审计"
def has_add_permission(self, request, obj=None):
return False
def has_change_permission(self, request, obj=None):
return False
@admin.register(ClientSubscriptionPolicy)
class ClientSubscriptionPolicyAdmin(admin.ModelAdmin):
form = ClientSubscriptionPolicyAdminForm
inlines = (ClientSubscriptionPolicyAuditInline,)
fields = (
"mode",
"reason",
"server_subscription_mode",
"updated_by",
"created_at",
"updated_at",
)
readonly_fields = (
"server_subscription_mode",
"updated_by",
"created_at",
"updated_at",
)
def has_module_permission(self, request):
return request.user.is_superuser
def has_view_permission(self, request, obj=None):
return request.user.is_superuser
def has_add_permission(self, request):
return request.user.is_superuser and not ClientSubscriptionPolicy.objects.exists()
def has_change_permission(self, request, obj=None):
return request.user.is_superuser
def has_delete_permission(self, request, obj=None):
return False
@admin.display(description="服务端订阅授权模式")
def server_subscription_mode(self, obj):
return get_subscription_mode()
def save_model(self, request, obj, form, change):
policy = set_client_subscription_policy(
mode=form.cleaned_data["mode"],
reason=form.cleaned_data["reason"],
actor=request.user,
)
obj.singleton_id = policy.singleton_id
obj.mode = policy.mode
obj.updated_by = policy.updated_by
obj.created_at = policy.created_at
obj.updated_at = policy.updated_at
def _masked_fingerprint(value: str) -> str:
if not value:
return ""