Skip to content

Commit

Permalink
members service: [inveniosoftware#855] 5) display membership discussi…
Browse files Browse the repository at this point in the history
…on link
  • Loading branch information
fenekku committed Jun 17, 2024
1 parent 9f968cb commit dbf1ce4
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 11 deletions.
17 changes: 16 additions & 1 deletion invenio_communities/members/records/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from invenio_records_resources.records.systemfields import IndexField
from invenio_requests.records.api import Request
from invenio_users_resources.records.api import GroupAggregate, UserAggregate
from sqlalchemy import or_
from sqlalchemy import or_, select

from ..errors import InvalidMemberError
from .models import ArchivedInvitationModel, MemberModel
Expand Down Expand Up @@ -160,6 +160,21 @@ def has_members(cls, community_id, role=None):
"""Get members of a community."""
return cls.model_cls.count_members(community_id, role=role)

@classmethod
def get_pending_request_id_if_any(cls, user_id, community_id):
"""Return request id of membership request/invitation still pending.
Return type UUID.
"""
stmt = (
select(cls.model_cls.request_id)
.where(cls.model_cls.user_id == user_id)
.where(cls.model_cls.community_id == community_id)
.where(cls.model_cls.active == False)
)
request_id = db.session.scalars(stmt).one_or_none()
return request_id


class Member(Record, MemberMixin):
"""A member/invitation record.
Expand Down
7 changes: 7 additions & 0 deletions invenio_communities/members/services/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -857,3 +857,10 @@ def close_membership_request(self, identity, request_id, uow=None):
member = self.record_cls.get_member_by_request(request_id)
assert member.active is False
uow.register(RecordDeleteOp(member, indexer=self.indexer, force=True))

def get_pending_request_id_if_any(self, user_id, community_id):
"""Utility function to get associated active request id.
Only pending members fit this. In other cases return None.
"""
return self.record_cls.get_pending_request_id_if_any(user_id, community_id)
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,23 @@
{%- from "invenio_theme/macros/truncate.html" import truncate_text %}
{%- from "invenio_communities/details/macros/access-status-label.html" import access_status_label -%}

{% macro button_to_request_membership(community) %}
{% if permissions.can_request_membership %}
{# TODO: Add relation_to_community for other flows #}
<div
id="request-membership-app"
data-community='{{ community | tojson }}'
class="display-inline-block"
{% macro button_for_membership(community) %}
{# an associated request id is defined/not None only if user has membership discussion active #}
{% if associated_request_id is defined and associated_request_id %}
<a href="{{ url_for('invenio_app_rdm_requests.user_dashboard_request_view', request_pid_value=associated_request_id) }}"
class="ui button labeled icon rel-mt-1 theme-secondary">
<i class="sign-in icon" aria-hidden="true"></i>
{{ _("Membership discussion") }}
</a>
{% elif permissions.can_request_membership %}
<div
id="request-membership-app"
data-community='{{ community | tojson }}'
class="display-inline-block"
>
</div>
</div>
{% else %}
{# show nothing #}
{% endif %}
{% endmacro %}

Expand Down Expand Up @@ -120,7 +128,7 @@ <h1 class="ui medium header mb-0">{{ community.metadata.title }}</h1>
</div>
<div
class="sixteen wide mobile sixteen wide tablet five wide computer right aligned middle aligned column">
{{ button_to_request_membership(community) }}
{{ button_for_membership(community) }}
{%- if not community_use_jinja_header %}
<a href="/uploads/new?community={{ community.slug }}"
class="ui positive button labeled icon rel-mt-1 theme-secondary">
Expand Down
16 changes: 16 additions & 0 deletions invenio_communities/views/communities.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,13 +391,18 @@ def members(pid_value, community, community_ui):
if not permissions["can_members_search_public"]:
raise PermissionDeniedError()

members_service = current_communities.service.members

return render_community_theme_template(
"invenio_communities/details/members/members.html",
theme=community_ui.get("theme", {}),
community=community_ui,
permissions=permissions,
roles_can_update=_get_roles_can_update(community.id),
roles_can_invite=_get_roles_can_invite(community.id),
associated_request_id=(
members_service.get_pending_request_id_if_any(g.identity.id, community.id)
),
)


Expand All @@ -423,26 +428,37 @@ def communities_about(pid_value, community, community_ui):
if not permissions["can_read"]:
raise PermissionDeniedError()

members_service = current_communities.service.members

return render_community_theme_template(
"invenio_communities/details/about/index.html",
theme=community_ui.get("theme", {}),
community=community_ui,
permissions=permissions,
custom_fields_ui=load_custom_fields(dump_only_required=False)["ui"],
associated_request_id=(
members_service.get_pending_request_id_if_any(
g.identity.id, community.id)
),
)


@pass_community(serialize=True)
def communities_curation_policy(pid_value, community, community_ui):
"""Community curation policy page."""
permissions = community.has_permissions_to(HEADER_PERMISSIONS)
members_service = current_communities.service.members
if not permissions["can_read"]:
raise PermissionDeniedError()
return render_community_theme_template(
"invenio_communities/details/curation_policy/index.html",
theme=community_ui.get("theme", {}),
community=community_ui,
permissions=permissions,
associated_request_id=(
members_service.get_pending_request_id_if_any(
g.identity.id, community.id)
),
)


Expand Down
59 changes: 58 additions & 1 deletion tests/members/test_members_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from invenio_cache import current_cache
from invenio_notifications.proxies import current_notifications_manager
from invenio_records_resources.services.errors import PermissionDeniedError
from invenio_requests.records.api import RequestEvent
from invenio_requests.records.api import Request, RequestEvent
from marshmallow import ValidationError

from invenio_communities.members.errors import AlreadyMemberError, InvalidMemberError
Expand Down Expand Up @@ -1208,6 +1208,63 @@ def test_request_cancel_request_flow(
)


def test_get_pending_request_id_if_any(
member_service,
community,
owner,
create_user,
requests_service,
db,
search_clear,
):
user = create_user()

# Case no membership (no associated request id)
request_id = member_service.get_pending_request_id_if_any(
user.id, community._record.id)
assert request_id is None

# Case pending membership (associated request id)
membership_request = member_service.request_membership(
user.identity,
community._record.id,
{"message": "Can I join the club?"},
)
request_id = member_service.get_pending_request_id_if_any(
user.id, community._record.id)
assert membership_request.id == str(request_id)

# Case (sanity check) pending membership from invitation (associated request id)
requests_service.execute_action(
user.identity, membership_request.id, "cancel"
)
data = {
"members": [{"type": "user", "id": str(user.id)}],
"role": "reader",
"message": "Welcome to the club!",
}
member_service.invite(owner.identity, community._record.id, data)
# get invitation_request_id
Request.index.refresh()
results = requests_service.search(
user.identity,
receiver={"user": user.id},
type="community-invitation",
).to_dict()
invitation_request_id = results["hits"]["hits"][0]["id"]
request_id = member_service.get_pending_request_id_if_any(
user.id, community._record.id)
assert invitation_request_id == str(request_id)

# Case membership established (associated request id but not pending)
requests_service.execute_action(
user.identity, invitation_request_id, "accept"
)
request_id = member_service.get_pending_request_id_if_any(
user.id, community._record.id)
assert request_id is None


#
# Change notifications
#
Expand Down

0 comments on commit dbf1ce4

Please sign in to comment.