request.py 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import typing
  2. from pyramid.request import Request
  3. from sqlalchemy.orm.exc import NoResultFound
  4. from tracim.exceptions import NotAuthentificated
  5. from tracim.exceptions import WorkspaceNotFound
  6. from tracim.exceptions import ImmutableAttribute
  7. from tracim.lib.core.user import UserApi
  8. from tracim.lib.core.workspace import WorkspaceApi
  9. from tracim.lib.utils.authorization import JSONDecodeError
  10. from tracim.models import User
  11. from tracim.models.data import Workspace
  12. class TracimRequest(Request):
  13. """
  14. Request with tracim specific params/methods
  15. """
  16. def __init__(
  17. self,
  18. environ,
  19. charset=None,
  20. unicode_errors=None,
  21. decode_param_names=None,
  22. **kw
  23. ):
  24. super().__init__(
  25. environ,
  26. charset,
  27. unicode_errors,
  28. decode_param_names,
  29. **kw
  30. )
  31. self._current_workspace = None # type: Workspace
  32. self._current_user = None # type: User
  33. # INFO - G.M - 18-05-2018 - Close db at the end of the request
  34. self.add_finished_callback(self._cleanup)
  35. @property
  36. def current_workspace(self) -> Workspace:
  37. """
  38. Get current workspace of the request according to authentification and
  39. request headers (to retrieve workspace). Setted by default value the
  40. first time if not configured.
  41. :return: Workspace of the request
  42. """
  43. if self._current_workspace is None:
  44. self.current_workspace = get_workspace(self.current_user, self)
  45. return self._current_workspace
  46. @current_workspace.setter
  47. def current_workspace(self, workspace: Workspace) -> None:
  48. """
  49. Setting current_workspace
  50. :param workspace:
  51. :return:
  52. """
  53. if self._current_workspace is not None:
  54. raise ImmutableAttribute(
  55. "Can't modify already setted current_workspace"
  56. )
  57. self._current_workspace = workspace
  58. @property
  59. def current_user(self) -> User:
  60. if self._current_user is None:
  61. self.current_user = get_safe_user(self)
  62. return self._current_user
  63. @current_user.setter
  64. def current_user(self, user: User) -> None:
  65. if self._current_user is not None:
  66. raise ImmutableAttribute(
  67. "Can't modify already setted current_user"
  68. )
  69. self._current_user = user
  70. def _cleanup(self, request: 'TracimRequest') -> None:
  71. """
  72. Close dbsession at the end of the request in order to avoid exception
  73. about not properly closed session or "object created in another thread"
  74. issue
  75. see https://github.com/tracim/tracim_backend/issues/62
  76. :param request: same as self, request
  77. :return: nothing.
  78. """
  79. self._current_user = None
  80. self._current_workspace = None
  81. self.dbsession.close()
  82. ###
  83. # Utils for TracimRequest
  84. ###
  85. def get_safe_user(
  86. request: TracimRequest,
  87. ) -> User:
  88. """
  89. Get current pyramid authenticated user from request
  90. :param request: pyramid request
  91. :return: current authenticated user
  92. """
  93. app_config = request.registry.settings['CFG']
  94. uapi = UserApi(None, session=request.dbsession, config=app_config)
  95. try:
  96. login = request.authenticated_userid
  97. if not login:
  98. raise NotAuthentificated('not authenticated user_id,'
  99. 'Failed Authentification ?')
  100. user = uapi.get_one_by_email(login)
  101. except NoResultFound:
  102. raise NotAuthentificated('User not found')
  103. return user
  104. def get_workspace(
  105. user: User,
  106. request: TracimRequest
  107. ) -> Workspace:
  108. """
  109. Get current workspace from request
  110. :param user: User who want to check the workspace
  111. :param request: pyramid request
  112. :return: current workspace
  113. """
  114. workspace_id = ''
  115. try:
  116. if 'workspace_id' not in request.json_body:
  117. raise WorkspaceNotFound('No workspace_id param in json body')
  118. workspace_id = request.json_body['workspace_id']
  119. wapi = WorkspaceApi(current_user=user, session=request.dbsession)
  120. workspace = wapi.get_one(workspace_id)
  121. except JSONDecodeError:
  122. raise WorkspaceNotFound('Bad json body')
  123. except NoResultFound:
  124. raise WorkspaceNotFound(
  125. 'Workspace {} does not exist '
  126. 'or is not visible for this user'.format(workspace_id)
  127. )
  128. return workspace