Added InviteCode system

This commit is contained in:
Walter 2025-02-20 22:41:07 +01:00
parent d91681a7ec
commit 3d98f297d9
8 changed files with 82 additions and 12 deletions

View File

@ -31,7 +31,7 @@ def load_insecure_key():
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY") or load_insecure_key()
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ") or "*"
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "*").split(" ")
# Application definition

View File

@ -1,7 +1,8 @@
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import Player, Log
from .models import Player, Log, InviteCode
admin.site.register(Log)
admin.site.register(Player)
admin.site.register(Player)
admin.site.register(InviteCode)

View File

@ -8,7 +8,7 @@ from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from users.models import Player
from users.validators import usernameValidator, username_change_validator
from users.validators import username_validator, username_change_validator, invitecode_validator
from bloonsa_game.models import Config as BloonsaConfig
class UserRegisterForm(UserCreationForm):
@ -23,12 +23,20 @@ class UserRegisterForm(UserCreationForm):
self.helper.form_action = '/users/register'
self.helper.add_input(Submit('submit', 'Create'))
invite_code = forms.CharField(max_length=64,
label="invite_code",
empty_value="code",
# help_text="",
required=True,
validators=[invitecode_validator,])
username = forms.CharField(min_length=3,
max_length=16,
label="Username",
required=True,
validators=[usernameValidator,],
help_text=_("3-16 chars, alphanumeric and _- pls"))
validators=[username_validator,],
#help_text=_("3-16 chars, alphanumeric and _- pls")
)
password1 = forms.CharField(
label="Password",

View File

@ -0,0 +1,33 @@
# Generated by Django 5.1.6 on 2025-02-20 21:11
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0025_alter_player_avatar'),
]
operations = [
migrations.CreateModel(
name='InviteCode',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.TextField(max_length=64)),
('code', models.TextField(max_length=64)),
('active', models.BooleanField(default=True)),
],
),
migrations.AlterField(
model_name='log',
name='action',
field=models.IntegerField(choices=[(0, 'Logged in'), (1, 'Registered'), (2, 'Logged out'), (3, 'Edited account settings'), (100, 'Loaded a level via ingame ID box'), (101, 'Loaded a level via URL'), (102, 'Loaded a random level'), (103, 'Submitted a score on level_id'), (104, 'Rated a level')]),
),
migrations.AddField(
model_name='player',
name='invite_code',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='users.invitecode'),
),
]

View File

@ -4,10 +4,18 @@ from django.contrib.auth.models import User
from django_resized import ResizedImageField
class InviteCode(models.Model):
title = models.TextField(max_length=64)
code = models.TextField(max_length=64)
active = models.BooleanField(default=True)
def __str__(self):
return f"{self.title} | code: {self.code}"
class Player(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="player")
# Profile
bio = models.TextField(max_length=128, null=True)
bio = models.TextField(max_length=128, null=True, blank=True)
avatar = ResizedImageField(default="defaults/avatars.jpg",
size=[256, 256],
upload_to="avatars",
@ -21,6 +29,7 @@ class Player(models.Model):
creation_date = models.DateTimeField(default=timezone.now)
latest_activity = models.DateTimeField(default=timezone.now)
suspected_cheater = models.BooleanField(default=False) # This should be set when tripping the anti-cheat
invite_code = models.ForeignKey(InviteCode, null=True, blank=True, on_delete=models.CASCADE)
# States
suspended = models.BooleanField(default=False) # This is a shadow-ban, stats will still save but not all will show up on leaderboards
banned = models.BooleanField(default=False) # Account gets logged out upon logging in
@ -50,6 +59,8 @@ class Player(models.Model):
return f"{states}{self.user} - {self.latest_ip}".strip(" ")
class Log(models.Model):
class Actions(models.IntegerChoices):
login = 0, "Logged in"
@ -68,4 +79,5 @@ class Log(models.Model):
note = models.TextField(null=True)
def __str__(self):
return f"{self.player.user.username} - {self.get_action_display()} <{self.note or ''}>"
return f"{self.player.user.username} - {self.get_action_display()} <{self.note or ''}>"

View File

@ -25,6 +25,9 @@ class BloonsaUtil:
if not request.user.is_authenticated:
return
if hasattr(request.user, "player"):
if not hasattr(request.user.player, "bloonsa_config"):
bloonsa_config = Config(player=request.user.player)
bloonsa_config.save()
return request.user.player
ip = self.get_ip(request=request)
player = Player(user=request.user,

View File

@ -3,9 +3,10 @@ import string
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from users.models import Player
from users.models import Player, InviteCode
def usernameValidator(username):
def username_validator(username):
if User.objects.filter(username__iexact=username).first() is not None:
raise ValidationError("Sorry, this username is already in use")
@ -23,3 +24,10 @@ def username_change_validator(username):
charset = set(string.ascii_letters + string.digits + "_-")
if not all(x in charset for x in username):
raise ValidationError("Username may only contain normal letters, numbers and _-")
def invitecode_validator(invitecode):
if len(invitecode) > 64:
raise ValidationError("Invite code too long")
if not InviteCode.objects.filter(code=invitecode).exists():
raise ValidationError("Invite code doesn't exist")

View File

@ -5,7 +5,7 @@ from django.shortcuts import render, redirect
from django.views.generic import TemplateView
from users.forms import UserRegisterForm, UserLoginForm, PlayerUpdateForm, UserUpdateForm, BloonsaConfigUpdateForm
from users.models import Player
from users.models import Player, InviteCode
from users.util import bloonsa_util, actions
@ -37,9 +37,14 @@ class RegisterView(TemplateView):
form = UserRegisterForm(request.POST)
if not form.is_valid():
return render(request=request, template_name="users/register.html", context={"form": form})
invite_code = InviteCode.objects.get(code=form.cleaned_data["invite_code"])
user = form.save()
player = bloonsa_util.init_player(request=request)
login(request=request, user=user)
player = bloonsa_util.init_player(request=request)
player.invite_code = invite_code
player.save()
bloonsa_util.log(player=player,
action=actions.login)
return redirect("bloonsa_game:game")