Skip to content

Commit

Permalink
moderation: add self-action prevention
Browse files Browse the repository at this point in the history
* Implement prevent_self_action decorator
* Prevent self-block, deactivate, impersonate
* Update tests for self-action prevention
* closes <inveniosoftware/invenio-administration#203>
  • Loading branch information
Samk13 committed Apr 26, 2024
1 parent 4c31af2 commit 6d9d9d2
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
34 changes: 34 additions & 0 deletions invenio_users_resources/decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2024 CERN.
# Copyright (C) 2024 KTH Royal Institute of Technology
#
# Invenio-Users-Resources is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
# details.

"""Users decorators."""
from functools import wraps

from flask import g
from flask_resources import resource_requestctx
from invenio_records_resources.resources.errors import PermissionDeniedError


def prevent_self_action():
"""Decorator that prevents users from taking actions on their own account."""

def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
user_id = str(resource_requestctx.view_args["id"])
current_user_id = str(g.identity.id)

if user_id == current_user_id:
raise PermissionDeniedError()

return func(*args, **kwargs)

return wrapper

return decorator
6 changes: 6 additions & 0 deletions invenio_users_resources/resources/users/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Copyright (C) 2022 TU Wien.
# Copyright (C) 2022 CERN.
# Copyright (C) 2022 European Union.
# Copyright (C) 2024 KTH Royal Institute of Technology
#
# Invenio-Users-Resources is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
Expand All @@ -20,6 +21,8 @@
)
from invenio_records_resources.resources.records.utils import search_preference

from invenio_users_resources.decorators import prevent_self_action


#
# Resource
Expand Down Expand Up @@ -108,6 +111,7 @@ def approve(self):
return "", 200

@request_view_args
@prevent_self_action()
def block(self):
"""Block user."""
self.service.block(
Expand All @@ -126,6 +130,7 @@ def restore(self):
return "", 200

@request_view_args
@prevent_self_action()
def deactivate(self):
"""Deactive user."""
self.service.deactivate(
Expand All @@ -144,6 +149,7 @@ def activate(self):
return "", 200

@request_view_args
@prevent_self_action()
def impersonate(self):
"""Impersonate the user."""
user = self.service.can_impersonate(
Expand Down
15 changes: 15 additions & 0 deletions tests/resources/test_resources_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# Copyright (C) 2022 European Union.
# Copyright (C) 2022 CERN.
# Copyright (C) 2024 KTH Royal Institute of Technology
#
# Invenio-Users-Resources is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
Expand Down Expand Up @@ -137,6 +138,13 @@ def test_block_user(client, headers, user_pub, user_moderator, db):
assert res.status_code == 200
assert res.json["blocked_at"] is not None

# Test user tries to block themselves
res = client.post(f"/users/{user_moderator.id}/block", headers=headers)
assert res.status_code == 403

res = client.get(f"/users/{user_moderator.id}")
assert res.status_code == 200


def test_deactivate_user(client, headers, user_pub, user_moderator, db):
"""Tests deactivate user endpoint."""
Expand All @@ -148,6 +156,13 @@ def test_deactivate_user(client, headers, user_pub, user_moderator, db):
assert res.status_code == 200
assert res.json["active"] == False

# Test user tries to deactivate themselves
res = client.post(f"/users/{user_moderator.id}/deactivate", headers=headers)
assert res.status_code == 403

res = client.get(f"/users/{user_moderator.id}")
assert res.status_code == 200


def test_management_permissions(client, headers, user_pub, db):
"""Test permissions at the resource level."""
Expand Down

0 comments on commit 6d9d9d2

Please sign in to comment.