Explorar el Código

add endpoint for revision download file

Guénaël Muller hace 6 años
padre
commit
eaf307881c

+ 4 - 0
tracim/exceptions.py Ver fichero

143
 
143
 
144
 class EmptyRawContentNotAllowed(EmptyValueNotAllowed):
144
 class EmptyRawContentNotAllowed(EmptyValueNotAllowed):
145
     pass
145
     pass
146
+
147
+
148
+class RevisionDoesNotMatchThisContent(TracimException):
149
+    pass

+ 13 - 3
tracim/lib/core/content.py Ver fichero

24
 
24
 
25
 from tracim.lib.utils.utils import cmp_to_key
25
 from tracim.lib.utils.utils import cmp_to_key
26
 from tracim.lib.core.notifications import NotifierFactory
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
 from tracim.exceptions import EmptyLabelNotAllowed
30
 from tracim.exceptions import EmptyLabelNotAllowed
29
 from tracim.exceptions import ContentNotFound
31
 from tracim.exceptions import ContentNotFound
30
 from tracim.exceptions import WorkspacesDoNotMatch
32
 from tracim.exceptions import WorkspacesDoNotMatch
486
             raise ContentNotFound('Content "{}" not found in database'.format(content_id)) from exc  # nopep8
488
             raise ContentNotFound('Content "{}" not found in database'.format(content_id)) from exc  # nopep8
487
         return content
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
         This method allow us to get directly any revision with its id
493
         This method allow us to get directly any revision with its id
492
         :param revision_id: The content's revision's id that we want to return
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
         :return: An item Content linked with the correct revision
497
         :return: An item Content linked with the correct revision
494
         """
498
         """
495
         assert revision_id is not None# DYN_REMOVE
499
         assert revision_id is not None# DYN_REMOVE
496
 
500
 
497
         revision = self._session.query(ContentRevisionRO).filter(ContentRevisionRO.revision_id == revision_id).one()
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
         return revision
509
         return revision
500
 
510
 
501
     # INFO - A.P - 2017-07-03 - python file object getter
511
     # INFO - A.P - 2017-07-03 - python file object getter

+ 10 - 0
tracim/models/context_models.py Ver fichero

43
         self.workspace_id = workspace_id
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
 class CommentPath(object):
56
 class CommentPath(object):
47
     """
57
     """
48
     Paths params with workspace id and content_id and comment_id model
58
     Paths params with workspace id and content_id and comment_id model

+ 23 - 4
tracim/views/contents_api/file_controller.py Ver fichero

20
 from tracim.lib.core.content import ContentApi
20
 from tracim.lib.core.content import ContentApi
21
 from tracim.views.controllers import Controller
21
 from tracim.views.controllers import Controller
22
 from tracim.views.core_api.schemas import FileContentSchema
22
 from tracim.views.core_api.schemas import FileContentSchema
23
+from tracim.views.core_api.schemas import WorkspaceAndContentRevisionIdPathSchema  # nopep8
23
 from tracim.views.core_api.schemas import FileRevisionSchema
24
 from tracim.views.core_api.schemas import FileRevisionSchema
24
 from tracim.views.core_api.schemas import SetContentStatusSchema
25
 from tracim.views.core_api.schemas import SetContentStatusSchema
25
 from tracim.views.core_api.schemas import FileContentModifySchema
26
 from tracim.views.core_api.schemas import FileContentModifySchema
97
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
98
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
98
     @require_workspace_role(UserRoleInWorkspace.READER)
99
     @require_workspace_role(UserRoleInWorkspace.READER)
99
     @require_content_types([file_type])
100
     @require_content_types([file_type])
100
-    @hapic.input_path(WorkspaceAndContentIdPathSchema())
101
+    @hapic.input_path(WorkspaceAndContentRevisionIdPathSchema())
101
     @hapic.output_file([])
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
     # preview
124
     # preview
106
     # pdf
125
     # pdf
335
         # download raw file of revision
354
         # download raw file of revision
336
         configurator.add_route(
355
         configurator.add_route(
337
             'download_revision',
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
             request_method='GET'
358
             request_method='GET'
340
         )
359
         )
341
         configurator.add_view(self.download_revisions_file, route_name='download_revision')  # nopep8
360
         configurator.add_view(self.download_revisions_file, route_name='download_revision')  # nopep8

+ 14 - 0
tracim/views/core_api/schemas.py Ver fichero

10
 from tracim.models.contents import ContentTypeLegacy as ContentType
10
 from tracim.models.contents import ContentTypeLegacy as ContentType
11
 from tracim.models.contents import ContentStatusLegacy as ContentStatus
11
 from tracim.models.contents import ContentStatusLegacy as ContentStatus
12
 from tracim.models.context_models import ContentCreation
12
 from tracim.models.context_models import ContentCreation
13
+from tracim.models.context_models import WorkspaceAndContentRevisionPath
13
 from tracim.models.context_models import CommentCreation
14
 from tracim.models.context_models import CommentCreation
14
 from tracim.models.context_models import TextBasedContentUpdate
15
 from tracim.models.context_models import TextBasedContentUpdate
15
 from tracim.models.context_models import SetContentStatus
16
 from tracim.models.context_models import SetContentStatus
89
 class ContentIdPathSchema(marshmallow.Schema):
90
 class ContentIdPathSchema(marshmallow.Schema):
90
     content_id = marshmallow.fields.Int(example=6, required=True)
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
 class WorkspaceAndContentIdPathSchema(
97
 class WorkspaceAndContentIdPathSchema(
94
     WorkspaceIdPathSchema,
98
     WorkspaceIdPathSchema,
99
         return WorkspaceAndContentPath(**data)
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
 class CommentsPathSchema(WorkspaceAndContentIdPathSchema):
116
 class CommentsPathSchema(WorkspaceAndContentIdPathSchema):
103
     comment_id = marshmallow.fields.Int(
117
     comment_id = marshmallow.fields.Int(
104
         example=6,
118
         example=6,