feat: add client subscription startup policy

This commit is contained in:
QiuSW
2026-07-28 15:14:48 +08:00
parent f0f34156da
commit 1c100c5d7e
15 changed files with 290 additions and 21 deletions
+101 -2
View File
@@ -14,6 +14,7 @@ from django.conf import settings
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.core.cache import cache
from django.core.exceptions import ImproperlyConfigured
from django.core.files.base import ContentFile
from django.core.management import call_command
from django.test import TestCase, override_settings
@@ -463,6 +464,12 @@ class ClientLatestReleaseApiTests(TestCase):
def setUp(self):
cache.clear()
self.client = APIClient()
self.client_policy_override = override_settings(
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY="off",
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY_UPDATED_AT="2026-07-28T00:00:00+08:00",
)
self.client_policy_override.enable()
self.addCleanup(self.client_policy_override.disable)
def create_release(
self,
@@ -502,7 +509,17 @@ class ClientLatestReleaseApiTests(TestCase):
self.assertEqual(response.status_code, 200)
self.assertNotIn(GenerateRateThrottle, ClientLatestReleaseView.throttle_classes)
self.assertEqual(response["Cache-Control"], "no-store")
self.assertEqual(response.data["platform"], "windows")
self.assertEqual(
response.data["client_policy"],
{
"policy_version": 1,
"subscription_check_enabled": False,
"subscription_enforcement_enabled": False,
"updated_at": "2026-07-28T00:00:00+08:00",
},
)
self.assertEqual(
set(response.data["release"]),
{
@@ -624,9 +641,79 @@ class ClientLatestReleaseApiTests(TestCase):
"platform": "windows",
"release": None,
"message": "暂未发布",
"client_policy": {
"policy_version": 1,
"subscription_check_enabled": False,
"subscription_enforcement_enabled": False,
"updated_at": "2026-07-28T00:00:00+08:00",
},
},
)
@override_settings(
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY="observe",
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY_UPDATED_AT="2026-07-28T09:00:00+08:00",
)
def test_latest_release_returns_observe_client_policy_without_release(self):
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response["Cache-Control"], "no-store")
self.assertIsNone(response.data["release"])
self.assertEqual(
response.data["client_policy"],
{
"policy_version": 1,
"subscription_check_enabled": True,
"subscription_enforcement_enabled": False,
"updated_at": "2026-07-28T09:00:00+08:00",
},
)
@override_settings(
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY="enforce",
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY_UPDATED_AT="2026-07-28T10:00:00+08:00",
)
def test_latest_release_returns_enforce_client_policy_with_release(self):
self.create_release()
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.data["client_policy"],
{
"policy_version": 1,
"subscription_check_enabled": True,
"subscription_enforcement_enabled": True,
"updated_at": "2026-07-28T10:00:00+08:00",
},
)
@override_settings(
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY="invalid",
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY_UPDATED_AT="2026-07-28T10:00:00+08:00",
)
def test_latest_release_rejects_invalid_client_policy_configuration(self):
with self.assertRaises(ImproperlyConfigured):
self.client.get(self.url)
@override_settings(
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY="enforce",
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY_UPDATED_AT="",
)
def test_latest_release_rejects_missing_enforced_policy_timestamp(self):
with self.assertRaises(ImproperlyConfigured):
self.client.get(self.url)
@override_settings(
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY="observe",
CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY_UPDATED_AT="2026-07-28 10:00:00",
)
def test_latest_release_rejects_naive_policy_timestamp(self):
with self.assertRaises(ImproperlyConfigured):
self.client.get(self.url)
def test_latest_release_returns_unpublished_when_current_release_has_no_download_url(self):
self.create_release(external_url="", file_name="")
@@ -668,7 +755,16 @@ class ClientLatestReleaseApiTests(TestCase):
response = self.client.get(self.url, secure=True)
self.assertEqual(response.status_code, 200)
self.assertEqual(set(response.data), {"platform", "release"})
self.assertEqual(set(response.data), {"platform", "release", "client_policy"})
self.assertEqual(
set(response.data["client_policy"]),
{
"policy_version",
"subscription_check_enabled",
"subscription_enforcement_enabled",
"updated_at",
},
)
self.assertEqual(
set(response.data["release"]),
{
@@ -686,7 +782,6 @@ class ClientLatestReleaseApiTests(TestCase):
"id",
"is_current",
"created_at",
"updated_at",
"MEDIA_ROOT",
str(settings.MEDIA_ROOT),
"user",
@@ -1466,6 +1561,7 @@ class GenerateApiTests(TestCase):
self.assertEqual(data["manage_url"], "https://cm.example.test/subscription")
self.assertEqual(data["access_source"], "open_mode")
self.assertEqual(data["entitlement_status"], "required")
self.assertFalse(data["real_entitlement_allowed"])
self.assertTrue(data["notice_id"])
self.assertFalse(SoftwareEntitlement.objects.filter(user=self.user).exists())
@@ -1482,6 +1578,7 @@ class GenerateApiTests(TestCase):
self.assertTrue(data["allowed"])
self.assertEqual(data["access_source"], "shadow_fallback")
self.assertEqual(data["entitlement_status"], "required")
self.assertFalse(data["real_entitlement_allowed"])
self.assertEqual(data["plan"]["code"], "shadow-fallback")
@override_settings(CMSHOPEE_SUBSCRIPTION_MODE="open")
@@ -1571,6 +1668,7 @@ class GenerateApiTests(TestCase):
)
self.assertEqual(data["access_source"], "entitlement")
self.assertEqual(data["entitlement_status"], "active")
self.assertTrue(data["real_entitlement_allowed"])
@override_settings(CMSHOPEE_SUBSCRIPTION_MODE="enforce")
def test_cmshopee_subscription_status_is_expired_after_grace_period(self):
@@ -1589,6 +1687,7 @@ class GenerateApiTests(TestCase):
self.assertFalse(data["allowed"])
self.assertEqual(data["code"], "subscription_expired")
self.assertEqual(data["entitlement_status"], "expired")
self.assertFalse(data["real_entitlement_allowed"])
@override_settings(CMSHOPEE_SUBSCRIPTION_MODE="enforce")
def test_cmshopee_enforcement_rejects_without_subscription(self):