diff --git a/langate/api/serializers.py b/langate/api/serializers.py index 934dac6..2042167 100644 --- a/langate/api/serializers.py +++ b/langate/api/serializers.py @@ -6,7 +6,7 @@ class DeviceSerializer(serializers.ModelSerializer): - name = serializers.SlugField(max_length=100) + name = serializers.RegexField("^[a-zA-Z0-9 _]+$", max_length=100) class Meta: model = Device diff --git a/langate/api/views.py b/langate/api/views.py index fddc990..7f5dac4 100644 --- a/langate/api/views.py +++ b/langate/api/views.py @@ -1,5 +1,6 @@ from django.core.exceptions import PermissionDenied from django.contrib.auth.models import User +from django.contrib.auth import logout from django.conf import settings from .serializers import DeviceSerializer, UserSerializer @@ -69,15 +70,18 @@ def put(self, request, ident, format=None): def delete(self, request, ident, format=None): - # Deleting the device you are currently on is not allowed via the API. - # Instead the user can log out from the portal. - client_ip = request.META.get('HTTP_X_FORWARDED_FOR') dev = self.get_device(ident, request.user) if dev.ip == client_ip: - raise APIException("Deleting your current device is not allowed via the API.") + # If the user decides to remove the device he is currently on, + # We remove the device and log him out. + + dev.delete() + logout(request) + + return Response(status=status.HTTP_204_NO_CONTENT) else: dev.delete() @@ -98,7 +102,6 @@ def get_device(self, ident, user): else: raise PermissionDenied - def get(self, request, ident): dev = self.get_device(ident, request.user) diff --git a/langate/langate/settings.py b/langate/langate/settings.py index 7095517..7c12e75 100644 --- a/langate/langate/settings.py +++ b/langate/langate/settings.py @@ -179,3 +179,49 @@ class Tournament(Enum): # Network management interface NETWORK = network.Ipset() + + +# Logging settings + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + + + 'formatters': { + 'verbose': { + 'format': '{asctime} [{levelname}] [{module}] {message}', + 'style': '{', + }, + }, + + 'handlers': { + 'django_file': { + 'level': 'INFO', + 'class': 'logging.FileHandler', + 'formatter': 'verbose', + 'filename': os.path.join(BASE_DIR, 'logs/django.log'), + }, + + 'langate_file': { + 'level': 'INFO', + 'class': 'logging.FileHandler', + 'formatter': 'verbose', + 'filename': os.path.join(BASE_DIR, 'logs/langate.log'), + }, + }, + + 'loggers': { + 'django': { + 'handlers': ['django_file'], + 'level': 'DEBUG', + 'propagate': True, + }, + + 'langate.events': { + 'handlers': ['langate_file'], + 'level': 'DEBUG', + 'propagate': True, + } + }, +} diff --git a/langate/portal/models.py b/langate/portal/models.py index 7d387b1..b165fe0 100644 --- a/langate/portal/models.py +++ b/langate/portal/models.py @@ -1,5 +1,6 @@ from enum import Enum +import logging from django.contrib.auth.models import User from django.db import models from django.db.models.signals import post_save, post_delete @@ -10,6 +11,7 @@ # Create your models here. +event_logger = logging.getLogger('langate.events') class Role(Enum): P = "Player" @@ -56,15 +58,17 @@ class Device(models.Model): # Area of the device, i.e. LAN or WiFi area = models.CharField(max_length=4, default="LAN") - # FIXME : we should consider also the case when an user deletes its last device ! # Functions listening modifications of user @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): if created: - if(instance.is_staff): + + if instance.is_staff: + event_logger.info("Added new user {} (with Administrator role).".format(instance.username)) Profile.objects.create(user=instance, role=Role.A.value) else: + event_logger.info("Added new user {}.".format(instance.username)) Profile.objects.create(user=instance) @@ -73,25 +77,34 @@ def save_user_profile(sender, instance, **kwargs): instance.profile.save() +@receiver(post_delete, sender=User) +def delete_user(sender, instance, **kwargs): + event_logger.info("Removed user {}.".format(instance.username)) + + @receiver(post_save, sender=Device) def create_device(sender, instance, created, **kwargs): # On creating a new device, we need to use the networking module to retrieve # some information : for example the MAC address or the area of the device based on the IP. if created: - ip = instance.ip # FIXME : IP should exist at this stage but it will fail really bad if it doesn't, should we handle this ? + ip = instance.ip # IP should exist at this stage and it will fail really bad if it doesn't. instance.mac = network.get_mac(ip) instance.area = "LAN" # FIXME: replace with a call to the networking module settings.NETWORK.connect_user(instance.mac) + + event_logger.info("Connected device {} at {} to the internet.".format(instance.mac, instance.ip)) + instance.save() - @receiver(post_delete, sender=Device) def delete_device(sender, instance, **kwargs): # When deleting a device, we need to unregister it from the network. + event_logger.info("Disconnected device {} at {} of the internet.".format(instance.mac, instance.ip)) + settings.NETWORK.disconnect_user(instance.mac) diff --git a/langate/portal/templates/portal/connected.html b/langate/portal/templates/portal/connected.html index ad4eed5..b4e77d4 100644 --- a/langate/portal/templates/portal/connected.html +++ b/langate/portal/templates/portal/connected.html @@ -83,6 +83,7 @@ +