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

FileController.update_file_info()   A

Complexity

Conditions 2

Size

Total Lines 37
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

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