Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mplement Time and Activity Logging Endpoints #2623

Merged
merged 1 commit into from
Aug 11, 2024
Merged
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
4 changes: 4 additions & 0 deletions blt/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from blt import settings
from company.views import ShowBughuntView
from website.api.views import (
ActivityLogViewSet,
AuthApiViewset,
BugHuntApiViewset,
BugHuntApiViewsetV2,
Expand All @@ -31,6 +32,7 @@
ProjectViewSet,
StatsApiViewset,
TagApiViewset,
TimeLogViewSet,
UrlCheckApiViewset,
UserIssueViewSet,
UserProfileViewSet,
Expand Down Expand Up @@ -105,6 +107,8 @@
router.register(r"userissues", UserIssueViewSet, basename="userissues")
router.register(r"profile", UserProfileViewSet, basename="profile")
router.register(r"domain", DomainViewSet, basename="domain")
router.register(r"timelogs", TimeLogViewSet, basename="timelogs")
router.register(r"activitylogs", ActivityLogViewSet, basename="activitylogs")

from allauth.socialaccount.providers.facebook import views as facebook_views
from allauth.socialaccount.providers.github import views as github_views
Expand Down
78 changes: 78 additions & 0 deletions website/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@

from django.conf import settings
from django.contrib.sites.shortcuts import get_current_site
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.files.storage import default_storage
from django.core.mail import send_mail
from django.db.models import Count, Q, Sum
from django.template.loader import render_to_string
from django.utils import timezone
from django.utils.text import slugify
from rest_framework import filters, status, viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.decorators import action
from rest_framework.exceptions import NotFound, ParseError
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import AllowAny, IsAuthenticated, IsAuthenticatedOrReadOnly
from rest_framework.response import Response
from rest_framework.views import APIView

from website.models import (
ActivityLog,
Company,
Contributor,
Domain,
Expand All @@ -27,11 +32,13 @@
Points,
Project,
Tag,
TimeLog,
Token,
User,
UserProfile,
)
from website.serializers import (
ActivityLogSerializer,
BugHuntPrizeSerializer,
BugHuntSerializer,
CompanySerializer,
Expand All @@ -40,6 +47,7 @@
IssueSerializer,
ProjectSerializer,
TagSerializer,
TimeLogSerializer,
UserProfileSerializer,
)
from website.views import LeaderboardBase, image_validator
Expand Down Expand Up @@ -735,3 +743,73 @@
class TagApiViewset(viewsets.ModelViewSet):
queryset = Tag.objects.all()
serializer_class = TagSerializer


class TimeLogViewSet(viewsets.ModelViewSet):
queryset = TimeLog.objects.all()
serializer_class = TimeLogSerializer
permission_classes = [IsAuthenticated]

def perform_create(self, serializer):
try:
serializer.save(user=self.request.user)
except ValidationError as e:
raise ParseError(detail=str(e))

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.
except Exception as e:
raise ParseError(detail="An unexpected error occurred while creating the time log.")

@action(detail=False, methods=["post"])
def start(self, request):
"""Starts a new time log"""
data = request.data
data["start_time"] = timezone.now() # Set start time to current tim

serializer = self.get_serializer(data=data)
try:
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
return Response(serializer.data, status=status.HTTP_201_CREATED)
except ValidationError as e:
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.
except Exception as e:
return Response(
{"detail": "An unexpected error occurred while starting the time log."},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)

@action(detail=True, methods=["post"])
def stop(self, request, pk=None):
"""Stops the time log and calculates duration"""
try:
timelog = self.get_object()
except ObjectDoesNotExist:
raise NotFound(detail="Time log not found.")

timelog.end_time = timezone.now()
if timelog.start_time:
timelog.duration = timelog.end_time - timelog.start_time

try:
timelog.save()
return Response(TimeLogSerializer(timelog).data, status=status.HTTP_200_OK)
except ValidationError as e:
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.
except Exception as e:
return Response(
{"detail": "An unexpected error occurred while stopping the time log."},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)


class ActivityLogViewSet(viewsets.ModelViewSet):
queryset = ActivityLog.objects.all()
serializer_class = ActivityLogSerializer
permission_classes = [IsAuthenticated]

def perform_create(self, serializer):
try:
serializer.save(user=self.request.user, recorded_at=timezone.now())
except ValidationError as e:
raise ParseError(detail=str(e))

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.
except Exception as e:
raise ParseError(detail="An unexpected error occurred while creating the activity log.")
22 changes: 22 additions & 0 deletions website/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from rest_framework import serializers

from website.models import (
ActivityLog,
Company,
Contributor,
Domain,
Expand All @@ -11,6 +12,7 @@
Points,
Project,
Tag,
TimeLog,
User,
UserProfile,
)
Expand Down Expand Up @@ -125,3 +127,23 @@ class ContributorSerializer(serializers.ModelSerializer):
class Meta:
model = Contributor
fields = "__all__"


class TimeLogSerializer(serializers.ModelSerializer):
class Meta:
model = TimeLog
fields = ["id", "user", "start_time", "end_time", "duration", "github_issue_url", "created"]
read_only_fields = [
"id",
"user",
"end_time",
"duration",
"created",
] # These fields will be managed automatically


class ActivityLogSerializer(serializers.ModelSerializer):
class Meta:
model = ActivityLog
fields = ["id", "user", "window_title", "url", "recorded_at", "created"]
read_only_fields = ["id", "user", "recorded_at", "created"] # Auto-filled fields
Loading