From b944d58943319cf06724bc044b9898f55737837c Mon Sep 17 00:00:00 2001 From: MOIS3Y Date: Thu, 27 Jul 2023 11:26:27 +0900 Subject: [PATCH] Create: collector models, protect storage, download view --- .gitignore | 3 + logs_collector/collector/admin.py | 18 +++++ .../collector/migrations/0001_initial.py | 52 ++++++++++++++ logs_collector/collector/models.py | 70 ++++++++++++++++++- logs_collector/collector/urls.py | 9 +++ logs_collector/collector/utils.py | 0 logs_collector/collector/views.py | 24 ++++++- logs_collector/logs_collector/settings.py | 24 +++---- logs_collector/logs_collector/urls.py | 13 +++- 9 files changed, 195 insertions(+), 18 deletions(-) create mode 100644 logs_collector/collector/migrations/0001_initial.py create mode 100644 logs_collector/collector/urls.py create mode 100644 logs_collector/collector/utils.py diff --git a/.gitignore b/.gitignore index 5d381cc..e6db759 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,6 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +# Project specific +**/archives +**/media diff --git a/logs_collector/collector/admin.py b/logs_collector/collector/admin.py index 8c38f3f..c0faffb 100644 --- a/logs_collector/collector/admin.py +++ b/logs_collector/collector/admin.py @@ -1,3 +1,21 @@ from django.contrib import admin +from .models import Platform, Archive, Ticket + + # Register your models here. +class PlatformAdmin(admin.ModelAdmin): + pass + + +class TicketAdmin(admin.ModelAdmin): + pass + + +class ArchiveAdmin(admin.ModelAdmin): + pass + + +admin.site.register(Platform, PlatformAdmin) +admin.site.register(Ticket, TicketAdmin) +admin.site.register(Archive, ArchiveAdmin) diff --git a/logs_collector/collector/migrations/0001_initial.py b/logs_collector/collector/migrations/0001_initial.py new file mode 100644 index 0000000..911dd53 --- /dev/null +++ b/logs_collector/collector/migrations/0001_initial.py @@ -0,0 +1,52 @@ +# Generated by Django 4.2 on 2023-07-27 02:04 + +import collector.models +from django.conf import settings +import django.core.files.storage +from django.db import migrations, models +import django.db.models.deletion +import pathlib + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Platform', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=20)), + ], + ), + migrations.CreateModel( + name='Ticket', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('number', models.IntegerField()), + ('resolved', models.BooleanField(default=False)), + ('note', models.TextField(blank=True)), + ('time_create', models.DateTimeField(auto_now_add=True)), + ('time_update', models.DateTimeField(auto_now=True)), + ('platform', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='collector.platform')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Archive', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('file', models.FileField(blank=True, null=True, storage=django.core.files.storage.FileSystemStorage(base_url='/archives/', location=pathlib.PurePosixPath('/home/stepan/Documents/Dev/ISPsystem/logs-collector/logs_collector/archives')), upload_to=collector.models.logs_dir_path)), + ('sha1', models.CharField(editable=False, max_length=1024)), + ('time_create', models.DateTimeField(auto_now_add=True)), + ('time_update', models.DateTimeField(auto_now=True)), + ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='collector.ticket')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/logs_collector/collector/models.py b/logs_collector/collector/models.py index 71a8362..913ad4a 100644 --- a/logs_collector/collector/models.py +++ b/logs_collector/collector/models.py @@ -1,3 +1,69 @@ -from django.db import models +import hashlib +from functools import partial -# Create your models here. +from django.contrib.auth.models import User +from django.db import models +from django.conf import settings +from django.core.files.storage import FileSystemStorage +from django.db.models import FileField + + +# Create a custom storage location, using a value from your settings file +sensitive_upload_storage = FileSystemStorage( + location=settings.MEDIA_ROOT_FOR_SENSITIVE_FILES, + base_url=settings.MEDIA_URL_FOR_SENSITIVE_FILES +) +# ... and a file field that will use the custom storage +AuthenticatedFileField = partial(FileField, storage=sensitive_upload_storage) + + +def logs_dir_path(instance, filename): + # file will be uploaded to + # MEDIA_ROOT_FOR_SENSITIVE_FILES// + return f'{instance.ticket}/{filename}' + + +class Archive(models.Model): + file = AuthenticatedFileField( + upload_to=logs_dir_path, + blank=True, + null=True + ) + sha1 = models.CharField(max_length=1024, editable=False) + time_create = models.DateTimeField(auto_now_add=True) + time_update = models.DateTimeField(auto_now=True) + ticket = models.ForeignKey('Ticket', on_delete=models.CASCADE) + user = models.ForeignKey(User, on_delete=models.CASCADE) + + def save(self, *args, **kwargs): + # calculate sha 1 hash sum and write sha1 field to db + with self.file.open('rb') as f: + sha1 = hashlib.sha1() + for byte_block in iter(lambda: f.read(4096), b""): + sha1.update(byte_block) + self.sha1 = sha1.hexdigest() + # Call the "real" save() method + super().save(*args, **kwargs) + + def __str__(self): + return str(self.file) + + +class Platform(models.Model): + name = models.CharField(max_length=20) + + def __str__(self): + return self.name + + +class Ticket(models.Model): + number = models.IntegerField() + resolved = models.BooleanField(default=False) + note = models.TextField(blank=True) + time_create = models.DateTimeField(auto_now_add=True) + time_update = models.DateTimeField(auto_now=True) + platform = models.ForeignKey('Platform', on_delete=models.CASCADE) + user = models.ForeignKey(User, on_delete=models.CASCADE) + + def __str__(self): + return str(self.number) diff --git a/logs_collector/collector/urls.py b/logs_collector/collector/urls.py new file mode 100644 index 0000000..6a5f4ea --- /dev/null +++ b/logs_collector/collector/urls.py @@ -0,0 +1,9 @@ +from django.urls import path +from . import views + + +urlpatterns = [ + path('', views.index, name='index',), + path('test//', views.test_page, name='test_page'), + path('archives//', views.download, name="download") +] diff --git a/logs_collector/collector/utils.py b/logs_collector/collector/utils.py new file mode 100644 index 0000000..e69de29 diff --git a/logs_collector/collector/views.py b/logs_collector/collector/views.py index 91ea44a..0f9ac07 100644 --- a/logs_collector/collector/views.py +++ b/logs_collector/collector/views.py @@ -1,3 +1,25 @@ -from django.shortcuts import render +# from django.shortcuts import render +from django.contrib.auth.decorators import login_required +from django.http import FileResponse, HttpResponse, Http404 +from .models import Archive + # Create your views here. +# handles the url "/archives/{PATH}"". +@login_required +def download(request, ticket, file): + path = f'{ticket}/{file}' + try: + file = Archive.objects.get(file=path) + except Archive.DoesNotExist: + return Http404 + + return FileResponse(file.file) + + +def index(request): + return HttpResponse('

Index Page

') + + +def test_page(request, path): + return HttpResponse(f'

{path} Page

') diff --git a/logs_collector/logs_collector/settings.py b/logs_collector/logs_collector/settings.py index 776c9b4..88b5d7a 100644 --- a/logs_collector/logs_collector/settings.py +++ b/logs_collector/logs_collector/settings.py @@ -1,14 +1,3 @@ -""" -Django settings for logs_collector project. - -Generated by 'django-admin startproject' using Django 4.2. - -For more information on this file, see -https://docs.djangoproject.com/en/4.2/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/4.2/ref/settings/ -""" import environ from pathlib import Path @@ -22,8 +11,6 @@ BASE_DIR = Path(__file__).resolve().parent.parent environ.Env.read_env(BASE_DIR / '.env') -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = env('SECRET_KEY') @@ -32,7 +19,9 @@ SECRET_KEY = env('SECRET_KEY') DEBUG = env('DEBUG') ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=["*"]) -CSRF_TRUSTED_ORIGINS = env.list("CSRF_TRUSTED_ORIGINS", default=["*"]) + +# TODO: required for docker image +# CSRF_TRUSTED_ORIGINS = env.list("CSRF_TRUSTED_ORIGINS", default=["*"]) # Application definition @@ -46,6 +35,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'collector.apps.CollectorConfig', # main app 'rest_framework', + 'django_cleanup.apps.CleanupConfig', # required bottom ] MIDDLEWARE = [ @@ -130,3 +120,9 @@ STATIC_URL = 'static/' # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +MEDIA_ROOT = BASE_DIR / 'media' +MEDIA_URL = 'media/' + +MEDIA_ROOT_FOR_SENSITIVE_FILES = BASE_DIR / 'archives' +MEDIA_URL_FOR_SENSITIVE_FILES = '/archives/' diff --git a/logs_collector/logs_collector/urls.py b/logs_collector/logs_collector/urls.py index ca8ff1f..dbc5b65 100644 --- a/logs_collector/logs_collector/urls.py +++ b/logs_collector/logs_collector/urls.py @@ -14,9 +14,20 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ +from django.conf.urls.static import static from django.contrib import admin -from django.urls import path +from django.urls import path, include + +from logs_collector import settings + urlpatterns = [ path('admin/', admin.site.urls), + path('', include('collector.urls')), ] + + +if settings.DEBUG: + urlpatterns += static( + settings.MEDIA_URL, document_root=settings.MEDIA_ROOT + )