def confirm_role_action(state_entries,
                        header,
                        confirm,
                        role_rel_address,
                        state,
                        rel_type="user_id"):
    proposal_address = addresser.proposal.address(object_id=confirm.role_id,
                                                  related_id=getattr(
                                                      confirm, rel_type))

    proposal_entry = state_accessor.get_state_entry(state_entries,
                                                    proposal_address)
    proposal_container = message_accessor.get_prop_container(proposal_entry)
    proposal = message_accessor.get_prop_from_container(
        proposal_container, proposal_id=confirm.proposal_id)

    proposal.status = proposal_state_pb2.Proposal.CONFIRMED
    proposal.closer = header.signer_public_key
    proposal.close_reason = confirm.reason

    address_values = {proposal_address: proposal_container.SerializeToString()}

    try:
        role_rel_entry = state_accessor.get_state_entry(
            state_entries, role_rel_address)
        role_rel_container = message_accessor.get_role_rel_container(
            role_rel_entry)
    except KeyError:
        role_rel_container = role_state_pb2.RoleRelationshipContainer()

    try:
        role_rel = message_accessor.get_role_rel(role_rel_container,
                                                 confirm.role_id)

    except KeyError:
        role_rel = role_rel_container.relationships.add()
        role_rel.role_id = confirm.role_id

    role_rel.identifiers.append(getattr(confirm, rel_type))

    address_values[role_rel_address] = role_rel_container.SerializeToString()

    state_accessor.set_state(state, address_values)
def verify_user_with_role_permission_on_proposal(proposal_address, user_id,
                                                 role_id,
                                                 txn_signer_rel_address,
                                                 state):

    state_entries = state_accessor.get_state(
        state, [txn_signer_rel_address, proposal_address])
    try:
        entry = state_accessor.get_state_entry(state_entries,
                                               txn_signer_rel_address)
        role_rel_container = message_accessor.get_role_rel_container(entry)
    except KeyError:
        raise InvalidTransaction(
            "Signer {} does not have the Role permissions "
            "to close the proposal".format(user_id))
    if not message_accessor.is_in_role_rel_container(
            role_rel_container, role_id=role_id, identifier=user_id):
        raise InvalidTransaction("Signer {} does not have the Role "
                                 "permissions to close the "
                                 "proposal".format(user_id))
def get_state_entries(header, confirm, txn_signer_rel_address, state):
    """Fetch a collection of state entries veri

    Args:
        header (TransactionHeader): The transaction header protobuf class.:
        confirm: ConfirmAddRoleAdmin, RejectAddRoleAdmin, ...
        txn_signer_rel_address: Transaction signer role relationship address
        state (Context): The class responsible for gets and sets of state.

    Returns:
        (dict of addresses)
    """

    proposal_address = addresser.make_proposal_address(
        object_id=confirm.role_id, related_id=confirm.user_id)

    state_entries = get_state(state,
                              [txn_signer_rel_address, proposal_address])

    if not proposal_validator.proposal_exists_and_open(
            state_entries, proposal_address, confirm.proposal_id):
        raise InvalidTransaction("The proposal {} does not exist or "
                                 "is not open".format(confirm.proposal_id))
    try:
        entry = get_state_entry(state_entries, txn_signer_rel_address)
        role_rel_container = message_accessor.get_role_rel_container(entry)
    except KeyError:
        raise InvalidTransaction(
            "Signer {} does not have the Role permissions "
            "to close the proposal".format(header.signer_public_key))
    if not message_accessor.is_in_role_rel_container(
            role_rel_container,
            role_id=confirm.role_id,
            identifier=header.signer_public_key):
        raise InvalidTransaction("Signer {} does not have the Role "
                                 "permissions to close the "
                                 "proposal".format(header.signer_public_key))

    return state_entries
示例#4
0
def validate_role_task_proposal(header, propose, state):
    """Applies state validation rules for ADDRoleTaskProposal.
        - The Role exists.
        - The Task exists.
        - The Transaction was signed by a Role Owner.
        - There is no open Proposal for the same change.
        - The task is not already part of the Role.

    Args:
        header (TransactionHeader): The propobuf transaction header.
        propose (ProposeAddRoleTask): The protobuf transaction.
        state (Context): A connection to the validator to ask about state.

    Returns:
        (list of StateEntry)

    """

    role_address = addresser.role.address(propose.role_id)

    task_address = addresser.task.address(propose.task_id)

    proposal_address = addresser.proposal.address(propose.role_id,
                                                  propose.task_id)

    txn_signer_role_owner_address = addresser.role.owner.address(
        propose.role_id, header.signer_public_key)

    role_tasks_address = addresser.role.task.address(propose.role_id,
                                                     propose.task_id)

    state_entries = state_accessor.get_state(
        state=state,
        addresses=[
            role_address,
            task_address,
            proposal_address,
            role_tasks_address,
            txn_signer_role_owner_address,
        ],
    )

    role_validator.validate_identifier_is_role(state_entries=state_entries,
                                               address=role_address,
                                               identifier=propose.role_id)

    task_validator.validate_identifier_is_task(state_entries=state_entries,
                                               identifier=propose.task_id,
                                               address=task_address)
    try:
        role_task_entry = state_accessor.get_state_entry(
            state_entries, role_tasks_address)
        role_task_container = message_accessor.get_role_rel_container(
            role_task_entry)
        if message_accessor.is_in_role_rel_container(
                role_task_container,
                role_id=propose.role_id,
                identifier=propose.task_id):
            raise InvalidTransaction("Role {} already contains task {}".format(
                propose.role_id, propose.task_id))
    except KeyError:
        # The Task is not in the RoleTask state
        pass

    try:
        role_owner_entry = state_accessor.get_state_entry(
            state_entries, txn_signer_role_owner_address)
        role_owner_container = message_accessor.get_role_rel_container(
            role_owner_entry)

        if not message_accessor.is_in_role_rel_container(
                role_owner_container,
                role_id=propose.role_id,
                identifier=header.signer_public_key,
        ):
            raise InvalidTransaction(
                "Txn signer {} is not a role owner".format(
                    header.signer_public_key))
    except KeyError:
        raise InvalidTransaction("Txn signer {} is not a role owner.".format(
            header.signer_public_key))

    if not has_no_open_proposal(
            state_entries=state_entries,
            object_id=propose.role_id,
            related_id=propose.task_id,
            proposal_address=proposal_address,
            proposal_type=proposal_state_pb2.Proposal.ADD_ROLE_TASK,
    ):
        raise InvalidTransaction(
            "There is already an open proposal to add task {} to "
            "role {}".format(propose.task_id, propose.role_id))
    return state_entries
示例#5
0
def validate_role_rel_proposal(header, propose, rel_address, state, is_remove=False):
    """Validates that the User exists, the Role exists, and the User is not
    in the Role's relationship specified by rel_address.

    Args:
        header (TransactionHeader): The transaction header.
        propose (ProposeAddRole_____): The role relationship proposal.
        rel_address (str): The Role relationship address produced by the Role
            and the User.
        state (sawtooth_sdk.Context): The way to communicate to the validator
            the state gets and sets.

    Returns:
        (dict of addresses)
    """

    user_address = addresser.make_user_address(propose.user_id)
    role_address = addresser.make_role_attributes_address(propose.role_id)
    proposal_address = addresser.make_proposal_address(
        object_id=propose.role_id, related_id=propose.user_id
    )

    state_entries = state_accessor.get_state(
        state, [user_address, role_address, proposal_address, rel_address]
    )
    user_validator.validate_identifier_is_user(
        state_entries, identifier=propose.user_id, address=user_address
    )
    user_entry = state_accessor.get_state_entry(state_entries, user_address)
    user = message_accessor.get_user_from_container(
        message_accessor.get_user_container(user_entry), propose.user_id
    )

    if header.signer_public_key not in [user.user_id, user.manager_id]:
        raise InvalidTransaction(
            "Txn signer {} is not the user or the user's "
            "manager {}".format(
                header.signer_public_key, [user.user_id, user.manager_id]
            )
        )

    validate_identifier_is_role(
        state_entries, identifier=propose.role_id, address=role_address
    )

    try:
        role_admins_entry = state_accessor.get_state_entry(state_entries, rel_address)
        role_rel_container = message_accessor.get_role_rel_container(role_admins_entry)

        if (header.signer_public_key not in [user.user_id, user.manager_id]) and (
            not message_accessor.is_in_role_rel_container(
                role_rel_container, propose.role_id, propose.user_id
            )
        ):
            raise InvalidTransaction(
                "Txn signer {} is not the user or the user's "
                "manager {} nor the group owner / admin".format(
                    header.signer_public_key, [user.user_id, user.manager_id]
                )
            )

        if (not is_remove) and message_accessor.is_in_role_rel_container(
            role_rel_container, propose.role_id, propose.user_id
        ):
            raise InvalidTransaction(
                "User {} is already in the Role {} "
                "relationship".format(propose.user_id, propose.role_id)
            )
    except KeyError:
        # The role rel container doesn't exist so no role relationship exists
        pass

    return state_entries