-
Notifications
You must be signed in to change notification settings - Fork 979
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix requirements and docker-compose * fix docker compose and dependencies * add sdk and api folder structure * add sdk methods and fix some urls * update models for API * add urls for api * add methods for viewing file, inbox, outbox, getting designation with serializers and minor bug fixes * fix serializers and fix file attachment functionality in forward_file * sync with upstream * add views and fix urls * create file * create file change * fix create_file, without upload_file feature * fix sdk forward_file : accept remarks * add view_history in sdk * add blueprint for draft and archive methods to sdk * fix FileHeaderSerializer to include id * fix empty file upload error * fix inbox outbox methods to return unique ids * fix complete_flag to is_read * fix inbox outbox methods to not show archived * add view_archived method to sdk * add archive_file method to sdk * fix inbox and outbox output and add support for attachments * add draft methods to sdk * fix default values of named params * fix css for filetracking.html * fix fts serializer.py * add dept adding method to sdk * add helper methods to sdk * fix inbox based on SDK * remove track from TabMenu * fix outbox using SDK * fix archive view for SDK * fix Drafts based on SDK * fix the view file functionality in the web app * fix frontend * fix .gitignore to untrack migrations * fix 1. order of files in inbox and outbox 2. order of files is mantained in uniqueList function * fix login required on viewing file * fix create_file method so that subject and description are also accepted * add rest api for create file and view file * add rest api for create, view and delete file * add rest api for inbox, outbox, history view * add rest api for draft view, forward file * prevent student access of the filetracking module * add dropdown filtering based on reciever username and update notallowed template * add option to unarchive files * fix template for filetrackingnotallowed page * fix attachments view in the history of the file * make the fields in draft view editable * update the views --------- Co-authored-by: Aragorn-64 <[email protected]> Co-authored-by: aish0749 <[email protected]>
- Loading branch information
1 parent
ee8f6be
commit 4962f02
Showing
30 changed files
with
1,915 additions
and
640 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,3 +72,6 @@ node_modules/ | |
|
||
FusionIIIT/static/ | ||
package-lock.json | ||
|
||
# migrations | ||
migrations/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from applications.filetracking.models import File, Tracking | ||
from django.core.files import File as DjangoFile | ||
from rest_framework import serializers | ||
|
||
|
||
class FileSerializer(serializers.ModelSerializer): | ||
class Meta: | ||
model = File | ||
fields = '__all__' | ||
|
||
|
||
class TrackingSerializer(serializers.ModelSerializer): | ||
class Meta: | ||
model = Tracking | ||
fields = '__all__' | ||
|
||
|
||
class FileHeaderSerializer(serializers.ModelSerializer): | ||
''' | ||
This serializes everything except the attachments of a file and whether it is read or not | ||
''' | ||
class Meta: | ||
model = File | ||
exclude = ['upload_file', 'is_read'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from django.conf.urls import url | ||
from .views import ( | ||
CreateFileView, | ||
ViewFileView, | ||
ViewInboxView, | ||
ViewOutboxView, | ||
ViewHistoryView, | ||
ForwardFileView, | ||
DraftFileView, | ||
CreateDraftFile, | ||
GetDesignationsView, | ||
) | ||
|
||
urlpatterns = [ | ||
url(r'^file/$', CreateFileView.as_view(), name='create_file'), | ||
url(r'^file/(?P<file_id>\d+)/$', ViewFileView.as_view(), name='view_file'), | ||
url(r'^inbox/$', ViewInboxView.as_view(), name='view_inbox'), | ||
url(r'^outbox/$', ViewOutboxView.as_view(), name='view_outbox'), | ||
url(r'^history/(?P<file_id>\d+)/$', ViewHistoryView.as_view(), name='view_history'), | ||
url(r'^forwardfile/(?P<file_id>\d+)/$', ForwardFileView.as_view(), name='forward_file'), | ||
url(r'^draft/$', DraftFileView.as_view(), name='view_drafts'), | ||
url(r'^createdraft/$', CreateDraftFile.as_view(), name='create_draft'), | ||
url(r'^designations/(?P<username>\w+)/$', GetDesignationsView.as_view(), name='get_designations'), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
import logging | ||
from venv import logger | ||
from django.forms import ValidationError | ||
from rest_framework.views import APIView | ||
from rest_framework.response import Response | ||
from rest_framework import status, permissions | ||
from rest_framework.authentication import TokenAuthentication | ||
from ..models import File, Tracking | ||
from ..sdk.methods import create_draft, create_file, view_drafts, view_file, delete_file, view_inbox, view_outbox, view_history, forward_file, get_designations | ||
|
||
class CreateFileView(APIView): | ||
authentication_classes = [TokenAuthentication] | ||
permission_classes = [permissions.IsAuthenticated] | ||
|
||
def post(self, request): | ||
try: | ||
current_user = request.user.username | ||
current_designation = request.data.get('designation') | ||
receiver_username = request.data.get('receiver_username') | ||
receiver_designation = request.data.get('receiver_designation') | ||
subject = request.data.get('subject') | ||
description = request.data.get('description') | ||
|
||
if None in [current_designation, receiver_username, receiver_designation, subject, description]: | ||
return Response({'error': 'One or more required fields are missing.'}, status=status.HTTP_400_BAD_REQUEST) | ||
|
||
file_id = create_file(uploader=current_user, uploader_designation=current_designation, | ||
receiver=receiver_username, receiver_designation=receiver_designation, subject=subject, description=description) | ||
|
||
return Response({'file_id': file_id}, status=status.HTTP_201_CREATED) | ||
except Exception as e: | ||
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) | ||
|
||
|
||
class ViewFileView(APIView): | ||
authentication_classes = [TokenAuthentication] | ||
permission_classes = [permissions.IsAuthenticated] | ||
|
||
def get(self, request, file_id): | ||
try: | ||
file_details = view_file(int(file_id)) | ||
# print(file_details) | ||
return Response(file_details, status=status.HTTP_200_OK) | ||
except ValueError: | ||
return Response({'error': 'Invalid file ID format.'}, status=status.HTTP_400_BAD_REQUEST) | ||
except File.DoesNotExist: | ||
return Response({'error': 'File not found.'}, status=status.HTTP_404_NOT_FOUND) | ||
except Exception as e: | ||
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) | ||
|
||
def delete(self, request, file_id): | ||
try: | ||
# file_details = view_file(int(file_id)) | ||
# print(file_details) | ||
success = delete_file(int(file_id)) | ||
if success: | ||
return Response({'message': 'File deleted successfully'}, | ||
status=status.HTTP_204_NO_CONTENT) | ||
else : | ||
return | ||
|
||
except ValueError: | ||
return Response({'error': 'Invalid file ID format'}, | ||
status=status.HTTP_400_BAD_REQUEST) | ||
except File.DoesNotExist: | ||
return Response({'error': 'File not found'}, | ||
status=status.HTTP_404_NOT_FOUND) | ||
except ValidationError as e: | ||
return Response(e.detail, status=status.HTTP_400_BAD_REQUEST) # Handle ValidationError specifically | ||
except Exception as e: # Catch unexpected errors | ||
logger.error(f"Unexpected error in DeleteFileView: {e}") | ||
return Response({'error': 'An internal server error occurred'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) | ||
|
||
|
||
class ViewInboxView(APIView): | ||
authentication_classes = [TokenAuthentication] | ||
permission_classes = [permissions.IsAuthenticated] | ||
|
||
def get(self, request): | ||
""" | ||
API endpoint to view inbox files. | ||
Expects query parameters: | ||
- username (required): User requesting the inbox. | ||
- designation (optional): Designation to filter files by. | ||
- src_module (required): Source module to filter files by. | ||
Returns: | ||
JSON response containing a list of serialized file data, including sender information. | ||
""" | ||
|
||
username = request.query_params.get('username') | ||
designation = request.query_params.get('designation') | ||
src_module = request.query_params.get('src_module') | ||
|
||
|
||
# if not username or not src_module: | ||
# return Response({'error': 'Missing required query parameters: username and src_module.'}, status=400) | ||
|
||
inbox_files = view_inbox(username, designation, src_module) | ||
return Response(inbox_files) | ||
|
||
class ViewOutboxView(APIView): | ||
authentication_classes = [TokenAuthentication] | ||
permission_classes = [permissions.IsAuthenticated] | ||
|
||
|
||
def get(self, request): | ||
""" | ||
API endpoint to view outbox files. | ||
Expects query parameters: | ||
- username (required): User requesting the outbox. | ||
- designation (optional): Designation to filter files by. | ||
- src_module (required): Source module to filter files by. | ||
Returns: | ||
JSON response containing a paginated list of serialized file data. | ||
""" | ||
|
||
username = request.query_params.get('username') | ||
designation = request.query_params.get('designation') | ||
src_module = request.query_params.get('src_module') | ||
|
||
|
||
if not username or not src_module: | ||
return Response({'error': 'Missing required query parameters: username and src_module.'}, status=400) | ||
|
||
outbox_files = view_outbox(username, designation, src_module) | ||
return Response(outbox_files) | ||
|
||
|
||
class ViewHistoryView(APIView): | ||
authentication_classes = [TokenAuthentication] | ||
permission_classes = [permissions.IsAuthenticated] | ||
|
||
def get(self, request, file_id): | ||
""" | ||
View history of a particular file with the given file_id. | ||
Args: | ||
request (rest_framework.request.Request): The incoming request object. | ||
file_id (int): Primary key of the file to retrieve history for. | ||
Returns: | ||
rest_framework.response.Response: JSON response containing serialized tracking history. | ||
""" | ||
|
||
try: | ||
history = view_history(file_id) | ||
return Response(history) | ||
except Tracking.DoesNotExist: | ||
return Response({'error': f'File with ID {file_id} not found.'}, status=404) | ||
except Exception as e: | ||
logger.error(f"An unexpected error occurred: {e}") | ||
return Response({'error': 'Internal server error.'}, status=500) | ||
|
||
class ForwardFileView(APIView): | ||
# # # Authentication and permission classes (adjust based on your needs) | ||
authentication_classes = [TokenAuthentication] | ||
permission_classes = [permissions.IsAuthenticated] | ||
|
||
def post(self, request, file_id): | ||
# # Extract data from request.data | ||
receiver = request.data.get('receiver') | ||
receiver_designation = request.data.get('receiver_designation') | ||
file_extra_JSON = request.data.get('file_extra_JSON', {}) | ||
remarks = request.data.get('remarks', "") | ||
|
||
# Validate data | ||
if not receiver or not receiver_designation: | ||
raise ValidationError("Missing required fields: receiver and receiver_designation") | ||
|
||
# # Extract and validate file attachment (if present) | ||
file_attachment = request.FILES.get('file_attachment') | ||
if file_attachment: | ||
if file_attachment.size > 10 * 1024 * 1024: # Adjust size limit as needed | ||
raise ValidationError("File size exceeds limit (10 MB)") | ||
|
||
# Call forward_file function | ||
try: | ||
new_tracking_id = forward_file( | ||
int(file_id), | ||
receiver, | ||
receiver_designation, | ||
file_extra_JSON, | ||
remarks, | ||
file_attachment | ||
) | ||
logging.info(f"Successfully forwarded file {file_id} with tracking ID: {new_tracking_id}") | ||
except Exception as e: | ||
logging.error(f"Error forwarding file {file_id}: {str(e)}") | ||
raise ValidationError(str(e)) # Re-raise exception with a user-friendly message | ||
|
||
# Return response | ||
return Response({'tracking_id': new_tracking_id}, status=status.HTTP_201_CREATED) | ||
|
||
class CreateDraftFile(APIView): | ||
authentication_classes = [TokenAuthentication] | ||
permission_classes = [permissions.IsAuthenticated] | ||
|
||
def post(self, request): | ||
uploader = request.data.get('uploader') | ||
uploader_designation = request.data.get('uploader_designation') | ||
src_module = request.data.get('src_module', 'filetracking') | ||
src_object_id = request.data.get('src_object_id', '') | ||
file_extra_JSON = request.data.get('file_extra_JSON', {}) | ||
attached_file = request.FILES.get('attached_file', None) | ||
|
||
try: | ||
file_id = create_draft( | ||
uploader=uploader, | ||
uploader_designation=uploader_designation, | ||
src_module=src_module, | ||
src_object_id=src_object_id, | ||
file_extra_JSON=file_extra_JSON, | ||
attached_file=attached_file | ||
) | ||
return Response({'file_id': file_id}, status=status.HTTP_201_CREATED) | ||
except Exception as e: | ||
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) | ||
|
||
class DraftFileView(APIView): | ||
authentication_classes = [TokenAuthentication] | ||
permission_classes = [permissions.IsAuthenticated] | ||
|
||
def get(self, request): | ||
username = request.query_params.get('username') | ||
designation = request.query_params.get('designation') | ||
src_module = request.query_params.get('src_module') | ||
|
||
try: | ||
draft_files = view_drafts(username, designation, src_module) | ||
print(draft_files) | ||
return Response(draft_files, status=status.HTTP_200_OK) | ||
except Exception as e: | ||
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) | ||
|
||
|
||
|
||
class GetDesignationsView(APIView): | ||
#authentication_classes = [TokenAuthentication] | ||
#permission_classes = [permissions.IsAuthenticated] | ||
|
||
def get(self, request, username, *args, **kwargs): | ||
user_designations = get_designations(username) | ||
return Response({'designations': user_designations}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from django.shortcuts import render, get_object_or_404 | ||
from django.contrib.auth.models import User | ||
from applications.globals.models import ExtraInfo, HoldsDesignation | ||
|
||
|
||
def user_check(request): | ||
""" | ||
This function is used to check if the user is a student or not. | ||
Its return type is bool. | ||
@param: | ||
request - contains metadata about the requested page | ||
@Variables: | ||
current_user - get user from request | ||
user_details - extract details of the user from the database | ||
desig_id - check for designation | ||
student - designation for a student | ||
final_user - final designation of the request(our user) | ||
""" | ||
try: | ||
current_user = get_object_or_404(User, username=request.user.username) | ||
user_details = ExtraInfo.objects.select_related('user','department').get(user=request.user) | ||
des = HoldsDesignation.objects.all().select_related().filter(user=request.user).first() | ||
if str(des.designation) == "student": | ||
return True | ||
else: | ||
return False | ||
except Exception as e: | ||
return False | ||
|
||
def user_is_student(view_func): | ||
def _wrapped_view(request, *args, **kwargs): | ||
if user_check(request): | ||
return render(request, 'filetracking/fileTrackingNotAllowed.html') | ||
else: | ||
return view_func(request, *args, **kwargs) | ||
return _wrapped_view | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.