Browse Source

fix allowed_dims endpoint

Guénaël Muller 6 years ago
parent
commit
223c92f0fb

+ 15 - 15
tracim/config.py View File

@@ -411,26 +411,26 @@ class CFG(object):
411 411
         #     self.RADICALE_CLIENT_BASE_URL_HOST,
412 412
         #     self.RADICALE_CLIENT_BASE_URL_PREFIX,
413 413
         # )
414
-        preview_jpg_allowed_sizes_str = settings.get('preview.jpg.allowed_sizes', '')  # nopep8
415
-        allowed_size = []
416
-        if preview_jpg_allowed_sizes_str:
417
-            for sizes in preview_jpg_allowed_sizes_str.split(','):
414
+        self.PREVIEW_JPG_RESTRICTED_DIMS = asbool(settings.get(
415
+            'preview.jpg.restricted_dims', False
416
+        ))
417
+        preview_jpg_allowed_dims_str = settings.get('preview.jpg.allowed_dims', '')  # nopep8
418
+        allowed_dims = []
419
+        if preview_jpg_allowed_dims_str:
420
+            for sizes in preview_jpg_allowed_dims_str.split(','):
418 421
                 parts = sizes.split('x')
419 422
                 assert len(parts) == 2
420 423
                 width, height = parts
421 424
                 assert width.isdecimal()
422 425
                 assert height.isdecimal()
423
-                size = PreviewSize(int(width), int(height))
424
-                allowed_size.append(size)
426
+                size = PreviewDim(int(width), int(height))
427
+                allowed_dims.append(size)
425 428
 
426
-            self.PREVIEW_JPG_RESTRICTED_SIZES = asbool(settings.get(
427
-                'preview.jpg.restricted_sizes', False
428
-            ))
429
-        if not allowed_size:
430
-            size = PreviewSize(256, 256)
431
-            allowed_size.append(size)
429
+        if not allowed_dims:
430
+            size = PreviewDim(256, 256)
431
+            allowed_dims.append(size)
432 432
 
433
-        self.PREVIEW_JPG_ALLOWED_SIZES = allowed_size
433
+        self.PREVIEW_JPG_ALLOWED_DIMS = allowed_dims
434 434
 
435 435
     def configure_filedepot(self):
436 436
         depot_storage_name = self.DEPOT_STORAGE_NAME
@@ -449,14 +449,14 @@ class CFG(object):
449 449
         TREEVIEW_ALL = 'all'
450 450
 
451 451
 
452
-class PreviewSize(object):
452
+class PreviewDim(object):
453 453
 
454 454
     def __init__(self, width: int, height: int) -> None:
455 455
         self.width = width
456 456
         self.height = height
457 457
 
458 458
     def __repr__(self):
459
-        return "<PreviewSize width:{width} height:{height}>".format(
459
+        return "<PreviewDim width:{width} height:{height}>".format(
460 460
             width=self.width,
461 461
             height=self.height,
462 462
         )

+ 3 - 2
tracim/exceptions.py View File

@@ -152,5 +152,6 @@ class RevisionDoesNotMatchThisContent(TracimException):
152 152
 class PageOfPreviewNotFound(NotFound):
153 153
     pass
154 154
 
155
-class PreviewSizeNotAllowed(TracimException):
156
-    pass
155
+
156
+class PreviewDimNotAllowed(TracimException):
157
+    pass

+ 17 - 10
tracim/lib/core/content.py View File

@@ -23,11 +23,12 @@ from sqlalchemy import distinct
23 23
 from sqlalchemy import or_
24 24
 from sqlalchemy.sql.elements import and_
25 25
 
26
+from tracim.config import PreviewDim
26 27
 from tracim.lib.utils.utils import cmp_to_key
27 28
 from tracim.lib.core.notifications import NotifierFactory
28 29
 from tracim.exceptions import SameValueError
29 30
 from tracim.exceptions import PageOfPreviewNotFound
30
-from tracim.exceptions import PreviewSizeNotAllowed
31
+from tracim.exceptions import PreviewDimNotAllowed
31 32
 from tracim.exceptions import EmptyRawContentNotAllowed
32 33
 from tracim.exceptions import RevisionDoesNotMatchThisContent
33 34
 from tracim.exceptions import EmptyLabelNotAllowed
@@ -46,7 +47,8 @@ from tracim.models.data import RevisionReadStatus
46 47
 from tracim.models.data import UserRoleInWorkspace
47 48
 from tracim.models.data import Workspace
48 49
 from tracim.lib.utils.translation import fake_translator as _
49
-from tracim.models.context_models import RevisionInContext
50
+from tracim.models.context_models import RevisionInContext, \
51
+    PreviewAllowedDim
50 52
 from tracim.models.context_models import ContentInContext
51 53
 
52 54
 __author__ = 'damien'
@@ -762,6 +764,11 @@ class ContentApi(object):
762 764
         pdf_preview_path = self.preview_manager.get_pdf_preview(file_path)
763 765
         return pdf_preview_path
764 766
 
767
+    def get_jpg_preview_allowed_dim(self) -> PreviewAllowedDim:
768
+        return PreviewAllowedDim(
769
+            self._config.PREVIEW_JPG_RESTRICTED_DIMS,
770
+            self._config.PREVIEW_JPG_ALLOWED_DIMS,
771
+        )
765 772
     def get_jpg_preview_path(
766 773
         self,
767 774
         content_id: int,
@@ -789,17 +796,17 @@ class ContentApi(object):
789 796
                 ),
790 797
             )
791 798
         if not width and not height:
792
-            width = self._config.PREVIEW_JPG_ALLOWED_SIZES[0].width
793
-            height = self._config.PREVIEW_JPG_ALLOWED_SIZES[0].height
799
+            width = self._config.PREVIEW_JPG_ALLOWED_DIMS[0].width
800
+            height = self._config.PREVIEW_JPG_ALLOWED_DIMS[0].height
794 801
 
795
-        allowed_size = False
796
-        for preview_size in self._config.PREVIEW_JPG_ALLOWED_SIZES:
797
-            if width == preview_size.width and height == preview_size.height:
798
-                allowed_size = True
802
+        allowed_dim = False
803
+        for preview_dim in self._config.PREVIEW_JPG_ALLOWED_DIMS:
804
+            if width == preview_dim.width and height == preview_dim.height:
805
+                allowed_dim = True
799 806
                 break
800 807
 
801
-        if not allowed_size and self._config.PREVIEW_JPG_RESTRICTED_SIZES:
802
-            raise PreviewSizeNotAllowed(
808
+        if not allowed_dim and self._config.PREVIEW_JPG_RESTRICTED_DIMS:
809
+            raise PreviewDimNotAllowed(
803 810
                 'Size {width}x{height} is not allowed for jpeg preview'.format(
804 811
                     width=width,
805 812
                     height=height,

+ 12 - 0
tracim/models/context_models.py View File

@@ -5,6 +5,7 @@ from datetime import datetime
5 5
 from slugify import slugify
6 6
 from sqlalchemy.orm import Session
7 7
 from tracim import CFG
8
+from tracim.config import PreviewDim
8 9
 from tracim.models import User
9 10
 from tracim.models.auth import Profile
10 11
 from tracim.models.data import Content
@@ -15,6 +16,17 @@ from tracim.models.workspace_menu_entries import WorkspaceMenuEntry
15 16
 from tracim.models.contents import ContentTypeLegacy as ContentType
16 17
 
17 18
 
19
+class PreviewAllowedDim(object):
20
+
21
+    def __init__(
22
+            self,
23
+            restricted:bool,
24
+            dimensions: typing.List[PreviewDim]
25
+    ) -> None:
26
+        self.restricted = restricted
27
+        self.dimensions = dimensions
28
+
29
+
18 30
 class MoveParams(object):
19 31
     """
20 32
     Json body params for move action model

+ 1 - 1
tracim/tests/__init__.py View File

@@ -78,7 +78,7 @@ class FunctionalTest(unittest.TestCase):
78 78
             'depot_storage_dir': '/tmp/test/depot',
79 79
             'depot_storage_name': 'test',
80 80
             'preview_cache_dir': '/tmp/test/preview_cache',
81
-            'preview.jpg.restricted_sizes': True,
81
+            'preview.jpg.restricted_dims': True,
82 82
 
83 83
         }
84 84
         hapic.reset_context()

+ 103 - 0
tracim/tests/functional/test_contents.py View File

@@ -1055,6 +1055,58 @@ class TestFiles(FunctionalTest):
1055 1055
         assert res.content_type == 'image/png'
1056 1056
         assert res.content_length == len(image.getvalue())
1057 1057
 
1058
+    def test_api__get_allowed_size_dim__ok__nominal_case(self) -> None:
1059
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
1060
+        admin = dbsession.query(models.User) \
1061
+            .filter(models.User.email == 'admin@admin.admin') \
1062
+            .one()
1063
+        workspace_api = WorkspaceApi(
1064
+            current_user=admin,
1065
+            session=dbsession,
1066
+            config=self.app_config
1067
+        )
1068
+        content_api = ContentApi(
1069
+            current_user=admin,
1070
+            session=dbsession,
1071
+            config=self.app_config
1072
+        )
1073
+        business_workspace = workspace_api.get_one(1)
1074
+        tool_folder = content_api.get_one(1, content_type=ContentType.Any)
1075
+        test_file = content_api.create(
1076
+            content_type=ContentType.File,
1077
+            workspace=business_workspace,
1078
+            parent=tool_folder,
1079
+            label='Test file',
1080
+            do_save=False,
1081
+            do_notify=False,
1082
+        )
1083
+        test_file.file_extension = '.txt'
1084
+        test_file.depot_file = FileIntent(
1085
+            b'Test file',
1086
+            'Test_file.txt',
1087
+            'text/plain',
1088
+        )
1089
+        dbsession.flush()
1090
+        transaction.commit()
1091
+        self.testapp.authorization = (
1092
+            'Basic',
1093
+            (
1094
+                'admin@admin.admin',
1095
+                'admin@admin.admin'
1096
+            )
1097
+        )
1098
+        content_id = int(test_file.content_id)
1099
+        res = self.testapp.get(
1100
+            '/api/v2/workspaces/1/files/{}/preview/jpg/allowed_dims'.format(content_id),
1101
+            status=200,
1102
+        )
1103
+        res = res.json_body
1104
+        assert res['restricted'] == True
1105
+        assert len(res['dimensions']) == 1
1106
+        dim = res['dimensions'][0]
1107
+        assert dim['width'] == 256
1108
+        assert dim['height'] == 256
1109
+
1058 1110
     def test_api__get_jpeg_preview__ok__200__nominal_case(self) -> None:
1059 1111
         """
1060 1112
         Set one file of a content
@@ -1169,6 +1221,57 @@ class TestFiles(FunctionalTest):
1169 1221
         new_image = Image.open(io.BytesIO(res.body))
1170 1222
         assert 256, 256 == new_image.size
1171 1223
 
1224
+    def test_api__get_sized_jpeg_preview__err__400__SizeNotAllowed(self) -> None:
1225
+        """
1226
+        get 256x256 preview of a txt file
1227
+        """
1228
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
1229
+        admin = dbsession.query(models.User) \
1230
+            .filter(models.User.email == 'admin@admin.admin') \
1231
+            .one()
1232
+        workspace_api = WorkspaceApi(
1233
+            current_user=admin,
1234
+            session=dbsession,
1235
+            config=self.app_config
1236
+        )
1237
+        content_api = ContentApi(
1238
+            current_user=admin,
1239
+            session=dbsession,
1240
+            config=self.app_config
1241
+        )
1242
+        business_workspace = workspace_api.get_one(1)
1243
+        tool_folder = content_api.get_one(1, content_type=ContentType.Any)
1244
+        test_file = content_api.create(
1245
+            content_type=ContentType.File,
1246
+            workspace=business_workspace,
1247
+            parent=tool_folder,
1248
+            label='Test file',
1249
+            do_save=True,
1250
+            do_notify=False,
1251
+        )
1252
+        dbsession.flush()
1253
+        transaction.commit()
1254
+        content_id = int(test_file.content_id)
1255
+        image = create_test_image()
1256
+        self.testapp.authorization = (
1257
+            'Basic',
1258
+            (
1259
+                'admin@admin.admin',
1260
+                'admin@admin.admin'
1261
+            )
1262
+        )
1263
+        res = self.testapp.put(
1264
+            '/api/v2/workspaces/1/files/{}/raw'.format(content_id),
1265
+            upload_files=[
1266
+                ('files',image.name, image.getvalue())
1267
+            ],
1268
+            status=204,
1269
+        )
1270
+        res = self.testapp.get(
1271
+            '/api/v2/workspaces/1/files/{}/preview/jpg/512x512'.format(content_id),  # nopep8
1272
+            status=400
1273
+        )
1274
+
1172 1275
     def test_api__get_sized_jpeg_revision_preview__ok__200__nominal_case(self) -> None:
1173 1276
         """
1174 1277
         get 256x256 revision preview of a txt file

+ 19 - 6
tracim/views/contents_api/file_controller.py View File

@@ -7,9 +7,6 @@ from preview_generator.exception import UnavailablePreviewType
7 7
 from pyramid.config import Configurator
8 8
 from pyramid.response import FileResponse, FileIter
9 9
 
10
-from tracim.exceptions import EmptyLabelNotAllowed
11
-from tracim.models.data import UserRoleInWorkspace
12
-
13 10
 try:  # Python 3.5+
14 11
     from http import HTTPStatus
15 12
 except ImportError:
@@ -20,6 +17,7 @@ from tracim.extensions import hapic
20 17
 from tracim.lib.core.content import ContentApi
21 18
 from tracim.views.controllers import Controller
22 19
 from tracim.views.core_api.schemas import FileContentSchema
20
+from tracim.views.core_api.schemas import AllowedJpgPreviewDimSchema
23 21
 from tracim.views.core_api.schemas import ContentPreviewSizedPathSchema
24 22
 from tracim.views.core_api.schemas import RevisionPreviewSizedPathSchema
25 23
 from tracim.views.core_api.schemas import PageQuerySchema
@@ -31,11 +29,14 @@ from tracim.views.core_api.schemas import WorkspaceAndContentIdPathSchema
31 29
 from tracim.views.core_api.schemas import NoContentSchema
32 30
 from tracim.lib.utils.authorization import require_content_types
33 31
 from tracim.lib.utils.authorization import require_workspace_role
32
+from tracim.models.data import UserRoleInWorkspace
34 33
 from tracim.models.context_models import ContentInContext
35 34
 from tracim.models.context_models import RevisionInContext
36 35
 from tracim.models.contents import ContentTypeLegacy as ContentType
37 36
 from tracim.models.contents import file_type
38 37
 from tracim.models.revision_protection import new_revision
38
+from tracim.exceptions import EmptyLabelNotAllowed
39
+from tracim.exceptions import PreviewDimNotAllowed
39 40
 
40 41
 FILE_ENDPOINTS_TAG = 'Files'
41 42
 
@@ -217,16 +218,20 @@ class FileController(Controller):
217 218
             hapic_data.path.content_id,
218 219
             content_type=ContentType.Any
219 220
         )
221
+        allowed_dim = api.get_jpg_preview_allowed_dim()
220 222
         jpg_preview_path = api.get_jpg_preview_path(
221 223
             content_id=content.content_id,
222 224
             revision_id=content.revision_id,
223
-            page=hapic_data.query.page
225
+            page=hapic_data.query.page,
226
+            width=allowed_dim.dimensions[0].width,
227
+            height=allowed_dim.dimensions[0].height,
224 228
         )
225 229
         return FileResponse(jpg_preview_path)
226 230
 
227 231
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
228 232
     @require_workspace_role(UserRoleInWorkspace.READER)
229 233
     @require_content_types([file_type])
234
+    @hapic.handle_exception(PreviewDimNotAllowed, HTTPStatus.BAD_REQUEST)
230 235
     @hapic.input_query(PageQuerySchema())
231 236
     @hapic.input_path(ContentPreviewSizedPathSchema())
232 237
     @hapic.output_file([])
@@ -253,6 +258,7 @@ class FileController(Controller):
253 258
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
254 259
     @require_workspace_role(UserRoleInWorkspace.READER)
255 260
     @require_content_types([file_type])
261
+    @hapic.handle_exception(PreviewDimNotAllowed, HTTPStatus.BAD_REQUEST)
256 262
     @hapic.input_path(RevisionPreviewSizedPathSchema())
257 263
     @hapic.input_query(PageQuerySchema())
258 264
     @hapic.output_file([])
@@ -283,9 +289,16 @@ class FileController(Controller):
283 289
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
284 290
     @require_workspace_role(UserRoleInWorkspace.READER)
285 291
     @require_content_types([file_type])
286
-    @hapic.output_file([])
292
+    @hapic.input_path(WorkspaceAndContentIdPathSchema())
293
+    @hapic.output_body(AllowedJpgPreviewDimSchema())
287 294
     def allowed_dim_preview_jpg(self, context, request: TracimRequest, hapic_data=None):
288
-        raise NotImplemented()
295
+        app_config = request.registry.settings['CFG']
296
+        api = ContentApi(
297
+            current_user=request.current_user,
298
+            session=request.dbsession,
299
+            config=app_config,
300
+        )
301
+        return api.get_jpg_preview_allowed_dim()
289 302
 
290 303
     # File infos
291 304
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])

+ 13 - 0
tracim/views/core_api/schemas.py View File

@@ -112,6 +112,19 @@ class WidthAndHeightPathSchema(marshmallow.Schema):
112 112
     height = marshmallow.fields.Int(example=256)
113 113
 
114 114
 
115
+class AllowedJpgPreviewSizesSchema(marshmallow.Schema):
116
+    width = marshmallow.fields.Int(example=256)
117
+    height = marshmallow.fields.Int(example=256)
118
+
119
+
120
+class AllowedJpgPreviewDimSchema(marshmallow.Schema):
121
+    restricted = marshmallow.fields.Bool()
122
+    dimensions = marshmallow.fields.Nested(
123
+        AllowedJpgPreviewSizesSchema,
124
+        many=True
125
+    )
126
+
127
+
115 128
 class WorkspaceAndContentRevisionIdPathSchema(
116 129
     WorkspaceIdPathSchema,
117 130
     ContentIdPathSchema,