From 869a782c5dbcc46196ec24be6acc1637e9e8d602 Mon Sep 17 00:00:00 2001 From: SakshiUppoor Date: Mon, 23 Mar 2020 18:49:26 +0530 Subject: [PATCH 01/10] Add functions to check roles in models.py --- placementApp/models.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/placementApp/models.py b/placementApp/models.py index 6def98e..138799d 100644 --- a/placementApp/models.py +++ b/placementApp/models.py @@ -68,6 +68,15 @@ def has_perm(self, perm, obj=None): def has_module_perms(self, app_label): return True + def is_student(self): + return self.role == "STUDENT" + + def is_co(self): + return self.role == "CO" + + def is_tpo(self): + return self.role == "TPO" + class Student(User): sap_regex = RegexValidator( @@ -99,12 +108,14 @@ class Coordinator(User): @receiver(post_save, sender=settings.AUTH_USER_MODEL) def create_auth_token(sender, instance=None, created=False, **kwargs): + print("hello :)") if created: Token.objects.create(user=instance) @receiver(post_save, sender=Coordinator) def create_auth_token(sender, instance=None, created=False, **kwargs): + print("hello :))") if created: Token.objects.create(user=instance) From 40e315fdb88ab912aeea205b45240805cd54fc55 Mon Sep 17 00:00:00 2001 From: SakshiUppoor Date: Mon, 23 Mar 2020 18:52:09 +0530 Subject: [PATCH 02/10] Add permissions for StudentViewSet --- placementApp/permissions.py | 15 +++++++++++++++ placementApp/urls.py | 2 +- placementApp/views.py | 3 ++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/placementApp/permissions.py b/placementApp/permissions.py index e69de29..53245eb 100644 --- a/placementApp/permissions.py +++ b/placementApp/permissions.py @@ -0,0 +1,15 @@ +from rest_framework.permissions import BasePermission, SAFE_METHODS + +# from customer.models import User + + +class IsStaffOrOwner(BasePermission): + message = "You do not have the permission to perform this action." + + def has_permission(self, request, view): + if request.user.is_student() and view.action == "list": + return False + return request.user.is_authenticated + + def has_object_permission(self, request, view, obj): + return request.user.id == obj.id or request.user.is_co() or request.user.is_tpo() diff --git a/placementApp/urls.py b/placementApp/urls.py index 0e81985..25ada5f 100644 --- a/placementApp/urls.py +++ b/placementApp/urls.py @@ -3,7 +3,7 @@ from . import views router = routers.DefaultRouter() -router.register("students", views.StudentViewSet) +router.register("students", views.StudentViewSet, basename='Students') router.register("positions", views.PositionViewSet) urlpatterns = [ diff --git a/placementApp/views.py b/placementApp/views.py index 264247d..e31b93a 100644 --- a/placementApp/views.py +++ b/placementApp/views.py @@ -7,6 +7,7 @@ from .models import Student, Position, Company from .serializers import * from .utils import generate_xls, get_curent_year +from .permissions import IsStaffOrOwner class StudentSignUpView(generics.CreateAPIView): @@ -59,7 +60,7 @@ def create(self, request, *args, **kwargs): class StudentViewSet( mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet, ): - permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + permission_classes = (IsStaffOrOwner,) queryset = Student.objects.all() serializer_class = StudentSerializer From 5ab4c4fe1ed595efcbdd1afc14eb4cc9f41b4735 Mon Sep 17 00:00:00 2001 From: SakshiUppoor Date: Tue, 24 Mar 2020 10:39:30 +0530 Subject: [PATCH 03/10] Add permissions to Student and Position ViewSets --- placementApp/permissions.py | 18 +++++++++++++++++- placementApp/views.py | 11 ++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/placementApp/permissions.py b/placementApp/permissions.py index 53245eb..0b652fb 100644 --- a/placementApp/permissions.py +++ b/placementApp/permissions.py @@ -12,4 +12,20 @@ def has_permission(self, request, view): return request.user.is_authenticated def has_object_permission(self, request, view, obj): - return request.user.id == obj.id or request.user.is_co() or request.user.is_tpo() + return ( + request.user.id == obj.id or request.user.is_co() or request.user.is_tpo() + ) + + +class IsStaffOrReadOnly(BasePermission): + message = "You do not have the permission to perform this action." + + def has_permission(self, request, view): + if view.action == "create": + return request.user.is_tpo() + return request.user.is_authenticated + + def has_object_permission(self, request, view, obj): + if view.action == "retrieve": + return True + return request.user.is_co() or request.user.is_tpo() diff --git a/placementApp/views.py b/placementApp/views.py index 35c01e1..42601e6 100644 --- a/placementApp/views.py +++ b/placementApp/views.py @@ -7,7 +7,7 @@ from rest_framework import viewsets, permissions, status, mixins, generics from rest_framework.response import Response from .utils import generate_xls, get_curent_year -from .permissions import IsStaffOrOwner +from .permissions import IsStaffOrOwner, IsStaffOrReadOnly class StudentSignUpView(generics.CreateAPIView): @@ -32,6 +32,7 @@ def create(self, request, *args, **kwargs): {"error": "Could not create Student"}, status=status.HTTP_400_BAD_REQUEST ) + class StudentViewSet( mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet, ): @@ -40,7 +41,6 @@ class StudentViewSet( serializer_class = StudentSerializer - class UpdateStudentViewSet(generics.RetrieveUpdateDestroyAPIView): lookup_field = "id" permission_classes = ( @@ -51,6 +51,7 @@ class UpdateStudentViewSet(generics.RetrieveUpdateDestroyAPIView): ) # Requires current user instance for further progress serializer_class = StudentSerializer + class CoordinatorSignUpView(generics.CreateAPIView): permission_classes = (permissions.AllowAny,) queryset = Coordinator.objects.all() @@ -74,6 +75,7 @@ def create(self, request, *args, **kwargs): status=status.HTTP_400_BAD_REQUEST, ) + class ApplicationViewSet( mixins.CreateModelMixin, mixins.RetrieveModelMixin, @@ -89,18 +91,17 @@ def perform_create(self, serializer): class PositionViewSet(viewsets.ModelViewSet): - permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + permission_classes = (IsStaffOrReadOnly,) queryset = Position.objects.all() serializer_class = PositionSerializer + class CompanyViewSet(viewsets.ModelViewSet): permission_classes = (permissions.IsAuthenticatedOrReadOnly,) queryset = Company.objects.all() serializer_class = CompanySerializer - - def get_xls(request, company_id): company = Company.objects.get(id=company_id) From 06eb69df834d7c736634c2b8a3b1438f13106bf7 Mon Sep 17 00:00:00 2001 From: SakshiUppoor Date: Tue, 24 Mar 2020 10:40:05 +0530 Subject: [PATCH 04/10] Apply black formatting --- placementApp/models.py | 5 ++--- placementApp/serializers.py | 5 +++-- placementApp/urls.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/placementApp/models.py b/placementApp/models.py index af4064a..091f9ad 100644 --- a/placementApp/models.py +++ b/placementApp/models.py @@ -70,7 +70,7 @@ def has_module_perms(self, app_label): def is_student(self): return self.role == "STUDENT" - + def is_co(self): return self.role == "CO" @@ -90,7 +90,7 @@ class Student(User): default=None, unique=True, ) - + department = models.CharField(max_length=5, blank=False, choices=DEPARTMENT_CHOICES) year = models.CharField(max_length=2, blank=False, choices=YEAR_CHOICES) Stud_req = ["department", "year", "sap_ID"] @@ -165,4 +165,3 @@ def __str__(self): return ( self.student.f_name + " " + self.student.l_name + ", " + self.position.title ) - diff --git a/placementApp/serializers.py b/placementApp/serializers.py index 5553746..3fd7602 100644 --- a/placementApp/serializers.py +++ b/placementApp/serializers.py @@ -42,7 +42,6 @@ class Meta: ) - class CoordinatorSignupSerializer(serializers.ModelSerializer): password = serializers.CharField( write_only=True, required=True, style={"input_type": "password"}, @@ -61,14 +60,16 @@ class Meta: "password2", ) + class CompanySerializer(serializers.ModelSerializer): class Meta: model = Company fields = "__all__" + class PositionSerializer(serializers.ModelSerializer): company = CompanySerializer() - #company = serializers.PrimaryKeyRelatedField(queryset=Company.objects.all()) + # company = serializers.PrimaryKeyRelatedField(queryset=Company.objects.all()) class Meta: model = Position fields = "__all__" diff --git a/placementApp/urls.py b/placementApp/urls.py index 3bfe948..1e6db84 100644 --- a/placementApp/urls.py +++ b/placementApp/urls.py @@ -3,7 +3,7 @@ from . import views router = routers.DefaultRouter() -router.register("students", views.StudentViewSet, basename='Students') +router.register("students", views.StudentViewSet, basename="Students") router.register("applications", views.ApplicationViewSet) router.register("positions", views.PositionViewSet) router.register("company", views.CompanyViewSet) From 9a08b49d4b86582ce2d4d56e06e2d36cf98c0e24 Mon Sep 17 00:00:00 2001 From: SakshiUppoor Date: Tue, 24 Mar 2020 10:48:33 +0530 Subject: [PATCH 05/10] Merge with upstream --- placementApp/admin.py | 1 + placementApp/serializers.py | 10 +++++++--- placementApp/views.py | 8 ++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/placementApp/admin.py b/placementApp/admin.py index cdc2587..8d51db7 100644 --- a/placementApp/admin.py +++ b/placementApp/admin.py @@ -47,6 +47,7 @@ class PositionAdmin(admin.ModelAdmin): "package", "interview_date", "deadline", + "id", ) search_fields = ("title", "company") diff --git a/placementApp/serializers.py b/placementApp/serializers.py index 3fd7602..032744b 100644 --- a/placementApp/serializers.py +++ b/placementApp/serializers.py @@ -66,10 +66,14 @@ class Meta: model = Company fields = "__all__" - -class PositionSerializer(serializers.ModelSerializer): +class PositionReadSerializer(serializers.ModelSerializer): company = CompanySerializer() - # company = serializers.PrimaryKeyRelatedField(queryset=Company.objects.all()) + class Meta: + model = Position + fields = "__all__" + +class PositionWriteSerializer(serializers.ModelSerializer): + company = serializers.PrimaryKeyRelatedField(queryset=Company.objects.all()) class Meta: model = Position fields = "__all__" diff --git a/placementApp/views.py b/placementApp/views.py index 42601e6..4fee32f 100644 --- a/placementApp/views.py +++ b/placementApp/views.py @@ -1,6 +1,6 @@ from django.shortcuts import HttpResponse from .models import Student, Position, Company, Application -from .serializers import StudentSerializer, PositionSerializer, CompanySerializer +from .serializers import StudentSerializer, PositionReadSerializer, PositionWriteSerializer, CompanySerializer from .serializers import * from django.contrib.auth import get_user_model from django.contrib.auth.hashers import make_password @@ -93,7 +93,11 @@ def perform_create(self, serializer): class PositionViewSet(viewsets.ModelViewSet): permission_classes = (IsStaffOrReadOnly,) queryset = Position.objects.all() - serializer_class = PositionSerializer + def get_serializer_class(self): + if self.action in ['list', 'retrieve']: + return PositionReadSerializer + print("here") + return PositionWriteSerializer class CompanyViewSet(viewsets.ModelViewSet): From d93d931cc9aa99aca36c3d6d7e0de428f573048b Mon Sep 17 00:00:00 2001 From: SakshiUppoor Date: Tue, 24 Mar 2020 15:03:02 +0530 Subject: [PATCH 06/10] Apply black formatting --- placementApp/serializers.py | 4 ++++ placementApp/views.py | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/placementApp/serializers.py b/placementApp/serializers.py index 032744b..84045cd 100644 --- a/placementApp/serializers.py +++ b/placementApp/serializers.py @@ -66,14 +66,18 @@ class Meta: model = Company fields = "__all__" + class PositionReadSerializer(serializers.ModelSerializer): company = CompanySerializer() + class Meta: model = Position fields = "__all__" + class PositionWriteSerializer(serializers.ModelSerializer): company = serializers.PrimaryKeyRelatedField(queryset=Company.objects.all()) + class Meta: model = Position fields = "__all__" diff --git a/placementApp/views.py b/placementApp/views.py index fd60bab..348b320 100644 --- a/placementApp/views.py +++ b/placementApp/views.py @@ -1,6 +1,11 @@ from django.shortcuts import HttpResponse from .models import Student, Position, Company, Application -from .serializers import StudentSerializer, PositionReadSerializer, PositionWriteSerializer, CompanySerializer +from .serializers import ( + StudentSerializer, + PositionReadSerializer, + PositionWriteSerializer, + CompanySerializer, +) from .serializers import * from django.contrib.auth import get_user_model from django.contrib.auth.hashers import make_password @@ -93,12 +98,13 @@ def perform_create(self, serializer): class PositionViewSet(viewsets.ModelViewSet): permission_classes = (IsStaffOrReadOnly,) queryset = Position.objects.all() + def get_serializer_class(self): - if self.action in ['list', 'retrieve']: + if self.action in ["list", "retrieve"]: return PositionReadSerializer - print("here") return PositionWriteSerializer + class CompanyViewSet(viewsets.ModelViewSet): permission_classes = (permissions.IsAuthenticatedOrReadOnly,) queryset = Company.objects.all() From 2758db2184e4c6259e2b6bbd93169480ebfc8f89 Mon Sep 17 00:00:00 2001 From: SakshiUppoor Date: Tue, 24 Mar 2020 15:40:29 +0530 Subject: [PATCH 07/10] Remove token generation functions and override save method --- placementApp/models.py | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/placementApp/models.py b/placementApp/models.py index 091f9ad..88c05b1 100644 --- a/placementApp/models.py +++ b/placementApp/models.py @@ -57,6 +57,10 @@ def __str__(self): objects = MyAccountManager() + def save(self, *args, **kwargs): + self.username = self.email + super(User, self).save(*args, **kwargs) + def __str__(self): return self.email @@ -105,27 +109,6 @@ class Coordinator(User): max_length=5, blank=False, choices=DEPARTMENT_CHOICES_COORD ) - -@receiver(post_save, sender=settings.AUTH_USER_MODEL) -def create_auth_token(sender, instance=None, created=False, **kwargs): - print("hello :)") - if created: - Token.objects.create(user=instance) - - -@receiver(post_save, sender=Coordinator) -def create_auth_token(sender, instance=None, created=False, **kwargs): - print("hello :))") - if created: - Token.objects.create(user=instance) - - -@receiver(post_save, sender=Student) -def create_auth_token(sender, instance=None, created=False, **kwargs): - if created: - Token.objects.create(user=instance) - - class Company(models.Model): name = models.CharField(max_length=128) category = models.CharField(max_length=1, choices=CATEGORY_CHOICES) From 043faacdc65742ee1c834c856f22709010377dde Mon Sep 17 00:00:00 2001 From: SakshiUppoor Date: Thu, 26 Mar 2020 22:00:33 +0530 Subject: [PATCH 08/10] Add permission to CompanyViewSet --- placementApp/models.py | 5 +++-- placementApp/permissions.py | 10 ++++------ placementApp/views.py | 37 +++++++++++++++++++++++-------------- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/placementApp/models.py b/placementApp/models.py index 88c05b1..94368f5 100644 --- a/placementApp/models.py +++ b/placementApp/models.py @@ -57,9 +57,9 @@ def __str__(self): objects = MyAccountManager() - def save(self, *args, **kwargs): + def save(self, *args, **kwargs): self.username = self.email - super(User, self).save(*args, **kwargs) + super(User, self).save(*args, **kwargs) def __str__(self): return self.email @@ -109,6 +109,7 @@ class Coordinator(User): max_length=5, blank=False, choices=DEPARTMENT_CHOICES_COORD ) + class Company(models.Model): name = models.CharField(max_length=128) category = models.CharField(max_length=1, choices=CATEGORY_CHOICES) diff --git a/placementApp/permissions.py b/placementApp/permissions.py index 0b652fb..3593347 100644 --- a/placementApp/permissions.py +++ b/placementApp/permissions.py @@ -3,7 +3,7 @@ # from customer.models import User -class IsStaffOrOwner(BasePermission): +class IsTPOOrOwner(BasePermission): message = "You do not have the permission to perform this action." def has_permission(self, request, view): @@ -12,12 +12,10 @@ def has_permission(self, request, view): return request.user.is_authenticated def has_object_permission(self, request, view, obj): - return ( - request.user.id == obj.id or request.user.is_co() or request.user.is_tpo() - ) + return request.user.id == obj.id or request.user.is_tpo() -class IsStaffOrReadOnly(BasePermission): +class IsTPOOrReadOnly(BasePermission): message = "You do not have the permission to perform this action." def has_permission(self, request, view): @@ -28,4 +26,4 @@ def has_permission(self, request, view): def has_object_permission(self, request, view, obj): if view.action == "retrieve": return True - return request.user.is_co() or request.user.is_tpo() + return request.user.is_tpo() diff --git a/placementApp/views.py b/placementApp/views.py index 348b320..aa8082d 100644 --- a/placementApp/views.py +++ b/placementApp/views.py @@ -1,4 +1,3 @@ -from django.shortcuts import HttpResponse from .models import Student, Position, Company, Application from .serializers import ( StudentSerializer, @@ -7,12 +6,14 @@ CompanySerializer, ) from .serializers import * +from .utils import generate_xls, get_curent_year +from .permissions import IsTPOOrOwner, IsTPOOrReadOnly from django.contrib.auth import get_user_model from django.contrib.auth.hashers import make_password +from django.http import JsonResponse +from django.shortcuts import HttpResponse from rest_framework import viewsets, permissions, status, mixins, generics from rest_framework.response import Response -from .utils import generate_xls, get_curent_year -from .permissions import IsStaffOrOwner, IsStaffOrReadOnly class StudentSignUpView(generics.CreateAPIView): @@ -41,7 +42,7 @@ def create(self, request, *args, **kwargs): class StudentViewSet( mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet, ): - permission_classes = (IsStaffOrOwner,) + permission_classes = (IsTPOOrOwner,) queryset = Student.objects.all() serializer_class = StudentSerializer @@ -96,7 +97,7 @@ def perform_create(self, serializer): class PositionViewSet(viewsets.ModelViewSet): - permission_classes = (IsStaffOrReadOnly,) + permission_classes = (IsTPOOrReadOnly,) queryset = Position.objects.all() def get_serializer_class(self): @@ -106,21 +107,29 @@ def get_serializer_class(self): class CompanyViewSet(viewsets.ModelViewSet): - permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + permission_classes = (IsTPOOrReadOnly,) queryset = Company.objects.all() serializer_class = CompanySerializer def get_xls(request, company_id): - company = Company.objects.get(id=company_id) + if request.user.is_authenticated and ( + request.user.is_tpo() or request.user.is_tpo() + ): + company = Company.objects.get(id=company_id) + + name_of_workbook = company.name + "-" + str(get_curent_year()) + ".xls" + response = HttpResponse(content_type="application/ms-excel") + response["Content-Disposition"] = ( + "attachment; filename=" + '"' + name_of_workbook + '"' + ) - name_of_workbook = company.name + "-" + str(get_curent_year()) + ".xls" - response = HttpResponse(content_type="application/ms-excel") - response["Content-Disposition"] = ( - "attachment; filename=" + '"' + name_of_workbook + '"' - ) + wb = generate_xls(company) + wb.save(response) - wb = generate_xls(company) - wb.save(response) + else: + response = JsonResponse( + {"error": "You do not have the permission to perform this action."} + ) return response From 245e1a7eec3ed8c178e673c8a8db6806d271b762 Mon Sep 17 00:00:00 2001 From: SakshiUppoor Date: Thu, 26 Mar 2020 22:01:35 +0530 Subject: [PATCH 09/10] Add permissions to Excel Sheet Generation View --- placementApp/permissions.py | 10 ++++++++++ placementApp/views.py | 32 ++++++++++++++------------------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/placementApp/permissions.py b/placementApp/permissions.py index 3593347..0aee3aa 100644 --- a/placementApp/permissions.py +++ b/placementApp/permissions.py @@ -27,3 +27,13 @@ def has_object_permission(self, request, view, obj): if view.action == "retrieve": return True return request.user.is_tpo() + + +class IsStaff(BasePermission): + message = "You do not have the permission to perform this action." + + def has_permission(self, request, view): + return request.user.is_co() or request.user.is_tpo() + + def has_object_permission(self, request, view, obj): + return True diff --git a/placementApp/views.py b/placementApp/views.py index aa8082d..bb75dec 100644 --- a/placementApp/views.py +++ b/placementApp/views.py @@ -7,11 +7,12 @@ ) from .serializers import * from .utils import generate_xls, get_curent_year -from .permissions import IsTPOOrOwner, IsTPOOrReadOnly +from .permissions import IsTPOOrOwner, IsTPOOrReadOnly, IsStaff from django.contrib.auth import get_user_model from django.contrib.auth.hashers import make_password from django.http import JsonResponse from django.shortcuts import HttpResponse +from rest_framework.decorators import api_view, permission_classes from rest_framework import viewsets, permissions, status, mixins, generics from rest_framework.response import Response @@ -112,24 +113,19 @@ class CompanyViewSet(viewsets.ModelViewSet): serializer_class = CompanySerializer +@api_view( + ["GET",] +) +@permission_classes((IsStaff,)) def get_xls(request, company_id): - if request.user.is_authenticated and ( - request.user.is_tpo() or request.user.is_tpo() - ): - company = Company.objects.get(id=company_id) - - name_of_workbook = company.name + "-" + str(get_curent_year()) + ".xls" - response = HttpResponse(content_type="application/ms-excel") - response["Content-Disposition"] = ( - "attachment; filename=" + '"' + name_of_workbook + '"' - ) + company = Company.objects.get(id=company_id) - wb = generate_xls(company) - wb.save(response) - - else: - response = JsonResponse( - {"error": "You do not have the permission to perform this action."} - ) + name_of_workbook = company.name + "-" + str(get_curent_year()) + ".xls" + response = HttpResponse(content_type="application/ms-excel") + response["Content-Disposition"] = ( + "attachment; filename=" + '"' + name_of_workbook + '"' + ) + wb = generate_xls(company) + wb.save(response) return response From c5da41a5ced5fdd02ad315a2d39b22e0c0b19d70 Mon Sep 17 00:00:00 2001 From: SakshiUppoor Date: Fri, 27 Mar 2020 13:59:33 +0530 Subject: [PATCH 10/10] Fix unauthorized user error in get_xls --- placementApp/permissions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/placementApp/permissions.py b/placementApp/permissions.py index 0aee3aa..b6e893c 100644 --- a/placementApp/permissions.py +++ b/placementApp/permissions.py @@ -33,7 +33,9 @@ class IsStaff(BasePermission): message = "You do not have the permission to perform this action." def has_permission(self, request, view): - return request.user.is_co() or request.user.is_tpo() + return request.user.is_authenticated and ( + request.user.is_co() or request.user.is_tpo() + ) def has_object_permission(self, request, view, obj): return True