Преглед на файлове

add endpoint for revision download file

Guénaël Muller преди 6 години
родител
ревизия
eaf307881c
променени са 5 файла, в които са добавени 64 реда и са изтрити 7 реда
  1. 4 0
      tracim/exceptions.py
  2. 13 3
      tracim/lib/core/content.py
  3. 10 0
      tracim/models/context_models.py
  4. 23 4
      tracim/views/contents_api/file_controller.py
  5. 14 0
      tracim/views/core_api/schemas.py

+ 4 - 0
tracim/exceptions.py Целия файл

@@ -143,3 +143,7 @@ class EmptyLabelNotAllowed(EmptyValueNotAllowed):
143 143
 
144 144
 class EmptyRawContentNotAllowed(EmptyValueNotAllowed):
145 145
     pass
146
+
147
+
148
+class RevisionDoesNotMatchThisContent(TracimException):
149
+    pass

+ 13 - 3
tracim/lib/core/content.py Целия файл

@@ -24,7 +24,9 @@ from sqlalchemy.sql.elements import and_
24 24
 
25 25
 from tracim.lib.utils.utils import cmp_to_key
26 26
 from tracim.lib.core.notifications import NotifierFactory
27
-from tracim.exceptions import SameValueError, EmptyRawContentNotAllowed
27
+from tracim.exceptions import SameValueError
28
+from tracim.exceptions import EmptyRawContentNotAllowed
29
+from tracim.exceptions import RevisionDoesNotMatchThisContent
28 30
 from tracim.exceptions import EmptyLabelNotAllowed
29 31
 from tracim.exceptions import ContentNotFound
30 32
 from tracim.exceptions import WorkspacesDoNotMatch
@@ -486,16 +488,24 @@ class ContentApi(object):
486 488
             raise ContentNotFound('Content "{}" not found in database'.format(content_id)) from exc  # nopep8
487 489
         return content
488 490
 
489
-    def get_one_revision(self, revision_id: int = None) -> ContentRevisionRO:
491
+    def get_one_revision(self, revision_id: int = None, content: Content= None) -> ContentRevisionRO:  # nopep8
490 492
         """
491 493
         This method allow us to get directly any revision with its id
492 494
         :param revision_id: The content's revision's id that we want to return
495
+        :param content: The content related to the revision, if None do not
496
+        check if revision is related to this content.
493 497
         :return: An item Content linked with the correct revision
494 498
         """
495 499
         assert revision_id is not None# DYN_REMOVE
496 500
 
497 501
         revision = self._session.query(ContentRevisionRO).filter(ContentRevisionRO.revision_id == revision_id).one()
498
-
502
+        if content and revision.content_id != content.content_id:
503
+            raise RevisionDoesNotMatchThisContent(
504
+                'revision {revision_id} is not a revision of content {content_id}'.format(  # nopep8
505
+                    revision_id=revision.revision_id,
506
+                    content_id=content.content_id,
507
+                    )
508
+            )
499 509
         return revision
500 510
 
501 511
     # INFO - A.P - 2017-07-03 - python file object getter

+ 10 - 0
tracim/models/context_models.py Целия файл

@@ -43,6 +43,16 @@ class WorkspaceAndContentPath(object):
43 43
         self.workspace_id = workspace_id
44 44
 
45 45
 
46
+class WorkspaceAndContentRevisionPath(object):
47
+    """
48
+    Paths params with workspace id and content_id model
49
+    """
50
+    def __init__(self, workspace_id: int, content_id: int, revision_id) -> None:
51
+        self.content_id = content_id
52
+        self.revision_id = revision_id
53
+        self.workspace_id = workspace_id
54
+
55
+
46 56
 class CommentPath(object):
47 57
     """
48 58
     Paths params with workspace id and content_id and comment_id model

+ 23 - 4
tracim/views/contents_api/file_controller.py Целия файл

@@ -20,6 +20,7 @@ from tracim.extensions import hapic
20 20
 from tracim.lib.core.content import ContentApi
21 21
 from tracim.views.controllers import Controller
22 22
 from tracim.views.core_api.schemas import FileContentSchema
23
+from tracim.views.core_api.schemas import WorkspaceAndContentRevisionIdPathSchema  # nopep8
23 24
 from tracim.views.core_api.schemas import FileRevisionSchema
24 25
 from tracim.views.core_api.schemas import SetContentStatusSchema
25 26
 from tracim.views.core_api.schemas import FileContentModifySchema
@@ -97,10 +98,28 @@ class FileController(Controller):
97 98
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
98 99
     @require_workspace_role(UserRoleInWorkspace.READER)
99 100
     @require_content_types([file_type])
100
-    @hapic.input_path(WorkspaceAndContentIdPathSchema())
101
+    @hapic.input_path(WorkspaceAndContentRevisionIdPathSchema())
101 102
     @hapic.output_file([])
102
-    def download_revisions_file(self, context, request: TracimRequest, hapic_data=None):
103
-        raise NotImplemented()
103
+    def download_revisions_file(self, context, request: TracimRequest, hapic_data=None):  # nopep8
104
+        app_config = request.registry.settings['CFG']
105
+        api = ContentApi(
106
+            current_user=request.current_user,
107
+            session=request.dbsession,
108
+            config=app_config,
109
+        )
110
+        content = api.get_one(
111
+            hapic_data.path.content_id,
112
+            content_type=ContentType.Any
113
+        )
114
+        revision = api.get_one_revision(
115
+            revision_id=hapic_data.path.revision_id,
116
+            content=content
117
+        )
118
+        file = DepotManager.get().get(revision.depot_file)
119
+        response = request.response
120
+        response.content_type = file.content_type
121
+        response.app_iter = FileIter(file)
122
+        return response
104 123
 
105 124
     # preview
106 125
     # pdf
@@ -335,7 +354,7 @@ class FileController(Controller):
335 354
         # download raw file of revision
336 355
         configurator.add_route(
337 356
             'download_revision',
338
-            '/workspaces/{workspace_id}/files/{content_id}/revisions/{content_revision}/raw',  # nopep8
357
+            '/workspaces/{workspace_id}/files/{content_id}/revisions/{revision_id}/raw',  # nopep8
339 358
             request_method='GET'
340 359
         )
341 360
         configurator.add_view(self.download_revisions_file, route_name='download_revision')  # nopep8

+ 14 - 0
tracim/views/core_api/schemas.py Целия файл

@@ -10,6 +10,7 @@ from tracim.models.contents import open_status
10 10
 from tracim.models.contents import ContentTypeLegacy as ContentType
11 11
 from tracim.models.contents import ContentStatusLegacy as ContentStatus
12 12
 from tracim.models.context_models import ContentCreation
13
+from tracim.models.context_models import WorkspaceAndContentRevisionPath
13 14
 from tracim.models.context_models import CommentCreation
14 15
 from tracim.models.context_models import TextBasedContentUpdate
15 16
 from tracim.models.context_models import SetContentStatus
@@ -89,6 +90,9 @@ class WorkspaceIdPathSchema(marshmallow.Schema):
89 90
 class ContentIdPathSchema(marshmallow.Schema):
90 91
     content_id = marshmallow.fields.Int(example=6, required=True)
91 92
 
93
+class RevisionIdPathSchema(marshmallow.Schema):
94
+    revision_id = marshmallow.fields.Int(example=6, required=True)
95
+
92 96
 
93 97
 class WorkspaceAndContentIdPathSchema(
94 98
     WorkspaceIdPathSchema,
@@ -99,6 +103,16 @@ class WorkspaceAndContentIdPathSchema(
99 103
         return WorkspaceAndContentPath(**data)
100 104
 
101 105
 
106
+class WorkspaceAndContentRevisionIdPathSchema(
107
+    WorkspaceIdPathSchema,
108
+    ContentIdPathSchema,
109
+    RevisionIdPathSchema,
110
+):
111
+    @post_load
112
+    def make_path_object(self, data):
113
+        return WorkspaceAndContentRevisionPath(**data)
114
+
115
+
102 116
 class CommentsPathSchema(WorkspaceAndContentIdPathSchema):
103 117
     comment_id = marshmallow.fields.Int(
104 118
         example=6,