Browse Source

fix allowed_dims endpoint

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

+ 15 - 15
tracim/config.py View File

411
         #     self.RADICALE_CLIENT_BASE_URL_HOST,
411
         #     self.RADICALE_CLIENT_BASE_URL_HOST,
412
         #     self.RADICALE_CLIENT_BASE_URL_PREFIX,
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
                 parts = sizes.split('x')
421
                 parts = sizes.split('x')
419
                 assert len(parts) == 2
422
                 assert len(parts) == 2
420
                 width, height = parts
423
                 width, height = parts
421
                 assert width.isdecimal()
424
                 assert width.isdecimal()
422
                 assert height.isdecimal()
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
     def configure_filedepot(self):
435
     def configure_filedepot(self):
436
         depot_storage_name = self.DEPOT_STORAGE_NAME
436
         depot_storage_name = self.DEPOT_STORAGE_NAME
449
         TREEVIEW_ALL = 'all'
449
         TREEVIEW_ALL = 'all'
450
 
450
 
451
 
451
 
452
-class PreviewSize(object):
452
+class PreviewDim(object):
453
 
453
 
454
     def __init__(self, width: int, height: int) -> None:
454
     def __init__(self, width: int, height: int) -> None:
455
         self.width = width
455
         self.width = width
456
         self.height = height
456
         self.height = height
457
 
457
 
458
     def __repr__(self):
458
     def __repr__(self):
459
-        return "<PreviewSize width:{width} height:{height}>".format(
459
+        return "<PreviewDim width:{width} height:{height}>".format(
460
             width=self.width,
460
             width=self.width,
461
             height=self.height,
461
             height=self.height,
462
         )
462
         )

+ 3 - 2
tracim/exceptions.py View File

152
 class PageOfPreviewNotFound(NotFound):
152
 class PageOfPreviewNotFound(NotFound):
153
     pass
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
 from sqlalchemy import or_
23
 from sqlalchemy import or_
24
 from sqlalchemy.sql.elements import and_
24
 from sqlalchemy.sql.elements import and_
25
 
25
 
26
+from tracim.config import PreviewDim
26
 from tracim.lib.utils.utils import cmp_to_key
27
 from tracim.lib.utils.utils import cmp_to_key
27
 from tracim.lib.core.notifications import NotifierFactory
28
 from tracim.lib.core.notifications import NotifierFactory
28
 from tracim.exceptions import SameValueError
29
 from tracim.exceptions import SameValueError
29
 from tracim.exceptions import PageOfPreviewNotFound
30
 from tracim.exceptions import PageOfPreviewNotFound
30
-from tracim.exceptions import PreviewSizeNotAllowed
31
+from tracim.exceptions import PreviewDimNotAllowed
31
 from tracim.exceptions import EmptyRawContentNotAllowed
32
 from tracim.exceptions import EmptyRawContentNotAllowed
32
 from tracim.exceptions import RevisionDoesNotMatchThisContent
33
 from tracim.exceptions import RevisionDoesNotMatchThisContent
33
 from tracim.exceptions import EmptyLabelNotAllowed
34
 from tracim.exceptions import EmptyLabelNotAllowed
46
 from tracim.models.data import UserRoleInWorkspace
47
 from tracim.models.data import UserRoleInWorkspace
47
 from tracim.models.data import Workspace
48
 from tracim.models.data import Workspace
48
 from tracim.lib.utils.translation import fake_translator as _
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
 from tracim.models.context_models import ContentInContext
52
 from tracim.models.context_models import ContentInContext
51
 
53
 
52
 __author__ = 'damien'
54
 __author__ = 'damien'
762
         pdf_preview_path = self.preview_manager.get_pdf_preview(file_path)
764
         pdf_preview_path = self.preview_manager.get_pdf_preview(file_path)
763
         return pdf_preview_path
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
     def get_jpg_preview_path(
772
     def get_jpg_preview_path(
766
         self,
773
         self,
767
         content_id: int,
774
         content_id: int,
789
                 ),
796
                 ),
790
             )
797
             )
791
         if not width and not height:
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
                 break
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
                 'Size {width}x{height} is not allowed for jpeg preview'.format(
810
                 'Size {width}x{height} is not allowed for jpeg preview'.format(
804
                     width=width,
811
                     width=width,
805
                     height=height,
812
                     height=height,

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

5
 from slugify import slugify
5
 from slugify import slugify
6
 from sqlalchemy.orm import Session
6
 from sqlalchemy.orm import Session
7
 from tracim import CFG
7
 from tracim import CFG
8
+from tracim.config import PreviewDim
8
 from tracim.models import User
9
 from tracim.models import User
9
 from tracim.models.auth import Profile
10
 from tracim.models.auth import Profile
10
 from tracim.models.data import Content
11
 from tracim.models.data import Content
15
 from tracim.models.contents import ContentTypeLegacy as ContentType
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
 class MoveParams(object):
30
 class MoveParams(object):
19
     """
31
     """
20
     Json body params for move action model
32
     Json body params for move action model

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

78
             'depot_storage_dir': '/tmp/test/depot',
78
             'depot_storage_dir': '/tmp/test/depot',
79
             'depot_storage_name': 'test',
79
             'depot_storage_name': 'test',
80
             'preview_cache_dir': '/tmp/test/preview_cache',
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
         hapic.reset_context()
84
         hapic.reset_context()

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

1055
         assert res.content_type == 'image/png'
1055
         assert res.content_type == 'image/png'
1056
         assert res.content_length == len(image.getvalue())
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
     def test_api__get_jpeg_preview__ok__200__nominal_case(self) -> None:
1110
     def test_api__get_jpeg_preview__ok__200__nominal_case(self) -> None:
1059
         """
1111
         """
1060
         Set one file of a content
1112
         Set one file of a content
1169
         new_image = Image.open(io.BytesIO(res.body))
1221
         new_image = Image.open(io.BytesIO(res.body))
1170
         assert 256, 256 == new_image.size
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
     def test_api__get_sized_jpeg_revision_preview__ok__200__nominal_case(self) -> None:
1275
     def test_api__get_sized_jpeg_revision_preview__ok__200__nominal_case(self) -> None:
1173
         """
1276
         """
1174
         get 256x256 revision preview of a txt file
1277
         get 256x256 revision preview of a txt file

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

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

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

112
     height = marshmallow.fields.Int(example=256)
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
 class WorkspaceAndContentRevisionIdPathSchema(
128
 class WorkspaceAndContentRevisionIdPathSchema(
116
     WorkspaceIdPathSchema,
129
     WorkspaceIdPathSchema,
117
     ContentIdPathSchema,
130
     ContentIdPathSchema,