user.py 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. # -*- coding: utf-8 -*-
  2. import threading
  3. import transaction
  4. import typing as typing
  5. from tracim.models.auth import User
  6. from sqlalchemy.orm.exc import NoResultFound
  7. from tracim.exceptions import BadUserPassword, UserNotExist
  8. from tracim.exceptions import AuthenticationFailed
  9. from tracim.models.context_models import UserInContext
  10. class UserApi(object):
  11. def __init__(self, current_user: typing.Optional[User], session, config):
  12. self._session = session
  13. self._user = current_user
  14. self._config = config
  15. def _base_query(self):
  16. return self._session.query(User)
  17. def _get_correct_user_type(
  18. self,
  19. user: User,
  20. in_context: bool,
  21. ) -> typing.Union[User, UserInContext]:
  22. """
  23. Choose user type object depending on in_context bool.
  24. :param user:
  25. :param in_context:
  26. :return: user as User or UserInContext if in_context is True
  27. """
  28. if in_context:
  29. user = UserInContext(
  30. user=user,
  31. dbsession=self._session,
  32. config=self._config,
  33. )
  34. return user
  35. # Getters
  36. def get_one(
  37. self,
  38. user_id: int,
  39. in_context: bool=False,
  40. ) -> typing.Union[UserInContext, User]:
  41. """
  42. Get one user by user id
  43. :param user_id:
  44. :param in_context: Return User or UserInContext Object
  45. :return: one user
  46. """
  47. user = self._base_query().filter(User.user_id == user_id).one()
  48. return self._get_correct_user_type(user, in_context)
  49. def get_one_by_email(
  50. self,
  51. email: str,
  52. in_context: bool=False,
  53. ) -> User:
  54. """
  55. Get one user by email
  56. :param email: Email of the user
  57. :param in_context: Return User or UserInContext Object
  58. :return: one user
  59. """
  60. user = self._base_query().filter(User.email == email).one()
  61. return self._get_correct_user_type(user, in_context)
  62. # FIXME - G.M - 24-04-2018 - Duplicate method with get_one.
  63. def get_one_by_id(self, id: int, in_context=False) -> User:
  64. return self.get_one(user_id=id, in_context=in_context)
  65. def get_current(self, in_context: bool=False):
  66. """
  67. Get current_user
  68. :param in_context:
  69. :return:
  70. """
  71. if not self._user:
  72. raise UserNotExist()
  73. return self._get_correct_user_type(self._user, in_context)
  74. def get_all(self) -> typing.Iterable[User]:
  75. return self._session.query(User).order_by(User.display_name).all()
  76. # Check methods
  77. def user_with_email_exists(self, email: str):
  78. try:
  79. self.get_one_by_email(email)
  80. return True
  81. # TODO - G.M - 09-04-2018 - Better exception
  82. except:
  83. return False
  84. def authenticate_user(self,
  85. email: str,
  86. password: str,
  87. in_context=False
  88. ) -> typing.Union[User, UserInContext]:
  89. """
  90. Authenticate user with email and password, raise AuthenticationFailed
  91. if uncorrect.
  92. :param email: email of the user
  93. :param password: cleartext password of the user
  94. :param in_context:
  95. :return: User who was authenticated.
  96. """
  97. try:
  98. user = self.get_one_by_email(email)
  99. if user.validate_password(password):
  100. return self._get_correct_user_type(user, in_context=in_context)
  101. else:
  102. raise BadUserPassword()
  103. except (BadUserPassword, NoResultFound):
  104. raise AuthenticationFailed
  105. # Actions
  106. def update(
  107. self,
  108. user: User,
  109. name: str=None,
  110. email: str=None,
  111. do_save=True,
  112. timezone: str='',
  113. ):
  114. if name is not None:
  115. user.display_name = name
  116. if email is not None:
  117. user.email = email
  118. user.timezone = timezone
  119. if do_save:
  120. self.save(user)
  121. def create_user(self, email=None, groups=[], save_now=False) -> User:
  122. user = User()
  123. if email:
  124. user.email = email
  125. for group in groups:
  126. user.groups.append(group)
  127. self._session.add(user)
  128. if save_now:
  129. self._session.flush()
  130. return user
  131. def save(self, user: User):
  132. self._session.flush()
  133. def execute_created_user_actions(self, created_user: User) -> None:
  134. """
  135. Execute actions when user just been created
  136. :return:
  137. """
  138. # NOTE: Cyclic import
  139. # TODO - G.M - 28-03-2018 - [Calendar] Reenable Calendar stuff
  140. #from tracim.lib.calendar import CalendarManager
  141. #from tracim.model.organisational import UserCalendar
  142. # TODO - G.M - 04-04-2018 - [auth]
  143. # Check if this is already needed with
  144. # new auth system
  145. created_user.ensure_auth_token(
  146. session=self._session,
  147. validity_seconds=self._config.USER_AUTH_TOKEN_VALIDITY
  148. )
  149. # Ensure database is up-to-date
  150. self._session.flush()
  151. transaction.commit()
  152. # TODO - G.M - 28-03-2018 - [Calendar] Reenable Calendar stuff
  153. # calendar_manager = CalendarManager(created_user)
  154. # calendar_manager.create_then_remove_fake_event(
  155. # calendar_class=UserCalendar,
  156. # related_object_id=created_user.user_id,
  157. # )