def put(self, user_id, name, email, timezone, next_url=None): user_id = tmpl_context.current_user.user_id current_user = tmpl_context.current_user user_api = UserApi(current_user) assert user_id == current_user.user_id if next_url: next = tg.url(next_url) else: next = self.url() try: email_user = user_api.get_one_by_email(email) if email_user != current_user: tg.flash(_('Email already in use'), CST.STATUS_ERROR) tg.redirect(next) except NoResultFound: pass # Only keep allowed field update updated_fields = self._clean_update_fields({ 'name': name, 'email': email, 'timezone': timezone, }) api = UserApi(tmpl_context.current_user) api.update(current_user, do_save=True, **updated_fields) tg.flash(_('profile updated.')) tg.redirect(next)
def put(self, user_id, name, email, timezone, next_url=None): user_id = tmpl_context.current_user.user_id current_user = tmpl_context.current_user user_api = UserApi(current_user) assert user_id==current_user.user_id if next_url: next = tg.url(next_url) else: next = self.url() try: email_user = user_api.get_one_by_email(email) if email_user != current_user: tg.flash(_('Email already in use'), CST.STATUS_ERROR) tg.redirect(next) except NoResultFound: pass # Only keep allowed field update updated_fields = self._clean_update_fields({ 'name': name, 'email': email, 'timezone': timezone, }) api = UserApi(tmpl_context.current_user) api.update(current_user, do_save=True, **updated_fields) tg.flash(_('profile updated.')) tg.redirect(next)
def test_get_one_by_email(self): api = UserApi(None) u = api.create_user() api.update(u, 'bibi', 'bibi@bibi', True) uid = u.user_id transaction.commit() eq_(uid, api.get_one_by_email('bibi@bibi').user_id)
def test_create_and_update_user(self): api = UserApi(None) u = api.create_user() api.update(u, 'bob', 'bob@bob', True) nu = api.get_one_by_email('bob@bob') ok_(nu!=None) eq_('bob@bob', nu.email) eq_('bob', nu.display_name)
def test_create_and_update_user(self): api = UserApi(None) u = api.create_user() api.update(u, 'bob', 'bob@bob', True) nu = api.get_one_by_email('bob@bob') ok_(nu != None) eq_('bob@bob', nu.email) eq_('bob', nu.display_name)
class TracimDomainController(object): """ The domain controller is used by http_authenticator to authenticate the user every time a request is sent """ def __init__(self, presetdomain=None, presetserver=None): self._api = UserApi(None) def getDomainRealm(self, inputURL, environ): return '/' def requireAuthentication(self, realmname, environ): return True def isRealmUser(self, realmname, username, environ): """ Called to check if for a given root, the username exists (though here we don't make difference between root as we're always starting at tracim's root """ try: self._api.get_one_by_email(username) return True except: return False def get_left_digest_response_hash(self, realmname, username, environ): """ Called by our http_authenticator to get the hashed md5 digest for the current user that is also sent by the webdav client """ try: user = self._api.get_one_by_email(username) return user.webdav_left_digest_response_hash except: return None def authDomainUser(self, realmname, username, password, environ): """ If you ever feel the need to send a request al-mano with a curl, this is the function that'll be called by http_authenticator to validate the password sent """ return self.isRealmUser(realmname, username, environ) and \ self._api.get_one_by_email(username).validate_password(password)
class TracimDomainController(object): """ The domain controller is used by http_authenticator to authenticate the user every time a request is sent """ def __init__(self, presetdomain = None, presetserver = None): self._api = UserApi(None) def getDomainRealm(self, inputURL, environ): return '/' def requireAuthentication(self, realmname, environ): return True def isRealmUser(self, realmname, username, environ): """ Called to check if for a given root, the username exists (though here we don't make difference between root as we're always starting at tracim's root """ try: self._api.get_one_by_email(username) return True except: return False def get_left_digest_response_hash(self, realmname, username, environ): """ Called by our http_authenticator to get the hashed md5 digest for the current user that is also sent by the webdav client """ try: user = self._api.get_one_by_email(username) return user.webdav_left_digest_response_hash except: return None def authDomainUser(self, realmname, username, password, environ): """ If you ever feel the need to send a request al-mano with a curl, this is the function that'll be called by http_authenticator to validate the password sent """ return self.isRealmUser(realmname, username, environ) and \ self._api.get_one_by_email(username).validate_password(password)
class LDAPSearchAuthenticatorPlugin(BaseLDAPSearchAuthenticatorPlugin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._auth = None self._user_api = UserApi(None) def set_auth(self, auth): self._auth = auth def authenticate(self, environ, identity, allow_auth_token: bool=False): # Note: super().authenticate return None if already authenticated or not found email = super().authenticate(environ, identity) if email: self._sync_ldap_user(email, environ, identity) if not email and allow_auth_token and self.user_exist(email): # Proceed to internal token auth user = self.sa_auth.dbsession.query(self.sa_auth.user_class).filter( and_( self.sa_auth.user_class.is_active == True, self.sa_auth.user_class.email == identity['login'] ) ).first() if user: user.ensure_auth_token() if user.auth_token == identity['password']: email = identity['login'] return email def _sync_ldap_user(self, email, environ, identity): # Create or get user for connected email if not self._user_api.user_with_email_exists(email): user = User(email=email, imported_from=LDAPAuth.name) DBSession.add(user) else: user = self._user_api.get_one_by_email(email) # Retrieve ldap user attributes self._auth.ldap_user_provider.add_metadata_for_auth(environ, identity) # Update user with ldap attributes user_ldap_values = identity.get('user').copy() for field_name in user_ldap_values: setattr(user, field_name, user_ldap_values[field_name]) DBSession.flush() transaction.commit() def user_exist(self, email): with make_connection(self.url, self.bind_dn, self.bind_pass) as conn: if self.start_tls: conn.start_tls() if not conn.bind(): return False search = self.search_pattern % email conn.search(self.base_dn, search, self.search_scope) if len(conn.response) > 0: return True return False
class UserCommand(AppContextCommand): ACTION_CREATE = 'create' ACTION_UPDATE = 'update' action = NotImplemented def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._session = DBSession self._transaction = transaction self._user_api = UserApi(None) self._group_api = GroupApi(None) def get_description(self): return '''Create or update user.''' def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument( "-l", "--login", help='User login (email)', dest='login', required=True ) parser.add_argument( "-p", "--password", help='User password', dest='password', required=False, default=None ) parser.add_argument( "-g", "--add-to-group", help='Add user to group', dest='add_to_group', nargs='*', action=Extender, default=[], ) parser.add_argument( "-rmg", "--remove-from-group", help='Remove user from group', dest='remove_from_group', nargs='*', action=Extender, default=[], ) parser.add_argument( "--send-email", help='Send mail to user', dest='send_email', required=False, action='store_true', default=False, ) return parser def _user_exist(self, login): return self._user_api.user_with_email_exists(login) def _get_group(self, name): return self._group_api.get_one_with_name(name) def _add_user_to_named_group(self, user, group_name): group = self._get_group(group_name) if user not in group.users: group.users.append(user) self._session.flush() def _remove_user_from_named_group(self, user, group_name): group = self._get_group(group_name) if user in group.users: group.users.remove(user) self._session.flush() def _create_user(self, login, password, **kwargs): if not password: if self._password_required(): raise CommandAbortedError("You must provide -p/--password parameter") password = '' try: user = User(email=login, password=password, **kwargs) self._session.add(user) self._session.flush() except IntegrityError: self._session.rollback() raise AlreadyExistError() return user def _update_password_for_login(self, login, password): user = self._user_api.get_one_by_email(login) user.password = password self._session.flush() transaction.commit() def take_action(self, parsed_args): super().take_action(parsed_args) user = self._proceed_user(parsed_args) self._proceed_groups(user, parsed_args) print("User created/updated") def _proceed_user(self, parsed_args): self._check_context(parsed_args) if self.action == self.ACTION_CREATE: try: user = self._create_user(login=parsed_args.login, password=parsed_args.password) except AlreadyExistError: raise CommandAbortedError("Error: User already exist (use `user update` command instead)") if parsed_args.send_email: email_manager = get_email_manager() email_manager.notify_created_account( user=user, password=parsed_args.password, ) else: if parsed_args.password: self._update_password_for_login(login=parsed_args.login, password=parsed_args.password) user = self._user_api.get_one_by_email(parsed_args.login) return user def _proceed_groups(self, user, parsed_args): # User always in "users" group self._add_user_to_named_group(user, 'users') for group_name in parsed_args.add_to_group: self._add_user_to_named_group(user, group_name) for group_name in parsed_args.remove_from_group: self._remove_user_from_named_group(user, group_name) def _password_required(self): if config.get('auth_type') == LDAPAuth.name: return False return True def _check_context(self, parsed_args): if config.get('auth_type') == LDAPAuth.name: auth_instance = config.get('auth_instance') if not auth_instance.ldap_auth.user_exist(parsed_args.login): raise LDAPUserUnknown( "LDAP is enabled and user with login/email \"%s\" not found in LDAP" % parsed_args.login )
def test_get_one_by_email_exception(self): api = UserApi(None) api.get_one_by_email('unknown')
class UserCommand(AppContextCommand): ACTION_CREATE = 'create' ACTION_UPDATE = 'update' action = NotImplemented def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._session = DBSession self._transaction = transaction self._user_api = UserApi(None) self._group_api = GroupApi(None) def get_description(self): return '''Create or update user.''' def get_parser(self, prog_name): parser = super().get_parser(prog_name) parser.add_argument("-l", "--login", help='User login (email)', dest='login', required=True) parser.add_argument("-p", "--password", help='User password', dest='password', required=False, default=None) parser.add_argument( "-g", "--add-to-group", help='Add user to group', dest='add_to_group', nargs='*', action=Extender, default=[], ) parser.add_argument( "-rmg", "--remove-from-group", help='Remove user from group', dest='remove_from_group', nargs='*', action=Extender, default=[], ) parser.add_argument( "--send-email", help='Send mail to user', dest='send_email', required=False, action='store_true', default=False, ) return parser def _user_exist(self, login): return self._user_api.user_with_email_exists(login) def _get_group(self, name): return self._group_api.get_one_with_name(name) def _add_user_to_named_group(self, user, group_name): group = self._get_group(group_name) if user not in group.users: group.users.append(user) self._session.flush() def _remove_user_from_named_group(self, user, group_name): group = self._get_group(group_name) if user in group.users: group.users.remove(user) self._session.flush() def _create_user(self, login, password, **kwargs): if not password: if self._password_required(): raise CommandAbortedError( "You must provide -p/--password parameter") password = '' try: user = User(email=login, password=password, **kwargs) user.update_webdav_digest_auth(password) self._session.add(user) self._session.flush() # We need to enable radicale if it not already done daemons = DaemonsManager() daemons.run('radicale', RadicaleDaemon) user_api = UserApi(user) user_api.execute_created_user_actions(user) except IntegrityError: self._session.rollback() raise AlreadyExistError() return user def _update_password_for_login(self, login, password): user = self._user_api.get_one_by_email(login) user.password = password user.update_webdav_digest_auth(password) self._session.flush() transaction.commit() def take_action(self, parsed_args): super().take_action(parsed_args) user = self._proceed_user(parsed_args) self._proceed_groups(user, parsed_args) print("User created/updated") def _proceed_user(self, parsed_args): self._check_context(parsed_args) if self.action == self.ACTION_CREATE: try: user = self._create_user(login=parsed_args.login, password=parsed_args.password) except AlreadyExistError: raise CommandAbortedError( "Error: User already exist (use `user update` command instead)" ) if parsed_args.send_email: email_manager = get_email_manager() email_manager.notify_created_account( user=user, password=parsed_args.password, ) else: if parsed_args.password: self._update_password_for_login(login=parsed_args.login, password=parsed_args.password) user = self._user_api.get_one_by_email(parsed_args.login) return user def _proceed_groups(self, user, parsed_args): # User always in "users" group self._add_user_to_named_group(user, 'users') for group_name in parsed_args.add_to_group: self._add_user_to_named_group(user, group_name) for group_name in parsed_args.remove_from_group: self._remove_user_from_named_group(user, group_name) def _password_required(self): if config.get('auth_type') == LDAPAuth.name: return False return True def _check_context(self, parsed_args): if config.get('auth_type') == LDAPAuth.name: auth_instance = config.get('auth_instance') if not auth_instance.ldap_auth.user_exist(parsed_args.login): raise LDAPUserUnknown( "LDAP is enabled and user with login/email \"%s\" not found in LDAP" % parsed_args.login)
def post(self) -> Response: cfg = CFG.get_instance() try: json = request.json_body except ValueError: return Response( status=400, json_body={'msg': 'Bad json'}, ) if json.get('token', None) != cfg.EMAIL_REPLY_TOKEN: # TODO - G.M - 2017-11-23 - Switch to status 403 ? # 403 is a better status code in this case. # 403 status response can't now return clean json, because they are # handled somewhere else to return html. return Response( status=400, json_body={'msg': 'Invalid token'} ) if 'user_mail' not in json: return Response( status=400, json_body={'msg': 'Bad json: user_mail is required'} ) if 'content_id' not in json: return Response( status=400, json_body={'msg': 'Bad json: content_id is required'} ) if 'payload' not in json: return Response( status=400, json_body={'msg': 'Bad json: payload is required'} ) uapi = UserApi(None) try: user = uapi.get_one_by_email(json['user_mail']) except NoResultFound: return Response( status=400, json_body={'msg': 'Unknown user email'}, ) api = ContentApi(user) try: thread = api.get_one(json['content_id'], content_type=ContentType.Any) except NoResultFound: return Response( status=400, json_body={'msg': 'Unknown content_id'}, ) # INFO - G.M - 2017-11-17 # When content_id is a sub-elem of a main content like Comment, # Attach the thread to the main content. if thread.type == ContentType.Comment: thread = thread.parent if thread.type == ContentType.Folder: return Response( status=400, json_body={'msg': 'comment for folder not allowed'}, ) if 'content' in json['payload']: api.create_comment( workspace=thread.workspace, parent=thread, content=json['payload']['content'], do_save=True, ) return Response( status=204, ) else: return Response( status=400, json_body={'msg': 'No content to add new comment'}, )
class LDAPSearchAuthenticatorPlugin(BaseLDAPSearchAuthenticatorPlugin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._auth = None self._user_api = UserApi(None) def set_auth(self, auth): self._auth = auth def authenticate(self, environ, identity, allow_auth_token: bool = False): # Note: super().authenticate return None if already authenticated or not found email = super().authenticate(environ, identity) if email: self._sync_ldap_user(email, environ, identity) if not email and allow_auth_token and self.user_exist(email): # Proceed to internal token auth user = self.sa_auth.dbsession.query( self.sa_auth.user_class).filter( and_(self.sa_auth.user_class.is_active == True, self.sa_auth.user_class.email == identity['login'])).first() if user: user.ensure_auth_token() if user.auth_token == identity['password']: email = identity['login'] return email def _sync_ldap_user(self, email, environ, identity): # Create or get user for connected email if not self._user_api.user_with_email_exists(email): user = User(email=email, imported_from=LDAPAuth.name) DBSession.add(user) else: user = self._user_api.get_one_by_email(email) # Retrieve ldap user attributes self._auth.ldap_user_provider.add_metadata_for_auth(environ, identity) # Update user with ldap attributes user_ldap_values = identity.get('user').copy() for field_name in user_ldap_values: setattr(user, field_name, user_ldap_values[field_name]) DBSession.flush() transaction.commit() def user_exist(self, email): with make_connection(self.url, self.bind_dn, self.bind_pass) as conn: if self.start_tls: conn.start_tls() if not conn.bind(): return False search = self.search_pattern % email conn.search(self.base_dn, search, self.search_scope) if len(conn.response) > 0: return True return False