|
40 | 40 | from ...proxies import current_roles
|
41 | 41 | from ..errors import AlreadyMemberError, InvalidMemberError
|
42 | 42 | from ..records.api import ArchivedInvitation
|
43 |
| -from .request import CommunityInvitation |
| 43 | +from .request import CommunityInvitation, MembershipRequestRequestType |
44 | 44 | from .schemas import (
|
45 | 45 | AddBulkSchema,
|
46 | 46 | DeleteBulkSchema,
|
47 | 47 | InvitationDumpSchema,
|
48 | 48 | InviteBulkSchema,
|
49 | 49 | MemberDumpSchema,
|
50 | 50 | PublicDumpSchema,
|
| 51 | + RequestMembershipSchema, |
51 | 52 | UpdateBulkSchema,
|
52 | 53 | )
|
53 | 54 |
|
@@ -103,6 +104,11 @@ def delete_schema(self):
|
103 | 104 | """Schema for bulk delete."""
|
104 | 105 | return ServiceSchemaWrapper(self, schema=DeleteBulkSchema)
|
105 | 106 |
|
| 107 | + @property |
| 108 | + def request_membership_schema(self): |
| 109 | + """Wrapped schema for request membership.""" |
| 110 | + return ServiceSchemaWrapper(self, schema=RequestMembershipSchema) |
| 111 | + |
106 | 112 | @property
|
107 | 113 | def archive_indexer(self):
|
108 | 114 | """Factory for creating an indexer instance."""
|
@@ -734,3 +740,110 @@ def rebuild_index(self, identity, uow=None):
|
734 | 740 | self.archive_indexer.bulk_index([inv.id for inv in archived_invitations])
|
735 | 741 |
|
736 | 742 | return True
|
| 743 | + |
| 744 | + # Request membership |
| 745 | + @unit_of_work() |
| 746 | + def request_membership(self, identity, community_id, data, uow=None): |
| 747 | + """Request membership to the community. |
| 748 | +
|
| 749 | + A user can only have one request per community. |
| 750 | +
|
| 751 | + All validations raise, so it's up to parent layer to handle them. |
| 752 | + """ |
| 753 | + community = self.community_cls.get_record(community_id) |
| 754 | + |
| 755 | + data, errors = self.request_membership_schema.load( |
| 756 | + data, |
| 757 | + context={"identity": identity}, |
| 758 | + ) |
| 759 | + message = data.get("message", "") |
| 760 | + |
| 761 | + self.require_permission( |
| 762 | + identity, |
| 763 | + "request_membership", |
| 764 | + record=community, |
| 765 | + ) |
| 766 | + |
| 767 | + # Create request |
| 768 | + title = _('Request to join "{community}"').format( |
| 769 | + community=community.metadata["title"], |
| 770 | + ) |
| 771 | + request_item = current_requests_service.create( |
| 772 | + identity, |
| 773 | + data={ |
| 774 | + "title": title, |
| 775 | + # "description": description, |
| 776 | + }, |
| 777 | + request_type=MembershipRequestRequestType, |
| 778 | + receiver=community, |
| 779 | + creator={"user": str(identity.user.id)}, |
| 780 | + topic=community, # user instead? |
| 781 | + # TODO: Consider expiration |
| 782 | + # expires_at=invite_expires_at(), |
| 783 | + uow=uow, |
| 784 | + ) |
| 785 | + |
| 786 | + if message: |
| 787 | + data = {"payload": {"content": message}} |
| 788 | + current_events_service.create( |
| 789 | + identity, |
| 790 | + request_item.id, |
| 791 | + data, |
| 792 | + CommentEventType, |
| 793 | + uow=uow, |
| 794 | + notify=False, |
| 795 | + ) |
| 796 | + |
| 797 | + # TODO: Add notification mechanism |
| 798 | + # uow.register( |
| 799 | + # NotificationOp( |
| 800 | + # MembershipRequestSubmittedNotificationBuilder.build( |
| 801 | + # request=request_item._request, |
| 802 | + # # explicit string conversion to get the value of LazyText |
| 803 | + # role=str(role.title), |
| 804 | + # message=message, |
| 805 | + # ) |
| 806 | + # ) |
| 807 | + # ) |
| 808 | + |
| 809 | + # Create an inactive member entry linked to the request. |
| 810 | + self._add_factory( |
| 811 | + identity, |
| 812 | + community=community, |
| 813 | + role=current_roles["reader"], |
| 814 | + visible=False, |
| 815 | + member={"type": "user", "id": str(identity.user.id)}, |
| 816 | + message=message, |
| 817 | + uow=uow, |
| 818 | + active=False, |
| 819 | + request_id=request_item.id, |
| 820 | + ) |
| 821 | + |
| 822 | + # No registered component with a request_membership method for now, |
| 823 | + # so no run_components for now. |
| 824 | + |
| 825 | + # Has to return the request so that frontend can redirect to it |
| 826 | + return request_item |
| 827 | + |
| 828 | + @unit_of_work() |
| 829 | + def update_membership_request(self, identity, community_id, data, uow=None): |
| 830 | + """Update membership request.""" |
| 831 | + # TODO: Implement me |
| 832 | + pass |
| 833 | + |
| 834 | + def search_membership_requests(self): |
| 835 | + """Search membership requests.""" |
| 836 | + # TODO: Implement me |
| 837 | + pass |
| 838 | + |
| 839 | + @unit_of_work() |
| 840 | + def accept_membership_request(self, identity, request_id, uow=None): |
| 841 | + """Accept membership request.""" |
| 842 | + # TODO: Implement me |
| 843 | + pass |
| 844 | + |
| 845 | + @unit_of_work() |
| 846 | + def decline_membership_request(self, identity, request_id, uow=None): |
| 847 | + """Decline membership request.""" |
| 848 | + # TODO: Implement me |
| 849 | + pass |
0 commit comments