user.py 7.5KB

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