photo-objects 0.0.6__tar.gz → 0.0.7__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.
Files changed (58) hide show
  1. {photo_objects-0.0.6 → photo_objects-0.0.7}/PKG-INFO +1 -1
  2. photo_objects-0.0.7/photo_objects/django/views/ui/configuration.py +188 -0
  3. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/ui/photo.py +3 -3
  4. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects.egg-info/PKG-INFO +1 -1
  5. {photo_objects-0.0.6 → photo_objects-0.0.7}/pyproject.toml +1 -1
  6. photo_objects-0.0.6/photo_objects/django/views/ui/configuration.py +0 -117
  7. {photo_objects-0.0.6 → photo_objects-0.0.7}/LICENSE +0 -0
  8. {photo_objects-0.0.6 → photo_objects-0.0.7}/README.md +0 -0
  9. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/__init__.py +0 -0
  10. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/config.py +0 -0
  11. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/__init__.py +0 -0
  12. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/admin.py +0 -0
  13. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/api/__init__.py +0 -0
  14. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/api/album.py +0 -0
  15. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/api/auth.py +0 -0
  16. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/api/photo.py +0 -0
  17. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/api/utils.py +0 -0
  18. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/apps.py +0 -0
  19. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/context_processors.py +0 -0
  20. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/forms.py +0 -0
  21. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/management/__init__.py +0 -0
  22. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/management/commands/__init__.py +0 -0
  23. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/management/commands/create-initial-admin-account.py +0 -0
  24. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/management/commands/create-site-albums.py +0 -0
  25. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/migrations/0001_initial.py +0 -0
  26. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/migrations/0002_created_at_updated_at.py +0 -0
  27. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/migrations/0003_admin_visibility.py +0 -0
  28. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/migrations/0004_camera_setup_and_settings.py +0 -0
  29. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/migrations/__init__.py +0 -0
  30. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/models.py +0 -0
  31. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/objsto.py +0 -0
  32. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/signals.py +0 -0
  33. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/templatetags/__init__.py +0 -0
  34. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/templatetags/photo_objects_extras.py +0 -0
  35. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/tests/__init__.py +0 -0
  36. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/tests/test_album.py +0 -0
  37. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/tests/test_auth.py +0 -0
  38. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/tests/test_photo.py +0 -0
  39. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/tests/test_utils.py +0 -0
  40. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/tests/utils.py +0 -0
  41. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/urls.py +0 -0
  42. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/__init__.py +0 -0
  43. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/api/__init__.py +0 -0
  44. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/api/album.py +0 -0
  45. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/api/auth.py +0 -0
  46. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/api/photo.py +0 -0
  47. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/api/utils.py +0 -0
  48. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/ui/__init__.py +0 -0
  49. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/ui/album.py +0 -0
  50. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/ui/utils.py +0 -0
  51. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/django/views/utils.py +0 -0
  52. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/error.py +0 -0
  53. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects/img.py +0 -0
  54. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects.egg-info/SOURCES.txt +0 -0
  55. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects.egg-info/dependency_links.txt +0 -0
  56. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects.egg-info/requires.txt +0 -0
  57. {photo_objects-0.0.6 → photo_objects-0.0.7}/photo_objects.egg-info/top_level.txt +0 -0
  58. {photo_objects-0.0.6 → photo_objects-0.0.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: photo-objects
3
- Version: 0.0.6
3
+ Version: 0.0.7
4
4
  Summary: Application for storing photos in S3 compatible object-storage.
5
5
  Author: Toni Kangas
6
6
  License: MIT License
@@ -0,0 +1,188 @@
1
+ from dataclasses import dataclass
2
+
3
+ from django.http import HttpRequest
4
+ from django.shortcuts import render
5
+ from django.urls import reverse
6
+ from django.utils.translation import gettext_lazy as _
7
+
8
+ from photo_objects.django.models import Album
9
+ from photo_objects.django.views.utils import BackLink, render_markdown
10
+
11
+ from .utils import json_problem_as_html
12
+
13
+
14
+ @dataclass
15
+ class Validation:
16
+ check: str
17
+ status: str
18
+ detail: str = None
19
+
20
+ def __post_init__(self):
21
+ self.detail = render_markdown(self.detail)
22
+
23
+
24
+ def status(ok: bool, warning=False) -> str:
25
+ if ok:
26
+ return _("OK")
27
+ if warning:
28
+ return _("Warning")
29
+ return _("Error")
30
+
31
+
32
+ def uses_https(request: HttpRequest) -> Validation:
33
+ ok = request.is_secure()
34
+ warning = False
35
+ detail = (
36
+ 'The request received by the API server was '
37
+ f'{"" if ok else "not "}secure.')
38
+
39
+ if not ok:
40
+ referer = request.META.get("HTTP_REFERER", "")
41
+ if request.site.domain in referer and referer.startswith("https://"):
42
+ warning = True
43
+
44
+ detail += _(
45
+ ' If you are running the API server behind a reverse proxy or '
46
+ 'a load-balancer, ensure that HTTPS termination is configured '
47
+ f'correctly. ({request.META})')
48
+
49
+ return Validation(
50
+ check=_("Site is served over HTTPS"),
51
+ status=status(ok, warning),
52
+ detail=detail
53
+ )
54
+
55
+
56
+ def site_is_configured(request: HttpRequest) -> Validation:
57
+ detail = (
58
+ 'Site domain is configured to a non-default value: '
59
+ f'`{request.site.domain}`'
60
+ )
61
+ try:
62
+ ok = request.site.domain != "example.com"
63
+ if not ok:
64
+ detail = (
65
+ 'Site domain is set to `example.com`. This is a placeholder '
66
+ 'domain and should be changed to the actual domain of the '
67
+ 'site.')
68
+ except Exception as e:
69
+ ok = False
70
+ detail = (
71
+ f"Failed to resolve site domain: got `{str(e)}`. Check that sites "
72
+ "framework is installed, site middleware is configured, and that "
73
+ "the site exists in the database.")
74
+
75
+ return Validation(
76
+ check=_("Site is configured"),
77
+ status=status(ok),
78
+ detail=detail,
79
+ )
80
+
81
+
82
+ def domain_matches_request(request: HttpRequest) -> Validation:
83
+ detail = None
84
+ try:
85
+ host = request.get_host().lower()
86
+ domain = request.site.domain.lower()
87
+ ok = request.get_host() == request.site.domain
88
+ if not ok:
89
+ detail = (
90
+ 'Host in the request does not match domain configured for '
91
+ f'the site: expected `{domain}`, got `{host}`.')
92
+ else:
93
+ detail = (
94
+ f'Host in the request, `{host}`, matches domain configured '
95
+ f'for the site, `{domain}`.'
96
+ )
97
+ except Exception as e:
98
+ ok = False
99
+ detail = (
100
+ f"Failed to resolve host or domain: got `{str(e)}`. Check that "
101
+ "sites framework is installed, site middleware is configured, "
102
+ "and that the site exists in the database.")
103
+
104
+ return Validation(
105
+ check=_("Configured domain matches host in request"),
106
+ status=status(ok),
107
+ detail=detail,
108
+ )
109
+
110
+
111
+ def site_preview_configured(
112
+ request: HttpRequest,
113
+ album: Album | Exception) -> Validation:
114
+ detail = None
115
+
116
+ if isinstance(album, Exception):
117
+ ok = False
118
+ detail = f'Failed to resolve site or album: `{str(album)}`'
119
+ else:
120
+ ok = album.cover_photo is not None
121
+ if ok:
122
+ detail = (
123
+ f'The `{album.key}` album has a cover photo configured. This '
124
+ 'photo will be used as the site preview image.'
125
+ )
126
+ else:
127
+ detail = (
128
+ f'Set cover photo for `{album.key}` album to configure '
129
+ 'the preview image.')
130
+
131
+ return Validation(
132
+ check=_("Site has a default preview image"),
133
+ status=status(ok),
134
+ detail=detail,
135
+ )
136
+
137
+
138
+ def site_description_configured(
139
+ request: HttpRequest,
140
+ album: Album | Exception) -> Validation:
141
+ detail = None
142
+
143
+ if isinstance(album, Exception):
144
+ ok = False
145
+ detail = f'Failed to resolve site or album: `{str(album)}`'
146
+ else:
147
+ ok = album.description is not None and len(album.description) > 0
148
+ if ok:
149
+ detail = (
150
+ f'The `{album.key}` album has a description. This description '
151
+ 'will be used as the site description.'
152
+ )
153
+ else:
154
+ detail = (
155
+ f'Set description for `{album.key}` album to configure '
156
+ 'the site description.')
157
+
158
+ return Validation(
159
+ check=_("Site has a default description"),
160
+ status=status(ok),
161
+ detail=detail,
162
+ )
163
+
164
+
165
+ @json_problem_as_html
166
+ def configuration(request: HttpRequest):
167
+ try:
168
+ site_id = request.site.id
169
+ album_key = f"_site_{site_id}"
170
+ album = Album.objects.get(key=album_key)
171
+ except Exception as e:
172
+ album = e
173
+
174
+ validations = [
175
+ uses_https(request),
176
+ site_is_configured(request),
177
+ domain_matches_request(request),
178
+ site_preview_configured(request, album),
179
+ site_description_configured(request, album),
180
+ ]
181
+
182
+ back = BackLink("Back to albums", reverse('photo_objects:list_albums'))
183
+
184
+ return render(request, "photo_objects/configuration.html", {
185
+ "title": "Configuration",
186
+ "validations": validations,
187
+ "back": back,
188
+ })
@@ -44,9 +44,9 @@ def upload_photos(request: HttpRequest, album_key: str):
44
44
  def _camera(photo: Photo):
45
45
  if photo.camera_make or photo.camera_model:
46
46
  return " ".join(i for i in [
47
- photo.camera_make,
48
- photo.camera_model,
49
- ] if i)
47
+ photo.camera_make,
48
+ photo.camera_model,
49
+ ] if i)
50
50
  return None
51
51
 
52
52
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: photo-objects
3
- Version: 0.0.6
3
+ Version: 0.0.7
4
4
  Summary: Application for storing photos in S3 compatible object-storage.
5
5
  Author: Toni Kangas
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "photo-objects"
7
- version = "0.0.6"
7
+ version = "0.0.7"
8
8
  dependencies = [
9
9
  "markdown~=3.7",
10
10
  "minio~=7.2",
@@ -1,117 +0,0 @@
1
- from dataclasses import dataclass
2
-
3
- from django.http import HttpRequest
4
- from django.shortcuts import render
5
- from django.urls import reverse
6
- from django.utils.translation import gettext_lazy as _
7
-
8
- from photo_objects.django.models import Album
9
- from photo_objects.django.views.utils import BackLink
10
-
11
- from .utils import json_problem_as_html
12
-
13
-
14
- @dataclass
15
- class Validation:
16
- check: str
17
- status: str
18
- detail: str = None
19
-
20
-
21
- def status(b: bool) -> str:
22
- return _("OK") if b else _("Error")
23
-
24
-
25
- def uses_https(request: HttpRequest) -> Validation:
26
- return Validation(
27
- check=_("Site is served over HTTPS"),
28
- status=status(request.is_secure()),
29
- )
30
-
31
-
32
- def site_is_configured(request: HttpRequest) -> Validation:
33
- detail = None
34
- try:
35
- ok = request.site.domain != "example.com"
36
- if not ok:
37
- detail = (
38
- f'Site domain is set to "example.com". This is a placeholder '
39
- 'domain and should be changed to the actual domain of the '
40
- 'site.')
41
- except Exception as e:
42
- ok = False
43
- detail = (
44
- f"Failed to resolve site domain: {str(e)}. Check that sites "
45
- "framework is installed, site middleware is configured, and that "
46
- "the site exists in the database.")
47
-
48
- return Validation(
49
- check=_("Site is configured"),
50
- status=status(ok),
51
- detail=detail,
52
- )
53
-
54
-
55
- def domain_matches_request(request: HttpRequest) -> Validation:
56
- detail = None
57
- try:
58
- host = request.get_host().lower()
59
- domain = request.site.domain.lower()
60
- ok = request.get_host() == request.site.domain
61
- if not ok:
62
- detail = (
63
- 'Host in the request does not match domain configured for '
64
- f'the site: expected "{domain}", got "{host}".')
65
- except Exception as e:
66
- ok = False
67
- detail = (
68
- f"Failed to resolve host or domain: {str(e)}. Check that "
69
- "sites framework is installed, site middleware is configured, "
70
- "and that the site exists in the database.")
71
-
72
- return Validation(
73
- check=_("Configured domain matches host in request"),
74
- status=status(ok),
75
- detail=detail,
76
- )
77
-
78
-
79
- def site_preview_configured(request: HttpRequest) -> Validation:
80
- detail = None
81
-
82
- try:
83
- site_id = request.site.id
84
- album_key = f"_site_{site_id}"
85
- album = Album.objects.get(key=album_key)
86
- ok = album.cover_photo is not None
87
- if not ok:
88
- detail = (
89
- f'Set cover photo for "{album_key}" album to configure '
90
- 'the preview image.')
91
- except Exception as e:
92
- ok = False
93
- detail = f'Failed to resolve site or album: {str(e)}'
94
-
95
- return Validation(
96
- check=_("Site has a default preview image"),
97
- status=status(ok),
98
- detail=detail,
99
- )
100
-
101
-
102
- @json_problem_as_html
103
- def configuration(request: HttpRequest):
104
- validations = [
105
- uses_https(request),
106
- site_is_configured(request),
107
- domain_matches_request(request),
108
- site_preview_configured(request),
109
- ]
110
-
111
- back = BackLink("Back to albums", reverse('photo_objects:list_albums'))
112
-
113
- return render(request, "photo_objects/configuration.html", {
114
- "title": "Configuration",
115
- "validations": validations,
116
- "back": back,
117
- })
File without changes
File without changes
File without changes