photo-objects 0.0.6__py3-none-any.whl → 0.0.7__py3-none-any.whl

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.
@@ -6,7 +6,7 @@ from django.urls import reverse
6
6
  from django.utils.translation import gettext_lazy as _
7
7
 
8
8
  from photo_objects.django.models import Album
9
- from photo_objects.django.views.utils import BackLink
9
+ from photo_objects.django.views.utils import BackLink, render_markdown
10
10
 
11
11
  from .utils import json_problem_as_html
12
12
 
@@ -17,31 +17,58 @@ class Validation:
17
17
  status: str
18
18
  detail: str = None
19
19
 
20
+ def __post_init__(self):
21
+ self.detail = render_markdown(self.detail)
20
22
 
21
- def status(b: bool) -> str:
22
- return _("OK") if b else _("Error")
23
+
24
+ def status(ok: bool, warning=False) -> str:
25
+ if ok:
26
+ return _("OK")
27
+ if warning:
28
+ return _("Warning")
29
+ return _("Error")
23
30
 
24
31
 
25
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
+
26
49
  return Validation(
27
50
  check=_("Site is served over HTTPS"),
28
- status=status(request.is_secure()),
51
+ status=status(ok, warning),
52
+ detail=detail
29
53
  )
30
54
 
31
55
 
32
56
  def site_is_configured(request: HttpRequest) -> Validation:
33
- detail = None
57
+ detail = (
58
+ 'Site domain is configured to a non-default value: '
59
+ f'`{request.site.domain}`'
60
+ )
34
61
  try:
35
62
  ok = request.site.domain != "example.com"
36
63
  if not ok:
37
64
  detail = (
38
- f'Site domain is set to "example.com". This is a placeholder '
65
+ 'Site domain is set to `example.com`. This is a placeholder '
39
66
  'domain and should be changed to the actual domain of the '
40
67
  'site.')
41
68
  except Exception as e:
42
69
  ok = False
43
70
  detail = (
44
- f"Failed to resolve site domain: {str(e)}. Check that sites "
71
+ f"Failed to resolve site domain: got `{str(e)}`. Check that sites "
45
72
  "framework is installed, site middleware is configured, and that "
46
73
  "the site exists in the database.")
47
74
 
@@ -61,11 +88,16 @@ def domain_matches_request(request: HttpRequest) -> Validation:
61
88
  if not ok:
62
89
  detail = (
63
90
  'Host in the request does not match domain configured for '
64
- f'the site: expected "{domain}", got "{host}".')
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
+ )
65
97
  except Exception as e:
66
98
  ok = False
67
99
  detail = (
68
- f"Failed to resolve host or domain: {str(e)}. Check that "
100
+ f"Failed to resolve host or domain: got `{str(e)}`. Check that "
69
101
  "sites framework is installed, site middleware is configured, "
70
102
  "and that the site exists in the database.")
71
103
 
@@ -76,21 +108,25 @@ def domain_matches_request(request: HttpRequest) -> Validation:
76
108
  )
77
109
 
78
110
 
79
- def site_preview_configured(request: HttpRequest) -> Validation:
111
+ def site_preview_configured(
112
+ request: HttpRequest,
113
+ album: Album | Exception) -> Validation:
80
114
  detail = None
81
115
 
82
- try:
83
- site_id = request.site.id
84
- album_key = f"_site_{site_id}"
85
- album = Album.objects.get(key=album_key)
116
+ if isinstance(album, Exception):
117
+ ok = False
118
+ detail = f'Failed to resolve site or album: `{str(album)}`'
119
+ else:
86
120
  ok = album.cover_photo is not None
87
- if not ok:
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:
88
127
  detail = (
89
- f'Set cover photo for "{album_key}" album to configure '
128
+ f'Set cover photo for `{album.key}` album to configure '
90
129
  'the preview image.')
91
- except Exception as e:
92
- ok = False
93
- detail = f'Failed to resolve site or album: {str(e)}'
94
130
 
95
131
  return Validation(
96
132
  check=_("Site has a default preview image"),
@@ -99,13 +135,48 @@ def site_preview_configured(request: HttpRequest) -> Validation:
99
135
  )
100
136
 
101
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
+
102
165
  @json_problem_as_html
103
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
+
104
174
  validations = [
105
175
  uses_https(request),
106
176
  site_is_configured(request),
107
177
  domain_matches_request(request),
108
- site_preview_configured(request),
178
+ site_preview_configured(request, album),
179
+ site_description_configured(request, album),
109
180
  ]
110
181
 
111
182
  back = BackLink("Back to albums", reverse('photo_objects:list_albums'))
@@ -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
@@ -42,11 +42,11 @@ photo_objects/django/views/api/photo.py,sha256=52UMP1r6TN_xfu8fHE25yOUiTa6W1F2Xb
42
42
  photo_objects/django/views/api/utils.py,sha256=uQzKdSKHRAux5OZzqgWQr0gsK_FeweQP0cg_67OWA_Y,264
43
43
  photo_objects/django/views/ui/__init__.py,sha256=vbFXPj5liue-M_CXQGP5PKhD98Z5ev53yKLPU8zWpUs,71
44
44
  photo_objects/django/views/ui/album.py,sha256=bgFPg9ipkQFqZK7cQgYT9gqpUgdSJ_1NTHlszsfclKU,5010
45
- photo_objects/django/views/ui/configuration.py,sha256=yDKlJUx5LexmpvvTPEZTH3RPtxMgXVInmNCFS-0sZv8,3375
46
- photo_objects/django/views/ui/photo.py,sha256=F7tqI_mtGFnelROTQbGmkK21OylheavoRzFgjlah1j0,6052
45
+ photo_objects/django/views/ui/configuration.py,sha256=bkckPtQHf7FYwEUIemtMTA1jaDHi7B7VA4ucO_4qt5E,5593
46
+ photo_objects/django/views/ui/photo.py,sha256=4NJSN5X_NcVcUEPaoGEGmXRDAgI5_KsOlHr7j-yo2QY,6040
47
47
  photo_objects/django/views/ui/utils.py,sha256=YV_YcUbX-zUkdFnBlezPChR6aPDhZJ9loSOHBSzF6Cc,273
48
- photo_objects-0.0.6.dist-info/licenses/LICENSE,sha256=V3w6hTjXfP65F4r_mejveHcV5igHrblxao3-2RlfVlA,1068
49
- photo_objects-0.0.6.dist-info/METADATA,sha256=bT0yaZdgZxa1XF8V1ABndbeJerRaU0g02PDXH6wRPKQ,3671
50
- photo_objects-0.0.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
- photo_objects-0.0.6.dist-info/top_level.txt,sha256=SZeL8mhf-WMGdhRtTGFvZc3aIRBboQls9O0cFDMGdQ0,14
52
- photo_objects-0.0.6.dist-info/RECORD,,
48
+ photo_objects-0.0.7.dist-info/licenses/LICENSE,sha256=V3w6hTjXfP65F4r_mejveHcV5igHrblxao3-2RlfVlA,1068
49
+ photo_objects-0.0.7.dist-info/METADATA,sha256=xYOJTlRMBdsnYh_0AHAzGcHybbiUodE4SY8Xvc0E85g,3671
50
+ photo_objects-0.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
+ photo_objects-0.0.7.dist-info/top_level.txt,sha256=SZeL8mhf-WMGdhRtTGFvZc3aIRBboQls9O0cFDMGdQ0,14
52
+ photo_objects-0.0.7.dist-info/RECORD,,