login/auth

This commit is contained in:
zman 2023-12-05 15:00:17 -05:00
parent 244af4792f
commit 636f39d7b0
10 changed files with 150 additions and 203 deletions

View File

@ -13,6 +13,7 @@ from server.models import (
PlayerGameData, PlayerGameData,
GuildGameDataSchema, GuildGameDataSchema,
WowClasses, WowClasses,
User,
) )
@ -28,10 +29,16 @@ def populate_guilds():
g = Guild.objects.get_or_create(name=guild)[0] g = Guild.objects.get_or_create(name=guild)[0]
def populate_players(): def populate_users():
players = ["Pixel", "Zman", "Skip"] users = [
for player in players: {"username": "Skip", "password": "password"},
p = Player.objects.get_or_create(name=player)[0] {"username": "Zman", "password": "password"},
{"username": "Pixel", "password": "password"},
]
for user in users:
u = User.objects.get_or_create(username=user["username"])[0]
u.set_password(user["password"])
u.save()
def populate_player_guilds(): def populate_player_guilds():
@ -189,12 +196,12 @@ def populate_guild_game_data_schema():
# get or create player game data # get or create player game data
p1 = PlayerGameData.objects.get_or_create( p1 = PlayerGameData.objects.get_or_create(
player=Player.objects.get(name=wow_gamer1["playerName"]), player=Player.objects.get(name=wow_gamer1["playerName"]),
game=Game.objects.get(name="World of Warcraft"), schema=s,
data=wow_gamer1, data=wow_gamer1,
)[0] )[0]
p2 = PlayerGameData.objects.get_or_create( p2 = PlayerGameData.objects.get_or_create(
player=Player.objects.get(name=wow_gamer2["playerName"]), player=Player.objects.get(name=wow_gamer2["playerName"]),
game=Game.objects.get(name="World of Warcraft"), schema=s,
data=wow_gamer2, data=wow_gamer2,
)[0] )[0]
@ -208,7 +215,7 @@ def populate_guild_game_data_schema():
# get or create player game data # get or create player game data
p1 = PlayerGameData.objects.get_or_create( p1 = PlayerGameData.objects.get_or_create(
player=Player.objects.get(name=csgo_epic_nerd1["playerName"]), player=Player.objects.get(name=csgo_epic_nerd1["playerName"]),
game=Game.objects.get(name="Counter Strike: Global Offensive"), schema=s,
data=csgo_epic_nerd1, data=csgo_epic_nerd1,
)[0] )[0]
@ -217,7 +224,7 @@ def populate():
with transaction.atomic(): with transaction.atomic():
populate_games() populate_games()
populate_guilds() populate_guilds()
populate_players() populate_users()
populate_player_guilds() populate_player_guilds()
populate_wow_classes() populate_wow_classes()
populate_guild_game_data_schema() populate_guild_game_data_schema()

View File

@ -1,5 +1,6 @@
# Generated by Django 4.2.7 on 2023-11-30 20:12 # Generated by Django 4.2.7 on 2023-12-05 19:19
from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
@ -9,13 +10,14 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='Game', name='Game',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=200)), ('name', models.CharField(max_length=200)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')), ('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
], ],
@ -27,7 +29,7 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='Guild', name='Guild',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=200)), ('name', models.CharField(max_length=200)),
('tag', models.CharField(max_length=10)), ('tag', models.CharField(max_length=10)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')), ('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
@ -37,13 +39,26 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'Guilds', 'verbose_name_plural': 'Guilds',
}, },
), ),
migrations.CreateModel(
name='GuildGameDataSchema',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('schema', models.JSONField()),
('game', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schemas', to='server.game')),
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schemas', to='server.guild')),
],
options={
'verbose_name': 'Guild Game Data Schema',
'verbose_name_plural': 'Guild Game Data Schemas',
},
),
migrations.CreateModel( migrations.CreateModel(
name='Player', name='Player',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=200)), ('name', models.CharField(max_length=200)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')), ('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='players', to='server.guild')), ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='player', to=settings.AUTH_USER_MODEL)),
], ],
options={ options={
'verbose_name': 'Player', 'verbose_name': 'Player',
@ -51,43 +66,43 @@ class Migration(migrations.Migration):
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='PlayerGameProfile', name='WowClasses',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=200)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')), ('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
('game', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='player_profiles', to='server.game')), ],
options={
'verbose_name': 'WoW Class',
'verbose_name_plural': 'WoW Classes',
},
),
migrations.CreateModel(
name='PlayerGuild',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('role', models.CharField(default='member', max_length=200)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='players', to='server.guild')),
('player', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='guilds', to='server.player')),
],
options={
'verbose_name': 'Player Guild',
'verbose_name_plural': 'Player Guilds',
},
),
migrations.CreateModel(
name='PlayerGameData',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
('data', models.JSONField()),
('player', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='game_profiles', to='server.player')), ('player', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='game_profiles', to='server.player')),
('schema', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='player_game_data', to='server.guildgamedataschema')),
], ],
options={ options={
'verbose_name': 'Player Game Profile', 'verbose_name': 'Player Game Data',
'verbose_name_plural': 'Player Game Profiles', 'verbose_name_plural': 'Player Game Data',
},
),
migrations.CreateModel(
name='WowProfile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('level', models.IntegerField()),
('class_name', models.CharField(max_length=200)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
('player_game_profile', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='wow_profile', to='server.playergameprofile')),
],
options={
'verbose_name': 'WoW Profile',
'verbose_name_plural': 'WoW Profiles',
},
),
migrations.CreateModel(
name='ValorantProfile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('rank', models.CharField(max_length=200)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
('player_game_profile', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='valorant_profile', to='server.playergameprofile')),
],
options={
'verbose_name': 'Valorant Profile',
'verbose_name_plural': 'Valorant Profiles',
}, },
), ),
] ]

View File

@ -1,43 +0,0 @@
# Generated by Django 4.2.7 on 2023-11-30 21:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('server', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='game',
name='id',
field=models.AutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='guild',
name='id',
field=models.AutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='player',
name='id',
field=models.AutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='playergameprofile',
name='id',
field=models.AutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='valorantprofile',
name='id',
field=models.AutoField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='wowprofile',
name='id',
field=models.AutoField(primary_key=True, serialize=False),
),
]

View File

@ -1,31 +0,0 @@
# Generated by Django 4.2.7 on 2023-11-30 21:55
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('server', '0002_alter_game_id_alter_guild_id_alter_player_id_and_more'),
]
operations = [
migrations.RemoveField(
model_name='player',
name='guild',
),
migrations.CreateModel(
name='PlayerGuild',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='players', to='server.guild')),
('player', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='guilds', to='server.player')),
],
options={
'verbose_name': 'Player Guild',
'verbose_name_plural': 'Player Guilds',
},
),
]

View File

@ -1,75 +0,0 @@
# Generated by Django 4.2.7 on 2023-12-05 14:47
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('server', '0003_remove_player_guild_playerguild'),
]
operations = [
migrations.CreateModel(
name='GuildGameDataSchema',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('schema', models.JSONField()),
('game', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schemas', to='server.game')),
('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schemas', to='server.guild')),
],
options={
'verbose_name': 'Guild Game Data Schema',
'verbose_name_plural': 'Guild Game Data Schemas',
},
),
migrations.CreateModel(
name='PlayerGameData',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
('data', models.JSONField()),
('game', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='player_profiles', to='server.game')),
('player', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='game_profiles', to='server.player')),
],
options={
'verbose_name': 'Player Game Data',
'verbose_name_plural': 'Player Game Data',
},
),
migrations.CreateModel(
name='WowClasses',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=200)),
('creation_date', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
],
options={
'verbose_name': 'WoW Class',
'verbose_name_plural': 'WoW Classes',
},
),
migrations.RemoveField(
model_name='valorantprofile',
name='player_game_profile',
),
migrations.RemoveField(
model_name='wowprofile',
name='player_game_profile',
),
migrations.AddField(
model_name='playerguild',
name='role',
field=models.CharField(default='member', max_length=200),
),
migrations.DeleteModel(
name='PlayerGameProfile',
),
migrations.DeleteModel(
name='ValorantProfile',
),
migrations.DeleteModel(
name='WowProfile',
),
]

View File

@ -1,4 +1,7 @@
from django.db import models from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class Guild(models.Model): class Guild(models.Model):
@ -22,9 +25,11 @@ class Guild(models.Model):
class Player(models.Model): class Player(models.Model):
""" """
This model is used to store the player data. This model is used to store the player data.
Players have a one to one relationship with users.
""" """
id = models.AutoField(primary_key=True) id = models.AutoField(primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="player")
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
creation_date = models.DateTimeField("date created", auto_now_add=True) creation_date = models.DateTimeField("date created", auto_now_add=True)
@ -36,6 +41,15 @@ class Player(models.Model):
verbose_name_plural = "Players" verbose_name_plural = "Players"
# Signal to create/update player when user is created/updated
@receiver(post_save, sender=User)
def create_or_update_user_player(sender, instance, created, **kwargs):
if created:
Player.objects.create(user=instance, name=instance.username) # Add default values for other fields if necessary
else:
instance.player.save() # Save the player instance if the user is updated
class PlayerGuild(models.Model): class PlayerGuild(models.Model):
""" """
This model is used to store the player's guild data. This model is used to store the player's guild data.
@ -85,8 +99,10 @@ class PlayerGameData(models.Model):
player = models.ForeignKey( player = models.ForeignKey(
Player, on_delete=models.CASCADE, related_name="game_profiles" Player, on_delete=models.CASCADE, related_name="game_profiles"
) )
game = models.ForeignKey( schema = models.ForeignKey(
Game, on_delete=models.CASCADE, related_name="player_profiles" "GuildGameDataSchema",
on_delete=models.CASCADE,
related_name="player_game_data",
) )
creation_date = models.DateTimeField("date created", auto_now_add=True) creation_date = models.DateTimeField("date created", auto_now_add=True)
data = models.JSONField() data = models.JSONField()

View File

@ -36,16 +36,15 @@ class GameSerializer(serializers.ModelSerializer):
class PlayerGameDataSerializer(serializers.ModelSerializer): class PlayerGameDataSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = PlayerGameData model = PlayerGameData
fields = ["id", "player", "game", "creation_date", "data"] fields = ["id", "player", "schema", "creation_date", "data"]
read_only_fields = ["id", "creation_date"] read_only_fields = ["id", "creation_date"]
def validate_data(self, value): def validate_data(self, value):
game_id = self.initial_data["game"]
try: try:
schema_obj = GuildGameDataSchema.objects.get( # get the schema for the player's guild and game
game=game_id, guild=self.initial_data["guild"] schema = GuildGameDataSchema.objects.get(
) guild=self.context["guild"], game=self.context["game"]
schema = schema_obj.schema ).schema
validate(value, schema) validate(value, schema)
@ -64,6 +63,12 @@ class GuildGameDataSchemaSerializer(serializers.ModelSerializer):
model = GuildGameDataSchema model = GuildGameDataSchema
fields = ["id", "guild", "game", "schema"] fields = ["id", "guild", "game", "schema"]
read_only_fields = ["id"] read_only_fields = ["id"]
def validate_schema(self, value):
# ensure schema has no more than 15 fields
# this is just an example it wont actually be this simple
if len(value["properties"]) > 15:
raise serializers.ValidationError("Schema cannot have more than 15 fields")
class PlayerGuildSerializer(serializers.ModelSerializer): class PlayerGuildSerializer(serializers.ModelSerializer):
@ -78,3 +83,8 @@ class WowClassesSerializer(serializers.ModelSerializer):
model = WowClasses model = WowClasses
fields = ["id", "name", "creation_date"] fields = ["id", "name", "creation_date"]
read_only_fields = ["id", "creation_date"] read_only_fields = ["id", "creation_date"]
class LoginSerializer(serializers.Serializer):
username = serializers.CharField(required=True)
password = serializers.CharField(write_only=True, required=True)

View File

@ -87,6 +87,14 @@ TEMPLATES = [
WSGI_APPLICATION = "server.wsgi.application" WSGI_APPLICATION = "server.wsgi.application"
# REST Framework
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
}
# Database # Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases # https://docs.djangoproject.com/en/4.2/ref/settings/#databases

View File

@ -13,6 +13,7 @@ from .views import (
GuildGameDataSchemaViewSet, GuildGameDataSchemaViewSet,
PlayerGuildViewSet, PlayerGuildViewSet,
WowClassesViewSet, WowClassesViewSet,
LoginView,
) )
router = DefaultRouter() router = DefaultRouter()
@ -42,6 +43,7 @@ urlpatterns = [
path("", hello_world, name="index"), path("", hello_world, name="index"),
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path("api/", include(router.urls)), path("api/", include(router.urls)),
path("login/", LoginView.as_view(), name="login"),
# Swagger # Swagger
re_path( re_path(
r"^swagger(?P<format>\.json|\.yaml)$", r"^swagger(?P<format>\.json|\.yaml)$",

View File

@ -1,5 +1,11 @@
from django.http import HttpResponse from django.http import HttpResponse
from rest_framework import viewsets from rest_framework import viewsets, status
from django.contrib.auth import authenticate, login
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAuthenticated, IsAdminUser
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from .models import ( from .models import (
Game, Game,
Guild, Guild,
@ -17,43 +23,75 @@ from .serializers import (
PlayerGameDataSerializer, PlayerGameDataSerializer,
GuildGameDataSchemaSerializer, GuildGameDataSchemaSerializer,
WowClassesSerializer, WowClassesSerializer,
LoginSerializer,
) )
class LoginView(APIView):
permission_classes = [AllowAny]
@swagger_auto_schema(
operation_description="Login to the system",
request_body=LoginSerializer,
responses={
status.HTTP_200_OK: openapi.Response('Login Successful'),
status.HTTP_401_UNAUTHORIZED: openapi.Response('Invalid Credentials'),
}
)
def post(self, request, format=None):
serializer = LoginSerializer(data=request.data)
if serializer.is_valid():
username = serializer.validated_data['username']
password = serializer.validated_data['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return Response({'detail': 'Login successful'}, status=status.HTTP_200_OK)
else:
return Response({'detail': 'Invalid Credentials'}, status=status.HTTP_401_UNAUTHORIZED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def hello_world(request): def hello_world(request):
return HttpResponse("Hello, World!") return HttpResponse("Hello, World!")
class GameViewSet(viewsets.ModelViewSet): class GameViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = Game.objects.all() queryset = Game.objects.all()
serializer_class = GameSerializer serializer_class = GameSerializer
class GuildViewSet(viewsets.ModelViewSet): class GuildViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = Guild.objects.all() queryset = Guild.objects.all()
serializer_class = GuildSerializer serializer_class = GuildSerializer
class PlayerViewSet(viewsets.ModelViewSet): class PlayerViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = Player.objects.all() queryset = Player.objects.all()
serializer_class = PlayerSerializer serializer_class = PlayerSerializer
class PlayerGameDataViewSet(viewsets.ModelViewSet): class PlayerGameDataViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = PlayerGameData.objects.all() queryset = PlayerGameData.objects.all()
serializer_class = PlayerGameDataSerializer serializer_class = PlayerGameDataSerializer
class GuildGameDataSchemaViewSet(viewsets.ModelViewSet): class GuildGameDataSchemaViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = GuildGameDataSchema.objects.all() queryset = GuildGameDataSchema.objects.all()
serializer_class = GuildGameDataSchemaSerializer serializer_class = GuildGameDataSchemaSerializer
class PlayerGuildViewSet(viewsets.ModelViewSet): class PlayerGuildViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = PlayerGuild.objects.all() queryset = PlayerGuild.objects.all()
serializer_class = PlayerGuildSerializer serializer_class = PlayerGuildSerializer
class WowClassesViewSet(viewsets.ModelViewSet): class WowClassesViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = WowClasses.objects.all() queryset = WowClasses.objects.all()
serializer_class = WowClassesSerializer serializer_class = WowClassesSerializer