Passed
Pull Request — develop (#77)
by inkhey
01:18
created

FileController.preview_pdf()   A

Complexity

Conditions 1

Size

Total Lines 35
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 29
dl 0
loc 35
rs 9.184
c 0
b 0
f 0
cc 1
nop 4
1
# coding=utf-8
2
import typing
3
4
import transaction
5
from depot.manager import DepotManager
6
from preview_generator.exception import UnavailablePreviewType
7
from pyramid.config import Configurator
8
9
from hapic.data import HapicFile
10
from tracim_backend.app_models.contents import CONTENT_TYPES
11
from tracim_backend.app_models.contents import FILE_TYPE
12
from tracim_backend.exceptions import ContentLabelAlreadyUsedHere
13
from tracim_backend.exceptions import ContentNotFound
14
from tracim_backend.exceptions import EmptyLabelNotAllowed
15
from tracim_backend.exceptions import PageOfPreviewNotFound
16
from tracim_backend.exceptions import ParentNotFound
17
from tracim_backend.exceptions import PreviewDimNotAllowed
18
from tracim_backend.exceptions import UnavailablePreview
19
from tracim_backend.extensions import hapic
20
from tracim_backend.lib.core.content import ContentApi
21
from tracim_backend.lib.utils.authorization import require_content_types
22
from tracim_backend.lib.utils.authorization import require_workspace_role
23
from tracim_backend.lib.utils.request import TracimRequest
24
from tracim_backend.models.context_models import ContentInContext
25
from tracim_backend.models.context_models import RevisionInContext
26
from tracim_backend.models.data import ActionDescription
27
from tracim_backend.models.data import UserRoleInWorkspace
28
from tracim_backend.models.revision_protection import new_revision
29
from tracim_backend.views.controllers import Controller
30
from tracim_backend.views.core_api.schemas import AllowedJpgPreviewDimSchema
31
from tracim_backend.views.core_api.schemas import ContentDigestSchema
32
from tracim_backend.views.core_api.schemas import ContentPreviewSizedPathSchema
33
from tracim_backend.views.core_api.schemas import FileContentModifySchema
34
from tracim_backend.views.core_api.schemas import FileContentSchema
35
from tracim_backend.views.core_api.schemas import FileQuerySchema
36
from tracim_backend.views.core_api.schemas import FileRevisionSchema
37
from tracim_backend.views.core_api.schemas import NoContentSchema
38
from tracim_backend.views.core_api.schemas import PageQuerySchema
39
from tracim_backend.views.core_api.schemas import \
40
    RevisionPreviewSizedPathSchema
41
from tracim_backend.views.core_api.schemas import SetContentStatusSchema
42
from tracim_backend.views.core_api.schemas import \
43
    WorkspaceAndContentIdPathSchema
44
from tracim_backend.views.core_api.schemas import \
45
    WorkspaceAndContentRevisionIdPathSchema
46
from tracim_backend.views.core_api.schemas import WorkspaceIdPathSchema
47
48
try:  # Python 3.5+
49
    from http import HTTPStatus
50
except ImportError:
51
    from http import client as HTTPStatus
52
53
54
SWAGGER_TAG__FILE_ENDPOINTS = 'Files'
55
56
57
class FileController(Controller):
58
    """
59
    Endpoints for File Content
60
    """
61
62
    # File data
63
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
64
    @require_workspace_role(UserRoleInWorkspace.CONTRIBUTOR)
65
    @hapic.input_path(WorkspaceIdPathSchema())
66
    @hapic.output_body(ContentDigestSchema())
67
    # TODO - G.M - 2018-07-24 - Use hapic for input file
68
    def create_file(self, context, request: TracimRequest, hapic_data=None):
69
        """
70
        Create a file .This will create 2 new
71
        revision.
72
        """
73
        app_config = request.registry.settings['CFG']
74
        api = ContentApi(
75
            show_archived=True,
76
            show_deleted=True,
77
            current_user=request.current_user,
78
            session=request.dbsession,
79
            config=app_config,
80
        )
81
        file = request.POST['files']
82
        api = ContentApi(
83
            current_user=request.current_user,
84
            session=request.dbsession,
85
            config=app_config
86
        )
87
88
        parent = None
89
        # TODO - G.M - 2018-09-28 - Support parent for file creation
90
        # if creation_data.parent_id:
91
        #     try:
92
        #         parent = api.get_one(content_id=creation_data.parent_id, content_type=CONTENT_TYPES.Any_SLUG)  # nopep8
93
        #     except ContentNotFound as exc:
94
        #         raise ParentNotFound(
95
        #             'Parent with content_id {} not found'.format(creation_data.parent_id)
96
        #         ) from exc
97
        content = api.create(
98
            filename=file.filename,
99
            content_type_slug=FILE_TYPE,
100
            workspace=request.current_workspace,
101
            parent=parent,
102
        )
103
        api.save(content, ActionDescription.CREATION)
104
        with new_revision(
105
                session=request.dbsession,
106
                tm=transaction.manager,
107
                content=content
108
        ):
109
            api.update_file_data(
110
                content,
111
                new_filename=file.filename,
112
                new_mimetype=file.type,
113
                new_content=file.file,
114
            )
115
116
        return api.get_content_in_context(content)
117
118
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
119
    @require_workspace_role(UserRoleInWorkspace.CONTRIBUTOR)
120
    @require_content_types([FILE_TYPE])
121
    @hapic.input_path(WorkspaceAndContentIdPathSchema())
122
    # TODO - G.M - 2018-07-24 - Use hapic for input file
123
    @hapic.output_body(NoContentSchema(), default_http_code=HTTPStatus.NO_CONTENT)  # nopep8
124
    def upload_file(self, context, request: TracimRequest, hapic_data=None):
125
        """
126
        Upload a new version of raw file of content. This will create a new
127
        revision.
128
        """
129
        app_config = request.registry.settings['CFG']
130
        api = ContentApi(
131
            show_archived=True,
132
            show_deleted=True,
133
            current_user=request.current_user,
134
            session=request.dbsession,
135
            config=app_config,
136
        )
137
        content = api.get_one(
138
            hapic_data.path.content_id,
139
            content_type=CONTENT_TYPES.Any_SLUG
140
        )
141
        file = request.POST['files']
142
        with new_revision(
143
                session=request.dbsession,
144
                tm=transaction.manager,
145
                content=content
146
        ):
147
            api.update_file_data(
148
                content,
149
                new_filename=file.filename,
150
                new_mimetype=file.type,
151
                new_content=file.file,
152
            )
153
154
        return
155
156 View Code Duplication
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
157
    @require_workspace_role(UserRoleInWorkspace.READER)
158
    @require_content_types([FILE_TYPE])
159
    @hapic.input_query(FileQuerySchema())
160
    @hapic.input_path(WorkspaceAndContentIdPathSchema())
161
    @hapic.output_file([])
162
    def download_file(self, context, request: TracimRequest, hapic_data=None):
163
        """
164
        Download raw file of last revision of content.
165
        """
166
        app_config = request.registry.settings['CFG']
167
        api = ContentApi(
168
            show_archived=True,
169
            show_deleted=True,
170
            current_user=request.current_user,
171
            session=request.dbsession,
172
            config=app_config,
173
        )
174
        content = api.get_one(
175
            hapic_data.path.content_id,
176
            content_type=CONTENT_TYPES.Any_SLUG
177
        )
178
        file = DepotManager.get().get(content.depot_file)
179
        return HapicFile(
180
            file_object=file,
181
            mimetype=file.content_type,
182
            filename=content.file_name,
183
            as_attachment=hapic_data.query.force_download
184
        )
185
186 View Code Duplication
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
187
    @require_workspace_role(UserRoleInWorkspace.READER)
188
    @require_content_types([FILE_TYPE])
189
    @hapic.input_query(FileQuerySchema())
190
    @hapic.input_path(WorkspaceAndContentRevisionIdPathSchema())
191
    @hapic.output_file([])
192
    def download_revisions_file(self, context, request: TracimRequest, hapic_data=None):  # nopep8
193
        """
194
        Download raw file for specific revision of content.
195
        """
196
        app_config = request.registry.settings['CFG']
197
        api = ContentApi(
198
            show_archived=True,
199
            show_deleted=True,
200
            current_user=request.current_user,
201
            session=request.dbsession,
202
            config=app_config,
203
        )
204
        content = api.get_one(
205
            hapic_data.path.content_id,
206
            content_type=CONTENT_TYPES.Any_SLUG
207
        )
208
        revision = api.get_one_revision(
209
            revision_id=hapic_data.path.revision_id,
210
            content=content
211
        )
212
        file = DepotManager.get().get(revision.depot_file)
213
        return HapicFile(
214
            file_object=file,
215
            mimetype=file.content_type,
216
            filename=revision.file_name,
217
            as_attachment=hapic_data.query.force_download
218
        )
219
220
    # preview
221
    # pdf
222
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
223
    @require_workspace_role(UserRoleInWorkspace.READER)
224
    @require_content_types([FILE_TYPE])
225
    @hapic.handle_exception(UnavailablePreviewType, HTTPStatus.BAD_REQUEST)
226
    @hapic.handle_exception(UnavailablePreview, HTTPStatus.BAD_REQUEST)
227
    @hapic.handle_exception(PageOfPreviewNotFound, HTTPStatus.BAD_REQUEST)
228
    @hapic.input_query(PageQuerySchema())
229
    @hapic.input_path(WorkspaceAndContentIdPathSchema())
230
    @hapic.output_file([])
231
    def preview_pdf(self, context, request: TracimRequest, hapic_data=None):
232
        """
233
        Obtain a specific page pdf preview of last revision of content.
234
        """
235
        app_config = request.registry.settings['CFG']
236
        api = ContentApi(
237
            show_archived=True,
238
            show_deleted=True,
239
            current_user=request.current_user,
240
            session=request.dbsession,
241
            config=app_config,
242
        )
243
        content = api.get_one(
244
            hapic_data.path.content_id,
245
            content_type=CONTENT_TYPES.Any_SLUG
246
        )
247
        pdf_preview_path = api.get_pdf_preview_path(
248
            content.content_id,
249
            content.revision_id,
250
            page_number=hapic_data.query.page
251
        )
252
        filename = "{}_page_{}.pdf".format(content.label, hapic_data.query.page)
253
        return HapicFile(
254
            file_path=pdf_preview_path,
255
            filename=filename,
256
            as_attachment=hapic_data.query.force_download
257
        )
258
259 View Code Duplication
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
260
    @require_workspace_role(UserRoleInWorkspace.READER)
261
    @require_content_types([FILE_TYPE])
262
    @hapic.handle_exception(UnavailablePreview, HTTPStatus.BAD_REQUEST)
263
    @hapic.handle_exception(UnavailablePreviewType, HTTPStatus.BAD_REQUEST)
264
    @hapic.input_query(FileQuerySchema())
265
    @hapic.input_path(WorkspaceAndContentIdPathSchema())
266
    @hapic.output_file([])
267
    def preview_pdf_full(self, context, request: TracimRequest, hapic_data=None):  # nopep8
268
        """
269
        Obtain a full pdf preview (all page) of last revision of content.
270
        """
271
        app_config = request.registry.settings['CFG']
272
        api = ContentApi(
273
            show_archived=True,
274
            show_deleted=True,
275
            current_user=request.current_user,
276
            session=request.dbsession,
277
            config=app_config,
278
        )
279
        content = api.get_one(
280
            hapic_data.path.content_id,
281
            content_type=CONTENT_TYPES.Any_SLUG
282
        )
283
        pdf_preview_path = api.get_full_pdf_preview_path(content.revision_id)
284
        filename = "{label}.pdf".format(label=content.label)
285
        return HapicFile(
286
            file_path=pdf_preview_path,
287
            filename=filename,
288
            as_attachment=hapic_data.query.force_download
289
        )
290
291 View Code Duplication
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
292
    @require_workspace_role(UserRoleInWorkspace.READER)
293
    @require_content_types([FILE_TYPE])
294
    @hapic.handle_exception(UnavailablePreview, HTTPStatus.BAD_REQUEST)
295
    @hapic.handle_exception(UnavailablePreviewType, HTTPStatus.BAD_REQUEST)
296
    @hapic.input_path(WorkspaceAndContentRevisionIdPathSchema())
297
    @hapic.input_query(FileQuerySchema())
298
    @hapic.output_file([])
299
    def preview_pdf_full_revision(self, context, request: TracimRequest, hapic_data=None):  # nopep8
300
        """
301
        Obtain full pdf preview of a specific revision of content.
302
        """
303
        app_config = request.registry.settings['CFG']
304
        api = ContentApi(
305
            show_archived=True,
306
            show_deleted=True,
307
            current_user=request.current_user,
308
            session=request.dbsession,
309
            config=app_config,
310
        )
311
        content = api.get_one(
312
            hapic_data.path.content_id,
313
            content_type=CONTENT_TYPES.Any_SLUG
314
        )
315
        revision = api.get_one_revision(
316
            revision_id=hapic_data.path.revision_id,
317
            content=content
318
        )
319
        pdf_preview_path = api.get_full_pdf_preview_path(
320
            revision.revision_id,
321
        )
322
        filename = "{label}.pdf".format(label=revision.label)
323
        return HapicFile(
324
            file_path=pdf_preview_path,
325
            filename=filename,
326
            as_attachment=hapic_data.query.force_download
327
        )
328
329
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
330
    @require_workspace_role(UserRoleInWorkspace.READER)
331
    @require_content_types([FILE_TYPE])
332
    @hapic.handle_exception(UnavailablePreview, HTTPStatus.BAD_REQUEST)
333
    @hapic.handle_exception(UnavailablePreviewType, HTTPStatus.BAD_REQUEST)
334
    @hapic.input_path(WorkspaceAndContentRevisionIdPathSchema())
335
    @hapic.input_query(PageQuerySchema())
336
    @hapic.output_file([])
337
    def preview_pdf_revision(self, context, request: TracimRequest, hapic_data=None):  # nopep8
338
        """
339
        Obtain a specific page pdf preview of a specific revision of content.
340
        """
341
        app_config = request.registry.settings['CFG']
342
        api = ContentApi(
343
            show_archived=True,
344
            show_deleted=True,
345
            current_user=request.current_user,
346
            session=request.dbsession,
347
            config=app_config,
348
        )
349
        content = api.get_one(
350
            hapic_data.path.content_id,
351
            content_type=CONTENT_TYPES.Any_SLUG
352
        )
353
        revision = api.get_one_revision(
354
            revision_id=hapic_data.path.revision_id,
355
            content=content
356
        )
357
        pdf_preview_path = api.get_pdf_preview_path(
358
            revision.content_id,
359
            revision.revision_id,
360
            page_number=hapic_data.query.page
361
        )
362
        filename = "{label}_page_{page_number}.pdf".format(
363
            label=content.label,
364
            page_number=hapic_data.query.page
365
        )
366
        return HapicFile(
367
            file_path=pdf_preview_path,
368
            filename=filename,
369
            as_attachment=hapic_data.query.force_download
370
        )
371
372
    # jpg
373
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
374
    @require_workspace_role(UserRoleInWorkspace.READER)
375
    @require_content_types([FILE_TYPE])
376
    @hapic.handle_exception(UnavailablePreview, HTTPStatus.BAD_REQUEST)
377
    @hapic.handle_exception(PageOfPreviewNotFound, HTTPStatus.BAD_REQUEST)
378
    @hapic.input_path(WorkspaceAndContentIdPathSchema())
379
    @hapic.input_query(PageQuerySchema())
380
    @hapic.output_file([])
381
    def preview_jpg(self, context, request: TracimRequest, hapic_data=None):
382
        """
383
        Obtain normally sied jpg preview of last revision of content.
384
        """
385
        app_config = request.registry.settings['CFG']
386
        api = ContentApi(
387
            show_archived=True,
388
            show_deleted=True,
389
            current_user=request.current_user,
390
            session=request.dbsession,
391
            config=app_config,
392
        )
393
        content = api.get_one(
394
            hapic_data.path.content_id,
395
            content_type=CONTENT_TYPES.Any_SLUG
396
        )
397
        allowed_dim = api.get_jpg_preview_allowed_dim()
398
        jpg_preview_path = api.get_jpg_preview_path(
399
            content_id=content.content_id,
400
            revision_id=content.revision_id,
401
            page_number=hapic_data.query.page,
402
            width=allowed_dim.dimensions[0].width,
403
            height=allowed_dim.dimensions[0].height,
404
        )
405
        filename = "{label}_page_{page_number}.jpg".format(
406
            label=content.label,
407
            page_number=hapic_data.query.page
408
        )
409
        return HapicFile(
410
            file_path=jpg_preview_path,
411
            filename=filename,
412
            as_attachment=hapic_data.query.force_download
413
        )
414
415 View Code Duplication
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
416
    @require_workspace_role(UserRoleInWorkspace.READER)
417
    @require_content_types([FILE_TYPE])
418
    @hapic.handle_exception(UnavailablePreview, HTTPStatus.BAD_REQUEST)
419
    @hapic.handle_exception(PageOfPreviewNotFound, HTTPStatus.BAD_REQUEST)
420
    @hapic.handle_exception(PreviewDimNotAllowed, HTTPStatus.BAD_REQUEST)
421
    @hapic.input_query(PageQuerySchema())
422
    @hapic.input_path(ContentPreviewSizedPathSchema())
423
    @hapic.output_file([])
424
    def sized_preview_jpg(self, context, request: TracimRequest, hapic_data=None):  # nopep8
425
        """
426
        Obtain resized jpg preview of last revision of content.
427
        """
428
        app_config = request.registry.settings['CFG']
429
        api = ContentApi(
430
            show_archived=True,
431
            show_deleted=True,
432
            current_user=request.current_user,
433
            session=request.dbsession,
434
            config=app_config,
435
        )
436
        content = api.get_one(
437
            hapic_data.path.content_id,
438
            content_type=CONTENT_TYPES.Any_SLUG
439
        )
440
        jpg_preview_path = api.get_jpg_preview_path(
441
            content_id=content.content_id,
442
            revision_id=content.revision_id,
443
            page_number=hapic_data.query.page,
444
            height=hapic_data.path.height,
445
            width=hapic_data.path.width,
446
        )
447
        filename = "{label}_page_{page_number}_{width}x{height}.jpg".format(
448
            label=content.label,
449
            page_number=hapic_data.query.page,
450
            width=hapic_data.path.width,
451
            height=hapic_data.path.height
452
        )
453
        return HapicFile(
454
            file_path=jpg_preview_path,
455
            filename=filename,
456
            as_attachment=hapic_data.query.force_download
457
        )
458
459 View Code Duplication
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
460
    @require_workspace_role(UserRoleInWorkspace.READER)
461
    @require_content_types([FILE_TYPE])
462
    @hapic.handle_exception(UnavailablePreview, HTTPStatus.BAD_REQUEST)
463
    @hapic.handle_exception(PageOfPreviewNotFound, HTTPStatus.BAD_REQUEST)
464
    @hapic.handle_exception(PreviewDimNotAllowed, HTTPStatus.BAD_REQUEST)
465
    @hapic.input_path(RevisionPreviewSizedPathSchema())
466
    @hapic.input_query(PageQuerySchema())
467
    @hapic.output_file([])
468
    def sized_preview_jpg_revision(self, context, request: TracimRequest, hapic_data=None):  # nopep8
469
        """
470
        Obtain resized jpg preview of a specific revision of content.
471
        """
472
        app_config = request.registry.settings['CFG']
473
        api = ContentApi(
474
            show_archived=True,
475
            show_deleted=True,
476
            current_user=request.current_user,
477
            session=request.dbsession,
478
            config=app_config,
479
        )
480
        content = api.get_one(
481
            hapic_data.path.content_id,
482
            content_type=CONTENT_TYPES.Any_SLUG
483
        )
484
        revision = api.get_one_revision(
485
            revision_id=hapic_data.path.revision_id,
486
            content=content
487
        )
488
        jpg_preview_path = api.get_jpg_preview_path(
489
            content_id=content.content_id,
490
            revision_id=revision.revision_id,
491
            page_number=hapic_data.query.page,
492
            height=hapic_data.path.height,
493
            width=hapic_data.path.width,
494
        )
495
        filename = "{label}_page_{page_number}_{width}x{height}.jpg".format(
496
            label=revision.label,
497
            page_number=hapic_data.query.page,
498
            width=hapic_data.path.width,
499
            height=hapic_data.path.height
500
        )
501
        return HapicFile(
502
            file_path=jpg_preview_path,
503
            filename=filename,
504
            as_attachment=hapic_data.query.force_download
505
        )
506
507
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
508
    @require_workspace_role(UserRoleInWorkspace.READER)
509
    @require_content_types([FILE_TYPE])
510
    @hapic.input_path(WorkspaceAndContentIdPathSchema())
511
    @hapic.output_body(AllowedJpgPreviewDimSchema())
512
    def allowed_dim_preview_jpg(self, context, request: TracimRequest, hapic_data=None):  # nopep8
513
        """
514
        Get allowed dimensions of jpg preview. If restricted is true,
515
        only those dimensions are strictly accepted.
516
        """
517
        app_config = request.registry.settings['CFG']
518
        api = ContentApi(
519
            show_archived=True,
520
            show_deleted=True,
521
            current_user=request.current_user,
522
            session=request.dbsession,
523
            config=app_config,
524
        )
525
        return api.get_jpg_preview_allowed_dim()
526
527
    # File infos
528
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
529
    @require_workspace_role(UserRoleInWorkspace.READER)
530
    @require_content_types([FILE_TYPE])
531
    @hapic.input_path(WorkspaceAndContentIdPathSchema())
532
    @hapic.output_body(FileContentSchema())
533
    def get_file_infos(self, context, request: TracimRequest, hapic_data=None) -> ContentInContext:  # nopep8
534
        """
535
        Get thread content
536
        """
537
        app_config = request.registry.settings['CFG']
538
        api = ContentApi(
539
            show_archived=True,
540
            show_deleted=True,
541
            current_user=request.current_user,
542
            session=request.dbsession,
543
            config=app_config,
544
        )
545
        content = api.get_one(
546
            hapic_data.path.content_id,
547
            content_type=CONTENT_TYPES.Any_SLUG
548
        )
549
        return api.get_content_in_context(content)
550
551
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
552
    @hapic.handle_exception(EmptyLabelNotAllowed, HTTPStatus.BAD_REQUEST)
553
    @hapic.handle_exception(ContentLabelAlreadyUsedHere, HTTPStatus.BAD_REQUEST)
554
    @require_workspace_role(UserRoleInWorkspace.CONTRIBUTOR)
555
    @require_content_types([FILE_TYPE])
556
    @hapic.input_path(WorkspaceAndContentIdPathSchema())
557
    @hapic.input_body(FileContentModifySchema())
558
    @hapic.output_body(FileContentSchema())
559
    def update_file_info(self, context, request: TracimRequest, hapic_data=None) -> ContentInContext:  # nopep8
560
        """
561
        update thread
562
        """
563
        app_config = request.registry.settings['CFG']
564
        api = ContentApi(
565
            show_archived=True,
566
            show_deleted=True,
567
            current_user=request.current_user,
568
            session=request.dbsession,
569
            config=app_config,
570
        )
571
        content = api.get_one(
572
            hapic_data.path.content_id,
573
            content_type=CONTENT_TYPES.Any_SLUG
574
        )
575
        with new_revision(
576
                session=request.dbsession,
577
                tm=transaction.manager,
578
                content=content
579
        ):
580
            api.update_content(
581
                item=content,
582
                new_label=hapic_data.body.label,
583
                new_content=hapic_data.body.raw_content,
584
585
            )
586
            api.save(content)
587
        return api.get_content_in_context(content)
588
589
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
590
    @require_workspace_role(UserRoleInWorkspace.READER)
591
    @require_content_types([FILE_TYPE])
592
    @hapic.input_path(WorkspaceAndContentIdPathSchema())
593
    @hapic.output_body(FileRevisionSchema(many=True))
594
    def get_file_revisions(
595
            self,
596
            context,
597
            request: TracimRequest,
598
            hapic_data=None
599
    ) -> typing.List[RevisionInContext]:
600
        """
601
        get file revisions
602
        """
603
        app_config = request.registry.settings['CFG']
604
        api = ContentApi(
605
            show_archived=True,
606
            show_deleted=True,
607
            current_user=request.current_user,
608
            session=request.dbsession,
609
            config=app_config,
610
        )
611
        content = api.get_one(
612
            hapic_data.path.content_id,
613
            content_type=CONTENT_TYPES.Any_SLUG
614
        )
615
        revisions = content.revisions
616
        return [
617
            api.get_revision_in_context(revision)
618
            for revision in revisions
619
        ]
620
621
    @hapic.with_api_doc(tags=[SWAGGER_TAG__FILE_ENDPOINTS])
622
    @hapic.handle_exception(EmptyLabelNotAllowed, HTTPStatus.BAD_REQUEST)
623
    @require_workspace_role(UserRoleInWorkspace.CONTRIBUTOR)
624
    @require_content_types([FILE_TYPE])
625
    @hapic.input_path(WorkspaceAndContentIdPathSchema())
626
    @hapic.input_body(SetContentStatusSchema())
627
    @hapic.output_body(NoContentSchema(), default_http_code=HTTPStatus.NO_CONTENT)  # nopep8
628
    def set_file_status(self, context, request: TracimRequest, hapic_data=None) -> None:  # nopep8
629
        """
630
        set file status
631
        """
632
        app_config = request.registry.settings['CFG']
633
        api = ContentApi(
634
            show_archived=True,
635
            show_deleted=True,
636
            current_user=request.current_user,
637
            session=request.dbsession,
638
            config=app_config,
639
        )
640
        content = api.get_one(
641
            hapic_data.path.content_id,
642
            content_type=CONTENT_TYPES.Any_SLUG
643
        )
644
        with new_revision(
645
                session=request.dbsession,
646
                tm=transaction.manager,
647
                content=content
648
        ):
649
            api.set_status(
650
                content,
651
                hapic_data.body.status,
652
            )
653
            api.save(content)
654
        return
655
656
    def bind(self, configurator: Configurator) -> None:
657
        """
658
        Add route to configurator.
659
        """
660
661
        # file info #
662
        # Get file info
663
        configurator.add_route(
664
            'file_info',
665
            '/workspaces/{workspace_id}/files/{content_id}',
666
            request_method='GET'
667
        )
668
        configurator.add_view(self.get_file_infos, route_name='file_info')  # nopep8
669
        # update file
670
        configurator.add_route(
671
            'update_file_info',
672
            '/workspaces/{workspace_id}/files/{content_id}',
673
            request_method='PUT'
674
        )  # nopep8
675
        configurator.add_view(self.update_file_info, route_name='update_file_info')  # nopep8
676
677
        # raw file #
678
        # create file
679
        configurator.add_route(
680
            'create_file',
681
            '/workspaces/{workspace_id}/files',  # nopep8
682
            request_method='POST'
683
        )
684
        configurator.add_view(self.create_file, route_name='create_file')  # nopep8
685
        # upload raw file
686
        configurator.add_route(
687
            'upload_file',
688
            '/workspaces/{workspace_id}/files/{content_id}/raw',  # nopep8
689
            request_method='PUT'
690
        )
691
        configurator.add_view(self.upload_file, route_name='upload_file')  # nopep8
692
        # download raw file
693
        configurator.add_route(
694
            'download_file',
695
            '/workspaces/{workspace_id}/files/{content_id}/raw',  # nopep8
696
            request_method='GET'
697
        )
698
        configurator.add_view(self.download_file, route_name='download_file')  # nopep8
699
        # download raw file of revision
700
        configurator.add_route(
701
            'download_revision',
702
            '/workspaces/{workspace_id}/files/{content_id}/revisions/{revision_id}/raw',  # nopep8
703
            request_method='GET'
704
        )
705
        configurator.add_view(self.download_revisions_file, route_name='download_revision')  # nopep8
706
707
        # previews #
708
        # get preview pdf full
709
        configurator.add_route(
710
            'preview_pdf_full',
711
            '/workspaces/{workspace_id}/files/{content_id}/preview/pdf/full',  # nopep8
712
            request_method='GET'
713
        )
714
        configurator.add_view(self.preview_pdf_full, route_name='preview_pdf_full')  # nopep8
715
        # get preview pdf
716
        configurator.add_route(
717
            'preview_pdf',
718
            '/workspaces/{workspace_id}/files/{content_id}/preview/pdf',  # nopep8
719
            request_method='GET'
720
        )
721
        configurator.add_view(self.preview_pdf, route_name='preview_pdf')  # nopep8
722
        # get preview jpg allowed dims
723
        configurator.add_route(
724
            'allowed_dim_preview_jpg',
725
            '/workspaces/{workspace_id}/files/{content_id}/preview/jpg/allowed_dims',  # nopep8
726
            request_method='GET'
727
        )
728
        configurator.add_view(self.allowed_dim_preview_jpg, route_name='allowed_dim_preview_jpg')  # nopep8
729
        # get preview jpg
730
        configurator.add_route(
731
            'preview_jpg',
732
            '/workspaces/{workspace_id}/files/{content_id}/preview/jpg',  # nopep8
733
            request_method='GET'
734
        )
735
        configurator.add_view(self.preview_jpg, route_name='preview_jpg')  # nopep8
736
        # get preview jpg with size
737
        configurator.add_route(
738
            'sized_preview_jpg',
739
            '/workspaces/{workspace_id}/files/{content_id}/preview/jpg/{width}x{height}',  # nopep8
740
            request_method='GET'
741
        )
742
        configurator.add_view(self.sized_preview_jpg, route_name='sized_preview_jpg')  # nopep8
743
        # get jpg preview for revision
744
        configurator.add_route(
745
            'sized_preview_jpg_revision',
746
            '/workspaces/{workspace_id}/files/{content_id}/revisions/{revision_id}/preview/jpg/{width}x{height}',  # nopep8
747
            request_method='GET'
748
        )
749
        configurator.add_view(self.sized_preview_jpg_revision, route_name='sized_preview_jpg_revision')  # nopep8
750
        # get full pdf preview for revision
751
        configurator.add_route(
752
            'preview_pdf_full_revision',
753
            '/workspaces/{workspace_id}/files/{content_id}/revisions/{revision_id}/preview/pdf/full',  # nopep8
754
            request_method='GET'
755
        )
756
        configurator.add_view(self.preview_pdf_full_revision, route_name='preview_pdf_full_revision')  # nopep8
757
        # get pdf preview for revision
758
        configurator.add_route(
759
            'preview_pdf_revision',
760
            '/workspaces/{workspace_id}/files/{content_id}/revisions/{revision_id}/preview/pdf',  # nopep8
761
            request_method='GET'
762
        )
763
        configurator.add_view(self.preview_pdf_revision, route_name='preview_pdf_revision')  # nopep8
764
        # others #
765
        # get file revisions
766
        configurator.add_route(
767
            'file_revisions',
768
            '/workspaces/{workspace_id}/files/{content_id}/revisions',  # nopep8
769
            request_method='GET'
770
        )
771
        configurator.add_view(self.get_file_revisions, route_name='file_revisions')  # nopep8
772
773
        # get file status
774
        configurator.add_route(
775
            'set_file_status',
776
            '/workspaces/{workspace_id}/files/{content_id}/status',  # nopep8
777
            request_method='PUT'
778
        )
779
        configurator.add_view(self.set_file_status, route_name='set_file_status')  # nopep8
780