meringue 1.2.0.dev6__tar.gz → 1.2.0.dev8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/.gitignore +1 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/PKG-INFO +1 -1
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/__init__.py +1 -1
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/conf/__init__.py +1 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/conf/default_settings.py +7 -1
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/protected/fields.py +45 -8
- meringue-1.2.0.dev8/meringue/protected/utils.py +6 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/protected/views.py +7 -4
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/AUTHORS +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/LICENSE +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/README.md +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/api/__init__.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/api/apps.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/api/docs/__init__.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/api/docs/patchers.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/api/docs/views.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/api/handlers.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/api/routers.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/api/utils.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/__init__.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/apps.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/locale/en/LC_MESSAGES/django.po +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/locale/ru/LC_MESSAGES/django.po +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/models.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/options.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/query.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/templatetags/__init__.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/templatetags/meringue_base.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/translation.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/upload_handlers.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/utils/__init__.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/utils/crypt.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/utils/datetime.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/utils/frontend.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/core/views.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/protected/__init__.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/protected/apps.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/__init__.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/actions.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/apps.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/constants.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/drf_fields.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/exceptions.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/generators.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/images.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/properties.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/shortcuts.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/storage.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/templatetags/__init__.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/templatetags/m_thumbnails.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/meringue/thumbnail/types.py +0 -0
- {meringue-1.2.0.dev6 → meringue-1.2.0.dev8}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: meringue
|
|
3
|
-
Version: 1.2.0.
|
|
3
|
+
Version: 1.2.0.dev8
|
|
4
4
|
Summary: A set of various functionality for a Django based web application.
|
|
5
5
|
Project-URL: Documentation, https://dd.github.io/Meringue
|
|
6
6
|
Project-URL: Repository, https://github.com/dd/Meringue
|
|
@@ -123,5 +123,11 @@ PROTECTED_SERVE_WITH_NGINX: Final[bool] = not settings.DEBUG
|
|
|
123
123
|
The option implies the distribution of protected files by nginx. Instead of serving the file in
|
|
124
124
|
response.
|
|
125
125
|
|
|
126
|
-
The view [
|
|
126
|
+
The view [x_accel_redirect_view][meringue.protected.views.x_accel_redirect_view] adds the
|
|
127
|
+
X-Accel-Redirect header with a link to the file.
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
PROTECTED_NGINX_LOCATION_GETTER: Final[str] = "meringue.protected.utils.nginx_location_getter"
|
|
131
|
+
"""
|
|
132
|
+
Default getter for the link to the file where nginx should serve it after access verification.
|
|
127
133
|
"""
|
|
@@ -9,16 +9,23 @@ try:
|
|
|
9
9
|
except ImportError:
|
|
10
10
|
hosts_reverse = None
|
|
11
11
|
|
|
12
|
+
from meringue.conf import m_settings
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
class ProtectedFileMixin:
|
|
14
16
|
@property
|
|
15
17
|
def url(self):
|
|
18
|
+
"""
|
|
19
|
+
Link to the view with access verification to the file
|
|
20
|
+
"""
|
|
21
|
+
|
|
16
22
|
self._require_file()
|
|
17
23
|
|
|
18
24
|
reverse_kwargs = {
|
|
19
25
|
"cid": ContentType.objects.get_for_model(self.instance.__class__).id,
|
|
20
26
|
"field": self.field.name,
|
|
21
27
|
"pk": self.instance.pk,
|
|
28
|
+
"disp": self.field.m_protected_disposition,
|
|
22
29
|
}
|
|
23
30
|
if self.field.m_protected_host_name:
|
|
24
31
|
result_url = hosts_reverse(
|
|
@@ -30,8 +37,20 @@ class ProtectedFileMixin:
|
|
|
30
37
|
result_url = reverse(self.field.m_protected_view_name, kwargs=reverse_kwargs)
|
|
31
38
|
return result_url
|
|
32
39
|
|
|
40
|
+
@property
|
|
41
|
+
def redirect_url(self):
|
|
42
|
+
"""
|
|
43
|
+
Link to the file where nginx should serve it after access verification.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
return self.field.m_protected_nginx_location_getter(self)
|
|
47
|
+
|
|
33
48
|
@property
|
|
34
49
|
def original_url(self):
|
|
50
|
+
"""
|
|
51
|
+
The original link to the file.
|
|
52
|
+
"""
|
|
53
|
+
|
|
35
54
|
self._require_file()
|
|
36
55
|
return self.storage.url(self.name)
|
|
37
56
|
|
|
@@ -49,18 +68,27 @@ class ProtectedFileField(FileField):
|
|
|
49
68
|
|
|
50
69
|
def __init__(
|
|
51
70
|
self,
|
|
71
|
+
view_name,
|
|
52
72
|
verbose_name=None,
|
|
53
73
|
name=None,
|
|
54
74
|
upload_to="protected",
|
|
55
75
|
storage=None,
|
|
56
|
-
|
|
57
|
-
|
|
76
|
+
host_name=None,
|
|
77
|
+
disposition="attachment",
|
|
78
|
+
nginx_location_getter=m_settings.PROTECTED_NGINX_LOCATION_GETTER,
|
|
58
79
|
**kwargs,
|
|
59
80
|
):
|
|
60
|
-
self.m_protected_view_name =
|
|
61
|
-
self.m_protected_host_name =
|
|
81
|
+
self.m_protected_view_name = view_name
|
|
82
|
+
self.m_protected_host_name = host_name
|
|
83
|
+
self.m_protected_disposition = disposition
|
|
84
|
+
self.m_protected_nginx_location_getter = nginx_location_getter
|
|
62
85
|
super().__init__(verbose_name, name, upload_to, storage, **kwargs)
|
|
63
86
|
|
|
87
|
+
def deconstruct(self):
|
|
88
|
+
name, path, args, kwargs = super().deconstruct()
|
|
89
|
+
kwargs['view_name'] = self.m_protected_view_name
|
|
90
|
+
return name, path, args, kwargs
|
|
91
|
+
|
|
64
92
|
|
|
65
93
|
class ProtectedImageFieldFile(ProtectedFileMixin, ImageFieldFile):
|
|
66
94
|
pass
|
|
@@ -75,15 +103,24 @@ class ProtectedImageField(ImageField):
|
|
|
75
103
|
|
|
76
104
|
def __init__(
|
|
77
105
|
self,
|
|
106
|
+
view_name,
|
|
78
107
|
verbose_name=None,
|
|
79
108
|
name=None,
|
|
80
109
|
width_field=None,
|
|
81
110
|
height_field=None,
|
|
82
|
-
|
|
83
|
-
|
|
111
|
+
host_name=None,
|
|
112
|
+
disposition="attachment",
|
|
113
|
+
nginx_location_getter=m_settings.PROTECTED_NGINX_LOCATION_GETTER,
|
|
84
114
|
**kwargs,
|
|
85
115
|
):
|
|
86
116
|
kwargs.setdefault("upload_to", "protected")
|
|
87
|
-
self.m_protected_view_name =
|
|
88
|
-
self.m_protected_host_name =
|
|
117
|
+
self.m_protected_view_name = view_name
|
|
118
|
+
self.m_protected_host_name = host_name
|
|
119
|
+
self.m_protected_disposition = disposition
|
|
120
|
+
self.m_protected_nginx_location_getter = nginx_location_getter
|
|
89
121
|
super().__init__(verbose_name, name, width_field, height_field, **kwargs)
|
|
122
|
+
|
|
123
|
+
def deconstruct(self):
|
|
124
|
+
name, path, args, kwargs = super().deconstruct()
|
|
125
|
+
kwargs['view_name'] = self.m_protected_view_name
|
|
126
|
+
return name, path, args, kwargs
|
|
@@ -15,7 +15,7 @@ from meringue.protected.fields import ProtectedFieldFile
|
|
|
15
15
|
from meringue.protected.fields import ProtectedImageFieldFile
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def
|
|
18
|
+
def x_accel_redirect_view(request, cid, field, pk, disp="inline"):
|
|
19
19
|
"""
|
|
20
20
|
The view checks the user's access to view and serves the file.
|
|
21
21
|
|
|
@@ -41,14 +41,17 @@ def protected_file_view(request, cid, field, pk):
|
|
|
41
41
|
file_name = Path(file.name).name
|
|
42
42
|
response = HttpResponse()
|
|
43
43
|
response["Content-Type"] = mimetypes.guess_type(file.path)[0]
|
|
44
|
-
response["Content-Disposition"] = f"
|
|
44
|
+
response["Content-Disposition"] = f"{disp}; filename={quote(file_name)}"
|
|
45
45
|
|
|
46
46
|
if isinstance(file, ProtectedFieldFile | ProtectedImageFieldFile):
|
|
47
|
-
redirect_url = file.
|
|
47
|
+
redirect_url = file.redirect_url
|
|
48
48
|
else:
|
|
49
49
|
redirect_url = file.url
|
|
50
50
|
|
|
51
51
|
response["X-Accel-Redirect"] = redirect_url
|
|
52
52
|
return response
|
|
53
53
|
|
|
54
|
-
return FileResponse(
|
|
54
|
+
return FileResponse(
|
|
55
|
+
open(file.path, "rb"),
|
|
56
|
+
as_attachment = disp == "attachment",
|
|
57
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|