Пример #1
0
    def pwd_expired_change(self, **kw):
        require_authenticated()
        return_to = kw.get('return_to')
        kw = F.password_change_form.to_python(kw, None)
        ap = plugin.AuthenticationProvider.get(request)
        try:
            expired_username = session.get('expired-username')
            expired_user = M.User.query.get(
                username=expired_username) if expired_username else None
            ap.set_password(expired_user or c.user, kw['oldpw'], kw['pw'])
            expired_user.set_tool_data('allura',
                                       pwd_reset_preserve_session=session.id)
            expired_user.set_tool_data(
                'AuthPasswordReset', hash='',
                hash_expiry='')  # Clear password reset token

        except wexc.HTTPUnauthorized:
            flash('Incorrect password', 'error')
            redirect(tg.url('/auth/pwd_expired', dict(return_to=return_to)))
        flash('Password changed')
        session.pop('pwd-expired', None)
        session['username'] = session.get('expired-username')
        session.pop('expired-username', None)

        session.save()
        h.auditlog_user('Password reset (via expiration process)')
        if return_to and return_to != request.url:
            redirect(return_to)
        else:
            redirect('/')
Пример #2
0
    def pwd_expired_change(self, **kw):
        require_authenticated()
        return_to = kw.get("return_to")
        kw = F.password_change_form.to_python(kw, None)
        ap = plugin.AuthenticationProvider.get(request)
        try:
            expired_username = session.get("expired-username")
            expired_user = M.User.query.get(username=expired_username) if expired_username else None
            ap.set_password(expired_user or c.user, kw["oldpw"], kw["pw"])
            expired_user.set_tool_data("allura", pwd_reset_preserve_session=session.id)
            expired_user.set_tool_data("AuthPasswordReset", hash="", hash_expiry="")  # Clear password reset token

        except wexc.HTTPUnauthorized:
            flash("Incorrect password", "error")
            redirect(tg.url("/auth/pwd_expired", dict(return_to=return_to)))
        flash("Password changed")
        session.pop("pwd-expired", None)
        session["username"] = session.get("expired-username")
        session.pop("expired-username", None)

        session.save()
        h.auditlog_user("Password reset (via expiration process)")
        if return_to and return_to != request.url:
            redirect(return_to)
        else:
            redirect("/")
Пример #3
0
    def pwd_expired_change(self, **kw):
        require_authenticated()
        return_to = kw.get('return_to')
        kw = F.password_change_form.to_python(kw, None)
        ap = plugin.AuthenticationProvider.get(request)
        try:
            expired_username = session.get('expired-username')
            expired_user = M.User.query.get(username=expired_username) if expired_username else None
            ap.set_password(expired_user or c.user, kw['oldpw'], kw['pw'])
            expired_user.set_tool_data('allura', pwd_reset_preserve_session=session.id)
            expired_user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')  # Clear password reset token

        except wexc.HTTPUnauthorized:
            flash('Incorrect password', 'error')
            redirect(tg.url('/auth/pwd_expired', dict(return_to=return_to)))
        flash('Password changed')
        session.pop('pwd-expired', None)
        session['username'] = session.get('expired-username')
        session.pop('expired-username', None)

        session.save()
        h.auditlog_user('Password reset (via expiration process)')
        if return_to and return_to != request.url:
            redirect(return_to)
        else:
            redirect('/')
Пример #4
0
 def make_password_reset_url(self, username):
     user = M.User.by_username(username)
     if not user or user.is_anonymous():
         raise HTTPNotFound()
     h.auditlog_user(
         'Generated new password reset URL and shown to admin user',
         user=user)
     return user.make_password_reset_url()
Пример #5
0
    def password_recovery_hash(self, email=None, **kw):
        provider = plugin.AuthenticationProvider.get(request)
        if not provider.forgotten_password_process:
            raise wexc.HTTPNotFound()
        if not email:
            redirect('/')

        user_record = M.User.by_email_address(email)
        allow_non_primary_email_reset = asbool(
            config.get('auth.allow_non_primary_email_password_reset', True))

        if not re.match(r"[^@]+@[^@]+\.[^@]+", email):
            flash('Enter email in correct format!', 'error')
            redirect('/auth/forgotten_password')

        if not allow_non_primary_email_reset:
            message = 'If the given email address is on record, '\
                      'a password reset email has been sent to the account\'s primary email address.'
            email_record = M.EmailAddress.get(
                email=provider.get_primary_email_address(
                    user_record=user_record),
                confirmed=True)
        else:
            message = 'A password reset email has been sent, if the given email address is on record in our system.'
            email_record = M.EmailAddress.get(email=email, confirmed=True)

        if user_record and email_record and email_record.confirmed:
            hash = h.nonce(42)
            user_record.set_tool_data(
                'AuthPasswordReset',
                hash=hash,
                hash_expiry=datetime.datetime.utcnow() +
                datetime.timedelta(seconds=int(
                    config.get('auth.recovery_hash_expiry_period', 600))))

            log.info('Sending password recovery link to %s',
                     email_record.email)
            subject = '%s Password recovery' % config['site_name']
            text = g.jinja2_env.get_template(
                'allura:templates/mail/forgot_password.txt').render(
                    dict(
                        user=user_record,
                        config=config,
                        hash=hash,
                    ))

            allura.tasks.mail_tasks.sendsimplemail.post(
                toaddr=email_record.email,
                fromaddr=config['forgemail.return_path'],
                reply_to=config['forgemail.return_path'],
                subject=subject,
                message_id=h.gen_message_id(),
                text=text)
        h.auditlog_user('Password recovery link sent to: %s',
                        email,
                        user=user_record)
        flash(message)
        redirect('/')
Пример #6
0
 def set_random_password(self, username=None):
     user = M.User.by_username(username)
     if not user or user.is_anonymous():
         raise HTTPNotFound()
     pwd = h.random_password()
     AuthenticationProvider.get(request).set_password(user, None, pwd)
     h.auditlog_user('Set random password', user=user)
     flash('Password is set', 'ok')
     redirect(request.referer)
Пример #7
0
 def set_random_password(self, username=None):
     user = M.User.by_username(username)
     if not user or user.is_anonymous():
         raise HTTPNotFound()
     pwd = h.random_password()
     AuthenticationProvider.get(request).set_password(user, None, pwd)
     h.auditlog_user('Set random password', user=user)
     flash('Password is set', 'ok')
     redirect(request.referer)
Пример #8
0
 def set_new_password(self, hash=None, pw=None, pw2=None):
     provider = plugin.AuthenticationProvider.get(request)
     if not provider.forgotten_password_process:
         raise wexc.HTTPNotFound()
     user = self._validate_hash(hash)
     user.set_password(pw)
     user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')  # Clear password reset token
     h.auditlog_user('Password changed (through recovery process)', user=user)
     flash('Password changed')
     redirect('/auth/?return_to=/')  # otherwise the default return_to would be the forgotten_password referrer page
Пример #9
0
    def password_recovery_hash(self, email=None, **kw):
        provider = plugin.AuthenticationProvider.get(request)
        if not provider.forgotten_password_process:
            raise wexc.HTTPNotFound()
        if not email:
            redirect("/")

        user_record = M.User.by_email_address(email)
        allow_non_primary_email_reset = asbool(config.get("auth.allow_non_primary_email_password_reset", True))

        if not re.match(r"[^@]+@[^@]+\.[^@]+", email):
            flash("Enter email in correct format!", "error")
            redirect("/auth/forgotten_password")

        if not allow_non_primary_email_reset:
            message = (
                "If the given email address is on record, "
                "a password reset email has been sent to the account's primary email address."
            )
            email_record = M.EmailAddress.get(
                email=provider.get_primary_email_address(user_record=user_record), confirmed=True
            )
        else:
            message = "A password reset email has been sent, if the given email address is on record in our system."
            email_record = M.EmailAddress.get(email=email, confirmed=True)

        if user_record and email_record and email_record.confirmed:
            hash = h.nonce(42)
            user_record.set_tool_data(
                "AuthPasswordReset",
                hash=hash,
                hash_expiry=datetime.datetime.utcnow()
                + datetime.timedelta(seconds=int(config.get("auth.recovery_hash_expiry_period", 600))),
            )

            log.info("Sending password recovery link to %s", email_record.email)
            subject = "%s Password recovery" % config["site_name"]
            text = g.jinja2_env.get_template("allura:templates/mail/forgot_password.txt").render(
                dict(user=user_record, config=config, hash=hash)
            )

            allura.tasks.mail_tasks.sendsimplemail.post(
                toaddr=email_record.email,
                fromaddr=config["forgemail.return_path"],
                reply_to=config["forgemail.return_path"],
                subject=subject,
                message_id=h.gen_message_id(),
                text=text,
            )
        h.auditlog_user("Password recovery link sent to: %s", email, user=user_record)
        flash(message)
        redirect("/")
Пример #10
0
    def change_password(self, **kw):
        kw = F.password_change_form.to_python(kw, None)
        ap = plugin.AuthenticationProvider.get(request)
        try:
            ap.set_password(c.user, kw["oldpw"], kw["pw"])
            c.user.set_tool_data("allura", pwd_reset_preserve_session=session.id)
            c.user.set_tool_data("AuthPasswordReset", hash="", hash_expiry="")

        except wexc.HTTPUnauthorized:
            flash("Incorrect password", "error")
            redirect(".")
        flash("Password changed")
        h.auditlog_user("Password changed")
        redirect(".")
Пример #11
0
 def update(self, preferences=None, **kw):
     if asbool(config.get("auth.allow_edit_prefs", True)):
         if not preferences.get("display_name"):
             flash("Display Name cannot be empty.", "error")
             redirect(".")
         old = c.user.get_pref("display_name")
         c.user.set_pref("display_name", preferences["display_name"])
         if old != preferences["display_name"]:
             h.auditlog_user("Display Name changed %s => %s", old, preferences["display_name"])
         for k, v in preferences.iteritems():
             if k == "results_per_page":
                 v = int(v)
             c.user.set_pref(k, v)
     redirect(".")
Пример #12
0
 def test_audit_log(self, req1, req2):
     req1.url = req2.url = 'http://host.domain/path/'
     c.user = M.User.by_username('test-user-1')
     h.auditlog_user('test activity user 1')
     h.auditlog_user('test activity user 2', user=M.User.by_username('test-user-2'))
     r = self.app.get('/nf/admin/user/test-admin')
     assert_in('Add comment', r)
     assert_not_in('test activity', r)
     r = self.app.get('/nf/admin/user/test-user-1')
     assert_in('test activity user 1', r)
     assert_not_in('test activity user 2', r)
     r = self.app.get('/nf/admin/user/test-user-2')
     assert_not_in('test activity user 1', r)
     assert_in('test activity user 2', r)
Пример #13
0
 def set_new_password(self, hash=None, pw=None, pw2=None):
     provider = plugin.AuthenticationProvider.get(request)
     if not provider.forgotten_password_process:
         raise wexc.HTTPNotFound()
     user = self._validate_hash(hash)
     user.set_password(pw)
     user.set_tool_data('AuthPasswordReset', hash='',
                        hash_expiry='')  # Clear password reset token
     h.auditlog_user('Password changed (through recovery process)',
                     user=user)
     flash('Password changed')
     redirect(
         '/auth/?return_to=/'
     )  # otherwise the default return_to would be the forgotten_password referrer page
Пример #14
0
 def test_audit_log(self, req1, req2):
     req1.url = req2.url = 'http://host.domain/path/'
     c.user = M.User.by_username('test-user-1')
     h.auditlog_user('test activity user 1')
     h.auditlog_user('test activity user 2', user=M.User.by_username('test-user-2'))
     r = self.app.get('/nf/admin/user/test-admin')
     assert_in('Add comment', r)
     assert_not_in('test activity', r)
     r = self.app.get('/nf/admin/user/test-user-1')
     assert_in('test activity user 1', r)
     assert_not_in('test activity user 2', r)
     r = self.app.get('/nf/admin/user/test-user-2')
     assert_not_in('test activity user 1', r)
     assert_in('test activity user 2', r)
Пример #15
0
 def update(self, preferences=None, **kw):
     if asbool(config.get('auth.allow_edit_prefs', True)):
         if not preferences.get('display_name'):
             flash("Display Name cannot be empty.", 'error')
             redirect('.')
         old = c.user.get_pref('display_name')
         c.user.set_pref('display_name', preferences['display_name'])
         if old != preferences['display_name']:
             h.auditlog_user('Display Name changed %s => %s', old, preferences['display_name'])
         for k, v in preferences.iteritems():
             if k == 'results_per_page':
                 v = int(v)
             c.user.set_pref(k, v)
     redirect('.')
Пример #16
0
    def change_password(self, **kw):
        kw = F.password_change_form.to_python(kw, None)
        ap = plugin.AuthenticationProvider.get(request)
        try:
            ap.set_password(c.user, kw['oldpw'], kw['pw'])
            c.user.set_tool_data('allura', pwd_reset_preserve_session=session.id)
            c.user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')

        except wexc.HTTPUnauthorized:
            flash('Incorrect password', 'error')
            redirect('.')
        flash('Password changed')
        h.auditlog_user('Password changed')
        redirect('.')
Пример #17
0
 def update(self, preferences=None, **kw):
     if asbool(config.get('auth.allow_edit_prefs', True)):
         if not preferences.get('display_name'):
             flash("Display Name cannot be empty.", 'error')
             redirect('.')
         old = c.user.get_pref('display_name')
         c.user.set_pref('display_name', preferences['display_name'])
         if old != preferences['display_name']:
             h.auditlog_user('Display Name changed %s => %s', old,
                             preferences['display_name'])
         for k, v in preferences.iteritems():
             if k == 'results_per_page':
                 v = int(v)
             c.user.set_pref(k, v)
     redirect('.')
Пример #18
0
    def change_password(self, **kw):
        kw = F.password_change_form.to_python(kw, None)
        ap = plugin.AuthenticationProvider.get(request)
        try:
            ap.set_password(c.user, kw['oldpw'], kw['pw'])
            c.user.set_tool_data('allura',
                                 pwd_reset_preserve_session=session.id)
            c.user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')

        except wexc.HTTPUnauthorized:
            flash('Incorrect password', 'error')
            redirect('.')
        flash('Password changed')
        h.auditlog_user('Password changed')
        redirect('.')
Пример #19
0
    def password_recovery_hash(self, email=None, **kw):
        provider = plugin.AuthenticationProvider.get(request)
        if not provider.forgotten_password_process:
            raise wexc.HTTPNotFound()
        if not email:
            redirect('/')

        user_record = M.User.by_email_address(email)
        allow_non_primary_email_reset = asbool(config.get('auth.allow_non_primary_email_password_reset', True))

        if not re.match(r"[^@]+@[^@]+\.[^@]+", email):
            flash('Enter email in correct format!','error')
            redirect('/auth/forgotten_password')

        if not allow_non_primary_email_reset:
            message = 'If the given email address is on record, '\
                      'a password reset email has been sent to the account\'s primary email address.'
            email_record = M.EmailAddress.get(email=provider.get_primary_email_address(user_record=user_record),
                                                    confirmed=True)
        else:
            message = 'A password reset email has been sent, if the given email address is on record in our system.'
            email_record = M.EmailAddress.get(email=email, confirmed=True)

        if user_record and email_record and email_record.confirmed:
            hash = h.nonce(42)
            user_record.set_tool_data('AuthPasswordReset',
                                      hash=hash,
                                      hash_expiry=datetime.datetime.utcnow() +
                                      datetime.timedelta(seconds=int(config.get('auth.recovery_hash_expiry_period', 600))))

            log.info('Sending password recovery link to %s', email_record.email)
            subject = '%s Password recovery' % config['site_name']
            text = g.jinja2_env.get_template('allura:templates/mail/forgot_password.txt').render(dict(
                user=user_record,
                config=config,
                hash=hash,
            ))

            allura.tasks.mail_tasks.sendsimplemail.post(
                toaddr=email_record.email,
                fromaddr=config['forgemail.return_path'],
                reply_to=config['forgemail.return_path'],
                subject=subject,
                message_id=h.gen_message_id(),
                text=text)
        h.auditlog_user('Password recovery link sent to: %s', email, user=user_record)
        flash(message)
        redirect('/')
Пример #20
0
    def _verify_addr(self, addr):
        confirmed_by_other = M.EmailAddress.find(
            dict(email=addr.email, confirmed=True)).all() if addr else []
        confirmed_by_other = filter(lambda item: item != addr,
                                    confirmed_by_other)

        if addr and not confirmed_by_other:
            addr.confirmed = True
            user = addr.claimed_by_user(include_pending=True)
            flash('Email address confirmed')
            h.auditlog_user('Email address verified: %s',
                            addr.email,
                            user=user)
            if user.pending:
                plugin.AuthenticationProvider.get(request).activate_user(user)
        else:
            flash('Unknown verification link', 'error')
Пример #21
0
    def _verify_addr(self, addr):
        confirmed_by_other = M.EmailAddress.find(dict(email=addr.email, confirmed=True)).all() if addr else []
        confirmed_by_other = filter(lambda item: item != addr, confirmed_by_other)

        if addr and not confirmed_by_other:
            addr.confirmed = True
            user = addr.claimed_by_user(include_pending=True)
            flash('Email address confirmed')
            h.auditlog_user('Email address verified: %s',  addr.email, user=user)
            if(user.get_pref('email_address') == None):
                user.set_pref('email_address', addr.email)
            if user.pending:
                plugin.AuthenticationProvider.get(request).activate_user(user)
                projectname = plugin.AuthenticationProvider.get(request).user_project_shortname(user)
                n = M.Neighborhood.query.get(name='Users')
                n.register_project(projectname, user=user, user_project=True)
        else:
            flash('Unknown verification link', 'error')
Пример #22
0
    def _verify_addr(self, addr):
        confirmed_by_other = M.EmailAddress.find(
            dict(email=addr.email, confirmed=True)).all() if addr else []
        confirmed_by_other = filter(lambda item: item != addr,
                                    confirmed_by_other)

        if addr and not confirmed_by_other:
            addr.confirmed = True
            user = addr.claimed_by_user(include_pending=True)
            flash('Email address confirmed')
            h.auditlog_user('Email address verified: %s',
                            addr.email,
                            user=user)
            if (user.get_pref('email_address') == None):
                user.set_pref('email_address', addr.email)
            if user.pending:
                plugin.AuthenticationProvider.get(request).activate_user(user)
                projectname = plugin.AuthenticationProvider.get(
                    request).user_project_shortname(user)
                n = M.Neighborhood.query.get(name='Users')
                n.register_project(projectname, user=user, user_project=True)
        else:
            flash('Unknown verification link', 'error')
Пример #23
0
 def test_message_html(self):
     al = h.auditlog_user('our message <script>alert(1)</script>')
     assert_equal(
         al.message,
         textwrap.dedent('''\
         IP Address: 127.0.0.1
         User-Agent: None
         our message <script>alert(1)</script>'''))
     assert_equal(
         al.message_html,
         textwrap.dedent('''\
         IP Address: 127.0.0.1<br>
         User-Agent: None<br>
         <strong>our message &lt;script&gt;alert(1)&lt;/script&gt;</strong>'''
                         ))
Пример #24
0
    def disable_users(cls, usernames, message):
        auth_provider = AuthenticationProvider.get(request=None)

        # would be nice to use the BatchIndexer extension around this but that only works for artifacts not users

        for username in usernames:
            user = M.User.query.get(username=username)
            if not user:
                log.info('Could not find user: %s', username)
            elif user.disabled:
                log.info('User is already disabled: %s', username)
                session(user).expunge(user)
            else:
                log.info('Disabling user: %s', username)
                auth_provider.disable_user(user)
                session(user).flush(user)
                if message:
                    log_entry = h.auditlog_user(message, user=user)
                    session(log_entry).flush(log_entry)
Пример #25
0
    def disable_users(cls, usernames, message):
        auth_provider = AuthenticationProvider.get(request=None)

        # would be nice to use the BatchIndexer extension around this but that only works for artifacts not users

        for username in usernames:
            user = M.User.query.get(username=username)
            if not user:
                log.info('Could not find user: %s', username)
            elif user.disabled:
                log.info('User is already disabled: %s', username)
                session(user).expunge(user)
            else:
                log.info('Disabling user: %s', username)
                auth_provider.disable_user(user)
                session(user).flush(user)
                if message:
                    log_entry = h.auditlog_user(message, user=user)
                    session(log_entry).flush(log_entry)
Пример #26
0
    def execute(cls, options):
        provider = ProjectRegistrationProvider.get()
        auth_provider = AuthenticationProvider.get(Request.blank('/'))
        for proj in options.projects:
            proj = cls.get_project(proj)
            if proj:
                if proj.is_user_project:
                    # disable user as well
                    user = proj.user_project_of
                    if user:
                        auth_provider.disable_user(user, audit=False)
                        msg = u'Account disabled because user-project was specified for deletion. Reason: {}'.format(
                            options.reason)
                        log_entry = h.auditlog_user(msg, user=user)
                        session(log_entry).flush(log_entry)
                    else:
                        log.info('Could not find associated user for user-project %s', proj.shortname)

                log.info('Purging %s Reason: %s', proj.url(), options.reason)
                provider.purge_project(proj, disable_users=options.disable_users, reason=options.reason)
Пример #27
0
    def execute(cls, options):
        provider = ProjectRegistrationProvider.get()
        auth_provider = AuthenticationProvider.get(Request.blank('/'))
        for proj in options.projects:
            proj = cls.get_project(proj)
            if proj:
                if proj.is_user_project:
                    # disable user as well
                    user = proj.user_project_of
                    if user:
                        auth_provider.disable_user(user, audit=False)
                        msg = u'Account disabled because user-project was specified for deletion. Reason: {}'.format(
                            options.reason)
                        log_entry = h.auditlog_user(msg, user=user)
                        session(log_entry).flush(log_entry)
                    else:
                        log.info(
                            'Could not find associated user for user-project %s',
                            proj.shortname)

                log.info('Purging %s Reason: %s', proj.url(), options.reason)
                provider.purge_project(proj,
                                       disable_users=options.disable_users,
                                       reason=options.reason)
Пример #28
0
    def _update_emails(self, user, admin=False, form_params={}):
        # not using **kw in method signature, to ensure 'admin' can't be passed in via a form submit
        kw = form_params
        addr = kw.pop('addr', None)
        new_addr = kw.pop('new_addr', None)
        primary_addr = kw.pop('primary_addr', None)
        provider = plugin.AuthenticationProvider.get(request)
        for i, (old_a, data) in enumerate(zip(user.email_addresses, addr
                                              or [])):
            obj = user.address_object(old_a)
            if data.get('delete') or not obj:
                if not admin and (not kw.get('password')
                                  or not provider.validate_password(
                                      user, kw.get('password'))):
                    flash(
                        'You must provide your current password to delete an email',
                        'error')
                    return
                if primary_addr == user.email_addresses[i]:
                    if select_new_primary_addr(user, ignore_emails=primary_addr) is None \
                            and asbool(config.get('auth.require_email_addr', False)):
                        flash(
                            'You must have at least one verified email address.',
                            'error')
                        return
                    else:
                        # clear it now, a new one will get set below
                        user.set_pref('email_address', None)
                        primary_addr = None
                        user.set_tool_data('AuthPasswordReset',
                                           hash='',
                                           hash_expiry='')
                h.auditlog_user('Email address deleted: %s',
                                user.email_addresses[i],
                                user=user)
                del user.email_addresses[i]
                if obj:
                    obj.delete()
        if new_addr.get('claim') or new_addr.get('addr'):
            user.set_tool_data('AuthPasswordReset', hash='',
                               hash_expiry='')  # Clear password reset token
            claimed_emails_limit = config.get(
                'user_prefs.maximum_claimed_emails', None)
            if claimed_emails_limit and len(
                    user.email_addresses) >= int(claimed_emails_limit):
                flash(
                    'You cannot claim more than %s email addresses.' %
                    claimed_emails_limit, 'error')
                return
            if not admin and (not kw.get('password')
                              or not provider.validate_password(
                                  user, kw.get('password'))):
                flash(
                    'You must provide your current password to claim new email',
                    'error')
                return

            claimed_emails = M.EmailAddress.find({
                'email': new_addr['addr']
            }).all()

            if any(email.claimed_by_user_id == user._id
                   for email in claimed_emails):
                flash('Email address already claimed', 'error')

            elif mail_util.isvalid(new_addr['addr']):
                em = M.EmailAddress.create(new_addr['addr'])
                if em:
                    user.email_addresses.append(em.email)
                    em.claimed_by_user_id = user._id

                    confirmed_emails = filter(lambda email: email.confirmed,
                                              claimed_emails)
                    if not confirmed_emails:
                        if not admin:
                            em.send_verification_link()
                        else:
                            AuthController()._verify_addr(em)
                    else:
                        em.send_claim_attempt()

                    if not admin:
                        user.set_tool_data('AuthPasswordReset',
                                           hash='',
                                           hash_expiry='')
                        flash(
                            'A verification email has been sent.  Please check your email and click to confirm.'
                        )

                    h.auditlog_user('New email address: %s',
                                    new_addr['addr'],
                                    user=user)
                else:
                    flash('Email address %s is invalid' % new_addr['addr'],
                          'error')
            else:
                flash('Email address %s is invalid' % new_addr['addr'],
                      'error')
        if not primary_addr and not user.get_pref(
                'email_address') and user.email_addresses:
            primary_addr = select_new_primary_addr(user)
        if primary_addr:
            if user.get_pref('email_address') != primary_addr:
                if not admin and (not kw.get('password')
                                  or not provider.validate_password(
                                      user, kw.get('password'))):
                    flash(
                        'You must provide your current password to change primary address',
                        'error')
                    return
                h.auditlog_user('Primary email changed: %s => %s',
                                user.get_pref('email_address'),
                                primary_addr,
                                user=user)
            user.set_pref('email_address', primary_addr)
            user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
Пример #29
0
def test_user_backfill_login_details():
    with h.push_config(request, user_agent='TestBrowser/55'):
        # these shouldn't match
        h.auditlog_user('something happened')
        h.auditlog_user('blah blah Password changed')
    with h.push_config(request, user_agent='TestBrowser/56'):
        # these should all match, but only one entry created for this ip/ua
        h.auditlog_user('Account activated')
        h.auditlog_user('Successful login')
        h.auditlog_user('Password changed')
    with h.push_config(request, user_agent='TestBrowser/57'):
        # this should match too
        h.auditlog_user('Set up multifactor TOTP')
    ThreadLocalORMSession.flush_all()

    auth_provider = plugin.AuthenticationProvider.get(None)
    c.user.backfill_login_details(auth_provider)

    details = M.UserLoginDetails.query.find({
        'user_id': c.user._id
    }).sort('ua').all()
    assert_equal(len(details), 2, details)
    assert_equal(details[0].ip, '127.0.0.1')
    assert_equal(details[0].ua, 'TestBrowser/56')
    assert_equal(details[1].ip, '127.0.0.1')
    assert_equal(details[1].ua, 'TestBrowser/57')
Пример #30
0
def test_user_backfill_login_details():
    with h.push_config(request, user_agent='TestBrowser/55'):
        # these shouldn't match
        h.auditlog_user('something happened')
        h.auditlog_user('blah blah Password changed')
    with h.push_config(request, user_agent='TestBrowser/56'):
        # these should all match, but only one entry created for this ip/ua
        h.auditlog_user('Account activated')
        h.auditlog_user('Successful login')
        h.auditlog_user('Password changed')
    with h.push_config(request, user_agent='TestBrowser/57'):
        # this should match too
        h.auditlog_user('Set up multifactor TOTP')
    ThreadLocalORMSession.flush_all()

    auth_provider = plugin.AuthenticationProvider.get(None)
    c.user.backfill_login_details(auth_provider)

    assert_equal(sorted(c.user.previous_login_details), [
        {'ip': '127.0.0.1', 'ua': 'TestBrowser/56'},
        {'ip': '127.0.0.1', 'ua': 'TestBrowser/57'},
    ])
Пример #31
0
    def _update_emails(self, user, admin=False, form_params={}):
        # not using **kw in method signature, to ensure 'admin' can't be passed in via a form submit
        kw = form_params
        addr = kw.pop('addr', None)
        new_addr = kw.pop('new_addr', None)
        primary_addr = kw.pop('primary_addr', None)
        provider = plugin.AuthenticationProvider.get(request)
        for i, (old_a, data) in enumerate(zip(user.email_addresses, addr or [])):
            obj = user.address_object(old_a)
            if data.get('delete') or not obj:
                if not admin and (not kw.get('password') or not provider.validate_password(user, kw.get('password'))):
                    flash('You must provide your current password to delete an email', 'error')
                    return
                if primary_addr == user.email_addresses[i]:
                    if select_new_primary_addr(user, ignore_emails=primary_addr) is None \
                            and asbool(config.get('auth.require_email_addr', False)):
                        flash('You must have at least one verified email address.', 'error')
                        return
                    else:
                        # clear it now, a new one will get set below
                        user.set_pref('email_address', None)
                        primary_addr = None
                        user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
                h.auditlog_user('Email address deleted: %s', user.email_addresses[i], user=user)
                del user.email_addresses[i]
                if obj:
                    obj.delete()
        if new_addr.get('claim') or new_addr.get('addr'):
            user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')  # Clear password reset token
            claimed_emails_limit = config.get('user_prefs.maximum_claimed_emails', None)
            if claimed_emails_limit and len(user.email_addresses) >= int(claimed_emails_limit):
                flash('You cannot claim more than %s email addresses.' % claimed_emails_limit, 'error')
                return
            if not admin and (not kw.get('password') or not provider.validate_password(user, kw.get('password'))):
                flash('You must provide your current password to claim new email', 'error')
                return

            claimed_emails = M.EmailAddress.find({'email': new_addr['addr']}).all()

            if any(email.claimed_by_user_id == user._id for email in claimed_emails):
                flash('Email address already claimed', 'error')

            elif mail_util.isvalid(new_addr['addr']):
                em = M.EmailAddress.create(new_addr['addr'])
                if em:
                    user.email_addresses.append(em.email)
                    em.claimed_by_user_id = user._id

                    confirmed_emails = filter(lambda email: email.confirmed, claimed_emails)
                    if not confirmed_emails:
                        if not admin:
                            em.send_verification_link()
                        else:
                            AuthController()._verify_addr(em)
                    else:
                        em.send_claim_attempt()

                    if not admin:
                        user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
                        flash('A verification email has been sent.  Please check your email and click to confirm.')

                    h.auditlog_user('New email address: %s', new_addr['addr'], user=user)
                else:
                    flash('Email address %s is invalid' % new_addr['addr'], 'error')
            else:
                flash('Email address %s is invalid' % new_addr['addr'], 'error')
        if not primary_addr and not user.get_pref('email_address') and user.email_addresses:
            primary_addr = select_new_primary_addr(user)
        if primary_addr:
            if user.get_pref('email_address') != primary_addr:
                if not admin and (not kw.get('password') or not provider.validate_password(user, kw.get('password'))):
                    flash('You must provide your current password to change primary address', 'error')
                    return
                h.auditlog_user(
                    'Primary email changed: %s => %s',
                    user.get_pref('email_address'),
                    primary_addr,
                    user=user)
            user.set_pref('email_address', primary_addr)
            user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')