diff --git a/safeshare/safeshare/settings.py b/safeshare/safeshare/settings.py index 156dd82..80cac0c 100644 --- a/safeshare/safeshare/settings.py +++ b/safeshare/safeshare/settings.py @@ -115,31 +115,31 @@ WSGI_APPLICATION = 'safeshare.wsgi.application' # Database # https://docs.djangoproject.com/en/4.2/ref/settings/#databases -if os.getenv('GITHUB_WORKFLOW'): - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': 'github-actions', - 'USER': 'postgres', - 'PASSWORD': 'postgres', - 'HOST': 'localhost', - 'PORT': '5432' - } - } -else: - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.mysql', - 'NAME': env.str('DB_NAME', 'safeshare'), - 'USER': env.str('DB_USER', 'mariadb'), - 'PASSWORD': env.str('DB_PASSWORD', 'mariadb'), - 'HOST': env.str('DB_HOST', 'localhost'), - 'PORT': env.str('DB_PORT', '3306'), - 'OPTIONS': { - 'init_command': "SET sql_mode='STRICT_TRANS_TABLES', innodb_strict_mode=1", - }, - } - } +# if os.getenv('GITHUB_WORKFLOW'): +# DATABASES = { +# 'default': { +# 'ENGINE': 'django.db.backends.postgresql', +# 'NAME': 'github-actions', +# 'USER': 'postgres', +# 'PASSWORD': 'postgres', +# 'HOST': 'localhost', +# 'PORT': '5432' +# } +# } +# else: +# DATABASES = { +# 'default': { +# 'ENGINE': 'django.db.backends.mysql', +# 'NAME': env.str('DB_NAME', 'safeshare'), +# 'USER': env.str('DB_USER', 'mariadb'), +# 'PASSWORD': env.str('DB_PASSWORD', 'mariadb'), +# 'HOST': env.str('DB_HOST', 'localhost'), +# 'PORT': env.str('DB_PORT', '3306'), +# 'OPTIONS': { +# 'init_command': "SET sql_mode='STRICT_TRANS_TABLES', innodb_strict_mode=1", +# }, +# } +# } if env.bool('CACHE', default=False): CACHES = { diff --git a/safeshare/safeshare_app/post_and_get_file.py b/safeshare/safeshare_app/post_and_get_file.py index 3d11dbd..5f8604d 100644 --- a/safeshare/safeshare_app/post_and_get_file.py +++ b/safeshare/safeshare_app/post_and_get_file.py @@ -1,23 +1,33 @@ import requests import json +import time url = "http://127.0.0.1:8000/api/files/" file = {'file': open('test.text', 'rb')} +data = {'ttl': 2} -r = requests.post(url, files=file) +r = requests.post(url, files=file, data=data) # Print response message print(json.dumps(r.json(), indent=4)) key = r.json()['key'] +# Wait for file to expire +time.sleep(3) + url = "http://127.0.0.1:8000/api/files/" + key + "/" r = requests.get(url) -file = r.json()['file'] +# Print response message +print(json.dumps(r.json(), indent=4)) + +if r.json()['file'] is not None: + file = r.json()['file'] # Change file to bytes -file = bytes(file, 'utf-8') + file = bytes(file, 'utf-8') # Write response('file') to disk -with open('test2.text', 'wb') as f: - f.write(file) + with open('test2.text', 'wb') as f: + f.write(file) + diff --git a/safeshare/safeshare_app/views/file.py b/safeshare/safeshare_app/views/file.py index e1d336d..0f4fe9f 100644 --- a/safeshare/safeshare_app/views/file.py +++ b/safeshare/safeshare_app/views/file.py @@ -1,43 +1,103 @@ import uuid +import threading import redis from django.conf import settings from rest_framework.decorators import api_view from rest_framework.response import Response +from django.core.cache import cache -redis_instance = redis.StrictRedis(host=settings.REDIS_HOST, - port=settings.REDIS_PORT, db=0) +# redis_instance = redis.StrictRedis(host=settings.REDIS_HOST, +# port=settings.REDIS_PORT, db=0) @api_view(['GET', 'POST']) def manage_items(request, *args, **kwargs): if request.method == 'GET': # Not supposed to enumerate all items, so return 405 - return Response({ - 'msg': 'Method not allowed' - }, status=405) + return Response({'msg': 'Method not allowed'}, status=405) if request.method == 'POST': - key = uuid.uuid4().hex - file = request.FILES['file'] - filename = 'file.txt' + # Define a timeout value (in seconds) + timeout = 5 - # Convert file to bytes - file = file.read() - redis_instance.set(key, file) + ttl = request.data['ttl'] - response = { - 'key': key, - 'msg': f"{key} successfully set to {filename}: {file}" - } - return Response(response, 201) + if not ttl: + return Response({'msg': 'TTL not provided'}, status=400) + + try: + # Convert the TTL to an integer + ttl = int(ttl) + + if ttl <= 0: + return Response({'msg': 'TTL must be a positive integer'}, status=400) + except ValueError: + return Response({'msg': 'Invalid TTL format'}, status=400) + + # Define a function to save the file in a thread + def save_file_to_redis(): + key = uuid.uuid4().hex + + file = request.FILES['file'] + if not file: + return Response({'msg': 'No file provided'}, status=400) + + filename = file.name + + # Convert file to bytes + file = file.read() + + # Set with ttl if ttl is provided + cache.set(key, file, timeout=ttl) + + response = { + 'key': key, + 'msg': f"{key} successfully set to {filename}: {file}, with a ttl of {ttl} seconds" + } + + # Store the response in a shared variable + nonlocal saved_response + saved_response = response + + # Create a shared variable to store the response + saved_response = None + + # Create a new thread for the file-saving process + file_saving_thread = threading.Thread(target=save_file_to_redis) + + # Start the file-saving thread + file_saving_thread.start() + + # Use a Timer to add a timeout + timeout_event = threading.Event() + timeout_timer = threading.Timer(timeout, lambda: timeout_event.set()) + + try: + # Start the timer + timeout_timer.start() + + # Wait for the file-saving thread to complete + file_saving_thread.join() + + # Check if the thread completed without a timeout + if not timeout_event.is_set(): + if saved_response: + return Response(saved_response, status=201) + else: + return Response({'msg': 'File saving failed'}, status=500) + else: + return Response({'msg': 'File saving timed out'}, status=500) + finally: + # Always cancel the timer to prevent it from firing after the thread completes + timeout_timer.cancel() @api_view(['GET', 'PUT', 'DELETE']) def manage_item(request, *args, **kwargs): if request.method == 'GET': if kwargs['key']: - value = redis_instance.get(kwargs['key']) + value = cache.get(kwargs['key']) if value: response = { 'key': kwargs['key'], @@ -76,7 +136,7 @@ def manage_item(request, *args, **kwargs): elif request.method == 'DELETE': if kwargs['key']: - result = redis_instance.delete(kwargs['key']) + result = cache.delete(kwargs['key']) if result == 1: response = { 'msg': f"{kwargs['key']} successfully deleted"