diff --git a/sachet/server/users/views.py b/sachet/server/users/views.py index 48b218a..a500e39 100644 --- a/sachet/server/users/views.py +++ b/sachet/server/users/views.py @@ -123,7 +123,7 @@ class UserAPI(MethodView): def patch(user, self, username): patch_user = User.query.filter_by(username=username).first() - if Permissions.ADMIN not in user.permissions: + if not patch_user or Permissions.ADMIN not in user.permissions: resp = { "status": "fail", "message": "You are not authorized to access this page." @@ -152,8 +152,38 @@ class UserAPI(MethodView): } return jsonify(resp), 200 + @auth_required + def put(user, self, username): + put_user = User.query.filter_by(username=username).first() + + if not put_user or Permissions.ADMIN not in user.permissions: + resp = { + "status": "fail", + "message": "You are not authorized to access this page." + } + return jsonify(resp), 403 + + new_json = request.get_json() + + try: + deserialized = user_schema.load(new_json) + except ValidationError as e: + resp = { + "status": "fail", + "message": f"Invalid data: {str(e)}" + } + return jsonify(resp), 400 + + for k, v in deserialized.items(): + setattr(put_user, k, v) + + resp = { + "status": "success", + } + return jsonify(resp), 200 + users_blueprint.add_url_rule( "/users/", view_func=UserAPI.as_view("user_api"), - methods=['GET', 'PATCH'] + methods=['GET', 'PATCH', 'PUT'] ) diff --git a/tests/test_userinfo.py b/tests/test_userinfo.py index effaca0..343cd61 100644 --- a/tests/test_userinfo.py +++ b/tests/test_userinfo.py @@ -1,6 +1,9 @@ import pytest from bitmask import Bitmask -from sachet.server.models import Permissions +from sachet.server.models import Permissions, UserSchema +from datetime import datetime + +user_schema = UserSchema() def test_get(client, tokens, validate_info): """Test accessing the user information endpoint as a normal user.""" @@ -92,3 +95,42 @@ def test_patch(client, users, tokens, validate_info): ) assert resp.status_code == 200 validate_info("jeff", resp.get_json()) + +def test_put(client, users, tokens, validate_info): + """Test replacing user information as an administrator.""" + + # try with regular user to make sure it doesn't work + resp = client.patch( + "/users/jeff", + json = dict(), + headers={ + "Authorization": f"bearer {tokens['jeff']}" + } + ) + assert resp.status_code == 403 + + new_data = {k:v for k, v in users["jeff"].items()} + new_data["permissions"] = Bitmask(Permissions.ADMIN) + new_data["register_date"] = datetime(2022,2,2,0,0,0) + + resp = client.put( + "/users/jeff", + json = user_schema.dump(new_data), + headers={ + "Authorization": f"bearer {tokens['administrator']}" + } + ) + assert resp.status_code == 200 + + # modify the expected values + users["jeff"]["permissions"] = Bitmask(Permissions.ADMIN) + + # request new info + resp = client.get( + "/users/jeff", + headers={ + "Authorization": f"bearer {tokens['jeff']}" + } + ) + assert resp.status_code == 200 + validate_info("jeff", resp.get_json())