Skip to content
Open
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
19 changes: 19 additions & 0 deletions api/access.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from rest_framework.permissions import BasePermission
from .models import Todo

class AllUsers(BasePermission):
def has_object_permission(self, request, view, object):
todo = Todo.objects.filter(id = object.id)
if todo:
if request.user == todo[0].creator or request.user in todo[0].collaborators.all():
return True
return False
class Creator(BasePermission):
def has_permission(self, request, view):
todo = Todo.objects.filter(id = view.kwargs['id'])
if todo:
if request.user == todo[0].creator:
return True
return False


30 changes: 30 additions & 0 deletions api/migrations/0003_auto_20210731_1821.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 3.0.7 on 2021-07-31 12:51

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('api', '0002_todo_creator'),
]

operations = [
migrations.AddField(
model_name='todo',
name='collaborators',
field=models.ManyToManyField(related_name='collaborators', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='todo',
name='iscollab',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='todo',
name='iscreator',
field=models.BooleanField(default=False),
),
]
3 changes: 3 additions & 0 deletions api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
class Todo(models.Model):
creator = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
collaborators = models.ManyToManyField(User,related_name="collaborators")
iscollab = models.BooleanField(default=False)
iscreator = models.BooleanField(default=False)

def __str__(self):
return self.title
21 changes: 18 additions & 3 deletions api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from rest_framework import serializers
from .models import Todo

from django.contrib.auth.models import User

"""
TODO:
Expand All @@ -19,11 +19,26 @@ class TodoCreateSerializer(serializers.ModelSerializer):
also return the serialized Todo data (id etc.), alongwith 200 status code.
"""
def save(self, **kwargs):
data = self.validated_data
user = self.context['request'].user
data = self.validated_data
title = data['title']
todo = Todo.objects.create(creator=user, title=title)

return todo
class Meta:
model = Todo
fields = ('id', 'title',)


class TodoSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title','iscollab','iscreator')
extra_kwargs = {
'iscreator': {'read_only': True},
'iscollab': {'read_only': True}
}

class CollabSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ['collaborators']
6 changes: 5 additions & 1 deletion api/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.urls import path
from .views import TodoCreateView
from .views import *

"""
TODO:
Expand All @@ -9,4 +9,8 @@

urlpatterns = [
path('todo/create/', TodoCreateView.as_view()),
path('todo/', TodoAllView.as_view()),
path('todo/<int:id>/', TodoDetailView.as_view()),
path('todo/<int:id>/add-collaborators/', AddCollab.as_view()),
path('todo/<int:id>/remove-collaborators/', RemoveCollab.as_view()),
]
72 changes: 67 additions & 5 deletions api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
from rest_framework import permissions
from rest_framework import status
from rest_framework.response import Response
from .serializers import TodoCreateSerializer
from .serializers import *
from .models import Todo

from .access import AllUsers,Creator

"""
TODO:
Expand All @@ -30,6 +30,68 @@ def post(self, request):
Creates a Todo entry for the logged in user.
"""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(status=status.HTTP_200_OK)
if serializer.is_valid(raise_exception=True):
item = serializer.save()
return Response({
'id':item.id,
'title':item.title,
}, status=status.HTTP_201_OK)
else:
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)

class TodoAllView(generics.ListAPIView):
permission_classes = (permissions.IsAuthenticated, AllUsers)

serializer_class = TodoSerializer

def list(self, request, *args, **kwargs):
queryset1 = Todo.objects.filter(creator=request.user)
queryset2 = Todo.objects.filter(collaborators=request.user)
queryset = (queryset1 | queryset2).distinct()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)

class TodoDetailView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = (permissions.IsAuthenticated, AllUsers)
serializer_class = TodoSerializer


def get_queryset(self):
todocollab = Todo.objects.filter(Collaborators = self.request.user, id = self.kwargs['id'])
if todocollab:
todocollab[0].iscreator = False
todocollab[0].iscollab = True
todocollab[0].save()

todocreator = Todo.objects.filter(creator = self.request.user, id = self.kwargs['id'])
if todocreator:
todocreator[0].iscreator = True
todocreator[0].iscollab = False
todocreator[0].save()

return todocreator | todocollab

class AddCollab(generics.GenericAPIView):
permission_classes = (permissions.IsAuthenticated, Creator)
serializer_class = CollabSerializer


def post(self, request):
serializer = self.get_serializer(data = request.data)
if serializer.is_valid():
serializer.add_collaborators(self.kwargs['id'], request.user)
return Response({'message': 'Success'}, status = status.HTTP_201_CREATED)
else:
return Response({'message': 'Failure'}, status = status.HTTP_404_NOT_FOUND)

class RemoveCollab(generics.GenericAPIView):
permission_classes = (permissions.IsAuthenticated, Creator)
serializer_class = CollabSerializer

def delete(self, request):
serializer = self.get_serializer(data = request.data)
if serializer.is_valid():
serializer.remove_collaborators(self.kwargs['id'])
return Response({'message': 'Success'}, status = status.HTTP_200_OK)
else:
return Response({'message': 'Failure'}, status = status.HTTP_404_NOT_FOUND)
46 changes: 42 additions & 4 deletions authentication/serializers.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,61 @@
from rest_framework import serializers
from django.contrib.auth import authenticate
from django.contrib.auth.models import User

from rest_framework.validators import UniqueValidator

class TokenSerializer(serializers.Serializer):
token = serializers.CharField(max_length=500)


class LoginSerializer(serializers.Serializer):
# TODO: Implement login functionality
pass
username = serializers.CharField()
password = serializers.CharField(style = {'input_type': 'password'},write_only = True, )

def validate(self, data):
username = data.get('username')
password = data.get('password')
user = authenticate(username = username, password = password)

if user:
data['user'] = user
else:
raise serializers.ValidationError("Unable to login :( !")
return data


class RegisterSerializer(serializers.Serializer):
# TODO: Implement register functionality
pass
# firstname = serializers.CharField()
# lastname = serializers.CharField()
username = serializers.CharField(required = True,validators = [UniqueValidator(queryset = User.objects.all())])
password = serializers.CharField(style = {'input_type': 'password'}, min_length = 8,write_only = True,required = True)
name = serializers.CharField(source='first_name', max_length=150)
email = serializers.EmailField(max_length=255, required = True, allow_blank=False)
def create(self, validated_data):
user = User(
first_name = validated_data['first_name'],
username = validated_data['username'],
email = validated_data['email'],
password = validated_data['password'],
)
user.set_password((validated_data['password']))
user.save()
return user
class Meta:
model = User
fields = ['name', 'email', 'username', 'password']
extra_kwargs = {'password':{'write_only':True}}





class UserSerializer(serializers.ModelSerializer):
# TODO: Implement the functionality to display user details
pass
name = serializers.CharField(source='first_name', max_length=150, required=False)
class Meta:
model = User
fields = ('id','username', 'email','name' )


40 changes: 33 additions & 7 deletions authentication/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
from rest_framework.authtoken.models import Token
from .serializers import (
LoginSerializer, RegisterSerializer, UserSerializer, TokenSerializer)


from django.contrib.auth.models import User
from django.contrib.auth import authenticate
def create_auth_token(user):
"""
Returns the token required for authentication for a user.
Returns the token required for authentication for a user.
"""
token, _ = Token.objects.get_or_create(user=user)
return token
Expand All @@ -21,16 +21,36 @@ class LoginView(generics.GenericAPIView):
Implement login functionality, taking username and password
as input, and returning the Token.
"""
pass
permissions_classes = [permissions.AllowAny]
serializer_class = LoginSerializer

def post(self, request):
serializer = LoginSerializer(data=request.data)
if serializer.is_valid():
token = create_auth_token(serializer.validated_data['user'])
return Response({'token': token.key }, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)



class RegisterView(generics.GenericAPIView):
class RegisterView(generics.CreateAPIView):
"""
TODO:
Implement register functionality, registering the user by
taking his details, and returning the Token.
"""
pass
permission_classes = ()
serializer_class = RegisterSerializer

def post(self, request):
serializer = self.get_serializer(data = request.data)
if serializer.is_valid():
self.perform_create(serializer)
token=create_auth_token(serializer.instance)
return Response({'token':token.key}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)



class UserProfileView(generics.RetrieveAPIView):
Expand All @@ -39,4 +59,10 @@ class UserProfileView(generics.RetrieveAPIView):
Implement the functionality to retrieve the details
of the logged in user.
"""
pass
permission_classes = [permissions.IsAuthenticated]
serializer_class = UserSerializer

queryset = User.objects.all()

def get_data(self):
return self.request.user
3 changes: 2 additions & 1 deletion todo/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
'rest_framework.authtoken',
'drf_yasg',
'corsheaders',
'api'
'api',
'authentication',
]

MIDDLEWARE = [
Expand Down