user.py 7.0KB

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