def change_password():
    """Updates the password for the user"""
    if not request.json:
        response = {'message': 'no post body'}
        return jsonify(response), 400
    else:
        # Check the post body for the correct keys
        if 'old_password' not in request.json:
            response = {'message': 'old_password missing in post body'}
            return jsonify(response), 400
        if 'new_password' not in request.json:
            response = {'message': 'new_password missing in post body'}
            return jsonify(response), 400
        if 'new_password2' not in request.json:
            response = {'message': 'new_password2 missing in post body'}
            return jsonify(response), 400

        # Check to see if the old password was correct
        user_management = UserManagement()
        old_password = request.json['old_password']
        username = get_jwt_identity()
        authorized = user_management.authenticate_user(username=username,
                                                       password=old_password)
        log_request(request, username, authorized)

        if not authorized:
            msg = 'Current password is incorrect.'
            response = {'message': msg, 'errors': [msg]}
            return jsonify(response), 400

        # Check to make sure the two new passwords match
        new_password = request.json['new_password']
        new_password2 = request.json['new_password2']
        if new_password != new_password2:
            msg = 'New passwords did not match.'
            response = {'message': msg, 'errors': [msg]}
            return jsonify(response), 400

        # Update the user's password
        updated, errors = user_management.update_password(username,
                                                          new_password,
                                                          display_error=True)
        if updated:
            response = {
                'message': 'password updated for %s' % (username),
                'errors': []
            }
            return jsonify(response), 201
        else:
            response = {'message': 'password update failed', 'errors': errors}
            return jsonify(response), 400
def user_authenticate():
    """
    Authenticates a user and returns a json web token
    In the response body, refresh_token is the refresh token
        and jwt is the access token
    """
    if not request.json:
        response = {'message': 'no post body'}
        return jsonify(response), 400

    auth_user = request.json
    if 'username' not in auth_user or 'password' not in auth_user:
        response = {'message': 'missing key in post body'}
        return jsonify(response), 400

    username = auth_user['username']
    password = auth_user['password']

    user_management = UserManagement()
    user = user_management.get_user(username)
    if not user:
        authorized = False
    else:
        authorized = user_management.authenticate_user(username=username,
                                                       password=password)

    last_reset = str(user['pw_update_ts'])
    domain = conf.SUBDOMAIN
    bad_attempts = count_bad_login_attempts(username, 'dev', last_reset)
    if bad_attempts > 10:
        msg = 'account locked for user %s' % (auth_user['username'])
        response = {'message': msg}
        return jsonify(response), 423

    log_request(request, username, authorized)

    if authorized:
        access_token = create_access_token(identity=username)
        refresh_token = create_refresh_token(identity=username)
        response = jsonify({'login': True})
        set_access_cookies(response,
                           access_token,
                           max_age=conf.JWT_ACCESS_TOKEN_EXPIRES)
        set_refresh_cookies(response,
                            refresh_token,
                            max_age=conf.JWT_REFRESH_TOKEN_EXPIRES)
        return response, 200
    else:
        msg = 'authentication failed for user %s' % (auth_user['username'])
        response = {'message': msg}
        return jsonify(response), 401
def test_change_password():
    user_management = UserManagement()
    user_management.delete_user(conf.TEST_USER)
    user_management.add_user(conf.TEST_USER, conf.TEST_PASSWORD)

    response = CLIENT.post('/service/user/authenticate',
                           json=dict(username=conf.TEST_USER,
                                     password=conf.TEST_PASSWORD))
    assert response.status_code == 200
    jwt = utils._get_cookie_from_response(response, 'access_token_cookie')
    csrf = utils._get_cookie_from_response(response, 'csrf_access_token')

    # JSON body is required to update password
    response = CLIENT.post('/service/user/change-password',
                           headers={
                               'Cookies': 'access_token_cookie=%s' % (jwt),
                               'X-CSRF-TOKEN': csrf['csrf_access_token']
                           })
    assert response.status_code == 400

    # Old password must be correct to change password
    response = CLIENT.post('/service/user/change-password',
                           json=dict(old_password='******',
                                     new_password=conf.TEST_PASSWORD + '!1',
                                     new_password2=conf.TEST_PASSWORD + '!1'),
                           headers={
                               'Cookies': 'access_token_cookie=%s' % (jwt),
                               'X-CSRF-TOKEN': csrf['csrf_access_token']
                           })
    assert response.status_code == 400

    # New passwords must match to update password
    response = CLIENT.post('/service/user/change-password',
                           json=dict(old_password=conf.TEST_PASSWORD,
                                     new_password=conf.TEST_PASSWORD + '!1',
                                     new_password2=conf.TEST_PASSWORD + '!2'),
                           headers={
                               'Cookies': 'access_token_cookie=%s' % (jwt),
                               'X-CSRF-TOKEN': csrf['csrf_access_token']
                           })
    assert response.status_code == 400

    # Success!
    response = CLIENT.post('/service/user/change-password',
                           json=dict(old_password=conf.TEST_PASSWORD,
                                     new_password=conf.TEST_PASSWORD + '!1',
                                     new_password2=conf.TEST_PASSWORD + '!1'),
                           headers={
                               'Cookies': 'access_token_cookie=%s' % (jwt),
                               'X-CSRF-TOKEN': csrf['csrf_access_token']
                           })
    assert response.status_code == 201

    # Make sure password update worked
    authorized = user_management.authenticate_user(
        username=conf.TEST_USER, password='******')

    url = '/service/user/logout'
    response = CLIENT.post(url)
    assert response.status_code == 200

    user_management.delete_user(conf.TEST_USER)
    user = user_management.get_user(conf.TEST_USER)
    assert user == None