Skip to content

Commit

Permalink
communities: implement service methods for deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
max-moser committed Sep 19, 2023
1 parent e6f1115 commit 335aece
Show file tree
Hide file tree
Showing 10 changed files with 510 additions and 9 deletions.
14 changes: 14 additions & 0 deletions invenio_communities/communities/resources/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# This file is part of Invenio.
# Copyright (C) 2016-2021 CERN.
# Copyright (C) 2023 TU Wien.
#
# 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 @@ -14,6 +15,7 @@
ResponseHandler,
create_error_handler,
)
from invenio_i18n import lazy_gettext as _
from invenio_records_resources.resources import RecordResourceConfig
from invenio_records_resources.services.base.config import ConfiguratorMixin, FromConfig
from invenio_requests.resources.requests.config import RequestSearchRequestArgsSchema
Expand All @@ -22,6 +24,7 @@
UICommunityJSONSerializer,
)
from invenio_communities.errors import (
CommunityDeletedError,
CommunityFeaturedEntryDoesNotExistError,
LogoSizeLimitError,
OpenRequestsForCommunityDeletionError,
Expand Down Expand Up @@ -54,6 +57,17 @@
description=str(e),
)
),
CommunityDeletedError: create_error_handler(
lambda e: (
HTTPJSONException(code=404, description=_("Community not found"))
if not e.community.tombstone.is_visible
else HTTPJSONException(
code=410,
description=_("Community deleted"),
tombstone=e.community.tombstone.dump(),
)
)
),
}
)

Expand Down
54 changes: 53 additions & 1 deletion invenio_communities/communities/resources/ui_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# This file is part of Invenio.
# Copyright (C) 2022 CERN.
# Copyright (C) 2023 TU Wien.
#
# 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 @@ -12,11 +13,14 @@

from flask import g
from flask_resources import BaseObjectSchema
from invenio_i18n import get_locale
from invenio_i18n import lazy_gettext as _
from invenio_records_resources.services.custom_fields import CustomFieldsSchemaUI
from invenio_vocabularies.contrib.awards.serializer import AwardL10NItemSchema
from invenio_vocabularies.contrib.funders.serializer import FunderL10NItemSchema
from invenio_vocabularies.resources import VocabularyL10Schema
from marshmallow import Schema, fields
from marshmallow import Schema, fields, post_dump
from marshmallow_utils.fields import FormatEDTF as FormatEDTF_

from invenio_communities.proxies import current_communities

Expand All @@ -30,6 +34,44 @@ def _community_permission_check(action, community, identity):
).allows(identity)


def mask_removed_by(obj):
"""Mask information about who removed the community."""
return_value = _("Unknown")
removed_by = obj.get("removed_by", None)

if removed_by is not None:
user = removed_by.get("user", None)

if user == "system":
return_value = _("System (automatic)")
elif user is not None:
return_value = _("User")

return return_value


# Partial to make short definitions in below schema.
FormatEDTF = partial(FormatEDTF_, locale=get_locale)


class TombstoneSchema(Schema):
"""Schema for a record tombstone."""

removal_reason = fields.Nested(VocabularyL10Schema, attribute="removal_reason")

note = fields.String(attribute="note")

removed_by = fields.Function(mask_removed_by)

removal_date_l10n_medium = FormatEDTF(attribute="removal_date", format="medium")

removal_date_l10n_long = FormatEDTF(attribute="removal_date", format="long")

citation_text = fields.String(attribute="citation_text")

is_visible = fields.Boolean(attribute="is_visible")


class FundingSchema(Schema):
"""Schema for dumping types in the UI."""

Expand All @@ -47,6 +89,8 @@ class UICommunitySchema(BaseObjectSchema):
attribute="metadata.funding",
)

tombstone = fields.Nested(TombstoneSchema, attribute="tombstone")

# Custom fields
custom_fields = fields.Nested(
partial(CustomFieldsSchemaUI, fields_var="COMMUNITIES_CUSTOM_FIELDS")
Expand All @@ -64,6 +108,14 @@ def get_permissions(self, obj):
)
return {"can_include_directly": can_include_directly, "can_update": can_update}

@post_dump
def hide_tombstone(self, obj, **kwargs):
"""Hide the tombstone information if it's not visible."""
if not obj.get("tombstone", {}).get("is_visible", False):
obj.pop("tombstone", None)

return obj


class TypesSchema(Schema):
"""Schema for dumping types in the UI."""
Expand Down
41 changes: 41 additions & 0 deletions invenio_communities/communities/services/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from invenio_access.permissions import system_identity, system_process
from invenio_db import db
from invenio_i18n import lazy_gettext as _
from invenio_i18n.proxies import current_i18n
from invenio_oaiserver.models import OAISet
from invenio_pidstore.errors import PIDDeletedError, PIDDoesNotExistError
from invenio_records_resources.services.records.components import (
Expand All @@ -26,6 +27,7 @@
from ...proxies import current_roles
from ...utils import on_user_membership_change
from ..records.systemfields.access import VisibilityEnum
from ..records.systemfields.deletion_status import CommunityDeletionStatusEnum


class PIDComponent(ServiceComponent):
Expand Down Expand Up @@ -232,6 +234,44 @@ def update(self, identity, data=None, record=None, **kwargs):
record.custom_fields = data.get("custom_fields", {})


class CommunityDeletionComponent(ServiceComponent):
"""Service component for record deletion."""

def delete_community(self, identity, data=None, record=None, **kwargs):
"""Set the community's deletion status and tombstone information."""
# Set the record's deletion status and tombstone information
record.deletion_status = CommunityDeletionStatusEnum.DELETED
record.tombstone = data

# Set `removed_by` information for the tombstone
record.tombstone.removed_by = identity.id

def update_tombstone(self, identity, data=None, record=None, **kwargs):
"""Update the community's tombstone information."""
record.tombstone = data

def restore_community(self, identity, data=None, record=None, **kwargs):
"""Reset the community's deletion status and tombstone information."""
record.deletion_status = CommunityDeletionStatusEnum.PUBLISHED

# Remove the tombstone information
record.tombstone = None

# Set a record to 'metadata only' if its files got cleaned up
if not record.files.entries:
record.files.enabled = False

def mark_community(self, identity, data=None, record=None, **kwargs):
"""Mark the community for purge."""
record.deletion_status = CommunityDeletionStatusEnum.MARKED
record.tombstone = record.tombstone

def unmark_community(self, identity, data=None, record=None, **kwargs):
"""Unmark the community for purge, resetting it to soft-deleted state."""
record.deletion_status = CommunityDeletionStatusEnum.DELETED
record.tombstone = record.tombstone


DefaultCommunityComponents = [
MetadataComponent,
CustomFieldsComponent,
Expand All @@ -241,4 +281,5 @@ def update(self, identity, data=None, record=None, **kwargs):
OwnershipComponent,
FeaturedCommunityComponent,
OAISetComponent,
CommunityDeletionComponent,
]
3 changes: 2 additions & 1 deletion invenio_communities/communities/services/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
)

from ...permissions import CommunityPermissionPolicy, can_perform_action
from ..schema import CommunityFeaturedSchema, CommunitySchema
from ..schema import CommunityFeaturedSchema, CommunitySchema, TombstoneSchema
from .components import DefaultCommunityComponents
from .links import CommunityLink
from .sort import CommunitiesSortParam
Expand Down Expand Up @@ -95,6 +95,7 @@ class CommunityServiceConfig(RecordServiceConfig, ConfiguratorMixin):
# Service schema
schema = CommunitySchema
schema_featured = CommunityFeaturedSchema
schema_tombstone = TombstoneSchema

result_list_cls_featured = CommunityFeaturedList
result_item_cls_featured = FeaturedCommunityItem
Expand Down
Loading

0 comments on commit 335aece

Please sign in to comment.