Exemplo n.º 1
0
class EditTemplateStateChange(BaseStateChange):
    """State change to edit a template."""

    descriptive_text = {
        "verb":
        "edit",
        "default_string":
        "template",
        "detail_string":
        "template field {field_name} to new value {new_field_data}"
    }

    allowable_targets = [TemplateModel]
    settable_classes = ["all_models"]

    template_object_id = field_utils.IntegerField(
        label="ID of Template to edit", required=True)
    field_name = field_utils.CharField(label="Field to edit", required=True)
    new_field_data = field_utils.DictField(label="Data to edit", required=True)

    def validate(self, actor, target):
        result = target.data.update_field(self.template_object_id,
                                          self.field_name, self.new_field_data)
        if result.__class__.__name__ == "ValidationError":
            raise result

    def implement(self, actor, target, **kwargs):

        target.data.update_field(self.template_object_id, self.field_name,
                                 self.new_field_data)
        target.save()

        return target
Exemplo n.º 2
0
class RemoveConditionStateChange(BaseStateChange):
    """State change to remove condition from Community."""

    descriptive_text = {
        "verb": "remove",
        "default_string": "condition",
        "detail_string": "condition with {element_id}"
    }

    is_foundational = True
    section = "Leadership"
    allowable_targets = ["all_community_models", PermissionsItem]

    element_id = field_utils.IntegerField(label="Element ID to remove")
    leadership_type = field_utils.CharField(label="Leadership type to remove condition from")

    def is_conditionally_foundational(self, action):
        """Edit condition is foundational when the condition is owner/governor."""
        return self.leadership_type in ["owner", "governor"]

    def validate(self, actor, target):
        if hasattr(target, "is_community") and target.is_community and not self.leadership_type:
            raise ValidationError("leadership_type cannot be None")

    def implement(self, actor, target, **kwargs):

        attr_name = "condition" if not self.leadership_type else self.leadership_type + "_condition"
        manager = getattr(target, attr_name)

        if self.element_id:
            manager.remove_condition(self.element_id)
            manager.save()
            return manager
        else:
            manager.delete()
Exemplo n.º 3
0
class ChangeOwnerStateChange(BaseStateChange):
    """State change for changing which community owns the object. Not to be confused with state changes which
    change who the owners are within a community."""

    descriptive_text = {
        "verb": "change",
        "default_string": "owner of community",
        "detail_string": "owner of community to {new_owner_id}",
        "preposition": "for"
    }

    is_foundational = True
    section = "Leadership"

    # Fields
    new_owner_content_type = field_utils.IntegerField(
        label="New owner's content type id", required=True)
    new_owner_id = field_utils.IntegerField(label="New owner's ID",
                                            required=True)

    def get_new_owner(self):
        """Helper method to get model instance of new owner from params."""
        content_type = ContentType.objects.get_for_id(
            self.new_owner_content_type)
        model_class = content_type.model_class()
        return model_class.objects.get(id=self.new_owner_id)

    def validate(self, actor, target):

        try:
            new_owner = self.get_new_owner()
        except ObjectDoesNotExist:
            message = f"Couldn't find instance of content type {self.new_owner_content_type} & id {self.new_owner_id}"
            raise ValidationError(message)

        if not hasattr(new_owner,
                       "is_community") or not new_owner.is_community:
            message = f"New owner must be a descendant of community model, not {self.new_owner_content_type}"
            raise ValidationError(message)

    def implement(self, actor, target, **kwargs):
        target.owner = self.get_new_owner()
        target.save()
        return target
Exemplo n.º 4
0
class EditConditionStateChange(BaseStateChange):
    """State change to add condition to permission or leadership role."""

    descriptive_text = {
        "verb": "edit",
        "default_string": "condition",
        "detail_string": "condition with {element_id}"
    }

    section = "Permissions"
    allowable_targets = ["all_community_models", PermissionsItem]

    element_id = field_utils.IntegerField(label="Element ID", required=True)
    condition_data = field_utils.DictField(label="New condition data", null_value=dict)
    permission_data = field_utils.DictField(label="Data for permissions set on condition", null_value=list)
    leadership_type = field_utils.CharField(label="Leadership type to set condition on")

    def is_conditionally_foundational(self, action):
        """Edit condition is foundational when the condition is owner/governor."""
        return self.leadership_type in ["owner", "governor"]

    def validate(self, actor, target):

        if hasattr(target, "is_community") and target.is_community:

            if not self.leadership_type:
                raise ValidationError("leadership_type cannot be None")

            if self.leadership_type not in ["owner", "governor"]:
                raise ValidationError("leadership_type must be 'owner' or 'governor'")

        if self.leadership_type:
            condition_manager = getattr(target, self.leadership_type + "_condition")
        else:
            condition_manager = target.condition

        element = condition_manager.get_condition_data(self.element_id)
        is_valid, message = validate_condition(
            element.condition_type, self.condition_data, self.permission_data, target)
        if not is_valid:
            raise ValidationError(message)

    def implement(self, actor, target, **kwargs):

        attr_name = "condition" if not self.leadership_type else self.leadership_type + "_condition"
        manager = getattr(target, attr_name)
        data = {"condition_data": self.condition_data, "permission_data": self.permission_data}
        manager.edit_condition(element_id=self.element_id, data_for_condition=data)
        manager.save()

        return manager
Exemplo n.º 5
0
class ApplyTemplateStateChange(BaseStateChange):
    """State change object for applying a template."""

    descriptive_text = {
        "verb": "apply",
        "past_tense": "applied",
        "default_string": "template",
        "preposition": "for"
    }

    pass_action = True
    linked_filters = ["CreatorFilter"]

    # Fields
    template_model_pk = field_utils.IntegerField(
        label="PK of Template to apply", required=True)
    supplied_fields = field_utils.DictField(
        label="Fields to supply when applying template", null_value=dict)
    template_is_foundational = field_utils.BooleanField(
        label="Template makes foundational changes")

    def validate(self, actor, target):

        # check template_model_pk is valid
        template = TemplateModel.objects.filter(pk=self.template_model_pk)
        if not template:
            raise ValidationError(
                f"No template in database with ID {self.template_model_pk}")

        # check that supplied fields match template's siupplied fields
        needed_field_keys = set(
            [key for key, value in template[0].get_supplied_fields().items()])
        supplied_field_keys = set(
            [key for key, value in self.supplied_fields.items()])
        if needed_field_keys - supplied_field_keys:
            missing_fields = ', '.join(
                list(needed_field_keys - supplied_field_keys))
            raise ValidationError(
                f"Template needs values for fields {missing_fields}")

        # attempt to apply actions (but rollback commit regardless)
        mock_action = MockAction(actor=actor, target=target, change=self)
        result = template[0].template_data.apply_template(
            actor=actor,
            target=target,
            trigger_action=mock_action,
            supplied_fields=self.supplied_fields,
            rollback=True)
        if "errors" in result:
            raise ValidationError(
                f"Template errors: {'; '.join([error for error in result['errors']])}"
            )

    def implement(self, actor, target, **kwargs):
        """Implements the given template, relies on logic in apply_template."""
        action = kwargs.get("action", None)
        template_model = TemplateModel.objects.get(pk=self.template_model_pk)
        return template_model.template_data.apply_template(
            actor=actor,
            target=target,
            trigger_action=action,
            supplied_fields=self.supplied_fields)