def test_reset_user_password_link(self): # Set password CreateTestData.create_user(name="bob", email="*****@*****.**", password="******") # Set password to something new model.User.by_name(u"bob").password = "******" model.repo.commit_and_remove() test2_encoded = model.User.by_name(u"bob").password assert test2_encoded != "test2" assert model.User.by_name(u"bob").password == test2_encoded # Click link from reset password email create_reset_key(model.User.by_name(u"bob")) reset_password_link = get_reset_link(model.User.by_name(u"bob")) offset = reset_password_link.replace("http://test.ckan.net", "") res = self.app.get(offset) # Reset password form fv = res.forms["user-reset"] fv["password1"] = "test1" fv["password2"] = "test1" res = fv.submit("save", status=302) # Check a new password is stored assert model.User.by_name(u"bob").password != test2_encoded
def test_reset_user_password_link(self): # Set password CreateTestData.create_user(name='bob', email='*****@*****.**', password='******') # Set password to something new model.User.by_name(u'bob').password = '******' model.repo.commit_and_remove() test2_encoded = model.User.by_name(u'bob').password assert test2_encoded != 'test2' assert model.User.by_name(u'bob').password == test2_encoded # Click link from reset password email create_reset_key(model.User.by_name(u'bob')) reset_password_link = get_reset_link(model.User.by_name(u'bob')) offset = reset_password_link.replace('http://test.ckan.net', '') print offset res = self.app.get(offset) # Reset password form fv = res.forms['user-reset'] fv['password1'] = 'test1' fv['password2'] = 'test1' res = fv.submit('save', status=302) # Check a new password is stored assert model.User.by_name(u'bob').password != test2_encoded
def post(self, id): context, user_dict = self._prepare(id) context[u'reset_password'] = True user_state = user_dict[u'state'] try: new_password = self._get_form_password() user_dict[u'password'] = new_password username = request.form.get(u'name') if (username is not None and username != u''): user_dict[u'name'] = username user_dict[u'reset_key'] = g.reset_key user_dict[u'state'] = model.State.ACTIVE logic.get_action(u'user_update')(context, user_dict) mailer.create_reset_key(context[u'user_obj']) h.flash_success(_(u'Your password has been reset.')) return h.redirect_to(u'home.index') except logic.NotAuthorized: h.flash_error(_(u'Unauthorized to edit user %s') % id) except logic.NotFound: h.flash_error(_(u'User not found')) except dictization_functions.DataError: h.flash_error(_(u'Integrity Error')) except logic.ValidationError as e: h.flash_error(u'%r' % e.error_dict) except ValueError as e: h.flash_error(text_type(e)) user_dict[u'state'] = user_state return base.render(u'user/perform_reset.html', { u'user_dict': user_dict })
def perform_reset(self, id): # FIXME 403 error for invalid key is a non helpful page context = {'model': model, 'session': model.Session, 'user': id, 'keep_email': True} try: check_access('user_reset', context) except NotAuthorized: abort(403, _('Unauthorized to reset password.')) try: data_dict = {'id': id} user_dict = get_action('user_show')(context, data_dict) user_obj = context['user_obj'] except NotFound as e: abort(404, _('User not found')) c.reset_key = request.params.get('key') if not mailer.verify_reset_link(user_obj, c.reset_key): h.flash_error(_('Invalid reset key. Please try again.')) abort(403) if request.method == 'POST': try: context['reset_password'] = True user_state = user_dict['state'] new_password = self._get_form_password() user_dict['password'] = new_password username = request.params.get('name') if (username is not None and username != ''): user_dict['name'] = username user_dict['reset_key'] = c.reset_key user_dict['state'] = model.State.ACTIVE user = get_action('user_update')(context, user_dict) mailer.create_reset_key(user_obj) h.flash_success(_("Your password has been reset.")) h.redirect_to('/') except NotAuthorized: h.flash_error(_('Unauthorized to edit user %s') % id) except NotFound as e: h.flash_error(_('User not found')) except DataError: h.flash_error(_(u'Integrity Error')) except ValidationError as e: h.flash_error(u'%r' % e.error_dict) except ValueError as ve: h.flash_error(unicode(ve)) user_dict['state'] = user_state c.user_dict = user_dict return render('user/perform_reset.html')
def test_perform_reset_doesnt_activate_deleted_user(self): password = "******" params = {"password1": password, "password2": password} user = CreateTestData.create_user(name="deleted_user", email="*****@*****.**") user.delete() create_reset_key(user) assert user.is_deleted(), user.state offset = url_for(controller="user", action="perform_reset", id=user.id, key=user.reset_key) res = self.app.post(offset, params=params, status=302) user = model.User.get(user.id) assert user.is_deleted(), user
def test_perform_reset_for_key_change(self): password = "******" params = {"password1": password, "password2": password} user = factories.User() user_obj = helpers.model.User.by_name(user["name"]) create_reset_key(user_obj) key = user_obj.reset_key app = self._get_test_app() offset = url_for(controller="user", action="perform_reset", id=user_obj.id, key=user_obj.reset_key) response = app.post(offset, params=params, status=302) user_obj = helpers.model.User.by_name(user["name"]) # Update user_obj assert_true(key != user_obj.reset_key)
def test_perform_reset_for_key_change(self): password = '******' params = {'password1': password, 'password2': password} user = factories.User() user_obj = helpers.model.User.by_name(user['name']) create_reset_key(user_obj) key = user_obj.reset_key app = self._get_test_app() offset = url_for(controller='user', action='perform_reset', id=user_obj.id, key=user_obj.reset_key) response = app.post(offset, params=params, status=302) user_obj = helpers.model.User.by_name(user['name']) # Update user_obj assert_true(key != user_obj.reset_key)
def test_perform_reset_doesnt_activate_deleted_user(self): password = '******' params = { 'password1': password, 'password2': password } user = CreateTestData.create_user(name='deleted_user', email='*****@*****.**') user.delete() create_reset_key(user) assert user.is_deleted(), user.state offset = url_for(controller='user', action='perform_reset', id=user.id, key=user.reset_key) res = self.app.post(offset, params=params, status=403) user = model.User.get(user.id) assert user.is_deleted(), user
def test_perform_reset_doesnt_activate_deleted_user(app): password = "******" params = {"password1": password, "password2": password} user = CreateTestData.create_user(name="deleted_user", email="*****@*****.**") user.delete() create_reset_key(user) assert user.is_deleted(), user.state offset = url_for( controller="user", action="perform_reset", id=user.id, key=user.reset_key, ) res = app.post(offset, params=params, status=403) user = model.User.get(user.id) assert user.is_deleted(), user
def password_reset(self, user_id): context = { 'model': model, 'session': model.Session, 'user': user_id, 'keep_email': True } try: check_access('user_reset', context) except NotAuthorized: return h.redirect_to('home') try: logic.get_action('user_show')(context, {'id': user_id}) user_obj = context['user_obj'] except logic.NotFound: return base.render('user/expired_key.html') c.reset_key = request.params.get('key') if not ckan_mailer.verify_reset_link(user_obj, c.reset_key): # Invalid reset key. return base.render('user/expired_key.html') if request.method == 'POST': user_data = { 'id': user_obj.id, 'password': request.params.get('password') } if request.params.get('email', None) is not None: user_data['email'] = request.params.get('email') user_updated = self._edit_user(user_data) ckan_mailer.create_reset_key(user_obj) response.headers['Content-Type'] = self.json_content_type json_response = { 'success': user_updated, 'redirect_url': h.url_for('/ingresar') } return h.json.dumps(json_response, for_json=True) return base.render('user/perform_reset.html', extra_vars={'user': user_obj})
def command(self): output_file = self.args[0] msg = "Are you sure you want to reset ALL of the user passwords?" confirm = query_yes_no(msg, default='no') if confirm == 'no': sys.stderr.write("Aborting...\n") sys.exit(1) self._load_config() import ckan.model as model import ckan.lib.search as search with open(output_file, 'wb') as f: writer = csv.writer(f) writer.writerow(['id', 'email-address', 'reset-key']) for user in model.User.all(): create_reset_key(user) user.save() writer.writerow([user.id, user.email, user.reset_key])
def reset_password(id): ''' This method is copied from the ckan user view class method PerformResetView.post It is a exact copy so will need to be checked and updated if necessary on any CKAN upgrades This method is used to update the internal method _get_form_password() ''' context, user_dict = PerformResetView._prepare(PerformResetView(), id) context[u'reset_password'] = True user_state = user_dict[u'state'] try: # Modifications begin new_password = _get_form_password() # Modifications end user_dict[u'password'] = new_password username = request.form.get(u'name') if (username is not None and username != u''): user_dict[u'name'] = username user_dict[u'reset_key'] = g.reset_key user_dict[u'state'] = model.State.ACTIVE get_action(u'user_update')(context, user_dict) mailer.create_reset_key(context[u'user_obj']) h.flash_success(_(u'Your password has been reset.')) return h.redirect_to(u'home.index') except NotAuthorized: h.flash_error(_(u'Unauthorized to edit user %s') % id) except NotFound: h.flash_error(_(u'User not found')) except dictization_functions.DataError: h.flash_error(_(u'Integrity Error')) except ValidationError as e: h.flash_error(u'%r' % e.error_dict) except ValueError as e: h.flash_error(text_type(e)) user_dict[u'state'] = user_state return render(u'user/perform_reset.html', {u'user_dict': user_dict})
class CustomUserController(UserController): def perform_reset(self, id): # FIXME 403 error for invalid key is a non helpful page context = { 'model': model, 'session': model.Session, 'user': id, 'keep_email': True } try: check_access('user_reset', context) except NotAuthorized: abort(403, _('Unauthorized to reset password.')) try: data_dict = {'id': id} user_dict = get_action('user_show')(context, data_dict) user_obj = context['user_obj'] except NotFound, e: abort(404, _('User not found')) c.reset_key = request.params.get('key') if not mailer.verify_reset_link(user_obj, c.reset_key): h.flash_error(_('Invalid reset key. Please try again.')) abort(403) if request.method == 'POST': try: context['reset_password'] = True new_password = self._get_form_password() user_dict['password'] = new_password user_dict['reset_key'] = c.reset_key user_dict['state'] = model.State.ACTIVE user = get_action('user_update')(context, user_dict) mailer.create_reset_key(user_obj) h.flash_success(_("Your password has been reset.")) h.redirect_to('/') except NotAuthorized: h.flash_error(_('Unauthorized to edit user %s') % id) except NotFound, e: h.flash_error(_('User not found')) except DataError: h.flash_error(_(u'Integrity Error'))
abort(404, _('User not found')) c.reset_key = request.params.get('key') if not mailer.verify_reset_link(user_obj, c.reset_key): h.flash_error(_('Invalid reset key. Please try again.')) abort(403) if request.method == 'POST': try: context['reset_password'] = True new_password = self._get_form_password() user_dict['password'] = new_password user_dict['reset_key'] = c.reset_key user_dict['state'] = model.State.ACTIVE user = get_action('user_update')(context, user_dict) mailer.create_reset_key(user_obj) h.flash_success(_("Your password has been reset.")) h.redirect_to('/') except NotAuthorized: h.flash_error(_('Unauthorized to edit user %s') % id) except NotFound, e: h.flash_error(_('User not found')) except DataError: h.flash_error(_(u'Integrity Error')) except ValidationError, e: h.flash_error(u'%r' % e.error_dict) except ValueError, ve: h.flash_error(unicode(ve)) c.user_dict = user_dict
def create_activation_key(user): """ Creates activation key for user :param user: the user for whom an activation key should be created :type user: dict """ mailer.create_reset_key(user)
def user_invite(context, data_dict): '''Invite a new user. You must be authorized to create group members. :param email: the email of the user to be invited to the group :type email: string :param group_id: the id or name of the group :type group_id: string :param role: role of the user in the group. One of ``member``, ``editor``, or ``admin`` :type role: string :returns: the newly created yser :rtype: dictionary ''' toolkit.check_access('user_invite', context, data_dict) schema = context.get('schema', logic.schema.default_user_invite_schema()) data, errors = toolkit.navl_validate(data_dict, schema, context) if errors: raise toolkit.ValidationError(errors) model = context['model'] group = model.Group.get(data['group_id']) if not group: raise toolkit.ObjectNotFound() name = logic.action.create._get_random_username_from_email(data['email']) password = str(random.SystemRandom().random()) data['name'] = name data['password'] = password data['state'] = model.State.PENDING user_dict = toolkit.get_action('user_create')(context, data) user = model.User.get(user_dict['id']) member_dict = { 'username': user.id, 'id': data['group_id'], 'role': data['role'] } toolkit.get_action('group_member_create')(context, member_dict) if group.is_organization: group_dict = toolkit.get_action('organization_show')(context, {'id': data['group_id']}) else: group_dict = toolkit.get_action('group_show')(context, {'id': data['group_id']}) mailer.create_reset_key(user) # Email body group_type = (toolkit._('organization') if group_dict['is_organization'] else toolkit._('group')) role = data['role'] extra_vars = { 'reset_link': mailer.get_reset_link(user), 'site_title': config.get('ckan.site_title'), 'site_url': config.get('ckan.site_url'), 'user_name': user.name, 'role_name': authz.roles_trans().get(role, toolkit._(role)), 'group_type': group_type, 'group_title': group_dict.get('title'), } # NOTE: This template is translated body = render_jinja2('emails/invite_user.txt', extra_vars) subject = toolkit._('Invite for {site_title}').format( site_title=config.get('ckan.site_title')) mailer.mail_user(user, subject, body) return model_dictize.user_dictize(user, context)
def _login(context, data_dict): if toolkit.c.user: # Don't offer the reset form if already logged in log.warning("User already logged in") raise toolkit.NotAuthorized('user already logged in, logout first') # Check if parameters are present try: user_id = data_dict.get('id') if not user_id: email = data_dict['email'].lower() # Check email is valid if not util.check_email(email): raise toolkit.ValidationError({'email': 'invalid email'}) # get the user id user_id = util.get_user_id(email) if not user_id: raise toolkit.ValidationError({ 'email': 'email does not correspond to a registered user' }) except KeyError: raise toolkit.ValidationError({'email': 'missing email'}) try: orig_key = data_dict['key'] except KeyError: raise toolkit.ValidationError({'key': 'missing token'}) if len(orig_key) <= 32 and not orig_key.startswith("b'"): key = "b'{0}'".format(orig_key) else: key = orig_key log.debug('login: {0} ({1}) => {2}'.format(user_id, orig_key, key)) # get whether to return context (UI) or just a message (API) return_context = data_dict.get('return_context', False) try: data_dict = {'id': user_id} user_dict = logic.get_action('user_show')(context, data_dict) user_obj = context['user_obj'] email = user_dict.get('email', user_obj.email) except logic.NotFound: raise logic.NotFound('"%s" matched several users' % user_id) except toolkit.NotAuthorized: raise toolkit.NotAuthorized('Exception (Not Authorized) email = ' + str(email) + 'id = ' + str(user_id)) if not user_obj or not mailer.verify_reset_link(user_obj, key): raise toolkit.ValidationError({'key': 'token provided is not valid'}) flask.session['ckanext-passwordless-user'] = user_dict['name'] # remove token mailer.create_reset_key(user_obj) # log the user in programmatically try: _set_repoze_user_only(user_dict['name']) except TypeError as e: log.warning("Exception at login: {0}".format(e)) # delete attempts from Redis log.debug("Redis: reset attempts for {0}".format(email)) redis_conn = connect_to_redis() redis_conn.delete(email) # make sure the master API key exists apikey = util.renew_master_token(user_dict['name']) # return message or context if return_context: return context else: user_obj = context.get('user_obj', None) result_json = { 'user': { 'email': user_obj.email, 'id': user_obj.id, 'name': user_obj.name, 'apikey': apikey, 'fullname': user_obj.fullname }, 'message': "login success" } return result_json
def send_invite(user): _mailer.create_reset_key(user) body = _mailer.get_invite_body(user) subject = _('Invite for {site_title}').format(site_title=g.site_title) mail_user(user, subject, body)
class GDPRUserController(UserController): new_user_form = 'user/register.html' edit_user_form = 'user/gdpr_edit_user_form.html' def _save_new(self, context): context['schema'] = schema.user_new_form_schema() return UserController._save_new(self, context) def edit_me(self, locale=None): if not c.user: h.redirect_to(locale=locale, controller='user', action='login', id=None) user_ref = c.userobj.get_reference_preferred_for_uri() h.redirect_to(locale=locale, controller='ckanext.gdpr.controller:GDPRUserController', action='edit', id=user_ref) def perform_reset(self, id): # FIXME 403 error for invalid key is a non helpful page context = { 'model': model, 'session': model.Session, 'user': id, 'keep_email': True } try: logic.check_access('user_reset', context) except logic.NotAuthorized: abort(403, _('Unauthorized to reset password.')) try: data_dict = {'id': id} user_dict = logic.get_action('user_show')(context, data_dict) user_obj = context['user_obj'] except logic.NotFound, e: abort(404, _('User not found')) c.reset_key = request.params.get('key') if not mailer.verify_reset_link(user_obj, c.reset_key): h.flash_error(_('Invalid reset key. Please try again.')) abort(403) if request.method == 'POST': try: context['reset_password'] = True new_password = self._get_form_password() user_dict['password'] = new_password user_dict['reset_key'] = c.reset_key user_dict['state'] = model.State.ACTIVE # Include policies into user dict for key in request.params: if key.startswith('policy-'): user_dict[key] = request.params.getone(key) user = logic.get_action('user_update')(context, user_dict) mailer.create_reset_key(user_obj) h.flash_success(_("Your password has been reset.")) h.redirect_to('/') except logic.NotAuthorized: h.flash_error(_('Unauthorized to edit user %s') % id) except logic.NotFound, e: h.flash_error(_('User not found')) except dictization_functions.DataError: h.flash_error(_(u'Integrity Error'))
def send_reset_link(user): _mailer.create_reset_key(user) body = get_reset_link_body(user) subject = _('Reset your password') mail_user(user, subject, body)