threads_controller.py 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. # coding=utf-8
  2. import typing
  3. import transaction
  4. from pyramid.config import Configurator
  5. from tracim.models.data import UserRoleInWorkspace
  6. try: # Python 3.5+
  7. from http import HTTPStatus
  8. except ImportError:
  9. from http import client as HTTPStatus
  10. from tracim import TracimRequest
  11. from tracim.extensions import hapic
  12. from tracim.lib.core.content import ContentApi
  13. from tracim.views.controllers import Controller
  14. from tracim.views.core_api.schemas import TextBasedContentSchema
  15. from tracim.views.core_api.schemas import TextBasedRevisionSchema
  16. from tracim.views.core_api.schemas import SetContentStatusSchema
  17. from tracim.views.core_api.schemas import TextBasedContentModifySchema
  18. from tracim.views.core_api.schemas import WorkspaceAndContentIdPathSchema
  19. from tracim.views.core_api.schemas import NoContentSchema
  20. from tracim.lib.utils.authorization import require_content_types
  21. from tracim.lib.utils.authorization import require_workspace_role
  22. from tracim.exceptions import WorkspaceNotFound, ContentTypeNotAllowed
  23. from tracim.exceptions import InsufficientUserRoleInWorkspace
  24. from tracim.exceptions import NotAuthenticated
  25. from tracim.exceptions import AuthenticationFailed
  26. from tracim.models.context_models import ContentInContext
  27. from tracim.models.context_models import RevisionInContext
  28. from tracim.models.contents import ContentTypeLegacy as ContentType
  29. from tracim.models.contents import thread_type
  30. from tracim.models.revision_protection import new_revision
  31. THREAD_ENDPOINTS_TAG = 'Threads'
  32. class ThreadController(Controller):
  33. @hapic.with_api_doc(tags=[THREAD_ENDPOINTS_TAG])
  34. @require_workspace_role(UserRoleInWorkspace.READER)
  35. @require_content_types([thread_type])
  36. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  37. @hapic.output_body(TextBasedContentSchema())
  38. def get_thread(self, context, request: TracimRequest, hapic_data=None) -> ContentInContext: # nopep8
  39. """
  40. Get thread content
  41. """
  42. app_config = request.registry.settings['CFG']
  43. api = ContentApi(
  44. current_user=request.current_user,
  45. session=request.dbsession,
  46. config=app_config,
  47. )
  48. content = api.get_one(
  49. hapic_data.path.content_id,
  50. content_type=ContentType.Any
  51. )
  52. return api.get_content_in_context(content)
  53. @hapic.with_api_doc(tags=[THREAD_ENDPOINTS_TAG])
  54. @require_workspace_role(UserRoleInWorkspace.CONTRIBUTOR)
  55. @require_content_types([thread_type])
  56. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  57. @hapic.input_body(TextBasedContentModifySchema())
  58. @hapic.output_body(TextBasedContentSchema())
  59. def update_thread(self, context, request: TracimRequest, hapic_data=None) -> ContentInContext: # nopep8
  60. """
  61. update thread
  62. """
  63. app_config = request.registry.settings['CFG']
  64. api = ContentApi(
  65. current_user=request.current_user,
  66. session=request.dbsession,
  67. config=app_config,
  68. )
  69. content = api.get_one(
  70. hapic_data.path.content_id,
  71. content_type=ContentType.Any
  72. )
  73. with new_revision(
  74. session=request.dbsession,
  75. tm=transaction.manager,
  76. content=content
  77. ):
  78. api.update_content(
  79. item=content,
  80. new_label=hapic_data.body.label,
  81. new_content=hapic_data.body.raw_content,
  82. )
  83. api.save(content)
  84. return api.get_content_in_context(content)
  85. @hapic.with_api_doc(tags=[THREAD_ENDPOINTS_TAG])
  86. @require_workspace_role(UserRoleInWorkspace.READER)
  87. @require_content_types([thread_type])
  88. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  89. @hapic.output_body(TextBasedRevisionSchema(many=True))
  90. def get_thread_revisions(
  91. self,
  92. context,
  93. request: TracimRequest,
  94. hapic_data=None
  95. ) -> typing.List[RevisionInContext]:
  96. """
  97. get thread revisions
  98. """
  99. app_config = request.registry.settings['CFG']
  100. api = ContentApi(
  101. current_user=request.current_user,
  102. session=request.dbsession,
  103. config=app_config,
  104. )
  105. content = api.get_one(
  106. hapic_data.path.content_id,
  107. content_type=ContentType.Any
  108. )
  109. revisions = content.revisions
  110. return [
  111. api.get_revision_in_context(revision)
  112. for revision in revisions
  113. ]
  114. @hapic.with_api_doc(tags=[THREAD_ENDPOINTS_TAG])
  115. @require_workspace_role(UserRoleInWorkspace.CONTRIBUTOR)
  116. @require_content_types([thread_type])
  117. @hapic.input_path(WorkspaceAndContentIdPathSchema())
  118. @hapic.input_body(SetContentStatusSchema())
  119. @hapic.output_body(NoContentSchema(), default_http_code=HTTPStatus.NO_CONTENT) # nopep8
  120. def set_thread_status(self, context, request: TracimRequest, hapic_data=None) -> None: # nopep8
  121. """
  122. set thread status
  123. """
  124. app_config = request.registry.settings['CFG']
  125. api = ContentApi(
  126. current_user=request.current_user,
  127. session=request.dbsession,
  128. config=app_config,
  129. )
  130. content = api.get_one(
  131. hapic_data.path.content_id,
  132. content_type=ContentType.Any
  133. )
  134. with new_revision(
  135. session=request.dbsession,
  136. tm=transaction.manager,
  137. content=content
  138. ):
  139. api.set_status(
  140. content,
  141. hapic_data.body.status,
  142. )
  143. api.save(content)
  144. return
  145. def bind(self, configurator: Configurator) -> None:
  146. # Get thread
  147. configurator.add_route(
  148. 'thread',
  149. '/workspaces/{workspace_id}/threads/{content_id}',
  150. request_method='GET'
  151. )
  152. configurator.add_view(self.get_thread, route_name='thread') # nopep8
  153. # update thread
  154. configurator.add_route(
  155. 'update_thread',
  156. '/workspaces/{workspace_id}/threads/{content_id}',
  157. request_method='PUT'
  158. ) # nopep8
  159. configurator.add_view(self.update_thread, route_name='update_thread') # nopep8
  160. # get thread revisions
  161. configurator.add_route(
  162. 'thread_revisions',
  163. '/workspaces/{workspace_id}/threads/{content_id}/revisions', # nopep8
  164. request_method='GET'
  165. )
  166. configurator.add_view(self.get_thread_revisions, route_name='thread_revisions') # nopep8
  167. # get thread revisions
  168. configurator.add_route(
  169. 'set_thread_status',
  170. '/workspaces/{workspace_id}/threads/{content_id}/status', # nopep8
  171. request_method='PUT'
  172. )
  173. configurator.add_view(self.set_thread_status, route_name='set_thread_status') # nopep8