Beispiel #1
0
 def post(self, **kwargs):
     """Reset user password."""
     user = self.get_user(**kwargs)
     after_this_request(_commit)
     update_password(user, kwargs['password'])
     login_user(user)
     return self.success_response(user)
Beispiel #2
0
    def reset_password(token):
        """View function that handles a reset password request."""

        expired, invalid, user = reset_password_token_status(token)

        if invalid:
            do_flash(*get_message('INVALID_RESET_PASSWORD_TOKEN'))
        if expired:
            do_flash(*get_message('PASSWORD_RESET_EXPIRED',
                                  email=user.email,
                                  within=_security.reset_password_within))
        if invalid or expired:
            return redirect(url_for('browser.forgot_password'))
        has_error = False
        form = _security.reset_password_form()

        if form.validate_on_submit():
            try:
                update_password(user, form.password.data)
            except SOCKETErrorException as e:
                # Handle socket errors which are not covered by SMTPExceptions.
                logging.exception(str(e), exc_info=True)
                flash(
                    gettext(
                        u'SMTP Socket error: {}\nYour password has not been changed.'
                    ).format(e), 'danger')
                has_error = True
            except (SMTPConnectError, SMTPResponseException,
                    SMTPServerDisconnected, SMTPDataError, SMTPHeloError,
                    SMTPException, SMTPAuthenticationError, SMTPSenderRefused,
                    SMTPRecipientsRefused) as e:

                # Handle smtp specific exceptions.
                logging.exception(str(e), exc_info=True)
                flash(
                    gettext(
                        u'SMTP error: {}\nYour password has not been changed.'
                    ).format(e), 'danger')
                has_error = True
            except Exception as e:
                # Handle other exceptions.
                logging.exception(str(e), exc_info=True)
                flash(
                    gettext(u'Error: {}\nYour password has not been changed.').
                    format(e), 'danger')
                has_error = True

            if not has_error:
                after_this_request(_commit)
                do_flash(*get_message('PASSWORD_RESET'))
                login_user(user)
                return redirect(
                    get_url(_security.post_reset_view)
                    or get_url(_security.post_login_view))

        return _security.render_template(
            config_value('RESET_PASSWORD_TEMPLATE'),
            reset_password_form=form,
            reset_password_token=token,
            **_ctx('reset_password'))
def reset_password(token):
    """View function that handles a reset password request."""

    expired, invalid, user = reset_password_token_status(token)

    if invalid:
        return redirect(url_for('frontend.forgot_password') + '?invalid')
    elif expired:
        send_reset_password_instructions(user)
        return redirect(url_for('frontend.forgot_password') + '?expired')
    elif request.method == 'GET':
        return redirect(url_for('frontend.reset_password', token=token))

    form = _security.reset_password_form()

    if form.validate_on_submit():
        after_this_request(_commit)
        update_password(user, form.newPassword.data)
        login_user(user)
    else:
        return jsonify({'errors': form.errors}), HTTPStatus.BAD_REQUEST

    return jsonify({
        'token': user.get_auth_token(),
        'user': user,
    })
Beispiel #4
0
    def update_password(self):
        """Used in conjunction with reset password to set password to a known value"""
        schema = RELS['v1.AuthView:update'][request.method]
        args = reset_password_options.parse_args()

        try:
            validate(args, schema, format_checker=FormatChecker())
        except ValidationError as e:
            return dict(status=400, message=e.message), 400

        token = args.get('token')
        expired, invalid, user = reset_password_token_status(token)

        if invalid or not user:
            return dict(status=409, message="Invalid reset token"), 409

        if expired:
            return dict(status=409, message="Reset token has expired"), 409

        update_password(user, args.get('password'))
        user.reset_secret()
        send_password_reset_notice(user)

        #SEE 90720022, Login the user
        login_user(user)
        user.save() #saving the user as a precaution, want the log data

        return {'status': 200, 'message': 'Password updated', 'user': generate_response_dict(user=user)}
Beispiel #5
0
    def reset_password(token):
        """View function that handles a reset password request."""

        expired, invalid, user = reset_password_token_status(token)

        if invalid:
            do_flash(*get_message('INVALID_RESET_PASSWORD_TOKEN'))
        if expired:
            do_flash(*get_message('PASSWORD_RESET_EXPIRED', email=user.email,
                                  within=_security.reset_password_within))
        if invalid or expired:
            return redirect(url_for('browser.forgot_password'))
        has_error = False
        form = _security.reset_password_form()

        if form.validate_on_submit():
            try:
                update_password(user, form.password.data)
            except SOCKETErrorException as e:
                # Handle socket errors which are not covered by SMTPExceptions.
                logging.exception(str(e), exc_info=True)
                flash(gettext(u'SMTP Socket error: {}\n'
                              u'Your password has not been changed.'
                              ).format(e),
                      'danger')
                has_error = True
            except (SMTPConnectError, SMTPResponseException,
                    SMTPServerDisconnected, SMTPDataError, SMTPHeloError,
                    SMTPException, SMTPAuthenticationError, SMTPSenderRefused,
                    SMTPRecipientsRefused) as e:

                # Handle smtp specific exceptions.
                logging.exception(str(e), exc_info=True)
                flash(gettext(u'SMTP error: {}\n'
                              u'Your password has not been changed.'
                              ).format(e),
                      'danger')
                has_error = True
            except Exception as e:
                # Handle other exceptions.
                logging.exception(str(e), exc_info=True)
                flash(gettext(u'Error: {}\n'
                              u'Your password has not been changed.'
                              ).format(e),
                      'danger')
                has_error = True

            if not has_error:
                after_this_request(_commit)
                do_flash(*get_message('PASSWORD_RESET'))
                login_user(user)
                return redirect(get_url(_security.post_reset_view) or
                                get_url(_security.post_login_view))

        return _security.render_template(
            config_value('RESET_PASSWORD_TEMPLATE'),
            reset_password_form=form,
            reset_password_token=token,
            **_ctx('reset_password'))
Beispiel #6
0
def set_random_password(user: User):
    """
    Randomise a user's password.

    Remember to commit the session after calling this function!
    """
    new_random_password = "".join(
        [random.choice(string.ascii_lowercase) for _ in range(24)])
    update_password(user, new_random_password)
Beispiel #7
0
def reset_password(token):
    """
    ---
    post:
      tags: ["User"]
      description: Reset the user's password based on the given token
      responses:
        200:
          description: Ok
    """
    if not config.smtp.is_enabled():
        logger.warning('Missing SMTP Config.')
        return make_response(
            flask.jsonify(response=dict(message="Operation not implemented"),
                          success=False,
                          code=501), 501)

    try:
        if 'password' not in request.json or 'password_confirm' not in request.json:
            return make_response(
                flask.jsonify(response=dict(message="Invalid data provided"),
                              success=False,
                              code=406), 406)

        expired, invalid, user = reset_password_token_status(token)

        if not user or invalid:
            invalid = True

        if invalid or expired:
            return make_response(
                flask.jsonify(response=dict(message="Invalid Token"),
                              success=False,
                              code=406), 406)
        if request.is_json:
            form = ResetPasswordForm(MultiDict(request.get_json()))
            if form.validate_on_submit() and validate_strong_password(
                    form.password.data, form.password_confirm.data):
                update_password(user, form.password.data)
                _datastore.commit()
                return flask.jsonify(
                    response=dict(message="Password changed successfully"),
                    success=True,
                    code=200)

        return make_response(
            flask.jsonify(response=dict(message="Bad request"),
                          success=False,
                          code=400), 400)

    except Exception as e:
        logger.exception(e)
        return make_response(
            flask.jsonify(response=dict(token=token, message="Server Error"),
                          success=False,
                          code=500), 500)
Beispiel #8
0
def account_edit_own_password():
    form = forms.MembersEditPassword()
    _security = LocalProxy(lambda: current_app.extensions['security'])
    _datastore = LocalProxy(lambda: _security.datastore)
    if form.validate_on_submit():
        update_password(current_user, request.form['password'])
        _datastore.commit()
        flash("your password was updated", "confirmation")
        return redirect(request.url)
    return render_template('my_account/edit_password.html', form=form)
Beispiel #9
0
def account_edit_own_password():
    form = forms.MembersEditPassword()
    _security = LocalProxy(lambda: current_app.extensions['security'])
    _datastore = LocalProxy(lambda: _security.datastore)
    if form.validate_on_submit():
        update_password(current_user, request.form['password'])
        _datastore.commit()
        flash("your password was updated", "confirmation")
        return redirect(request.url)
    return render_template('my_account/edit_password.html', form=form)
Beispiel #10
0
    def post(self, **kwargs):
        """Reset user password."""
        # TODO there doesn't seem to be a `.resettable` or similar?
        if not current_security.recoverable:
            _abort(get_message("PASSWORD_RESET_DISABLED")[0])

        user = self.get_user(**kwargs)
        after_this_request(_commit)
        update_password(user, kwargs["password"])
        login_user(user)
        return self.success_response(user)
Beispiel #11
0
def reset_password(user):
    """
    Reset the user's current password.
    Send a password reset link to the user.
    """
    new_random_password = "".join(
        [random.choice(string.ascii_lowercase) for _ in range(24)])
    update_password(user, new_random_password)

    send_reset_password_instructions(user)

    # commit only if sending instructions worked
    db.session.commit()
Beispiel #12
0
    def reset_password(token):
        """View function that handles a reset password request."""
        expired, invalid, user = reset_password_token_status(token)

        if invalid:
            do_flash(*get_message('INVALID_RESET_PASSWORD_TOKEN'))
        if expired:
            do_flash(*get_message('PASSWORD_RESET_EXPIRED',
                                  email=user.email,
                                  within=_security.reset_password_within))
        if invalid or expired:
            return redirect(url_for('browser.forgot_password'))
        has_error = False
        form = _security.reset_password_form()

        if form.validate_on_submit():
            try:
                update_password(user, form.password.data)
            except SOCKETErrorException as e:
                # Handle socket errors which are not covered by SMTPExceptions.
                logging.exception(str(e), exc_info=True)
                flash(gettext(SMTP_SOCKET_ERROR).format(e), 'danger')
                has_error = True
            except (SMTPConnectError, SMTPResponseException,
                    SMTPServerDisconnected, SMTPDataError, SMTPHeloError,
                    SMTPException, SMTPAuthenticationError, SMTPSenderRefused,
                    SMTPRecipientsRefused) as e:

                # Handle smtp specific exceptions.
                logging.exception(str(e), exc_info=True)
                flash(gettext(SMTP_ERROR).format(e), 'danger')
                has_error = True
            except Exception as e:
                # Handle other exceptions.
                logging.exception(str(e), exc_info=True)
                flash(gettext(PASS_ERROR).format(e), 'danger')
                has_error = True

            if not has_error:
                after_this_request(view_commit)
                auth_obj = AuthSourceManager(form, [INTERNAL])
                session['_auth_source_manager_obj'] = auth_obj.as_dict()

                if user.login_attempts >= config.MAX_LOGIN_ATTEMPTS > 0:
                    flash(
                        gettext('You successfully reset your password but'
                                ' your account is locked. Please contact '
                                'the Administrator.'), 'warning')
                    return redirect(get_post_logout_redirect())
                do_flash(*get_message('PASSWORD_RESET'))
                login_user(user)
                auth_obj = AuthSourceManager(form, [INTERNAL])
                session['auth_source_manager'] = auth_obj.as_dict()

                return redirect(
                    get_url(_security.post_reset_view)
                    or get_url(_security.post_login_view))

        return _security.render_template(
            config_value('RESET_PASSWORD_TEMPLATE'),
            reset_password_form=form,
            reset_password_token=token,
            **_ctx('reset_password'))
Beispiel #13
0
def create_user(  # noqa: C901
    user_roles: Union[Dict[str, str], List[Dict[str, str]], str, List[str]] = None,
    check_deliverability: bool = True,
    **kwargs
) -> User:
    """Convenience wrapper to create a new User object and new Role objects (if user roles do not already exist),
    and new DataSource object that corresponds to the user."""

    # Check necessary input explicitly before anything happens
    if "email" not in kwargs:
        raise InvalidFlexMeasuresUser("No email address provided.")
    email = kwargs.pop("email").strip()
    try:
        email_info = validate_email(email, check_deliverability=False)
        # The mx check talks to the SMTP server. During testing, we skip it because it
        # takes a bit of time and without internet connection it fails.
        if check_deliverability and not current_app.testing:
            try:
                validate_email_deliverability(
                    email_info.domain, email_info["domain_i18n"]
                )
            except EmailUndeliverableError as eue:
                raise InvalidFlexMeasuresUser(
                    "The email address %s does not seem to be deliverable: %s"
                    % (email, str(eue))
                )
    except EmailNotValidError as enve:
        raise InvalidFlexMeasuresUser(
            "%s is not a valid email address: %s" % (email, str(enve))
        )
    if "username" not in kwargs:
        username = email.split("@")[0]
    else:
        username = kwargs.pop("username").strip()

    # Check integrity explicitly before anything happens
    existing_user_by_email = User.query.filter_by(email=email).one_or_none()
    if existing_user_by_email is not None:
        raise InvalidFlexMeasuresUser("User with email %s already exists." % email)
    existing_user_by_username = User.query.filter_by(username=username).one_or_none()
    if existing_user_by_username is not None:
        raise InvalidFlexMeasuresUser(
            "User with username %s already exists." % username
        )

    user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role)
    kwargs.update(email=email, username=username)
    user = user_datastore.create_user(**kwargs)

    if user.password is None:
        new_random_password = "".join(
            [random.choice(string.ascii_lowercase) for _ in range(12)]
        )
        update_password(user, new_random_password)

    # add roles to user (creating new roles if necessary)
    if user_roles:
        if not isinstance(user_roles, list):
            user_roles = [user_roles]  # type: ignore
        for user_role in user_roles:
            if isinstance(user_role, dict):
                role = user_datastore.find_role(user_role["name"])
            else:
                role = user_datastore.find_role(user_role)
            if role is None:
                if isinstance(user_role, dict):
                    role = user_datastore.create_role(**user_role)
                else:
                    role = user_datastore.create_role(name=user_role)
            user_datastore.add_role_to_user(user, role)

    # create data source
    db.session.add(DataSource(user=user))

    return user