user.py 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. # -*- coding: utf-8 -*-
  2. import argparse
  3. from pyramid.scripting import AppEnvironment
  4. import transaction
  5. from sqlalchemy.exc import IntegrityError
  6. from sqlalchemy.orm.exc import NoResultFound
  7. from tracim_backend import CFG
  8. from tracim_backend.command import AppContextCommand
  9. from tracim_backend.command import Extender
  10. from tracim_backend.exceptions import UserAlreadyExistError
  11. from tracim_backend.exceptions import GroupDoesNotExist
  12. from tracim_backend.exceptions import NotificationNotSend
  13. from tracim_backend.exceptions import BadCommandError
  14. from tracim_backend.lib.core.group import GroupApi
  15. from tracim_backend.lib.core.user import UserApi
  16. from tracim_backend.models import User
  17. from tracim_backend.models import Group
  18. class UserCommand(AppContextCommand):
  19. ACTION_CREATE = 'create'
  20. ACTION_UPDATE = 'update'
  21. action = NotImplemented
  22. def get_description(self) -> str:
  23. return '''Create or update user.'''
  24. def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
  25. parser = super().get_parser(prog_name)
  26. parser.add_argument(
  27. "-l",
  28. "--login",
  29. help='User login (email)',
  30. dest='login',
  31. required=True
  32. )
  33. parser.add_argument(
  34. "-p",
  35. "--password",
  36. help='User password',
  37. dest='password',
  38. required=False,
  39. default=None
  40. )
  41. parser.add_argument(
  42. "-g",
  43. "--add-to-group",
  44. help='Add user to group',
  45. dest='add_to_group',
  46. nargs='*',
  47. action=Extender,
  48. default=[],
  49. )
  50. parser.add_argument(
  51. "-rmg",
  52. "--remove-from-group",
  53. help='Remove user from group',
  54. dest='remove_from_group',
  55. nargs='*',
  56. action=Extender,
  57. default=[],
  58. )
  59. parser.add_argument(
  60. "--send-email",
  61. help='Send mail to user',
  62. dest='send_email',
  63. required=False,
  64. action='store_true',
  65. default=False,
  66. )
  67. return parser
  68. def _user_exist(self, login: str) -> User:
  69. return self._user_api.user_with_email_exists(login)
  70. def _get_group(self, name: str) -> Group:
  71. groups_availables = [group.group_name
  72. for group in self._group_api.get_all()]
  73. if name not in groups_availables:
  74. msg = "Group '{}' does not exist, choose a group name in : ".format(name) # nopep8
  75. for group in groups_availables:
  76. msg+= "'{}',".format(group)
  77. self._session.rollback()
  78. raise GroupDoesNotExist(msg)
  79. return self._group_api.get_one_with_name(name)
  80. def _add_user_to_named_group(
  81. self,
  82. user: str,
  83. group_name: str
  84. ) -> None:
  85. group = self._get_group(group_name)
  86. if user not in group.users:
  87. group.users.append(user)
  88. self._session.flush()
  89. def _remove_user_from_named_group(
  90. self,
  91. user: User,
  92. group_name: str
  93. ) -> None:
  94. group = self._get_group(group_name)
  95. if user in group.users:
  96. group.users.remove(user)
  97. self._session.flush()
  98. def _create_user(
  99. self,
  100. login: str,
  101. password: str,
  102. do_notify: bool,
  103. **kwargs
  104. ) -> User:
  105. if not password:
  106. if self._password_required():
  107. raise BadCommandError(
  108. "You must provide -p/--password parameter"
  109. )
  110. password = ''
  111. try:
  112. user = self._user_api.create_user(
  113. email=login,
  114. password=password,
  115. do_save=True,
  116. do_notify=do_notify,
  117. )
  118. # TODO - G.M - 04-04-2018 - [Caldav] Check this code
  119. # # We need to enable radicale if it not already done
  120. # daemons = DaemonsManager()
  121. # daemons.run('radicale', RadicaleDaemon)
  122. self._user_api.execute_created_user_actions(user)
  123. except IntegrityError:
  124. self._session.rollback()
  125. raise UserAlreadyExistError()
  126. except NotificationNotSend as exception:
  127. self._session.rollback()
  128. raise exception
  129. return user
  130. def _update_password_for_login(self, login: str, password: str) -> None:
  131. user = self._user_api.get_one_by_email(login)
  132. user.password = password
  133. self._session.flush()
  134. transaction.commit()
  135. def take_app_action(
  136. self,
  137. parsed_args: argparse.Namespace,
  138. app_context: AppEnvironment
  139. ) -> None:
  140. # TODO - G.M - 05-04-2018 -Refactor this in order
  141. # to not setup object var outside of __init__ .
  142. self._session = app_context['request'].dbsession
  143. self._app_config = app_context['registry'].settings['CFG']
  144. self._user_api = UserApi(
  145. current_user=None,
  146. session=self._session,
  147. config=self._app_config,
  148. )
  149. self._group_api = GroupApi(
  150. current_user=None,
  151. session=self._session,
  152. config=self._app_config,
  153. )
  154. user = self._proceed_user(parsed_args)
  155. self._proceed_groups(user, parsed_args)
  156. print("User created/updated")
  157. def _proceed_user(self, parsed_args: argparse.Namespace) -> User:
  158. self._check_context(parsed_args)
  159. if self.action == self.ACTION_CREATE:
  160. try:
  161. user = self._create_user(
  162. login=parsed_args.login,
  163. password=parsed_args.password,
  164. do_notify=parsed_args.send_email,
  165. )
  166. except UserAlreadyExistError:
  167. raise UserAlreadyExistError("Error: User already exist (use `user update` command instead)")
  168. except NotificationNotSend:
  169. raise NotificationNotSend("Error: Cannot send email notification, user not created.")
  170. # TODO - G.M - 04-04-2018 - [Email] Check this code
  171. # if parsed_args.send_email:
  172. # email_manager = get_email_manager()
  173. # email_manager.notify_created_account(
  174. # user=user,
  175. # password=parsed_args.password,
  176. # )
  177. else:
  178. if parsed_args.password:
  179. self._update_password_for_login(
  180. login=parsed_args.login,
  181. password=parsed_args.password
  182. )
  183. user = self._user_api.get_one_by_email(parsed_args.login)
  184. return user
  185. def _proceed_groups(
  186. self,
  187. user: User,
  188. parsed_args: argparse.Namespace
  189. ) -> None:
  190. # User always in "users" group
  191. self._add_user_to_named_group(user, 'users')
  192. for group_name in parsed_args.add_to_group:
  193. self._add_user_to_named_group(user, group_name)
  194. for group_name in parsed_args.remove_from_group:
  195. self._remove_user_from_named_group(user, group_name)
  196. def _password_required(self) -> bool:
  197. # TODO - G.M - 04-04-2018 - [LDAP] Check this code
  198. # if config.get('auth_type') == LDAPAuth.name:
  199. # return False
  200. return True
  201. def _check_context(self, parsed_args: argparse.Namespace) -> None:
  202. # TODO - G.M - 04-04-2018 - [LDAP] Check this code
  203. # if config.get('auth_type') == LDAPAuth.name:
  204. # auth_instance = config.get('auth_instance')
  205. # if not auth_instance.ldap_auth.user_exist(parsed_args.login):
  206. # raise LDAPUserUnknown(
  207. # "LDAP is enabled and user with login/email \"%s\" not found in LDAP" % parsed_args.login
  208. # )
  209. pass
  210. class CreateUserCommand(UserCommand):
  211. action = UserCommand.ACTION_CREATE
  212. class UpdateUserCommand(UserCommand):
  213. action = UserCommand.ACTION_UPDATE
  214. class LDAPUserUnknown(BadCommandError):
  215. pass