authorization.py 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. # -*- coding: utf-8 -*-
  2. from typing import TYPE_CHECKING
  3. import functools
  4. from pyramid.interfaces import IAuthorizationPolicy
  5. from zope.interface import implementer
  6. try:
  7. from json.decoder import JSONDecodeError
  8. except ImportError: # python3.4
  9. JSONDecodeError = ValueError
  10. from tracim.exceptions import InsufficientUserWorkspaceRole
  11. from tracim.exceptions import InsufficientUserProfile
  12. if TYPE_CHECKING:
  13. from tracim import TracimRequest
  14. ###
  15. # Pyramid default permission/authorization mecanism
  16. # INFO - G.M - 12-04-2018 - Setiing a Default permission on view is
  17. # needed to activate AuthentificationPolicy and
  18. # AuthorizationPolicy on pyramid request
  19. TRACIM_DEFAULT_PERM = 'tracim'
  20. @implementer(IAuthorizationPolicy)
  21. class AcceptAllAuthorizationPolicy(object):
  22. """
  23. Empty AuthorizationPolicy : Allow all request. As Pyramid need
  24. a Authorization policy when we use AuthentificationPolicy, this
  25. class permit use to disable pyramid authorization mecanism with
  26. working a AuthentificationPolicy.
  27. """
  28. def permits(self, context, principals, permision):
  29. return True
  30. def principals_allowed_by_permission(self, context, permission):
  31. raise NotImplementedError()
  32. ###
  33. # Authorization decorators for views
  34. # INFO - G.M - 12-04-2018
  35. # Instead of relying on pyramid authorization mecanism
  36. # We prefer to use decorators
  37. def require_same_user_or_profile(group: int):
  38. """
  39. Decorator for view to restrict access of tracim request if candidate user
  40. is distinct from authenticated user and not with high enough profile.
  41. :param group: value from Group Object
  42. like Group.TIM_USER or Group.TIM_MANAGER
  43. :return:
  44. """
  45. def decorator(func):
  46. @functools.wraps(func)
  47. def wrapper(self, context, request: 'TracimRequest'):
  48. auth_user = request.current_user
  49. candidate_user = request.candidate_user
  50. if auth_user.user_id == candidate_user.user_id or \
  51. auth_user.profile.id >= group:
  52. return func(self, context, request)
  53. raise InsufficientUserProfile()
  54. return wrapper
  55. return decorator
  56. def require_profile(group: int):
  57. """
  58. Decorator for view to restrict access of tracim request if profile is
  59. not high enough
  60. :param group: value from Group Object
  61. like Group.TIM_USER or Group.TIM_MANAGER
  62. :return:
  63. """
  64. def decorator(func):
  65. @functools.wraps(func)
  66. def wrapper(self, context, request: 'TracimRequest'):
  67. user = request.current_user
  68. if user.profile.id >= group:
  69. return func(self, context, request)
  70. raise InsufficientUserProfile()
  71. return wrapper
  72. return decorator
  73. def require_workspace_role(minimal_required_role: int):
  74. """
  75. Restricts access to endpoint to minimal role or raise an exception.
  76. Check role for current_workspace.
  77. :param minimal_required_role: value from UserInWorkspace Object like
  78. UserRoleInWorkspace.CONTRIBUTOR or UserRoleInWorkspace.READER
  79. :return: decorator
  80. """
  81. def decorator(func):
  82. @functools.wraps(func)
  83. def wrapper(self, context, request: 'TracimRequest'):
  84. user = request.current_user
  85. workspace = request.current_workspace
  86. if workspace.get_user_role(user) >= minimal_required_role:
  87. return func(self, context, request)
  88. raise InsufficientUserWorkspaceRole()
  89. return wrapper
  90. return decorator
  91. def require_candidate_workspace_role(minimal_required_role: int):
  92. """
  93. Restricts access to endpoint to minimal role or raise an exception.
  94. Check role for candidate_workspace.
  95. :param minimal_required_role: value from UserInWorkspace Object like
  96. UserRoleInWorkspace.CONTRIBUTOR or UserRoleInWorkspace.READER
  97. :return: decorator
  98. """
  99. def decorator(func):
  100. def wrapper(self, context, request: 'TracimRequest'):
  101. user = request.current_user
  102. workspace = request.candidate_workspace
  103. if workspace.get_user_role(user) >= minimal_required_role:
  104. return func(self, context, request)
  105. raise InsufficientUserWorkspaceRole()
  106. return wrapper
  107. return decorator