Commit 79bb34b9 authored by Erlend Ydse's avatar Erlend Ydse
Browse files

Move RememberMe to users app

parent 5799d4a3
# Generated by Django 3.1 on 2021-04-15 16:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0014_user_symmetric_friends'),
]
operations = [
migrations.CreateModel(
name='RememberMe',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('remember_me', models.CharField(max_length=500)),
],
),
]
......@@ -31,6 +31,18 @@ class User(AbstractUser):
symmetric_friends = models.ManyToManyField("self", blank=True)
class RememberMe(models.Model):
"""Django model for an remember_me cookie used for remember me functionality.
Attributes:
remember_me: Value of cookie used for remember me
"""
remember_me = models.CharField(max_length=500)
def __str__(self):
return self.remember_me
def athlete_directory_path(instance, filename):
"""
Return the path for an athlete's file
......
......@@ -4,7 +4,7 @@ from django import forms
from django.contrib.auth import get_user_model, password_validation
from rest_framework import serializers
from users.models import AthleteFile, Offer
from users.models import AthleteFile, Offer, RememberMe
class UserSerializer(serializers.HyperlinkedModelSerializer):
......@@ -105,6 +105,18 @@ class UserPutSerializer(serializers.ModelSerializer):
instance.symmetric_friends.add(validated_data["symmetric_friends"][0])
return instance
class RememberMeSerializer(serializers.HyperlinkedModelSerializer):
"""Serializer for an RememberMe. Hyperlinks are used for relationships by default.
Serialized fields: remember_me
Attributes:
remember_me: Value of cookie used for remember me functionality
"""
class Meta:
model = RememberMe
fields = ["remember_me"]
class AthleteFileSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source="owner.username")
......
......@@ -16,4 +16,5 @@ urlpatterns = [
views.AthleteFileDetail.as_view(),
name="athletefile-detail",
),
path("api/remember_me/", views.RememberMe.as_view(), name="remember_me"),
]
import base64
import pickle
from collections import namedtuple
from django.contrib.auth import get_user_model
from django.core.exceptions import PermissionDenied
from django.core.signing import Signer
from django.db.models import Q
from rest_framework import generics, mixins, permissions
from rest_framework.parsers import FormParser, MultiPartParser
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
from users.models import AthleteFile, Offer
from users.permissions import IsAthlete, IsCoach, IsCurrentUser
from users.serializers import (AthleteFileSerializer, OfferSerializer,
UserGetSerializer, UserPutSerializer,
UserSerializer)
RememberMeSerializer, UserGetSerializer,
UserPutSerializer, UserSerializer)
from workouts.mixins import CreateListModelMixin
from workouts.parsers import MultipartJsonParser
from workouts.permissions import IsOwner, IsReadOnly
......@@ -75,6 +83,52 @@ class UserDetail(
return self.partial_update(request, *args, **kwargs)
# Allow users to save a persistent session in their browser
class RememberMe(
mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView,
):
serializer_class = RememberMeSerializer
def get(self, request):
if request.user.is_authenticated == False:
raise PermissionDenied
else:
return Response({"remember_me": self.rememberme()})
def post(self, request):
cookie_object = namedtuple("Cookies", request.COOKIES.keys())(
*request.COOKIES.values()
)
user = self.get_user(cookie_object)
refresh = RefreshToken.for_user(user)
return Response(
{
"refresh": str(refresh),
"access": str(refresh.access_token),
}
)
def get_user(self, cookie_object):
decode = base64.b64decode(cookie_object.remember_me)
user, sign = pickle.loads(decode)
# Validate signature
if sign == self.sign_user(user):
return user
def rememberme(self):
creds = [self.request.user, self.sign_user(str(self.request.user))]
return base64.b64encode(pickle.dumps(creds))
def sign_user(self, username):
signer = Signer()
signed_user = signer.sign(username)
return signed_user
class OfferList(
mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView
):
......
# Generated by Django 3.1 on 2021-04-15 16:40
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('workouts', '0005_auto_20210307_2015'),
]
operations = [
migrations.DeleteModel(
name='RememberMe',
),
]
......@@ -139,16 +139,3 @@ class WorkoutFile(models.Model):
get_user_model(), on_delete=models.CASCADE, related_name="workout_files"
)
file = models.FileField(upload_to=workout_directory_path)
class RememberMe(models.Model):
"""Django model for an remember_me cookie used for remember me functionality.
Attributes:
remember_me: Value of cookie used for remember me
"""
remember_me = models.CharField(max_length=500)
def __str__(self):
return self.remember_me
......@@ -3,8 +3,7 @@
from rest_framework import serializers
from rest_framework.serializers import HyperlinkedRelatedField
from workouts.models import (Exercise, ExerciseInstance, RememberMe, Workout,
WorkoutFile)
from workouts.models import Exercise, ExerciseInstance, Workout, WorkoutFile
class ExerciseInstanceSerializer(serializers.HyperlinkedModelSerializer):
......@@ -221,17 +220,3 @@ class ExerciseSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Exercise
fields = ["url", "id", "name", "description", "unit", "instances"]
class RememberMeSerializer(serializers.HyperlinkedModelSerializer):
"""Serializer for an RememberMe. Hyperlinks are used for relationships by default.
Serialized fields: remember_me
Attributes:
remember_me: Value of cookie used for remember me functionality
"""
class Meta:
model = RememberMe
fields = ["remember_me"]
......@@ -46,6 +46,5 @@ urlpatterns = format_suffix_patterns(
path("api/auth/", include("rest_framework.urls")),
path("api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
path("api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
path("api/remember_me/", views.RememberMe.as_view(), name="remember_me"),
]
)
"""Contains views for the workouts application. These are mostly class-based views.
"""
import base64
import pickle
from collections import namedtuple
from django.core.exceptions import PermissionDenied
from django.core.signing import Signer
from django.db.models import Q
from rest_framework import filters, generics, mixins, permissions
from rest_framework.decorators import api_view
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework_simplejwt.tokens import RefreshToken
from workouts.mixins import CreateListModelMixin
from workouts.models import Exercise, ExerciseInstance, Workout, WorkoutFile
......@@ -22,8 +15,8 @@ from workouts.permissions import (IsCoachAndVisibleToCoach,
IsOwnerOfWorkout, IsPublic, IsReadOnly,
IsWorkoutPublic)
from workouts.serializers import (ExerciseInstanceSerializer,
ExerciseSerializer, RememberMeSerializer,
WorkoutFileSerializer, WorkoutSerializer)
ExerciseSerializer, WorkoutFileSerializer,
WorkoutSerializer)
@api_view(["GET"])
......@@ -45,53 +38,6 @@ def api_root(request, format=None):
)
# Allow users to save a persistent session in their browser
class RememberMe(
mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView,
):
serializer_class = RememberMeSerializer
def get(self, request):
if request.user.is_authenticated == False:
raise PermissionDenied
else:
return Response({"remember_me": self.rememberme()})
def post(self, request):
cookie_object = namedtuple("Cookies", request.COOKIES.keys())(
*request.COOKIES.values()
)
user = self.get_user(cookie_object)
refresh = RefreshToken.for_user(user)
return Response(
{
"refresh": str(refresh),
"access": str(refresh.access_token),
}
)
def get_user(self, cookie_object):
decode = base64.b64decode(cookie_object.remember_me)
user, sign = pickle.loads(decode)
# Validate signature
if sign == self.sign_user(user):
return user
def rememberme(self):
creds = [self.request.user, self.sign_user(str(self.request.user))]
return base64.b64encode(pickle.dumps(creds))
def sign_user(self, username):
signer = Signer()
signed_user = signer.sign(username)
return signed_user
class WorkoutList(
mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView
):
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment