From 168827b529fbec4181ca0a3d23eb5009d27a27b4 Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj Date: Fri, 10 May 2024 20:25:48 +0530 Subject: [PATCH 01/11] company id issue resolved --- website/models.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/website/models.py b/website/models.py index e002b42ce..e97018788 100644 --- a/website/models.py +++ b/website/models.py @@ -63,6 +63,11 @@ class Company(models.Model): def __str__(self): return self.name + def save(self, *args, **kwargs): + if not self.company_id: + self.company_id = str(uuid.uuid4()) + super().save(*args, **kwargs) + class Domain(models.Model): company = models.ForeignKey(Company, null=True, blank=True, on_delete=models.CASCADE) From d43ef267d9e248e9b930111f3d603fe09e5af3be Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj <106571927+Uttkarsh-raj@users.noreply.github.com> Date: Sat, 11 May 2024 11:01:42 +0530 Subject: [PATCH 02/11] handling empty string cases Co-authored-by: Arkadii Yakovets --- website/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/models.py b/website/models.py index e97018788..5fdec34be 100644 --- a/website/models.py +++ b/website/models.py @@ -64,7 +64,7 @@ def __str__(self): return self.name def save(self, *args, **kwargs): - if not self.company_id: + if self.company_id is None: self.company_id = str(uuid.uuid4()) super().save(*args, **kwargs) From 66f54d92a8e69ce9ef9fd9096be7f9817c5551a1 Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj Date: Sat, 11 May 2024 11:41:42 +0530 Subject: [PATCH 03/11] removed redundant field company_id --- .../migrations/0091_remove_company_company_id.py | 16 ++++++++++++++++ website/models.py | 10 +++++----- 2 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 website/migrations/0091_remove_company_company_id.py diff --git a/website/migrations/0091_remove_company_company_id.py b/website/migrations/0091_remove_company_company_id.py new file mode 100644 index 000000000..85123f6e8 --- /dev/null +++ b/website/migrations/0091_remove_company_company_id.py @@ -0,0 +1,16 @@ +# Generated by Django 5.0.3 on 2024-05-11 06:07 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("website", "0090_alter_domain_managers"), + ] + + operations = [ + migrations.RemoveField( + model_name="company", + name="company_id", + ), + ] diff --git a/website/models.py b/website/models.py index e97018788..694e78347 100644 --- a/website/models.py +++ b/website/models.py @@ -50,7 +50,7 @@ class Company(models.Model): managers = models.ManyToManyField(User, related_name="user_companies") name = models.CharField(max_length=255) logo = models.ImageField(upload_to="company_logos", null=True, blank=True) - company_id = models.CharField(max_length=255, unique=True, editable=False) # uuid + # company_id = models.CharField(max_length=255, unique=True, editable=False) # uuid url = models.URLField() email = models.EmailField(null=True, blank=True) twitter = models.CharField(max_length=30, null=True, blank=True) @@ -63,10 +63,10 @@ class Company(models.Model): def __str__(self): return self.name - def save(self, *args, **kwargs): - if not self.company_id: - self.company_id = str(uuid.uuid4()) - super().save(*args, **kwargs) + # def save(self, *args, **kwargs): + # if not self.company_id: + # self.company_id = str(uuid.uuid4()) + # super().save(*args, **kwargs) class Domain(models.Model): From 1f53245f072bc1c503167b112f37784a675f32c5 Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj <106571927+Uttkarsh-raj@users.noreply.github.com> Date: Sat, 11 May 2024 11:54:25 +0530 Subject: [PATCH 04/11] company_id field commented Co-authored-by: DonnieBLT <128622481+DonnieBLT@users.noreply.github.com> --- website/models.py | 1 - 1 file changed, 1 deletion(-) diff --git a/website/models.py b/website/models.py index c7f48f0fe..a5c05b6c7 100644 --- a/website/models.py +++ b/website/models.py @@ -50,7 +50,6 @@ class Company(models.Model): managers = models.ManyToManyField(User, related_name="user_companies") name = models.CharField(max_length=255) logo = models.ImageField(upload_to="company_logos", null=True, blank=True) - # company_id = models.CharField(max_length=255, unique=True, editable=False) # uuid url = models.URLField() email = models.EmailField(null=True, blank=True) twitter = models.CharField(max_length=30, null=True, blank=True) From d45c0f8ddfcfe4e8b936d35986d64b32ccdc8b05 Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj Date: Sat, 11 May 2024 22:48:53 +0530 Subject: [PATCH 05/11] get open issues api --- blt/urls.py | 2 ++ website/api/views.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/blt/urls.py b/blt/urls.py index 2d2db89a1..bcd2f7081 100644 --- a/blt/urls.py +++ b/blt/urls.py @@ -27,6 +27,7 @@ IssueViewSet, LeaderboardApiViewSet, LikeIssueApiView, + OpenIssuesViewSet, StatsApiViewset, UrlCheckApiViewset, UserIssueViewSet, @@ -117,6 +118,7 @@ handler500 = "website.views.handler500" urlpatterns = [ + path("open-issues/", OpenIssuesViewSet.as_view({"get": "get"}), name="open-issues"), path("company/", CompanyViewSet.as_view({"get": "list", "post": "create"}), name="company"), path("invite-friend/", website.views.invite_friend, name="invite_friend"), path("referral/", website.views.referral_signup, name="referral_signup"), diff --git a/website/api/views.py b/website/api/views.py index 8fc7048fb..5af9f9dd6 100644 --- a/website/api/views.py +++ b/website/api/views.py @@ -1,9 +1,11 @@ import uuid from datetime import datetime +from json import JSONDecodeError from django.conf import settings from django.contrib.auth.models import AnonymousUser from django.contrib.sites.shortcuts import get_current_site +from django.core.exceptions import ObjectDoesNotExist from django.core.files.storage import default_storage from django.core.mail import send_mail from django.db.models import Q, Sum @@ -617,3 +619,20 @@ class CompanyViewSet(viewsets.ModelViewSet): filter_backends = (filters.SearchFilter,) search_fields = ("id", "name") http_method_names = ("get", "post", "put") + + +class OpenIssuesViewSet(viewsets.ModelViewSet): + queryset = Issue.objects.all() + serializer_class = IssueSerializer + + def get(self, request, *args, **kwargs): + try: + domainUrl = request.GET.get("domain") + domainData = Domain.objects.get(url=domainUrl) + data = Issue.objects.filter(domain=domainData.id, status="open") + serializer = IssueSerializer(data, many=True) + return Response({"count": len(serializer.data), "result": serializer.data}, status=200) + except ObjectDoesNotExist: + return Response({"result": [], "message": "Object does not exist"}, status=404) + except JSONDecodeError: + return Response({"result": "error", "message": "Json decoding error"}, status=400) From 0236cdde562c9532ca1bbd49fbe39c3d4ce32219 Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj Date: Sat, 11 May 2024 22:53:34 +0530 Subject: [PATCH 06/11] get closed issues api --- blt/urls.py | 2 ++ website/api/views.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/blt/urls.py b/blt/urls.py index bcd2f7081..0eed0bc41 100644 --- a/blt/urls.py +++ b/blt/urls.py @@ -20,6 +20,7 @@ from website.api.views import ( BugHuntApiViewset, BugHuntApiViewsetV2, + ClosedIssuesViewSet, CompanyViewSet, DomainViewSet, FlagIssueApiView, @@ -119,6 +120,7 @@ urlpatterns = [ path("open-issues/", OpenIssuesViewSet.as_view({"get": "get"}), name="open-issues"), + path("closed-issues/", ClosedIssuesViewSet.as_view({"get": "get"}), name="closed-issues"), path("company/", CompanyViewSet.as_view({"get": "list", "post": "create"}), name="company"), path("invite-friend/", website.views.invite_friend, name="invite_friend"), path("referral/", website.views.referral_signup, name="referral_signup"), diff --git a/website/api/views.py b/website/api/views.py index 5af9f9dd6..1006b6ee6 100644 --- a/website/api/views.py +++ b/website/api/views.py @@ -636,3 +636,22 @@ def get(self, request, *args, **kwargs): return Response({"result": [], "message": "Object does not exist"}, status=404) except JSONDecodeError: return Response({"result": "error", "message": "Json decoding error"}, status=400) + + +class ClosedIssuesViewSet(viewsets.ModelViewSet): + queryset = Issue.objects.all() + serializer_class = IssueSerializer + + def get(self, request, *args, **kwargs): + try: + domainUrl = request.GET.get("domain") + domainData = Domain.objects.get(url=domainUrl) + data = Issue.objects.filter(domain=domainData.id, status="closed") + serializer = IssueSerializer(data, many=True) + return Response( + {"count": len(serializer.data), "response": serializer.data, "status": 200} + ) + except ObjectDoesNotExist: + return Response({"result": "error", "message": "Domain does not exist"}, status=404) + except JSONDecodeError: + return Response({"result": "error", "message": "Json decoding error"}, status=400) From 17b70321328751f58f84fcbb1f4104905e9c92b9 Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj Date: Sat, 11 May 2024 22:58:39 +0530 Subject: [PATCH 07/11] added 404 as valid test for test_url --- website/tests_urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/tests_urls.py b/website/tests_urls.py index 9f37a4491..43e65b86d 100644 --- a/website/tests_urls.py +++ b/website/tests_urls.py @@ -33,7 +33,7 @@ def tearDownClass(cls): def test_responses( self, - allowed_http_codes=[200, 302, 405, 401], + allowed_http_codes=[200, 302, 405, 401, 404], credentials={}, default_kwargs={}, ): From 66b59b31bd14d524d129401c1720be0157a2d459 Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj Date: Sun, 12 May 2024 12:48:33 +0530 Subject: [PATCH 08/11] made open issues under issues i.e. from /open-issues to issues/open/?domain= --- blt/urls.py | 8 ++++---- website/api/views.py | 33 ++++++++++++++++----------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/blt/urls.py b/blt/urls.py index 0eed0bc41..fbe27decd 100644 --- a/blt/urls.py +++ b/blt/urls.py @@ -20,7 +20,6 @@ from website.api.views import ( BugHuntApiViewset, BugHuntApiViewsetV2, - ClosedIssuesViewSet, CompanyViewSet, DomainViewSet, FlagIssueApiView, @@ -28,7 +27,6 @@ IssueViewSet, LeaderboardApiViewSet, LikeIssueApiView, - OpenIssuesViewSet, StatsApiViewset, UrlCheckApiViewset, UserIssueViewSet, @@ -119,8 +117,10 @@ handler500 = "website.views.handler500" urlpatterns = [ - path("open-issues/", OpenIssuesViewSet.as_view({"get": "get"}), name="open-issues"), - path("closed-issues/", ClosedIssuesViewSet.as_view({"get": "get"}), name="closed-issues"), + path("issues/open/", IssueViewSet.as_view({"get": "get_open_issues"}), name="open-issues"), + path( + "issues/closed/", IssueViewSet.as_view({"get": "get_closed_issues"}), name="closed-issues" + ), path("company/", CompanyViewSet.as_view({"get": "list", "post": "create"}), name="company"), path("invite-friend/", website.views.invite_friend, name="invite_friend"), path("referral/", website.views.referral_signup, name="referral_signup"), diff --git a/website/api/views.py b/website/api/views.py index 1006b6ee6..f7907a00f 100644 --- a/website/api/views.py +++ b/website/api/views.py @@ -209,6 +209,22 @@ def create(self, request, *args, **kwargs): return Response(self.get_issue_info(request, issue)) + @staticmethod + def _get_issue_by_status(domain_url, status): + domain_data = Domain.objects.get(url=domain_url) + data = Issue.objects.filter(domain=domain_data.id, status=status) + serializer = IssueSerializer(data, many=True) + return Response({"count": len(serializer.data), "result": serializer.data}, status=200) + + def get_open_issues(self, request, *args, **kwargs): + try: + domain_url = request.GET.get("domain") + return self._get_issue_by_status(domain_url, "open") + except ObjectDoesNotExist: + return Response({"result": [], "message": "Object does not exist"}, status=404) + except JSONDecodeError: + return Response({"result": "error", "message": "Json decoding error"}, status=400) + class LikeIssueApiView(APIView): authentication_classes = [TokenAuthentication] @@ -621,23 +637,6 @@ class CompanyViewSet(viewsets.ModelViewSet): http_method_names = ("get", "post", "put") -class OpenIssuesViewSet(viewsets.ModelViewSet): - queryset = Issue.objects.all() - serializer_class = IssueSerializer - - def get(self, request, *args, **kwargs): - try: - domainUrl = request.GET.get("domain") - domainData = Domain.objects.get(url=domainUrl) - data = Issue.objects.filter(domain=domainData.id, status="open") - serializer = IssueSerializer(data, many=True) - return Response({"count": len(serializer.data), "result": serializer.data}, status=200) - except ObjectDoesNotExist: - return Response({"result": [], "message": "Object does not exist"}, status=404) - except JSONDecodeError: - return Response({"result": "error", "message": "Json decoding error"}, status=400) - - class ClosedIssuesViewSet(viewsets.ModelViewSet): queryset = Issue.objects.all() serializer_class = IssueSerializer From c43c6e8c1e872bbb2721338802b283ffd1313f3a Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj Date: Mon, 13 May 2024 17:44:48 +0530 Subject: [PATCH 09/11] new endpoint /api/v1/issues/?status=&domain= added --- blt/urls.py | 13 +++++--- website/api/views.py | 75 ++++++++++++++++++-------------------------- 2 files changed, 40 insertions(+), 48 deletions(-) diff --git a/blt/urls.py b/blt/urls.py index fbe27decd..5e51dd30f 100644 --- a/blt/urls.py +++ b/blt/urls.py @@ -117,10 +117,10 @@ handler500 = "website.views.handler500" urlpatterns = [ - path("issues/open/", IssueViewSet.as_view({"get": "get_open_issues"}), name="open-issues"), - path( - "issues/closed/", IssueViewSet.as_view({"get": "get_closed_issues"}), name="closed-issues" - ), + # path("issues/open/", IssueViewSet.as_view({"get": "get_open_issues"}), name="open-issues"), + # path( + # "issues/closed/", IssueViewSet.as_view({"get": "get_closed_issues"}), name="closed-issues" + # ), path("company/", CompanyViewSet.as_view({"get": "list", "post": "create"}), name="company"), path("invite-friend/", website.views.invite_friend, name="invite_friend"), path("referral/", website.views.referral_signup, name="referral_signup"), @@ -513,6 +513,11 @@ ContributorStatsView.as_view(today=True), name="today-contributor-stats", ), + re_path( + r"^api/v1/issues/$", + IssueViewSet.as_view({"get": "list", "post": "create"}), + name="issue_list", + ), ] if settings.DEBUG: diff --git a/website/api/views.py b/website/api/views.py index f7907a00f..e92824a37 100644 --- a/website/api/views.py +++ b/website/api/views.py @@ -1,11 +1,9 @@ import uuid from datetime import datetime -from json import JSONDecodeError from django.conf import settings from django.contrib.auth.models import AnonymousUser from django.contrib.sites.shortcuts import get_current_site -from django.core.exceptions import ObjectDoesNotExist from django.core.files.storage import default_storage from django.core.mail import send_mail from django.db.models import Q, Sum @@ -166,18 +164,42 @@ def get_issue_info(self, request, issue): "screenshots": screenshots, } + @staticmethod + def _get_issue_by_status(domain_url, status): + if domain_url: + try: + domain_data = Domain.objects.get(url=domain_url) + data = Issue.objects.filter(domain=domain_data.id, status=status) + except Domain.DoesNotExist: + return Response({"result": [], "message": "Domain does not exist"}, status=404) + except Issue.DoesNotExist: + return Response({"result": [], "message": "Object does not exist"}, status=404) + else: + data = Issue.objects.filter(status=status) + serializer = IssueSerializer(data, many=True) + return Response({"count": len(serializer.data), "result": serializer.data}, status=200) + def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) - issues = [] - page = self.paginate_queryset(queryset) - if page is None: - return Response(issues) + status = request.GET.get("status") + domain_url = request.GET.get("domain") + match status: + case "open": + return self._get_issue_by_status(domain_url, "open") + + case "closed": + return self._get_issue_by_status(domain_url, "closed") - for issue in page: - issues.append(self.get_issue_info(request, issue)) + case _: + page = self.paginate_queryset(queryset) + if page is None: + return Response(issues) - return self.get_paginated_response(issues) + for issue in page: + issues.append(self.get_issue_info(request, issue)) + + return self.get_paginated_response(issues) def retrieve(self, request, pk, *args, **kwargs): issue = Issue.objects.filter(id=pk).first() @@ -209,22 +231,6 @@ def create(self, request, *args, **kwargs): return Response(self.get_issue_info(request, issue)) - @staticmethod - def _get_issue_by_status(domain_url, status): - domain_data = Domain.objects.get(url=domain_url) - data = Issue.objects.filter(domain=domain_data.id, status=status) - serializer = IssueSerializer(data, many=True) - return Response({"count": len(serializer.data), "result": serializer.data}, status=200) - - def get_open_issues(self, request, *args, **kwargs): - try: - domain_url = request.GET.get("domain") - return self._get_issue_by_status(domain_url, "open") - except ObjectDoesNotExist: - return Response({"result": [], "message": "Object does not exist"}, status=404) - except JSONDecodeError: - return Response({"result": "error", "message": "Json decoding error"}, status=400) - class LikeIssueApiView(APIView): authentication_classes = [TokenAuthentication] @@ -635,22 +641,3 @@ class CompanyViewSet(viewsets.ModelViewSet): filter_backends = (filters.SearchFilter,) search_fields = ("id", "name") http_method_names = ("get", "post", "put") - - -class ClosedIssuesViewSet(viewsets.ModelViewSet): - queryset = Issue.objects.all() - serializer_class = IssueSerializer - - def get(self, request, *args, **kwargs): - try: - domainUrl = request.GET.get("domain") - domainData = Domain.objects.get(url=domainUrl) - data = Issue.objects.filter(domain=domainData.id, status="closed") - serializer = IssueSerializer(data, many=True) - return Response( - {"count": len(serializer.data), "response": serializer.data, "status": 200} - ) - except ObjectDoesNotExist: - return Response({"result": "error", "message": "Domain does not exist"}, status=404) - except JSONDecodeError: - return Response({"result": "error", "message": "Json decoding error"}, status=400) From ab4ca78f2b6c2709ca72730023dc4a41bb919070 Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj Date: Tue, 14 May 2024 12:09:58 +0530 Subject: [PATCH 10/11] added the logic to queryset --- blt/urls.py | 2 +- website/api/views.py | 53 +++++++++++++++----------------------------- 2 files changed, 19 insertions(+), 36 deletions(-) diff --git a/blt/urls.py b/blt/urls.py index 5e51dd30f..eec5131bd 100644 --- a/blt/urls.py +++ b/blt/urls.py @@ -515,7 +515,7 @@ ), re_path( r"^api/v1/issues/$", - IssueViewSet.as_view({"get": "list", "post": "create"}), + IssueViewSet.as_view({"get": "list"}), name="issue_list", ), ] diff --git a/website/api/views.py b/website/api/views.py index e92824a37..804ba52c3 100644 --- a/website/api/views.py +++ b/website/api/views.py @@ -125,10 +125,20 @@ class IssueViewSet(viewsets.ModelViewSet): def get_queryset(self): anonymous_user = self.request.user.is_anonymous user_id = self.request.user.id + status = self.request.GET.get("status") + domain_url = self.request.GET.get("domain") + if anonymous_user: - return Issue.objects.exclude(Q(is_hidden=True)) + queryset = Issue.objects.exclude(Q(is_hidden=True)) else: - return Issue.objects.exclude(Q(is_hidden=True) & ~Q(user_id=user_id)) + queryset = Issue.objects.exclude(Q(is_hidden=True) & ~Q(user_id=user_id)) + + if status: + queryset = queryset.filter(status=status) + if domain_url: + queryset = queryset.filter(domain__url=domain_url) + + return queryset def get_issue_info(self, request, issue): if issue is None: @@ -164,42 +174,15 @@ def get_issue_info(self, request, issue): "screenshots": screenshots, } - @staticmethod - def _get_issue_by_status(domain_url, status): - if domain_url: - try: - domain_data = Domain.objects.get(url=domain_url) - data = Issue.objects.filter(domain=domain_data.id, status=status) - except Domain.DoesNotExist: - return Response({"result": [], "message": "Domain does not exist"}, status=404) - except Issue.DoesNotExist: - return Response({"result": [], "message": "Object does not exist"}, status=404) - else: - data = Issue.objects.filter(status=status) - serializer = IssueSerializer(data, many=True) - return Response({"count": len(serializer.data), "result": serializer.data}, status=200) - def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) issues = [] - status = request.GET.get("status") - domain_url = request.GET.get("domain") - match status: - case "open": - return self._get_issue_by_status(domain_url, "open") - - case "closed": - return self._get_issue_by_status(domain_url, "closed") - - case _: - page = self.paginate_queryset(queryset) - if page is None: - return Response(issues) - - for issue in page: - issues.append(self.get_issue_info(request, issue)) - - return self.get_paginated_response(issues) + page = self.paginate_queryset(queryset) + if page is None: + return Response(issues) + for issue in page: + issues.append(self.get_issue_info(request, issue)) + return self.get_paginated_response(issues) def retrieve(self, request, pk, *args, **kwargs): issue = Issue.objects.filter(id=pk).first() From 773fa1f8b7822511c545a292a83c6b8827530ccf Mon Sep 17 00:00:00 2001 From: Uttkarsh-raj Date: Wed, 15 May 2024 01:17:52 +0530 Subject: [PATCH 11/11] changes made to urls.py --- blt/urls.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/blt/urls.py b/blt/urls.py index 91102cb5e..7c7d8dec3 100644 --- a/blt/urls.py +++ b/blt/urls.py @@ -121,10 +121,6 @@ handler500 = "website.views.handler500" urlpatterns = [ - # path("issues/open/", IssueViewSet.as_view({"get": "get_open_issues"}), name="open-issues"), - # path( - # "issues/closed/", IssueViewSet.as_view({"get": "get_closed_issues"}), name="closed-issues" - # ), path("company/", CompanyViewSet.as_view({"get": "list", "post": "create"}), name="company"), path("invite-friend/", website.views.invite_friend, name="invite_friend"), path("referral/", website.views.referral_signup, name="referral_signup"), @@ -521,11 +517,6 @@ ContributorStatsView.as_view(today=True), name="today-contributor-stats", ), - re_path( - r"^api/v1/issues/$", - IssueViewSet.as_view({"get": "list"}), - name="issue_list", - ), ] if settings.DEBUG: