unique constraint for only one hostmask enabled at a time
this replaces the need for a game+hostmask unique constraint, with this change, a player can only have one active character they're playing with anyway, regardless of how many games there are Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
This commit is contained in:
		
							parent
							
								
									d0531bff53
								
							
						
					
					
						commit
						2ad79285b3
					
				| @ -0,0 +1,26 @@ | ||||
| # Generated by Django 5.0.5 on 2024-05-14 16:07 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('idlerpg', '0006_alter_character_status'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.RemoveConstraint( | ||||
|             model_name='character', | ||||
|             name='one_player_character_per_game', | ||||
|         ), | ||||
|         migrations.AddField( | ||||
|             model_name='character', | ||||
|             name='enabled', | ||||
|             field=models.BooleanField(default=True), | ||||
|         ), | ||||
|         migrations.AddConstraint( | ||||
|             model_name='character', | ||||
|             constraint=models.UniqueConstraint(condition=models.Q(('enabled', True)), fields=('hostmask',), name='one_enabled_character_at_a_time'), | ||||
|         ), | ||||
|     ] | ||||
| @ -95,6 +95,7 @@ class Character(models.Model): | ||||
|     password = models.CharField(max_length=256) | ||||
|     hostmask = models.CharField(max_length=256) | ||||
|     status = models.CharField(max_length=8, choices=CHARACTER_STATUSES, default='OFFLINE') | ||||
|     enabled = models.BooleanField(default=True) | ||||
| 
 | ||||
|     character_class = models.CharField(max_length=30) | ||||
|     level = models.PositiveIntegerField(default=0) | ||||
| @ -119,7 +120,8 @@ class Character(models.Model): | ||||
|         """Options for the Character and its objects.""" | ||||
| 
 | ||||
|         constraints = [ | ||||
|             models.UniqueConstraint("game", "hostmask", name="one_player_character_per_game"), | ||||
|             models.UniqueConstraint(fields=['hostmask'], condition=models.Q(enabled=True), | ||||
|                                     name='one_enabled_character_at_a_time'), | ||||
|         ] | ||||
| 
 | ||||
|     def __str__(self): | ||||
|  | ||||
| @ -7,6 +7,8 @@ import logging | ||||
| from datetime import timedelta | ||||
| from unittest.mock import patch | ||||
| 
 | ||||
| from django.db import transaction | ||||
| from django.db.utils import IntegrityError | ||||
| from django.test import TestCase | ||||
| from django.utils import timezone | ||||
| 
 | ||||
| @ -152,6 +154,27 @@ class CharacterTest(TestCase): | ||||
|         assert new_char.last_login == register_time | ||||
|         assert new_char.password[0:13] == 'pbkdf2_sha256' | ||||
| 
 | ||||
|     def test_cant_register_twice(self): | ||||
|         """Test that we get a unique constraint error if we try to make a second enabled character.""" | ||||
|         game = Game.objects.get(pk=1) | ||||
| 
 | ||||
|         register_time = timezone.now() | ||||
|         with patch('django.utils.timezone.now', return_value=register_time): | ||||
|             new_char = Character.objects.register('new1', game, 'pass', 'bss!bss@test_double_register', 'unit tester') | ||||
|         with self.assertRaises(IntegrityError): | ||||
|             with transaction.atomic(): | ||||
|                 Character.objects.register('new2', game, 'pass', 'bss!bss@test_double_register', 'unit tester') | ||||
| 
 | ||||
|         # try again with the first character un-enabled | ||||
|         new_char.enabled = False | ||||
|         new_char.save() | ||||
| 
 | ||||
|         register_time = timezone.now() | ||||
|         with patch('django.utils.timezone.now', return_value=register_time): | ||||
|             newer_char = Character.objects.register('new2', game, 'pass', 'bss!bss@test_double_register', 'unit tester') | ||||
| 
 | ||||
|         assert new_char.hostmask == newer_char.hostmask | ||||
| 
 | ||||
|     def test_level_up(self): | ||||
|         """Test the level up functionality.""" | ||||
|         char = Character.objects.get(pk=1) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user