From 11b05274cdf83fe76ea857c524af3bcb1492c1c7 Mon Sep 17 00:00:00 2001 From: wei-kuochen Date: Tue, 29 Sep 2026 14:07:16 +0900 Subject: [PATCH 1/2] fix group permission issue (No.306, 307, 312~326) --- modules/weko-groups/weko_groups/models.py | 2 +- modules/weko-groups/weko_groups/views.py | 25 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/modules/weko-groups/weko_groups/models.py b/modules/weko-groups/weko_groups/models.py index 571b6dd73d..cb7ac86c9f 100644 --- a/modules/weko-groups/weko_groups/models.py +++ b/modules/weko-groups/weko_groups/models.py @@ -517,7 +517,7 @@ def can_invite_others(self, user): return False elif self.is_admin(user): return True - elif self.subscription_policy != SubscriptionPolicy.CLOSED: + elif self.subscription_policy == SubscriptionPolicy.OPEN: return True else: return False diff --git a/modules/weko-groups/weko_groups/views.py b/modules/weko-groups/weko_groups/views.py index d2f9d33b7e..162231d86f 100644 --- a/modules/weko-groups/weko_groups/views.py +++ b/modules/weko-groups/weko_groups/views.py @@ -33,6 +33,9 @@ from six.moves.urllib.parse import urlparse from sqlalchemy.exc import IntegrityError from invenio_db import db +from weko_accounts.utils import roles_required +from weko_admin.config import WEKO_ADMIN_PERMISSION_ROLE_REPO, \ + WEKO_ADMIN_PERMISSION_ROLE_SYSTEM, WEKO_ADMIN_PERMISSION_ROLE_COMMUNITY from .forms import GroupForm, NewMemberForm from .models import Group, Membership @@ -116,6 +119,7 @@ def groupcount(): @blueprint.route('/grouplist', methods=['GET']) +@login_required def grouplist(): """ Get logined group list info. @@ -210,6 +214,9 @@ def invitations(): @blueprint.route('/new', methods=['GET', 'POST']) @register_breadcrumb(blueprint, 'breadcrumbs.settings.group.new', _('New')) @login_required +@roles_required([WEKO_ADMIN_PERMISSION_ROLE_SYSTEM, + WEKO_ADMIN_PERMISSION_ROLE_REPO, + WEKO_ADMIN_PERMISSION_ROLE_COMMUNITY]) def new(): """ Create new group. @@ -250,6 +257,9 @@ def new(): {'text': _('Manage')}] ) @login_required +@roles_required([WEKO_ADMIN_PERMISSION_ROLE_SYSTEM, + WEKO_ADMIN_PERMISSION_ROLE_REPO, + WEKO_ADMIN_PERMISSION_ROLE_COMMUNITY]) def manage(group_id): """ Manage your group. @@ -294,6 +304,9 @@ def manage(group_id): @blueprint.route('//delete', methods=['POST']) @login_required +@roles_required([WEKO_ADMIN_PERMISSION_ROLE_SYSTEM, + WEKO_ADMIN_PERMISSION_ROLE_REPO, + WEKO_ADMIN_PERMISSION_ROLE_COMMUNITY]) def delete(group_id): """ Delete group. @@ -328,6 +341,9 @@ def delete(group_id): @blueprint.route('//members', methods=['GET', 'POST']) @login_required +@roles_required([WEKO_ADMIN_PERMISSION_ROLE_SYSTEM, + WEKO_ADMIN_PERMISSION_ROLE_REPO, + WEKO_ADMIN_PERMISSION_ROLE_COMMUNITY]) @register_breadcrumb( blueprint, 'breadcrumbs.settings.group.members', _('Members'), dynamic_list_constructor=lambda: @@ -417,6 +433,9 @@ def leave(group_id): @blueprint.route('//members//approve', methods=['POST']) @login_required +@roles_required([WEKO_ADMIN_PERMISSION_ROLE_SYSTEM, + WEKO_ADMIN_PERMISSION_ROLE_REPO, + WEKO_ADMIN_PERMISSION_ROLE_COMMUNITY]) def approve(group_id, user_id): """ Approve a user. @@ -455,6 +474,9 @@ def approve(group_id, user_id): @blueprint.route('//members//remove', methods=['POST']) @login_required +@roles_required([WEKO_ADMIN_PERMISSION_ROLE_SYSTEM, + WEKO_ADMIN_PERMISSION_ROLE_REPO, + WEKO_ADMIN_PERMISSION_ROLE_COMMUNITY]) def remove(group_id, user_id): """ Remove user from a group. @@ -549,6 +571,9 @@ def reject(group_id): @blueprint.route('//members/new', methods=['GET', 'POST']) @login_required +@roles_required([WEKO_ADMIN_PERMISSION_ROLE_SYSTEM, + WEKO_ADMIN_PERMISSION_ROLE_REPO, + WEKO_ADMIN_PERMISSION_ROLE_COMMUNITY]) @register_breadcrumb( blueprint, 'breadcrumbs.settings.newmember', From 297905dece52f8e31f9ad7c24578252dd626a029 Mon Sep 17 00:00:00 2001 From: wei-kuochen Date: Tue, 29 Sep 2026 14:07:24 +0900 Subject: [PATCH 2/2] add test code --- modules/weko-groups/tests/test_views.py | 103 +++++++++++++++++++----- 1 file changed, 81 insertions(+), 22 deletions(-) diff --git a/modules/weko-groups/tests/test_views.py b/modules/weko-groups/tests/test_views.py index 39fbb05223..1263cec028 100644 --- a/modules/weko-groups/tests/test_views.py +++ b/modules/weko-groups/tests/test_views.py @@ -141,7 +141,15 @@ def test_invitations(app_2, users): # def new(): -def test_new(app_2, users): +user_results = [ + (0, 403), + (1, 302), + (2, 302), + (3, 302), + (4, 403), +] +@pytest.mark.parametrize('id, status_code', user_results) +def test_new(app_2, users, id, status_code): from sqlalchemy.exc import IntegrityError def validate_on_submit_True(): @@ -157,7 +165,7 @@ def validate_on_submit_False(): with app_2.test_request_context(): with app_2.test_client() as client: - with patch("flask_login.utils._get_user", return_value=users[3]["obj"]): + with patch("flask_login.utils._get_user", return_value=users[id]["obj"]): with patch("weko_groups.views.GroupForm", return_value=form): # "Encountered unknown tag 'assets'. Jinja was looking for the following tags: 'endblock'. The innermost block that needs to be closed is 'block'.", # But upon testing on the actual url on the browser "https://localhost/accounts/settings/groups/new" there is no problem @@ -171,7 +179,7 @@ def validate_on_submit_False(): with patch("weko_groups.views.GroupForm", return_value=form): with patch("weko_groups.views.Group.create", return_value=group): res = client.get(url_for('weko_groups.new')) - assert res.status_code == 302 + assert res.status_code == status_code # Exception coverage try: @@ -182,7 +190,15 @@ def validate_on_submit_False(): # def manage(group_id): -def test_manage(app_2, users): +user_results = [ + (0, 403), + (1, 302), + (2, 302), + (3, 302), + (4, 403), +] +@pytest.mark.parametrize('id, status_code', user_results) +def test_manage(app_2, users, id, status_code): def validate_on_submit_True(): return True @@ -207,11 +223,12 @@ def update_func(item): # "Encountered unknown tag 'assets'. Jinja was looking for the following tags: 'endblock'. The innermost block that needs to be closed is 'block'.", # But upon testing on the actual url on the browser "https://localhost/accounts/settings/groups/1" there is no problem # But upon testing on the actual url on the browser "https://localhost/accounts/settings/groups/1/manage" there is no problem - with patch("flask_login.utils._get_user", return_value=users[3]["obj"]): + with patch("flask_login.utils._get_user", return_value=users[id]["obj"]): with patch("weko_groups.views.Group", return_value=group): with patch("weko_groups.views.GroupForm", return_value=form): try: - client.get(url_for('weko_groups.manage', group_id=1)) + res = client.get(url_for('weko_groups.manage', group_id=1)) + assert res.status_code == status_code except: pass @@ -238,7 +255,15 @@ def validate_on_submit_True(): # def delete(group_id): -def test_delete(app_2, users): +user_results = [ + (0, 403), + (1, 302), + (2, 302), + (3, 302), + (4, 403), +] +@pytest.mark.parametrize('id, status_code', user_results) +def test_delete(app_2, users, id, status_code): def can_edit_True(item): return True @@ -256,10 +281,10 @@ def delete_func(): with app_2.test_request_context(): with app_2.test_client() as client: - with patch("flask_login.utils._get_user", return_value=users[3]["obj"]): + with patch("flask_login.utils._get_user", return_value=users[id]["obj"]): with patch("weko_groups.views.Group", return_value=group): res = client.post(url_for('weko_groups.delete', group_id=1)) - assert res.status_code == 302 + assert res.status_code == status_code def test_delete_2(app_2, users): @@ -272,7 +297,15 @@ def test_delete_2(app_2, users): # def members(group_id): -def test_members(app_2, users): +user_results = [ + (0, 403), + (1, 200), + (2, 200), + (3, 200), + (4, 403), +] +@pytest.mark.parametrize('id, status_code', user_results) +def test_members(app_2, users, id, status_code): def can_edit_True(item): return True @@ -290,7 +323,7 @@ def delete_func(): with app_2.test_request_context(): with app_2.test_client() as client: - with patch("flask_login.utils._get_user", return_value=users[3]["obj"]): + with patch("flask_login.utils._get_user", return_value=users[id]["obj"]): with patch("weko_groups.views.Group", return_value=group): res = client.post( url_for('weko_groups.members', group_id=1), @@ -299,7 +332,7 @@ def delete_func(): "s": "s", } ) - assert res.status_code == 200 + assert res.status_code == status_code def test_members_2(app_2, users): @@ -338,7 +371,15 @@ def test_leave_2(app_2, users): # def approve(group_id, user_id): -def test_approve(app_2, users): +user_results = [ + (0, 403), + (1, 302), + (2, 302), + (3, 302), + (4, 403), +] +@pytest.mark.parametrize('id, status_code', user_results) +def test_approve(app_2, users, id, status_code): def can_edit_True(item): return True @@ -347,10 +388,10 @@ def can_edit_True(item): with app_2.test_request_context(): with app_2.test_client() as client: - with patch("flask_login.utils._get_user", return_value=users[3]["obj"]): + with patch("flask_login.utils._get_user", return_value=users[id]["obj"]): with patch("weko_groups.views.Membership", return_value=membership): res = client.post(url_for('weko_groups.approve', group_id=1, user_id=users[3]["obj"].id)) - assert res.status_code == 302 + assert res.status_code == status_code def test_approve_2(app_2, users): @@ -363,7 +404,15 @@ def test_approve_2(app_2, users): # def remove(group_id, user_id): -def test_remove(app_2, users): +user_results = [ + (0, 403), + (1, 302), + (2, 302), + (3, 302), + (4, 403), +] +@pytest.mark.parametrize('id, status_code', user_results) +def test_remove(app_2, users, id, status_code): def can_edit_True(item): return True @@ -372,10 +421,10 @@ def can_edit_True(item): with app_2.test_request_context(): with app_2.test_client() as client: - with patch("flask_login.utils._get_user", return_value=users[3]["obj"]): + with patch("flask_login.utils._get_user", return_value=users[id]["obj"]): with patch("weko_groups.views.Group", return_value=group): res = client.post(url_for('weko_groups.remove', group_id=1, user_id=users[3]["obj"].id)) - assert res.status_code == 302 + assert res.status_code == status_code def test_remove_2(app_2, users): @@ -428,7 +477,15 @@ def reject(): # def new_member(group_id): -def test_new_member(app_2, users): +user_results = [ + (0, 403), + (1, 302), + (2, 302), + (3, 302), + (4, 403), +] +@pytest.mark.parametrize('id, status_code', user_results) +def test_new_member(app_2, users, id, status_code): def validate_on_submit_True(): return True @@ -449,15 +506,17 @@ def invite_by_emails(item): # "Encountered unknown tag 'assets'. Jinja was looking for the following tags: 'endblock'. The innermost block that needs to be closed is 'block'." # But upon testing on the actual url on the browser "https://localhost/accounts/settings/groups/1/members/new" there is no problem with app_2.test_client() as client: - with patch("flask_login.utils._get_user", return_value=users[3]["obj"]): + with patch("flask_login.utils._get_user", return_value=users[id]["obj"]): with patch("weko_groups.views.Group", return_value=group): with patch("weko_groups.views.NewMemberForm", return_value=form): try: - client.get(url_for('weko_groups.new_member', group_id=1)) + res = client.get(url_for('weko_groups.new_member', group_id=1)) + assert res.status_code == status_code except: pass try: - client.get(url_for('weko_groups.new_member', group_id=1)) + res = client.get(url_for('weko_groups.new_member', group_id=1)) + assert res.status_code == status_code except: pass