コード例 #1
0
ファイル: state_changes.py プロジェクト: glizzan/concord
class EditPermissionStateChange(BaseStateChange):

    descriptive_text = {
        "verb": "edit",
        "default_string": "permission",
        "preposition": "on"
    }

    section = "Permissions"
    allowable_targets = [PermissionsItem]
    settable_classes = ["all_models"]
    model_based_validation = (PermissionsItem, ["anyone", "roles", "actors"])

    actors = field_utils.ActorListField(
        label="Actors who have this permission", null_value=list)
    roles = field_utils.RoleListField(label="Roles who have this permission",
                                      null_value=list)
    anyone = field_utils.BooleanField(label="Everyone has the permission",
                                      null_value=False)

    def validate(self, actor, target):
        if not self.actors and not self.roles and not self.anyone:
            raise ValidationError(
                "Must change at least one field to edit permission.")

    def implement(self, actor, target, **kwargs):
        field_dict = {}
        if self.actors: field_dict["actors"] = self.actors
        if self.roles: field_dict["roles"] = self.roles
        if self.anyone: field_dict["anyone"] = self.anyone
        target.set_fields(**field_dict)
        target.save()
        return target
コード例 #2
0
ファイル: state_changes.py プロジェクト: glizzan/concord
class AddMembersStateChange(BaseStateChange):
    """State change to add members to Community."""

    descriptive_text = {
        "verb": "add",
        "default_string": "members to community",
        "detail_string": "{member_pk_list} as members"
    }

    section = "Community"
    allowable_targets = ["all_community_models"]
    linked_filters = ["SelfMembershipFilter"]

    member_pk_list = field_utils.ActorListField(label="People to add as members", required=True)

    def validate(self, actor, target):
        if not isinstance(self.member_pk_list, list):
            raise ValidationError(f"member_pk_list must be list, not {type(self.member_pk_list)}")
        if not all([isinstance(member_pk, int) for member_pk in self.member_pk_list]):
            raise ValidationError(message="member_pk_list must contain only integers")

    def implement(self, actor, target, **kwargs):
        target.roles.add_members(self.member_pk_list)
        target.save()
        return target
コード例 #3
0
ファイル: state_changes.py プロジェクト: glizzan/concord
class ChangeOwnersStateChange(BaseStateChange):
    """State change to add or remove owners from Community."""

    descriptive_text = {
        "verb": "change",
        "default_string": "owners of community"
    }

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

    roles_to_add = field_utils.RoleListField(label="Roles to add")
    roles_to_remove = field_utils.RoleListField(label="Roles to remove")
    actors_to_add = field_utils.ActorListField(label="People to add")
    actors_to_remove = field_utils.ActorListField(label="People to remove")

    def make_changes(self, actor, target):

        if self.actors_to_add:
            [target.roles.add_owner(pk) for pk in self.actors_to_add]

        if self.actors_to_remove:
            [target.roles.remove_owner(pk) for pk in self.actors_to_remove]

        if self.roles_to_add:
            [target.roles.add_owner_role(role) for role in self.roles_to_add]

        if self.roles_to_remove:
            [target.roles.remove_owner_role(role) for role in self.roles_to_remove]

        return target

    def validate(self, actor, target):
        if not self.roles_to_add and not self.roles_to_remove and not self.actors_to_add \
            and not self.actors_to_remove:
            raise ValidationError("Must add or remove at least one individual owner or owning role.")
        target = self.make_changes(actor, target)
        target.roles.validate_role_handler()
        target.refresh_from_db()

    def implement(self, actor, target, **kwargs):
        target = self.make_changes(actor, target)
        target.save()
        return target
コード例 #4
0
ファイル: state_changes.py プロジェクト: glizzan/concord
class RemovePeopleFromRoleStateChange(BaseStateChange):
    """State change to remove people from role in Community."""

    descriptive_text = {
        "verb": "remove",
        "default_string": "people from role",
        "detail_string": "people {people_to_remove} from role '{role_name}'",
        "preposition": "in"
    }

    section = "Community"
    allowable_targets = ["all_community_models"]

    role_name = field_utils.RoleField(label="Role to remove people from", required=True)
    people_to_remove = field_utils.ActorListField(label="People to remove from role", required=True)

    def is_conditionally_foundational(self, action):
        """If role_name is owner or governor role, should should be treated as a conditional
        change."""
        if self.role_name in action.target.roles.get_owners()["roles"]:
            return True
        if self.role_name in action.target.roles.get_governors()["roles"]:
            return True
        return False

    def validate(self, actor, target):
        """When removing people from a role, we must check that doing so does not leave us
        without any owners."""

        if self.role_name not in target.roles.get_owners()["roles"]:
            return  # this isn't an owner role

        if len(self.people_to_remove) < len(target.roles.get_users_given_role(self.role_name)):
            return  # removing these users will not result in empty role

        if len(target.roles.get_owners()["actors"]) > 0:
            return  # community has individual actor owners so it doesn't need roles

        for role in target.roles.get_owners()["roles"]:
            if role == self.role_name:
                continue
            actors = target.roles.get_users_given_role(role)
            if len(actors) > 0:
                return  # there are other owner roles with actors specified

        raise ValidationError("Cannot remove everyone from this role as " +
                              "doing so would leave the community without an owner")

    def implement(self, actor, target, **kwargs):
        target.roles.remove_people_from_role(self.role_name, self.people_to_remove)
        target.save()
        return target
コード例 #5
0
ファイル: state_changes.py プロジェクト: glizzan/concord
class RemoveMembersStateChange(BaseStateChange):
    """State change to remove members from Community."""

    descriptive_text = {
        "verb": "remove",
        "default_string": "members from community",
        "detail_string": "members {member_pk_list} from community",
        "preposition": "from"
    }

    section = "Community"
    linked_filters = ["SelfMembershipFilter"]
    allowable_targets = ["all_community_models"]

    member_pk_list = field_utils.ActorListField(label="People to remove as members", required=True)

    def validate(self, actor, target):
        """If any of the members to be removed are an owner or governor (either directly, or through
        being in an owner or governor role) the action is not valid."""

        governor_list, owner_list = [], []
        for pk in self.member_pk_list:
            is_governor, result = target.roles.is_governor(pk)
            if is_governor:
                governor_list.append(str(pk))
            is_owner, result = target.roles.is_owner(pk)
            if is_owner:
                owner_list.append(str(pk))
        if governor_list or owner_list:
            message = f"Cannot remove members as some are owners or governors. Owners: {', '.join(owner_list)}, " + \
                      f"Governors: {', '.join(governor_list)}"
            raise ValidationError(message)

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

        # Remove members from custom roles
        for role_name in target.roles.get_custom_roles():
            target.roles.remove_people_from_role(role_name, self.member_pk_list)
        # Now remove them from members
        target.roles.remove_members(self.member_pk_list)

        target.save()
        return target
コード例 #6
0
ファイル: state_changes.py プロジェクト: glizzan/concord
class AddPeopleToRoleStateChange(BaseStateChange):
    """State change to add people to role in Community."""

    descriptive_text = {
        "verb": "add",
        "default_string": "people to role",
        "detail_string": "people {people_to_add} to role '{role_name}'",
        "preposition": "in"
    }

    section = "Community"
    allowable_targets = ["all_community_models"]

    role_name = field_utils.RoleField(label="Role to add people to", required=True)
    people_to_add = field_utils.ActorListField(label="People to add to role", required=True)

    linked_filters = ["RoleMatchesFilter"]

    def is_conditionally_foundational(self, action):
        """If role_name is owner or governor role, should should be treated as a conditional change."""
        if self.role_name in action.target.roles.get_owners()["roles"]:
            return True
        if self.role_name in action.target.roles.get_governors()["roles"]:
            return True
        return False

    def validate(self, actor, target):
        if not isinstance(self.role_name, str):
            raise ValidationError(f"Role must be type str, not {str(type(self.role_name))}")
        if not target.roles.is_role(self.role_name):
            raise ValidationError(f"Role {self.role_name} does not exist")
        people_already_in_role = []
        for person in self.people_to_add:
            if target.roles.has_specific_role(self.role_name, person):
                people_already_in_role.append(str(person))
        if people_already_in_role:
            raise ValidationError(f"Users {list_to_text(people_already_in_role)} already in role {self.role_name}")

    def implement(self, actor, target, **kwargs):
        target.roles.add_people_to_role(self.role_name, self.people_to_add)
        target.save()
        return target
コード例 #7
0
ファイル: state_changes.py プロジェクト: glizzan/concord
class AddPermissionStateChange(BaseStateChange):
    """State change to add a permission to something."""

    descriptive_text = {  # note that description_present_tense and past tense are overridden below
        "verb": "add",
        "default_string": "permission"
    }

    section = "Permissions"
    model_based_validation = (PermissionsItem,
                              ["change_type", "anyone", "inverse"])

    change_type = field_utils.CharField(
        label="Type of action the permission covers", required=True)
    actors = field_utils.ActorListField(
        label="Actors who have this permission", null_value=list)
    roles = field_utils.RoleListField(label="Roles who have this permission",
                                      null_value=list)
    anyone = field_utils.BooleanField(label="Everyone has the permission",
                                      null_value=False)
    inverse = field_utils.BooleanField(
        label="Do the inverse of this permission", null_value=False)
    condition_data = field_utils.CharField(
        label="Condition for this permission")

    def description_present_tense(self):
        return f"add permission '{get_verb_given_permission_type(self.change_type)}'"

    def description_past_tense(self):
        return f"added permission '{get_verb_given_permission_type(self.change_type)}'"

    def is_conditionally_foundational(self, action):
        """Some state changes are only foundational in certain conditions. Those state changes override this
        method to apply logic and determine whether a specific instance is foundational or not."""
        from concord.utils.lookups import get_state_change_object
        change_object = get_state_change_object(self.change_type)
        return action.change.is_foundational

    def validate(self, actor, target):

        permission = get_state_change_object(self.change_type)

        # check that target is a valid class for the permission to be set on
        if target.__class__ not in permission.get_settable_classes():
            settable_classes_str = ", ".join(
                [str(option) for option in permission.get_settable_classes()])
            raise ValidationError(
                f"This kind of permission cannot be set on target {target} of class "
                + f"{target.__class__}, must be {settable_classes_str}")

        # validate condition data
        if self.condition_data:
            for condition in self.condition_data:
                is_valid, message = validate_condition(
                    condition["condition_type"], condition["condition_data"],
                    condition["permission_data"], target)
                if not is_valid:
                    raise ValidationError(message)

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

        permission = PermissionsItem()
        permission.set_fields(owner=target.get_owner(),
                              permitted_object=target,
                              anyone=self.anyone,
                              change_type=self.change_type,
                              inverse=self.inverse,
                              actors=self.actors,
                              roles=self.roles)
        permission.save()

        # if condition, add and save
        if self.condition_data:

            # create initial manager
            owner = permission.get_owner()
            manager = ConditionManager.objects.create(owner=owner,
                                                      community=owner.pk,
                                                      set_on="permission")
            permission.condition = manager

            # add conditions
            for condition in self.condition_data:
                data = {
                    "condition_type": condition["condition_type"],
                    "condition_data": condition["condition_data"],
                    "permission_data": condition["permission_data"]
                }
                manager.add_condition(data_for_condition=data)
                manager.save()

        return permission