auth.py 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. # -*- coding: utf-8 -*-
  2. import typing
  3. try:
  4. from json.decoder import JSONDecodeError
  5. except ImportError: # python3.4
  6. JSONDecodeError = ValueError
  7. from sqlalchemy.orm.exc import NoResultFound
  8. from pyramid.request import Request
  9. from pyramid.security import ALL_PERMISSIONS
  10. from pyramid.security import Allow
  11. from pyramid.security import unauthenticated_userid
  12. from tracim.models.auth import Group
  13. from tracim.models.auth import User
  14. from tracim.models.data import Workspace
  15. from tracim.models.data import UserRoleInWorkspace
  16. from tracim.lib.core.user import UserApi
  17. from tracim.lib.core.workspace import WorkspaceApi
  18. from tracim.lib.core.userworkspace import RoleApi
  19. # INFO - G.M - 06-04-2018 - Auth for pyramid
  20. # based on this tutorial : https://docs.pylonsproject.org/projects/pyramid-cookbook/en/latest/auth/basic.html # nopep8
  21. BASIC_AUTH_WEBUI_REALM = "tracim"
  22. def get_user(request: Request) -> typing.Optional[User]:
  23. """
  24. Get current pyramid user from request
  25. :param request: pyramid request
  26. :return:
  27. """
  28. app_config = request.registry.settings['CFG']
  29. uapi = UserApi(None, session=request.dbsession, config=app_config)
  30. user = None
  31. try:
  32. login = unauthenticated_userid(request)
  33. user = uapi.get_one_by_email(login)
  34. except NoResultFound:
  35. pass
  36. return user
  37. def get_workspace(request: Request) -> typing.Optional[Workspace]:
  38. """
  39. Get current workspace from request
  40. :param request: pyramid request
  41. :return:
  42. """
  43. workspace = None
  44. try:
  45. if 'workspace_id' not in request.json_body:
  46. return None
  47. workspace_id = request.json_body['workspace_id']
  48. wapi = WorkspaceApi(current_user=None, session=request.dbsession)
  49. workspace = wapi.get_one(workspace_id)
  50. except JSONDecodeError:
  51. pass
  52. except NoResultFound:
  53. pass
  54. return workspace
  55. def check_credentials(
  56. login: str,
  57. cleartext_password: str,
  58. request: Request
  59. ) -> typing.Optional[list]:
  60. """
  61. Check credential for pyramid basic_auth, checks also for
  62. global and Workspace related permissions.
  63. :param login: login of user
  64. :param cleartext_password: user password in cleartext
  65. :param request: Pyramid request
  66. :return: None if auth failed, list of permissions if auth succeed
  67. """
  68. user = get_user(request)
  69. # Do not accept invalid user
  70. if not user \
  71. or user.email != login \
  72. or not user.validate_password(cleartext_password):
  73. return None
  74. permissions = []
  75. # Global groups
  76. for group in user.groups:
  77. permissions.append(group.group_id)
  78. # Current workspace related group
  79. workspace = get_workspace(request)
  80. if workspace:
  81. roleapi = RoleApi(current_user=user, session=request.dbsession)
  82. role = roleapi.get_one(
  83. user_id=user.user_id,
  84. workspace_id=workspace.workspace_id,
  85. )
  86. permissions.append(role)
  87. return permissions
  88. # Global Permissions
  89. ADMIN_PERM = 'admin'
  90. MANAGE_GLOBAL_PERM = 'manage_global'
  91. USER_PERM = 'user'
  92. # Workspace-specific permission
  93. READ_PERM = 'read'
  94. CONTRIBUTE_PERM = 'contribute'
  95. MANAGE_CONTENT_PERM = 'manage_content'
  96. MANAGE_WORKSPACE_PERM = 'manage_workspace'
  97. class Root(object):
  98. """
  99. Root of all Pyramid requests, used to store global acl
  100. """
  101. __acl__ = ()