new apps.epic app migrations for token expiration & cooldown; reject token renamed to return token everywhere; new mapps.epic.models & .views for expiration & cooldown; new apps.dash.views to manage stacking of like Token types not just in the kit bag but in the Gameboard's Game Kit applet & in the Dashwallet's Tokens applet; Free Tokens now display correctly in kit bag; apps.lyric.admin now ensures superuser cannot grant Free Tokens without an expiration date; corresponding tests in .tests.integrated.test_admin.TokenAdminFormTest; screendumps occurring for every test, regardless of passfail status, after one fail fixed in FTs.base; FTs.test_gatekeeper.GameKitInsertTest.test_free_token_insert_via_kit_consumed_on_confirm, for test purposes only, ensures starting Free Token deleted before fresh one assigned w. full 7d expiration battery
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from django import forms
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import LoginToken, Token, User
|
||||
@@ -7,6 +8,23 @@ class UserAdmin(admin.ModelAdmin):
|
||||
list_display = ["email"]
|
||||
search_fields = ["email"]
|
||||
|
||||
|
||||
class TokenAdminForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Token
|
||||
fields = "__all__"
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
if cleaned_data.get("token_type") == Token.FREE and not cleaned_data.get("expires_at"):
|
||||
raise forms.ValidationError("Free Tokens must have an expiration date.")
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class TokenAdmin(admin.ModelAdmin):
|
||||
form = TokenAdminForm
|
||||
|
||||
|
||||
admin.site.register(User, UserAdmin)
|
||||
admin.site.register(LoginToken)
|
||||
admin.site.register(Token)
|
||||
admin.site.register(Token, TokenAdmin)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.lyric.models import User
|
||||
from apps.lyric.admin import TokenAdminForm
|
||||
from apps.lyric.models import Token, User
|
||||
|
||||
|
||||
class UserAdminTest(TestCase):
|
||||
@@ -23,3 +25,30 @@ class UserAdminTest(TestCase):
|
||||
response = self.client.get("/admin/lyric/user/?q=admin")
|
||||
self.assertContains(response, "admin@example.com")
|
||||
self.assertNotContains(response, "other@example.com")
|
||||
|
||||
|
||||
class TokenAdminFormTest(TestCase):
|
||||
def setUp(self):
|
||||
self.user = User.objects.create(email="gamer@example.com")
|
||||
|
||||
def _form(self, token_type, expires_at=None):
|
||||
return TokenAdminForm(data={
|
||||
"user": self.user.pk,
|
||||
"token_type": token_type,
|
||||
"expires_at": expires_at or "",
|
||||
})
|
||||
|
||||
def test_free_token_without_expires_at_is_invalid(self):
|
||||
form = self._form(Token.FREE)
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertIn("Free Tokens must have an expiration date", str(form.errors))
|
||||
|
||||
def test_free_token_with_expires_at_is_valid(self):
|
||||
form = self._form(Token.FREE, expires_at=timezone.now())
|
||||
self.assertTrue(form.is_valid())
|
||||
|
||||
def test_other_token_types_do_not_require_expires_at(self):
|
||||
for token_type in (Token.COIN, Token.TITHE, Token.PASS):
|
||||
with self.subTest(token_type=token_type):
|
||||
form = self._form(token_type)
|
||||
self.assertTrue(form.is_valid())
|
||||
|
||||
Reference in New Issue
Block a user