diff --git a/apps/jumpserver/rewriting/storage/__init__.py b/apps/jumpserver/rewriting/storage/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/jumpserver/rewriting/storage/permissions.py b/apps/jumpserver/rewriting/storage/permissions.py new file mode 100644 index 000000000..492a6d06f --- /dev/null +++ b/apps/jumpserver/rewriting/storage/permissions.py @@ -0,0 +1,24 @@ +# ~*~ coding: utf-8 ~*~ + +path_perms_map = { + 'xpack': '*', + 'replay': 'default', + 'applets': 'terminal.view_applet', + 'playbooks': 'ops.view_playbook' +} + + +def allow_access(private_file): + request = private_file.request + request_path = private_file.request.path + path_list = str(request_path)[1:].split('/') + path_base = path_list[1] if len(path_list) > 1 else None + path_perm = path_perms_map.get(path_base, None) + + if not path_perm: + return False + if path_perm == '*' or request.user.has_perms([path_perm]): + return True + if path_perm == 'default': + return request.user.is_authenticated and request.user.is_staff + return False diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index d74e604d3..9d68cc938 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -102,6 +102,7 @@ INSTALLED_APPS = [ 'django_filters', 'bootstrap3', 'captcha', + 'private_storage', 'django_celery_beat', 'django.contrib.auth', 'django.contrib.admin', @@ -263,11 +264,11 @@ STATICFILES_DIRS = ( ) # Media files (File, ImageField) will be save these - -MEDIA_URL = '/media/' - MEDIA_ROOT = os.path.join(PROJECT_DIR, 'data', 'media').replace('\\', '/') + '/' +PRIVATE_STORAGE_ROOT = MEDIA_ROOT +PRIVATE_STORAGE_AUTH_FUNCTION = 'jumpserver.rewriting.storage.permissions.allow_access' + # Use django-bootstrap-form to format template, input max width arg # BOOTSTRAP_COLUMN_COUNT = 11 diff --git a/apps/jumpserver/urls.py b/apps/jumpserver/urls.py index 2218edd6c..f005f81f0 100644 --- a/apps/jumpserver/urls.py +++ b/apps/jumpserver/urls.py @@ -2,6 +2,8 @@ from __future__ import unicode_literals import os +import private_storage.urls + from django.urls import path, include, re_path from django.conf import settings from django.conf.urls.static import static @@ -57,8 +59,11 @@ urlpatterns = [ ] # 静态文件处理路由 -urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \ - + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) +urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) +urlpatterns += [ + # Protect media + path('media/', include(private_storage.urls)), +] # js i18n 路由文件 urlpatterns += [ diff --git a/apps/ops/models/playbook.py b/apps/ops/models/playbook.py index 2bef76741..af0ec28db 100644 --- a/apps/ops/models/playbook.py +++ b/apps/ops/models/playbook.py @@ -4,6 +4,7 @@ import uuid from django.conf import settings from django.db import models from django.utils.translation import gettext_lazy as _ +from private_storage.fields import PrivateFileField from ops.const import CreateMethods from ops.exception import PlaybookNoValidEntry @@ -20,7 +21,7 @@ dangerous_keywords = ( class Playbook(JMSOrgBaseModel): id = models.UUIDField(default=uuid.uuid4, primary_key=True) name = models.CharField(max_length=128, verbose_name=_('Name'), null=True) - path = models.FileField(upload_to='playbooks/') + path = PrivateFileField(upload_to='playbooks/') creator = models.ForeignKey('users.User', verbose_name=_("Creator"), on_delete=models.SET_NULL, null=True) comment = models.CharField(max_length=1024, default='', verbose_name=_('Comment'), null=True, blank=True) create_method = models.CharField(max_length=128, choices=CreateMethods.choices, default=CreateMethods.blank,