auth.py 3.2KB

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