def create(cls, data, id_=None, delete_pid=False, dbcommit=False, reindex=False, email_notification=True, **kwargs): """Patron record creation. :param cls - class object :param data - dictionary representing a library user :param id_ - UUID, it would be generated if it is not given :param delete_pid - remove the pid present in the data if True :param dbcommit - commit the changes in the db after the creation :param reindex - index the record after the creation :param email_notification - send a reset password link to the user """ # remove spaces data = trim_barcode_for_record(data=data) # synchronize the rero id user profile data user = cls.sync_user_and_profile(data) try: record = super(Patron, cls).create(data, id_, delete_pid, dbcommit, reindex, **kwargs) record._update_roles() except Exception as e: db.session.rollback() raise e if user: # send the reset password notification if (email_notification and data.get('email')): send_reset_password_instructions(user) confirm_user(user) return record
def user(self): """User account linked to current record. :returns: User account. """ email = self.get('email') user = datastore.find_user(email=email) if not user: # Hash password before storing it. password = hash_password(email) # Create and save new user. user = datastore.create_user(email=email, password=password) datastore.commit() # Send welcome email send_welcome_email(self, user) # Directly confirm user (no account activation by email) confirm_user(user) else: # If user is not active, activate it. if not user.is_active: datastore.activate_user(user) return user
def update(self, data): """User record update. :param data - dictionary representing a user record to update """ from ..patrons.listener import update_from_profile self._validate(data=data) email = data.pop('email', None) roles = data.pop('roles', None) user = self.user with db.session.begin_nested(): if user.profile is None: user.profile = UserProfile(user_id=user.id) profile = user.profile for field in self.profile_fields: if field == 'birth_date': setattr(profile, field, datetime.strptime(data.get(field), '%Y-%m-%d')) else: setattr(profile, field, data.get(field, '')) # change password if data.get('password'): user.password = hash_password(data['password']) if email and email != user.email: user.email = email # remove the email from user data elif not email and user.email: user.email = None db.session.merge(user) db.session.commit() confirm_user(user) update_from_profile('user', self.user.profile) return self
def create(cls, data, **kwargs): """User record creation. :param cls - class object :param data - dictionary representing a user record """ with db.session.begin_nested(): email = data.pop('email', None) roles = data.pop('roles', None) cls._validate(data=data) password = data.pop('password', data.get('birth_date', '123456')) user = BaseUser(password=hash_password(password), profile=data, active=True) db.session.add(user) profile = user.profile for field in cls.profile_fields: value = data.get(field) if value is not None: if field == 'birth_date': value = datetime.strptime(value, '%Y-%m-%d') setattr(profile, field, value) # send the reset password notification for new users if email: user.email = email db.session.merge(user) db.session.commit() if user.email: send_reset_password_instructions(user) confirm_user(user) return cls(user)
def import_users(infile): """Import users.""" click.secho('Importing users from {file}'.format(file=infile.name)) data = json.load(infile) for user_data in data: try: email = user_data.get('email') # No email found in user's data, account cannot be created if not email: raise ClickException('Email not defined') user = datastore.find_user(email=email) # User already exists, skip account creation if user: raise ClickException( 'User with email {email} already exists'.format( email=email)) password = user_data.get( 'password', '$pbkdf2-sha512$25000$29ubk1KqFUJorTXmHAPAmA$ooj0RJyHyinmZw' '/.pNMXne8p70X/BDoX5Ypww24OIguSWEo3y.KT6hiwxwHS5OynZNkgnLvf' 'R3m1mNVfsHgfgA') del user_data['password'] if not user_data.get('role'): user_data['role'] = UserRecord.ROLE_USER if not datastore.find_role(user_data['role']): datastore.create_role(name=user_data['role']) datastore.commit() # Create account and activate it datastore.create_user(email=email, password=password, roles=[user_data['role']]) datastore.commit() user = datastore.find_user(email=email) confirm_user(user) datastore.commit() click.secho( 'User {email} with ID #{id} created successfully'.format( email=email, id=user.id), fg='green') # Create user resource user = UserRecord.create(user_data, dbcommit=True) user.reindex() except Exception as error: click.secho('User {user} could not be imported: {error}'.format( user=user_data, error=str(error)), fg='red') click.secho('Finished', fg='green')
def import_users(infile): """Import users.""" click.secho('Importing users from {file}'.format(file=infile)) data = json.load(infile) for user_data in data: try: email = user_data.get('email') # No email found in user's data, account cannot be created if not email: raise ClickException('Email not defined') user = datastore.find_user(email=email) # User already exists, skip account creation if user: raise ClickException( 'User with email {email} already exists'.format( email=email)) password = user_data.get('password', '123456') password = hash_password(password) del user_data['password'] if not user_data.get('roles'): user_data['roles'] = [UserRecord.ROLE_USER] roles = user_data.get('roles', []).copy() for role in roles: if not datastore.find_role(role): datastore.create_role(name=role) datastore.commit() # Create account and activate it datastore.create_user(email=email, password=password, roles=roles) datastore.commit() user = datastore.find_user(email=email) confirm_user(user) datastore.commit() click.secho( 'User {email} with ID #{id} created successfully'.format( email=email, id=user.id), fg='green') # Create user resource user = UserRecord.create(user_data, dbcommit=True) user.reindex() except Exception as error: click.secho( 'User {user} could not be imported: {error}'.format( user=user_data, error=str(error)), fg='red') click.secho('Finished', fg='green')
def create_user(): user_datastore.create_user(email='*****@*****.**', password=encrypt_password('tester')) user_datastore.create_role(name='PNT-Admin', description='Master Cagenix Admin') db.session.commit() user = user_datastore.find_user(email='*****@*****.**') confirm_user(user) role = user_datastore.find_role('PNT-Admin') user_datastore.add_role_to_user(user, role) db.session.commit() return redirect('/')
def create_user(app, email=None, password='******'): email = email or 'test+{}@hellovelocity.com'.format(''.join(random.sample('abcdefghijklmnopqrstuvwxyz', 10))) user = User( email=email, password=password, active=True) confirm_user(user) app.db.session.add(user) app.db.session.commit() return user
def create_users(): for u in (('matt', '*****@*****.**', 'password', ['admin'], True), ('joe', '*****@*****.**', 'password', ['editor'], True), ('jill', '*****@*****.**', 'password', ['author'], True), ('tiya', '*****@*****.**', 'password', [], False)): user = current_app.user_datastore.create_user(username=u[0], email=u[1], password=u[2], roles=u[3], active=u[4]) confirm_user(user) current_app.user_datastore.commit()
def add_users(self, info): users = info['users'] total = 0 for user_info in users: build_info = user_info for i in range(user_info.get('_meta_multiply_object', 1)): user = app.user_datastore.create_user(**build_info) confirm_user(user) total += 1 print('users: {}'.format(total)) return True
def user(self): """Invenio user of a patron.""" email = self.get('email') user = _datastore.find_user(email=email) if not user: password = hash_password(email) _datastore.create_user(email=email, password=password) _datastore.commit() # send password reset user = _datastore.find_user(email=email) send_reset_password_instructions(user) confirm_user(user) return user
def save_patron(data, record_type, fetcher, minter, record_indexer, record_class, parent_pid): """Save a record into the db and index it. If the user does not exists, it well be created and attached to the patron. """ email = data.get('email') data = clean_patron_fields(data) if email: find_user = datastore.find_user(email=email) if find_user is None: password = hash_password(email) datastore.create_user( email=email, password=password ) datastore.commit() # send password reset user = datastore.find_user(email=email) if user: send_reset_password_instructions(user) confirm_user(user) patron = Patron.get_patron_by_email(email) if patron: patron = Patron(data, model=patron.model) patron.update(data, dbcommit=True, reindex=True) else: patron = Patron.create(data, dbcommit=True, reindex=True) if patron.get('is_patron', False): patron.add_role('patrons') else: patron.remove_role('patrons') if patron.get('is_staff', False): patron.add_role('staff') # TODO: cataloguer role patron.add_role('cataloguer') else: patron.remove_role('cataloguer') # TODO: cataloguer role patron.remove_role('staff') patron.reindex() _next = url_for('invenio_records_ui.ptrn', pid_value=patron.pid) return _next, patron.persistent_identifier
def create_users(): for u in (('Rose', '*****@*****.**', 'rose', ['admin'], True), ('Joe', '*****@*****.**', 'joe', ['editor'], True), ('Chandle', '*****@*****.**', 'chandle', ['author'], True), ('Monica', '*****@*****.**', 'monica', [], False), ('Rich', '*****@*****.**', 'rich', ['Guest'], False), ('Pheb', '*****@*****.**', 'pheb', ['editor'], True)): user = current_app.user_datastore.create_user(username=u[0], email=u[1], password=u[2], roles=u[3], active=u[4]) confirm_user(user) current_app.user_datastore.commit()
def confirm_email(self): schema = RELS['v1.AuthView:confirm'][request.method] args = request_confirm_options.parse_args() try: validate(args, schema, format_checker=FormatChecker()) token = args.get('token') expired, invalid, user = confirm_email_token_status(token) if invalid or not user: return dict(status=409, message="Invalid confirmation token"), 409 if expired: return dict(status=409, message="Confirmation token has expired"), 409 confirmed = confirm_user(user) user.save() if not confirmed: return dict(status=409, message='Email already confirmed'), 409 except ValidationError as e: return dict(status=400, message=e.message), 400 return {'status': 200, 'message': 'Account confirmed.', 'user': generate_response_dict(user=user)}
def confirm_user(self): user = User.query.get(request.args['model_id']) return_url = request.headers['Referer'] if user is None: flash(gettext('User not found. Please try again.'), 'error') return redirect(return_url) confirm_user(user) db.session.commit() flash( gettext( 'The user\'s email address %s has been confirmed. They will now received emails.' % user.email)) return redirect(return_url)
def confirm_email(token): """View function which handles a email confirmation request.""" security = current_app.extensions.get('security') expired, invalid, user = confirm_email_token_status(token) if not user or invalid: invalid = True do_flash(*get_message('INVALID_CONFIRMATION_TOKEN')) if expired: send_confirmation_instructions(user) do_flash(*get_message('CONFIRMATION_EXPIRED', email=user.email, within=security.confirm_email_within)) if invalid or expired: return redirect( get_url(security.confirm_error_view) or url_for('send_confirmation')) if user != current_user: logout_user() login_user(user) if confirm_user(user): msg = 'EMAIL_CONFIRMED' else: msg = 'ALREADY_CONFIRMED' do_flash(*get_message(msg)) return redirect( get_url(security.post_confirm_view) or get_url(security.post_login_view))
def confirm_email(token): """View function which handles a email confirmation request.""" expired, invalid, user = confirm_email_token_status(token) if not user or invalid: invalid = True already_confirmed = user is not None and user.confirmed_at is not None expired_and_not_confirmed = expired and not already_confirmed if expired_and_not_confirmed: send_confirmation_instructions(user) if invalid or expired_and_not_confirmed: return redirect(get_url(_security.confirm_error_view)) if confirm_user(user): after_this_request(_commit) if user != current_user: logout_user() login_user(user) return redirect(get_url(_security.post_confirm_view))
def create_user_from_data(data): """Create a user and set the profile fields from a data. :param data: A dict containing a mix of patron and user data. :returns: The modified dict. """ from .modules.users.api import User data = deepcopy(data) profile_fields = [ 'first_name', 'last_name', 'street', 'postal_code', 'gender', 'city', 'birth_date', 'username', 'home_phone', 'business_phone', 'mobile_phone', 'other_phone', 'keep_history', 'country', 'email' ] user = User.get_by_username(data.get('username')) if not user: with db.session.begin_nested(): # create the user user = BaseUser(password=hash_password( data.get('birth_date', '123456')), profile=dict(), active=True) db.session.add(user) # set the user fields if data.get('email') is not None: user.email = data['email'] profile = user.profile # set the profile for field in profile_fields: value = data.get(field) if value is not None: if field == 'birth_date': value = datetime.strptime(value, '%Y-%m-%d') setattr(profile, field, value) db.session.merge(user) db.session.commit() confirm_user(user) user_id = user.id else: user_id = user.user.id # remove the user fields from the data for field in profile_fields: try: del data[field] except KeyError: pass data['user_id'] = user_id return data
def manual_confirm_user(user): """Confirm a user.""" user_obj = _datastore.get_user(user) if user_obj is None: raise click.UsageError('ERROR: User not found.') if confirm_user(user_obj): click.secho('User "%s" has been confirmed.' % user, fg='green') else: click.secho('User "%s" was already confirmed.' % user, fg='yellow')
def import_users(infile, verbose): """Import users.""" click.secho('Import users:', fg='green') data = json.load(infile) for patron_data in data: email = patron_data.get('email') if email is None: click.secho('\tUser email not defined!', fg='red') else: # create User password = patron_data.get('password', '123456') del(patron_data['password']) patron = Patron.get_patron_by_email(email) if patron: click.secho('\tUser exist: ' + email, fg='yellow') else: if verbose: click.echo('\tUser: '******'\tUser exist: ' + email, fg='yellow') else: pwd = hash_password(password) datastore.create_user( email=email, password=pwd ) datastore.commit() user = datastore.find_user(email=email) confirm = confirm_user(user) datastore.commit() if not confirm: click.secho( '\tUser not confirmed!' + email, fg='yellow' ) # else: # click.secho('\tUser confirmed!', fg='green') patron = Patron(patron, model=patron.model) if patron_data.get('is_patron', False): patron.add_role(role_name='patrons') if patron_data.get('is_staff', False): patron.add_role(role_name='staff') # TODO: staff role patron.add_role(role_name='cataloguer') patron.reindex()
def import_users(infile, verbose): """Import users. infile: Json organisation file """ click.secho('Import users:', fg='green') data = json.load(infile) for patron_data in data: email = patron_data.get('email') if email is None: click.secho('\tUser email not defined!', fg='red') else: # create User password = patron_data.get('password', '123456') del(patron_data['password']) patron = Patron.get_patron_by_email(email) if patron: click.secho('\tUser exist: ' + email, fg='yellow') else: if verbose: click.echo('\tUser: '******'\tUser exist: ' + email, fg='yellow') else: pwd = hash_password(password) datastore.create_user( email=email, password=pwd ) datastore.commit() user = datastore.find_user(email=email) confirm_user(user) datastore.commit() patron = Patron.create( patron_data, dbcommit=True, reindex=True ) patron.reindex()
def test_create_new(auth_client, session): # Make a new user and authorize resp = auth_client.post('/api/user', data={'name': 'me', 'email': '*****@*****.**', 'password': '******'}) auth_client.authorize(email="*****@*****.**", password="******") # Try getting route without confirming, should fail resp = auth_client.get('/api/user') assert resp.status_code == 401 # Confirm new user manually user = User.query.filter_by(email="*****@*****.**").one() confirm_user(user) session.commit() # Now should work resp = auth_client.get('/api/user') assert resp.status_code == 200 assert decode_json(resp)['email'] == '*****@*****.**'
def import_users(infile, verbose, password): """Import users. :param verbose: this function will be verbose. :param password: the password to use for user by default. :param infile: Json user file. """ click.secho('Import users:', fg='green') data = json.load(infile) for patron_data in data: email = patron_data.get('email') if email is None: click.secho('\tUser email not defined!', fg='red') else: # create User password = patron_data.get('password', password) patron_data.pop('password', None) patron = Patron.get_patron_by_email(email) if patron: click.secho('\tUser exist: ' + email, fg='yellow') else: if verbose: click.echo('\tUser: '******'\tUser exist: ' + email, fg='yellow') else: patron = Patron.create(patron_data, dbcommit=False, reindex=False, email_notification=False) patron.reindex() user = patron.user user.password = hash_password(password) user.active = True db.session.merge(user) db.session.commit() confirm_user(user)
def post(self, **kwargs): """Confirm user email.""" user = self.get_user(**kwargs) if user != current_user: logout_user() if confirm_user(user): after_this_request(_commit) return jsonify({"message": get_message("EMAIL_CONFIRMED")[0]}) else: return jsonify({"message": get_message("ALREADY_CONFIRMED")[0]})
def confirm(token): ''' Serve confirmaton page ''' expired, invalid, user = confirm_email_token_status(token) name, confirmed = None, None if user: if not expired and not invalid: confirmed = confirm_user(user) db.session.commit() name = user.name else: confirmed = None return render_template('confirm.html', confirmed=confirmed, expired=expired, invalid=invalid, name=name, action_url=url_for('index', _external=True))
def test_confirm_user_creates_default_profile(app): user = User.objects.create(email='*****@*****.**', password='******') with app.app_context(): confirm_user(user) assert user.profile.name == 'Anonymous'
def import_users(infile, append, verbose, password, lazy, dont_stop_on_error, debug): """Import users. :param verbose: this function will be verbose. :param password: the password to use for user by default. :param lazy: lazy reads file :param dont_stop_on_error: don't stop on error :param infile: Json user file. """ click.secho('Import users:', fg='green') if lazy: # try to lazy read json file (slower, better memory management) data = read_json_record(infile) else: # load everything in memory (faster, bad memory management) data = json.load(infile) pids = [] error_records = [] for count, patron_data in enumerate(data): email = patron_data.get('email') password = patron_data.get('password', password) username = patron_data['username'] if email is None: click.secho( '{count: <8} User {username} do not have email!'.format( count=count, username=username), fg='yellow') if password: patron_data.pop('password', None) # do nothing if the patron alredy exists patron = Patron.get_patron_by_username(username) if patron: click.secho('{count: <8} Patron already exist: {username}'.format( count=count, username=username), fg='yellow') continue if verbose: click.secho('{count: <8} Creating user: {username}'.format( count=count, username=username)) try: profile = UserProfile.get_by_username(username) click.secho( '{count: <8} User already exist: {username}'.format( count=count, username=username), fg='yellow') except NoResultFound: pass try: # patron creation patron = Patron.create( patron_data, # delete_pid=True, dbcommit=False, reindex=False, email_notification=False) user = patron.user user.password = hash_password(password) user.active = True db.session.merge(user) db.session.commit() confirm_user(user) patron.reindex() pids.append(patron.pid) except Exception as err: error_records.append(data) click.secho('{count: <8} User create error: {err}'.format( count=count, err=err), fg='red') if debug: traceback.print_exc() if not dont_stop_on_error: sys.exit(1) if debug: traceback.print_exc() if not dont_stop_on_error: sys.exit(1) if append: click.secho( 'Append fixtures new identifiers: {len}'.format(len=len(pids))) identifier = Patron.provider.identifier try: append_fixtures_new_identifiers(identifier, sorted(pids, key=lambda x: int(x)), PatronProvider.pid_type) except Exception as err: click.secho( "ERROR append fixtures new identifiers: {err}".format(err=err), fg='red') if error_records: name, ext = os.path.splitext(infile.name) err_file_name = '{name}_errors{ext}'.format(name=name, ext=ext) click.secho('Write error file: {name}'.format(name=err_file_name)) with open(err_file_name, 'w') as error_file: error_file.write('[\n') for error_record in error_records: for line in json.dumps(error_record, indent=2).split('\n'): error_file.write(' ' + line + '\n') error_file.write(']')
def confirm(self): ''' Marks the user's email as being confirmed. ''' return confirmable.confirm_user(self)
def import_users(infile, append, verbose, password, lazy, dont_stop_on_error, debug): """Import users. :param verbose: this function will be verbose. :param password: the password to use for user by default. :param lazy: lazy reads file :param dont_stop_on_error: don't stop on error :param infile: Json user file. """ click.secho('Import users:', fg='green') profile_fields = [ 'first_name', 'last_name', 'street', 'postal_code', 'gender', 'city', 'birth_date', 'username', 'home_phone', 'business_phone', 'mobile_phone', 'other_phone', 'keep_history', 'country', 'email' ] if lazy: # try to lazy read json file (slower, better memory management) data = read_json_record(infile) else: # load everything in memory (faster, bad memory management) data = json.load(infile) pids = [] error_records = [] for count, patron_data in enumerate(data, 1): password = patron_data.get('password', password) username = patron_data['username'] if password: patron_data.pop('password', None) if verbose: user_record = User.get_by_username(username) if not user_record: click.secho('{count: <8} Creating user: {username}'.format( count=count, username=username)) else: user = user_record.user for field in profile_fields: value = patron_data.get(field) if value is not None: if field == 'birth_date': value = datetime.strptime(value, '%Y-%m-%d') setattr(user.profile, field, value) db.session.merge(user) db.session.commit() click.secho('{count: <8} User updated: {username}'.format( count=count, username=username), fg='yellow') try: # patron creation patron = None patron_pid = patron_data.get('pid') if patron_pid: patron = Patron.get_record_by_pid(patron_pid) if not patron: patron = create_patron_from_data(data=patron_data, dbcommit=False, reindex=False) user = patron.user user.password = hash_password(password) user.active = True db.session.merge(user) db.session.commit() confirm_user(user) patron.reindex() pids.append(patron.pid) else: # remove profile fields from patron record for field in profile_fields: patron_data.pop(field, None) patron.update(data=patron_data, dbcommit=True, reindex=True) if verbose: click.secho( '{count: <8} Patron updated: {username}'.format( count=count, username=username), fg='yellow') except Exception as err: error_records.append(patron_data) click.secho('{count: <8} User create error: {err}'.format( count=count, err=err), fg='red') if debug: traceback.print_exc() if not dont_stop_on_error: sys.exit(1) if debug: traceback.print_exc() db.session.rollback() if append: click.secho(f'Append fixtures new identifiers: {len(pids)}') identifier = Patron.provider.identifier try: append_fixtures_new_identifiers(identifier, sorted(pids, key=lambda x: int(x)), PatronProvider.pid_type) except Exception as err: click.secho(f'ERROR append fixtures new identifiers: {err}', fg='red') if error_records: name, ext = os.path.splitext(infile.name) err_file_name = f'{name}_errors{ext}' click.secho(f'Write error file: {err_file_name}') error_file = JsonWriter(err_file_name) for error_record in error_records: error_file.write(error_record)
def user(): user = User.objects.create(email='*****@*****.**', password='******') with myapp.app_context(): confirm_user(user) return user