diff --git a/bugheist/urls.py b/bugheist/urls.py index 76e7f59cf..5277689f5 100644 --- a/bugheist/urls.py +++ b/bugheist/urls.py @@ -21,9 +21,8 @@ UploadCreate, InboundParseWebhookView, EachmonthLeaderboardView, - GloalLeaderboardView, + GlobalLeaderboardView, SpecificMonthLeaderboardView, - LeaderboardApiViewSet, IssueView, AllIssuesView, SpecificIssuesView, @@ -57,6 +56,7 @@ UserProfileViewSet, LikeIssueApiView, FlagIssueApiView, + LeaderboardApiViewSet ) from bugheist import settings @@ -281,12 +281,13 @@ re_path(r"^follow/(?P[^/]+)/", website.views.follow_user, name="follow_user"), re_path(r"^all_activity/$", AllIssuesView.as_view(), name="all_activity"), re_path(r"^label_activity/$", SpecificIssuesView.as_view(), name="all_activity"), - re_path(r"^leaderboard/$", GloalLeaderboardView.as_view(), name="leaderboard_global"), + re_path(r"^leaderboard/$", GlobalLeaderboardView.as_view(), name="leaderboard_global"), re_path(r"^leaderboard/monthly/$", SpecificMonthLeaderboardView.as_view(), name="leaderboard_specific_month"), re_path(r"^leaderboard/each-month/$", EachmonthLeaderboardView.as_view(), name="leaderboard_eachmonth"), - re_path(r"^leaderboard/api/$", LeaderboardApiViewSet.as_view(), name="leaderboard_api"), re_path(r"^api/v1/issue/like/(?P\w+)/$", LikeIssueApiView.as_view(), name="like_issue"), re_path(r"^api/v1/issue/flag/(?P\w+)/$", FlagIssueApiView.as_view(), name="flag_issue"), + re_path(r"^api/v1/leaderboard/$",LeaderboardApiViewSet.as_view(),name="leaderboard"), + re_path(r"^scoreboard/$", ScoreboardView.as_view(), name="scoreboard"), re_path(r"^issue/$", IssueCreate.as_view(), name="issue"), re_path( diff --git a/website/api/views.py b/website/api/views.py index 356a0fb17..1b002db4c 100644 --- a/website/api/views.py +++ b/website/api/views.py @@ -1,3 +1,5 @@ +from datetime import datetime + from django.core.mail import send_mail from django.template.loader import render_to_string from django.db.models import Sum @@ -8,6 +10,8 @@ from rest_framework.views import APIView from rest_framework.authentication import TokenAuthentication from rest_framework.permissions import IsAuthenticated +from rest_framework.pagination import PageNumberPagination +from rest_framework.decorators import action from website.models import ( Issue, @@ -26,6 +30,13 @@ IssueScreenshot ) +from website.views import ( + GlobalLeaderboardView, + EachmonthLeaderboardView, + SpecificMonthLeaderboardView, + LeaderboardBase + +) # API's @@ -46,12 +57,21 @@ class UserProfileViewSet(viewsets.ModelViewSet): """ User Profile View Set """ - + authentication_classes = [TokenAuthentication] + permission_classes = [IsAuthenticated] serializer_class = UserProfileSerializer queryset = UserProfile.objects.all() filter_backends = (filters.SearchFilter,) search_fields = ("id", "user__id", "user__username") - http_method_names = ["get", "post", "head"] + http_method_names = ["get", "post", "head","put"] + + def update(self, request, pk,*args, **kwargs): + + if UserProfile.objects.filter(id=pk).first().user != request.user: + return Response("NOT AUTHORIZED",401) + + return super().update(request, *args, **kwargs) + class DomainViewSet(viewsets.ModelViewSet): """ @@ -113,11 +133,11 @@ 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) - issues = [] for issue in page: issues.append(self.get_issue_info(request,issue)) @@ -221,4 +241,95 @@ class UserScoreApiView(APIView): def get(self,request,id,format=None,*args, **kwargs): total_score = Points.objects.filter(user__id=id).annotate(total_score=Sum('score')) - return Response({"total_score":total_score}) \ No newline at end of file + return Response({"total_score":total_score}) + + +class LeaderboardApiViewSet(APIView): + + + def get_queryset(self): + return User.objects.all() + + def filter(self,request,*args,**kwargs): + + paginator = PageNumberPagination() + global_leaderboard = LeaderboardBase() + + month = self.request.query_params.get("month") + year = self.request.query_params.get("year") + + if not year: + return Response("Year not passed",status=400) + + elif isinstance(year,str) and not year.isdigit(): + return Response("Invalid year passed",status=400) + + if month: + + if not month.isdigit(): + return Response("Invalid month passed",status=400) + + try: + date = datetime(int(year),int(month),1) + except: + return Response(f"Invalid month or year passed",status=400) + + queryset = global_leaderboard.get_leaderboard(month,year,api=True) + + page = paginator.paginate_queryset(queryset,request) + return paginator.get_paginated_response(page) + + + + def group_by_month(self,request,*args,**kwargs): + + + global_leaderboard = LeaderboardBase() + + year = self.request.query_params.get("year") + + if not year: year = datetime.now().year + + if isinstance(year,str) and not year.isdigit(): + return Response(f"Invalid query passed | Year:{year}",status=400) + + year = int(year) + + leaderboard = global_leaderboard.monthly_year_leaderboard(year,api=True) + month_winners = [] + + months = ["January","February","March","April","May","June","July","August","September","October","Novermber","December"] + + for month_indx,usr in enumerate(leaderboard): + + + month_winner = {"user":usr,"month":months[month_indx]} + month_winners.append(month_winner) + + return Response(month_winners) + + + + def global_leaderboard(self,request,*args,**kwargs): + + paginator = PageNumberPagination() + global_leaderboard = LeaderboardBase() + + queryset = global_leaderboard.get_leaderboard(api=True) + page = paginator.paginate_queryset(queryset,request) + + return paginator.get_paginated_response(page) + + def get(self,request,format=None,*args,**kwargs): + + filter = request.query_params.get("filter") + group_by_month = request.query_params.get("group_by_month") + + if filter: + return self.filter(request,*args,**kwargs) + + elif group_by_month: + return self.group_by_month(request,*args,**kwargs) + + else: + return self.global_leaderboard(request,*args,**kwargs) \ No newline at end of file diff --git a/website/tests_urls.py b/website/tests_urls.py index 4273db8ad..defc8952a 100644 --- a/website/tests_urls.py +++ b/website/tests_urls.py @@ -37,7 +37,7 @@ def tearDownClass(cls): def test_responses( self, - allowed_http_codes=[200, 302, 405], + allowed_http_codes=[200, 302, 405, 401], credentials={}, default_kwargs={}, ): diff --git a/website/views.py b/website/views.py index 7f82ed770..ace35395b 100644 --- a/website/views.py +++ b/website/views.py @@ -1220,9 +1220,8 @@ def get_leaderboard(self,month=None,year=None,api=False): total_score__gt=0, ) ) - if api: - return data.values('username') + return data.values('username','total_score') return data @@ -1254,12 +1253,18 @@ def monthly_year_leaderboard(self,year,api=False): return monthly_winner -class GloalLeaderboardView(LeaderboardBase,ListView): +class GlobalLeaderboardView(LeaderboardBase,ListView): + + ''' + Returns: All users:score data in descending order + ''' + + model = User template_name = "leaderboard_global.html" def get_context_data(self, *args, **kwargs): - context = super(GloalLeaderboardView, self).get_context_data(*args, **kwargs) + context = super(GlobalLeaderboardView, self).get_context_data(*args, **kwargs) if self.request.user.is_authenticated: context["wallet"] = Wallet.objects.get(user=self.request.user) @@ -1270,7 +1275,7 @@ def get_context_data(self, *args, **kwargs): class EachmonthLeaderboardView(LeaderboardBase,ListView): ''' - gives top user from each month for current year + Returns: Grouped user:score data in months for current year ''' model = User @@ -1308,6 +1313,11 @@ def get_context_data(self, *args, **kwargs): return context class SpecificMonthLeaderboardView(LeaderboardBase,ListView): + + ''' + Returns: leaderboard for filtered month and year requested in the query + ''' + model = User template_name = "leaderboard_specific_month.html" @@ -1335,27 +1345,9 @@ def get_context_data(self, *args, **kwargs): if not (month>=1 and month<=12): raise Http404(f"Invalid query passed | Month:{month}") - - context["leaderboard"] = self.get_leaderboard(month,year,api=False) return context -class LeaderboardApiViewSet(LeaderboardBase,APIView): - - def get(self,request,format=None): - - response = Response({"params":"no params passed [(monthly,bool),(year,int)]"}) - - if request.query_params.get('monthly')=="true": - queryset = self.current_month_leaderboard() - response = Response(queryset,status=200) - - elif request.query_params.get('year'): - queryset = self.monthly_year_leaderboard(year=request.query_params.get('year')) - response = Response(queryset,status=200) - - return response - class ScoreboardView(ListView): model = Domain