Compare commits

...

4 Commits

Author SHA1 Message Date
Benjamin Loh a7c11477af updated readme
updated readme
2023-11-07 20:41:06 +08:00
Benjamin Loh 8e6c5789ef removed redundant yaml files
removed redundant yaml files
2023-11-07 20:22:22 +08:00
Devoalda 372825d662 fix(File save update):
Updated file saved to use uuid instead of original filename
Updated Download to use the original filename
2023-11-02 10:16:06 +08:00
Devoalda a5e409c2fd Updated Readme 2023-11-01 16:00:42 +08:00
4 changed files with 57 additions and 64 deletions

View File

@ -35,6 +35,23 @@ docker-compose up
```
### Running Backend & Frontend Separately (Docker + Kubernetes)
### Prerequisites
Before you begin, make sure you have:
- A Kubernetes cluster up and running.
- `kubectl` installed and configured to communicate with your cluster.
- Proper permissions to create Deployments, Services, Persistent Volumes, and other Kubernetes resources.
### Overview of Components
- `frontend_deployment.yaml`: Deployment for the SafeShare frontend.
- `frontend_service.yaml`: Service exposing the SafeShare frontend.
- `backend_deployment.yaml`: Deployment for the SafeShare backend.
- `backend_service.yaml`: Service exposing the SafeShare backend.
- `redis_deployment.yaml`: Setup for Redis with persistent storage.
```bash
# Run frontend using docker-compose
docker compose -f docker-compose-frontend.yml up -d
@ -112,3 +129,15 @@ The files are deleted after a certain period of time (ttl).
The time period can be set in the `.env` file. (`TRASH_TIMEOUT`)
This service will periodically check redis for the files that have expired and delete them from the server's storage.
## Test Files
Theoretically, the application can handle any type of file. However, we have tested the application with the following file types:
- Text-based `.txt`, `.py`, etc.
- Image-based `.png`, `.jpg`, etc.
- Video-based `.mp4`, etc.
- Executable `.exe`, etc.
The Virus file used for testing is generated with [metasploit](https://www.metasploit.com/) (msfvenom). ([VirusTotal Report](https://www.virustotal.com/gui/file/2fd0c13298f99d5ae10765ef65e1667e205e932376396d92e4343468abe0c541/detection))
It is a simple reverse shell payload that connects to the attacker's machine, Harmless since it is not connected to the attacker's machine. But **DO NOT** run it on your machine.

View File

@ -1,30 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: safeshare-frontend
labels:
app: safeshare
tier: frontend
spec:
replicas: 1
selector:
matchLabels:
app: safeshare
tier: frontend
template:
metadata:
labels:
app: safeshare
tier: frontend
spec:
containers:
- name: safeshare-frontend
image: amusement3004/safeshare-frontend
imagePullPolicy: IfNotPresent
env: # Add these environment variables
- name: REACT_APP_API_HOST
value: safeshare-backend-service # The name of the backend service
- name: REACT_APP_API_PORT
value: "8000" # The port the backend service listens on
ports:
- containerPort: 3000

View File

@ -1,15 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: safeshare-frontend-service
labels:
app: safeshare
tier: frontend
spec:
type: NodePort
ports:
- port: 3000
nodePort: 32000 # Optional: This is an example. Kubernetes will assign an available port if you don't specify this.
selector:
app: safeshare
tier: frontend

View File

@ -65,9 +65,9 @@ class ManageItemsView(APIView):
timeout_timer.cancel()
def _save_file(self, file, ttl, responses):
key = uuid.uuid4().hex
filename = file.name
save_path = os.path.join(settings.MEDIA_ROOT, filename)
generated_uuid = uuid.uuid4().hex # Generate a UUID
filename = file.name # Get the original filename
save_path = os.path.join(settings.MEDIA_ROOT, generated_uuid) # Use the UUID as the new filename
hasher = hashlib.sha256()
with open(save_path, 'wb') as destination:
@ -103,21 +103,22 @@ class ManageItemsView(APIView):
logger.warning(f'Error detecting MIME type: {str(e)}')
mime_type = 'application/octet-stream'
# Store the file path, filename, MIME type, and other information in the cache
cache.set(key, {
'filename': filename,
# Store the file path, generated UUID, original filename, MIME type, and other information in the cache
cache.set(generated_uuid, {
'filename': filename, # Original filename
'generated_uuid': generated_uuid, # Generated UUID
'path': save_path,
'mime_type': mime_type, # Store the MIME type
'mime_type': mime_type,
}, timeout=ttl)
response = {
'key': key,
'filename': filename,
'mime_type': mime_type, # Include the MIME type in the response
'msg': f"{key} successfully set to {filename} with TTL {ttl} seconds",
'key': generated_uuid, # Return the generated UUID
'filename': filename, # Return the original filename
'mime_type': mime_type,
'msg': f"{generated_uuid} successfully set to {filename} with TTL {ttl} seconds",
}
responses.append(response)
logger.info(f'File {filename} successfully saved to cache with key {key} and TTL {ttl} seconds')
logger.info(f'File {filename} successfully saved to cache with key {generated_uuid} and TTL {ttl} seconds')
class ManageItemView(APIView):
@ -147,7 +148,8 @@ class ManageItemView(APIView):
response = HttpResponse(file_data, content_type=mime_type)
# Set the Content-Disposition with the original filename
response['Content-Disposition'] = f'attachment; filename="{quote(os.path.basename(file_path))}"'
original_filename = value.get('filename', 'file') # Get the original filename from the cache
response['Content-Disposition'] = f'attachment; filename="{quote(original_filename)}"'
logger.info(f'File {file_path} successfully retrieved from cache with key {key}')
return response
@ -174,7 +176,13 @@ PRIVATE_IPS_PREFIX = ('10.', '172.', '192.')
def get_client_ip(request):
"""
Get Client's IP
Get the client's IP address from the request.
This function extracts the client's IP address from various request headers,
taking into account possible proxy servers.
:param request: The HTTP request object.
:return: The client's IP address.
"""
remote_address = request.META.get('HTTP_X_FORWARDED_FOR') or request.META.get('REMOTE_ADDR')
ip = remote_address
@ -183,8 +191,9 @@ def get_client_ip(request):
if x_forwarded_for:
proxies = x_forwarded_for.split(',')
while len(proxies) > 0 and proxies[0].startswith(PRIVATE_IPS_PREFIX):
while proxies and proxies[0].startswith(PRIVATE_IPS_PREFIX):
proxies.pop(0)
if len(proxies) > 0:
if proxies:
ip = proxies[0]
return ip