Skip to content

Commit

Permalink
permissions: add community creator role
Browse files Browse the repository at this point in the history
* The `can_create` function will now check if `RDM_COMMUNITY_REQUIRED_TO_PUBLISH` is set to True, requiring the user to have the community manager role to create new communities.
* The community creator role can be overridden from the user side.
* Closes inveniosoftware/product-rdm#183
  • Loading branch information
Samk13 committed Oct 16, 2024
1 parent 05537f3 commit f05a52b
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 4 deletions.
7 changes: 5 additions & 2 deletions invenio_communities/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#
# This file is part of Invenio.
# Copyright (C) 2016-2024 CERN.
# Copyright (C) 2023 Graz University of Technology.
# Copyright (C) 2023 KTH Royal Institute of Technology.
# Copyright (C) 2023 Graz University of Technology.
# Copyright (C) 2023-2024 KTH Royal Institute of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
Expand Down Expand Up @@ -334,3 +334,6 @@

COMMUNITIES_DEFAULT_RECORD_SUBMISSION_POLICY = RecordSubmissionPolicyEnum.OPEN
"""Default value of record submission policy community access setting."""

COMMUNITIES_CREATOR_ROLE = "community-creator"
"""Depends on 'RDM_COMMUNITY_REQUIRED_TO_PUBLISH' set to True."""
15 changes: 14 additions & 1 deletion invenio_communities/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# Copyright (C) 2021 Graz University of Technology.
# Copyright (C) 2021 TU Wien.
# Copyright (C) 2022 Northwestern University.
# Copyright (C) 2024 KTH Royal Institute of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
Expand All @@ -16,7 +17,8 @@
from functools import partial, reduce
from itertools import chain

from flask_principal import UserNeed
from flask import current_app
from flask_principal import RoleNeed, UserNeed
from invenio_access.permissions import any_user, authenticated_user, system_process
from invenio_records.dictutils import dict_lookup
from invenio_records_permissions.generators import Generator
Expand Down Expand Up @@ -342,6 +344,17 @@ def roles(self, **kwargs):
return [r.name for r in current_roles.can("manage")]


class CommunityCreator(Generator):
"""Allows users with the "trusted-user" role."""

def needs(self, **kwargs):
"""Enabling Needs."""
role_name = current_app.config.get(
"COMMUNITIES_CREATOR_ROLE", "community-creator"
)
return [RoleNeed(role_name)]


class CommunityManagersForRole(CommunityRoles):
"""Roles representing all managers of a community for a role update."""

Expand Down
12 changes: 11 additions & 1 deletion invenio_communities/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# Copyright (C) 2021 Graz University of Technology.
# Copyright (C) 2021 TU Wien.
# Copyright (C) 2022 Northwestern University.
# Copyright (C) 2024 KTH Royal Institute of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
Expand All @@ -26,6 +27,7 @@
from .generators import (
AllowedMemberTypes,
AuthenticatedButNotCommunityMembers,
CommunityCreator,
CommunityCurators,
CommunityManagers,
CommunityManagersForRole,
Expand All @@ -45,7 +47,15 @@ class CommunityPermissionPolicy(BasePermissionPolicy):
"""Permissions for Community CRUD operations."""

# Community
can_create = [AuthenticatedUser(), SystemProcess()]
_can_create = [AuthenticatedUser(), SystemProcess()]

can_create = [
IfConfig(
"RDM_COMMUNITY_REQUIRED_TO_PUBLISH",
then_=[CommunityCreator(), Administration(), SystemProcess()],
else_=_can_create,
)
]

can_read = [
IfRestricted("visibility", then_=[CommunityMembers()], else_=[AnyUser()]),
Expand Down
54 changes: 54 additions & 0 deletions tests/communities/test_permissions.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2024 Northwestern University.
# Copyright (C) 2024 KTH Royal Institute of Technology.
#
# Invenio-RDM-Records is free software; you can redistribute it
# and/or modify it under the terms of the MIT License; see LICENSE file for
# more details.

"""Test permissions."""
from flask_principal import Identity, RoleNeed
from invenio_access.permissions import system_identity

from invenio_communities.permissions import CommunityPermissionPolicy

Expand Down Expand Up @@ -61,3 +64,54 @@ def test_can_request_membership(
)

app.config["COMMUNITIES_ALLOW_MEMBERSHIP_REQUESTS"] = allow_membership_requests_orig


def test_can_create(app, anon_identity, any_user, superuser_identity):
policy = CommunityPermissionPolicy

# Save the original configuration value
original_config = app.config.get("RDM_COMMUNITY_REQUIRED_TO_PUBLISH", False)

authenticated_identity = any_user.identity

# Create an identity for a user with the 'community-creator' role
# Copy the provides from authenticated_identity to ensure 'authenticated_user' is included
community_creator_identity = Identity(any_user.id)
community_creator_identity.provides.update(authenticated_identity.provides)
community_creator_identity.provides.add(RoleNeed("community-creator"))

# RDM_COMMUNITY_REQUIRED_TO_PUBLISH is True
app.config["RDM_COMMUNITY_REQUIRED_TO_PUBLISH"] = True

# Anonymous user cannot create communities
assert not policy(action="create").allows(anon_identity)

# Authenticated user without 'community-creator' role cannot create
assert not policy(action="create").allows(authenticated_identity)

# Authenticated user with 'community-creator' role can create
assert policy(action="create").allows(community_creator_identity)

# Superuser (admin) can create communities
assert policy(action="create").allows(superuser_identity)

# System process can create communities
assert policy(action="create").allows(system_identity)

# RDM_COMMUNITY_REQUIRED_TO_PUBLISH is False
app.config["RDM_COMMUNITY_REQUIRED_TO_PUBLISH"] = False

# Anonymous user cannot create communities
assert not policy(action="create").allows(anon_identity)

# Authenticated user without 'community-creator' role can create
assert policy(action="create").allows(authenticated_identity)

# Authenticated user with 'community-creator' role can create
assert policy(action="create").allows(community_creator_identity)

# Superuser (admin) can create communities
assert policy(action="create").allows(superuser_identity)

# System process can create communities
assert policy(action="create").allows(system_identity)

0 comments on commit f05a52b

Please sign in to comment.