Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/fleet_management/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from import_export.admin import ImportExportModelAdmin
from import_export.fields import Field
from import_export import resources
from .models import Car, Passenger, Drive, User, Project, VerificationToken
from .models import Car, Passenger, Drive, User, Project


class DriveResource(resources.ModelResource):
Expand Down
27 changes: 1 addition & 26 deletions backend/fleet_management/api.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
from rest_framework import generics, filters, permissions, views
from rest_framework import generics, filters, views
from rest_framework.response import Response

from .models import VerificationToken
from .serializers import VerificationTokenSerializer

from .permissions import GroupPermission, all_driver_methods
from .models import Car, Drive, Passenger, Project
from .serializers import (
Expand Down Expand Up @@ -76,25 +73,3 @@ class ProjectView(generics.ListAPIView):

serializer_class = ProjectSerializer
queryset = Project.objects.all()


class VerificationTokenView(generics.RetrieveUpdateAPIView):
permission_classes = (permissions.AllowAny,)
lookup_field = 'token'
serializer_class = VerificationTokenSerializer
queryset = VerificationToken.objects.all()

def update(self, request, *args, **kwargs):
kwargs['partial'] = False
return super().update(request, args, kwargs)

def perform_update(self, serializer: VerificationTokenSerializer):
"""
Updates token status.

If token is expired or already confirmed, the update is skipped.
"""
token = serializer.instance # type: VerificationToken

if token.is_active:
serializer.save()
13 changes: 1 addition & 12 deletions backend/fleet_management/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from factory import fuzzy

from fleet_management.models import (
Car, Drive, Passenger, Project, User, VerificationToken,
Car, Drive, Passenger, Project, User
)

COUNTRIES = ('UA', 'SS')
Expand Down Expand Up @@ -164,14 +164,3 @@ def passengers(self, create, extracted, **kwargs):
if extracted:
for passenger in extracted:
self.passengers.add(passenger)


class VerificationTokenFactory(factory.DjangoModelFactory):

comment = factory.Faker(
'text', max_nb_chars=VerificationToken.COMMENT_MAX_LENGTH,
)
token = factory.Faker('uuid4')

class Meta:
model = VerificationToken
37 changes: 0 additions & 37 deletions backend/fleet_management/models.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import pytz
import uuid
from datetime import datetime, timedelta
import calendar
import time

from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.utils.timezone import now
from django_countries.fields import CountryField
Expand Down Expand Up @@ -79,36 +75,3 @@ def fuel_consumption(self):
distance = self.end_mileage - self.start_mileage
fuel_consumption = (distance * float(self.car.fuel_consumption)) / 100
return round(fuel_consumption, 2)


class VerificationToken(models.Model):
"""
Keeps track of drives' verification statuses.
"""

EXPIRATION_DELTA = timedelta(days=7)
COMMENT_MAX_LENGTH = 2000

comment = models.CharField(max_length=COMMENT_MAX_LENGTH, blank=True)
is_confirmed = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
drive = models.ForeignKey(Drive, on_delete=models.CASCADE)
is_ok = models.NullBooleanField()
passenger = models.ForeignKey(Passenger, on_delete=models.CASCADE)
token = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)

@property
def is_expired(self):
utc_now = pytz.utc.localize(datetime.utcnow())
return utc_now > self.created_at + self.EXPIRATION_DELTA

@property
def is_active(self):
return not self.is_confirmed and not self.is_expired

@property
def verification_url(self):
return f"{settings.FRONTEND_URL}/confirmation/{self.token}"

def __str__(self):
return str(self.token)
34 changes: 11 additions & 23 deletions backend/fleet_management/serializers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
from django.db import transaction
from rest_framework import fields, serializers, status
from django.contrib.auth.models import Group

from rest_framework.exceptions import ValidationError

from .models import Car, Drive, Passenger, User, Project, VerificationToken
from .models import Car, Drive, Passenger, User, Project


class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = Group
fields = ('name',)


class UserSerializer(serializers.ModelSerializer):
groups = GroupSerializer(many=True)

class Meta:
model = User
fields = ('id', 'username', 'groups')
Expand Down Expand Up @@ -94,25 +104,3 @@ def is_valid(self, raise_exception=False):
if "non_field_errors" in err_codes and "unique" in err_codes["non_field_errors"]:
err.status_code = status.HTTP_409_CONFLICT
raise err


class VerificationTokenSerializer(serializers.ModelSerializer):
is_active = fields.BooleanField(read_only=True)

comment = fields.CharField(
max_length=VerificationToken.COMMENT_MAX_LENGTH,
write_only=True,
)
is_ok = fields.NullBooleanField(write_only=True)

class Meta:
model = VerificationToken
fields = ['comment', 'is_ok', 'is_active']

def update(self, instance, validated_data):
instance.comment = validated_data['comment']
instance.is_ok = validated_data['is_ok']
instance.is_confirmed = True
instance.save()

return instance
27 changes: 0 additions & 27 deletions backend/fleet_management/templates/new_drive_email.html

This file was deleted.

13 changes: 1 addition & 12 deletions backend/fleet_management/test_drives.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
from rest_framework import status
from rest_framework.test import APITransactionTestCase

from fleet_management.models import Car, Drive, Passenger, Project, VerificationToken
from fleet_management.models import Car, Drive, Passenger, Project
from fleet_management.factories import DriveFactory


class DrivesApiTest(APITransactionTestCase):

def create_passenger(self, first_name, last_name, email):
return Passenger.objects.create(
first_name=first_name,
Expand Down Expand Up @@ -177,16 +176,6 @@ def test_can_create_a_drive(self):
self.assertEqual(drive.start_location, res.data['start_location'])
self.assertEqual(drive.end_location, res.data['end_location'])

tokens = VerificationToken.objects.filter(drive=drive).all()

self.assertEqual(len(tokens), 2)
self.assertSetEqual(
{token.passenger.id for token in tokens},
{self.passengers[0].id, self.passengers[1].id},
)
self.assertSetEqual({token.is_confirmed for token in tokens}, {False, False})
self.assertSetEqual({token.is_ok for token in tokens}, {None, None})

def test_fuel_consumption_is_valid(self):
drive = DriveFactory(start_mileage=100300, end_mileage=100500)
drive.car.fuel_consumption = 9.73
Expand Down
37 changes: 0 additions & 37 deletions backend/fleet_management/test_factories.py

This file was deleted.

Loading