Skip to content

Commit 512d011

Browse files
authored
Merge pull request #4 from ravin-d-27/ravin
Modified Views.py for security
2 parents ef64fb4 + ef17ba0 commit 512d011

File tree

6 files changed

+103
-45
lines changed

6 files changed

+103
-45
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.0 on 2024-01-25 04:18
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('files', '0002_uploadedfile_notes'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='uploadedfile',
15+
name='hashed_file_id',
16+
field=models.CharField(blank=True, max_length=128, null=True),
17+
),
18+
]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Generated by Django 5.0 on 2024-01-25 04:25
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('files', '0003_uploadedfile_hashed_file_id'),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name='uploadedfile',
15+
name='hashed_file_id',
16+
),
17+
migrations.AddField(
18+
model_name='uploadedfile',
19+
name='unique_token',
20+
field=models.CharField(blank=True, max_length=32, unique=True),
21+
),
22+
]

File_Server/files/models.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
# files/models.py
2-
32
from django.db import models
43
from django.contrib.auth.models import User
4+
from django.contrib.auth.hashers import make_password
5+
import secrets
56

67
class UploadedFile(models.Model):
78
user = models.ForeignKey(User, on_delete=models.CASCADE)
89
file = models.FileField(upload_to='uploads/')
910
uploaded_at = models.DateTimeField(auto_now_add=True)
1011
notes = models.TextField(blank=True)
12+
13+
# Add a new field to store the unique token
14+
unique_token = models.CharField(max_length=32, unique=True, blank=True)
15+
16+
def save(self, *args, **kwargs):
17+
# Generate a unique token for the file
18+
if not self.unique_token:
19+
self.unique_token = secrets.token_urlsafe(16)
20+
super().save(*args, **kwargs)
1121

1222
def __str__(self):
13-
return f"{self.user.username} - {self.file.name}"
23+
return f"{self.user.username} - {self.file.name}"

File_Server/files/templates/files/file_list.html

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,28 @@ <h4 class="my-0 fw-normal"><b>{{ file.file.name|slice:"8:" }}</b></h4>
6767
<li><b>Note: </b>{{ file.notes }}</li>
6868
</ul>
6969

70-
<a href="{% url 'files:share_file' file_id=file.id %}" class="btn btn-primary" id='view' target="_blank">Share File Link</a>
71-
<a href="{% url 'files:download_file' file_id=file.id %}" class="btn btn-success" id='download'>Download File</a>
72-
<a href="{% url 'files:view_file' file_id=file.id %}" class="btn btn-warning" id='view' target="_blank">View File</a>
73-
<a class="btn btn-danger" id='delete' onclick="raise_alerts({{file.id}})">Delete File</a>
70+
<a href="{% url 'files:share_file' unique_token=file.unique_token %}" class="btn btn-primary" id='view' target="_blank">Share File Link</a>
71+
<a href="{% url 'files:download_file' unique_token=file.unique_token %}" class="btn btn-success" id='download'>Download File</a>
72+
<a href="{% url 'files:view_file' unique_token=file.unique_token %}" class="btn btn-warning" id='view' target="_blank">View File</a>
73+
<a class="btn btn-danger" id='delete' href="{% url 'files:delete_file' unique_token=file.unique_token %}">Delete File</a>
74+
7475
</div>
7576
</div>
7677
</div>
7778

7879
<script>
79-
function raise_alerts(file_id)
80-
{
81-
yes = confirm("Are you sure you want to delete this file?");
82-
83-
if (yes == true)
84-
{
85-
window.location.replace("{% url 'files:delete_file' file_id=file.id %}".replace('file.id', 'file_id)'));
86-
alert("File deleted successfully");
87-
}
88-
else
89-
{
90-
alert("File not deleted");
91-
}
92-
}
80+
function raise_alerts(file_id) {
81+
yes = confirm("Are you sure you want to delete this file?");
82+
83+
if (yes == true) {
84+
// Replace 'file.id' with the actual value of the file_id variable
85+
window.location.replace("{% url 'files:delete_file' unique_token='" + file_id + "' %}");
86+
87+
alert("File deleted successfully");
88+
} else {
89+
alert("File not deleted");
90+
}
91+
}
9392
</script>
9493
{% endfor %}
9594
</div>

File_Server/files/urls.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
# files/urls.py
2-
32
from django.urls import path
43
from .views import file_list, upload_file, download_file, delete_file, view_file, share_file
54

65
app_name= 'files'
76
urlpatterns = [
87
path('', file_list, name='file_list'),
98
path('upload/', upload_file, name='upload_file'),
10-
path('download/<int:file_id>/', download_file, name='download_file'),
11-
path('delete/<int:file_id>/', delete_file, name='delete_file'),
12-
path('view_file/<int:file_id>/', view_file, name='view_file'),
13-
path('share_file/<int:file_id>/', share_file, name='share_file'),
9+
path('download/<str:unique_token>/', download_file, name='download_file'),
10+
path('delete/<str:unique_token>/', delete_file, name='delete_file'),
11+
path('view_file/<str:unique_token>/', view_file, name='view_file'),
12+
path('share_file/<str:unique_token>/', share_file, name='share_file'),
1413
]

File_Server/files/views.py

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
# files/views.py
2-
3-
from django.shortcuts import render, redirect, get_object_or_404
4-
from django.http import HttpResponse
51
from django.contrib.auth.decorators import login_required
2+
from django.http import HttpResponse, FileResponse
3+
from django.shortcuts import render, redirect, get_object_or_404
4+
from django.contrib.auth.hashers import make_password
65
from .models import UploadedFile
76
from .forms import FileUploadForm
87
from storages.backends.s3boto3 import S3Boto3Storage
@@ -27,46 +26,57 @@ def upload_file(request):
2726
return render(request, 'files/upload_file.html', {'form': form})
2827

2928
@login_required
30-
def download_file(request, file_id):
31-
file = get_object_or_404(UploadedFile, id=file_id)
32-
response = HttpResponse(file.file, content_type='application/force-download')
33-
response['Content-Disposition'] = f'attachment; filename={file.file.name}'
29+
def download_file(request, unique_token):
30+
file_instance = get_object_or_404(UploadedFile, unique_token=unique_token)
31+
response = HttpResponse(file_instance.file, content_type='application/force-download')
32+
response['Content-Disposition'] = f'attachment; filename={file_instance.file.name}'
3433
return response
3534

35+
# views.py
3636

3737
@login_required
38-
def delete_file(request, file_id):
39-
file_instance = get_object_or_404(UploadedFile, id=file_id)
38+
def delete_file(request, unique_token):
39+
# Try to find the file by unique_token
40+
file_instance = get_object_or_404(UploadedFile, unique_token=unique_token)
41+
42+
# If file_instance is not found, try to find by hashed_file_id
43+
if not file_instance:
44+
hashed_file_id = unique_token
45+
try:
46+
file_instance = UploadedFile.objects.get(hashed_file_id=hashed_file_id)
47+
except UploadedFile.DoesNotExist:
48+
return HttpResponse("File not found.", status=404)
49+
4050
storage = S3Boto3Storage()
4151
file_path = file_instance.file.name
4252

4353
if storage.exists(file_path):
4454
storage.delete(file_path)
55+
4556
file_instance.delete()
46-
47-
57+
4858
files = UploadedFile.objects.filter(user=request.user)
4959
return redirect('files:file_list')
5060

51-
from django.http import FileResponse
61+
5262

5363
@login_required
54-
def view_file(request, file_id):
55-
file_instance = get_object_or_404(UploadedFile, id=file_id)
64+
def view_file(request, unique_token):
65+
file_instance = get_object_or_404(UploadedFile, unique_token=unique_token)
5666
file_path = file_instance.file.name
5767
file_extension = file_path.split('.')[-1].lower()
68+
5869
if file_extension in ['jpg', 'jpeg', 'png', 'gif']:
5970
return FileResponse(file_instance.file, content_type='image/'+file_extension)
6071
elif file_extension == 'pdf':
6172
response = FileResponse(file_instance.file, content_type='application/pdf')
6273
response['Content-Disposition'] = f'inline; filename={file_instance.file.name}'
6374
return response
6475
else:
65-
return redirect('files:download_file', file_id=file_id)
66-
76+
return redirect('files:download_file', file_id=file_instance.id)
6777

68-
def share_file(request, file_id):
69-
file_instance = get_object_or_404(UploadedFile, id=file_id)
78+
def share_file(request, unique_token):
79+
file_instance = get_object_or_404(UploadedFile, unique_token=unique_token)
7080
file_path = file_instance.file.name
7181
file_extension = file_path.split('.')[-1].lower()
7282
if file_extension in ['jpg', 'jpeg', 'png', 'gif']:
@@ -76,4 +86,4 @@ def share_file(request, file_id):
7686
response['Content-Disposition'] = f'inline; filename={file_instance.file.name}'
7787
return response
7888
else:
79-
return redirect('files:download_file', file_id=file_id)
89+
return redirect('files:download_file', unique_token=unique_token)

0 commit comments

Comments
 (0)