Example #1
0
def validate_task_rel_proposal(header, propose, rel_address, state):
    """Validates that the User exists, the Task exists, and the User is not
    in the Task's relationship specified by rel_address.

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

    Returns:
        (dict of addresses)
    """

    task_id = propose.task_id
    user_id = propose.user_id
    user_address = addresser.make_user_address(user_id)
    task_address = addresser.make_task_attributes_address(task_id)
    proposal_address = addresser.make_proposal_address(object_id=task_id,
                                                       related_id=user_id)

    state_entries = state_accessor.get_state(
        state, [user_address, task_address, proposal_address, rel_address])
    user_validator.validate_identifier_is_user(state_entries,
                                               identifier=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), user_id)

    validate_identifier_is_task(state_entries,
                                identifier=task_id,
                                address=task_address)

    try:
        task_rel_entry = state_accessor.get_state_entry(
            state_entries, rel_address)
        task_rel_container = message_accessor.get_task_rel_container(
            task_rel_entry)

        if (header.signer_public_key not in [
                user.user_id, user.manager_id
        ]) and (not message_accessor.is_in_task_rel_container(
                task_rel_container, task_id, user_id)):
            raise InvalidTransaction(
                "Txn signer {} is not the user or the user's "
                "manager {} nor the task owner / admin".format(
                    header.signer_public_key, [user.user_id, user.manager_id]))
        if message_accessor.is_in_task_rel_container(task_rel_container,
                                                     task_id, user_id):
            raise InvalidTransaction("User {} is already in the Task {} "
                                     "relationship".format(user_id, task_id))

    except KeyError:
        # The task rel container doesn't exist so no task relationship exists
        pass

    return state_entries
Example #2
0
def confirm_task_action(state_entries, header, confirm, task_rel_address,
                        state, is_remove):
    """ Updates proposal and task relationship objects according to the
        task admin/owner transaction.

        Args:
            state_entries: List of states for the proposal, task relationship,
            and task admins object.
            header (TransactionHeader): The protobuf TransactionHeader.
            confirm (RBACPayload): The protobuf RBACPayload.
            task_rel_address (str): The task relationship address.
            state (Context): The class that handles state gets and sets.
            is_remove (boolean): Determines if task admin/owner is being removed or added.

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

    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:
        task_rel_entry = state_accessor.get_state_entry(
            state_entries, task_rel_address)
        task_rel_container = message_accessor.get_task_rel_container(
            task_rel_entry)
    except KeyError:
        task_rel_container = task_state_pb2.TaskRelationshipContainer()

    try:
        task_rel = message_accessor.get_task_rel_from_container(
            container=task_rel_container,
            task_id=confirm.task_id,
            identifier=confirm.user_id,
        )
    except KeyError:
        task_rel = task_rel_container.relationships.add()
        task_rel.task_id = confirm.task_id

    if not is_remove:
        task_rel.identifiers.append(confirm.user_id)
    else:
        task_rel.identifiers.remove(confirm.user_id)

    address_values[task_rel_address] = task_rel_container.SerializeToString()

    state_accessor.set_state(state, address_values)
def create_role(new_role, state):
    role_container = role_state_pb2.RoleAttributesContainer()
    role = role_container.role_attributes.add()
    role.role_id = new_role.role_id
    role.name = new_role.name
    role.metadata = new_role.metadata

    entries_to_set = {
        addresser.make_role_attributes_address(
            new_role.role_id
        ): role_container.SerializeToString()
    }

    pubkeys_by_address = {}

    for admin in list(new_role.admins):
        admin_address = addresser.make_role_admins_address(
            role_id=new_role.role_id, user_id=admin
        )

        if admin_address in pubkeys_by_address:
            pubkeys_by_address[admin_address].append(admin)
        else:
            pubkeys_by_address[admin_address] = [admin]

    for owner in list(new_role.owners):
        owner_address = addresser.make_role_owners_address(
            role_id=new_role.role_id, user_id=owner
        )

        if owner_address in pubkeys_by_address:
            pubkeys_by_address[owner_address].append(owner)
        else:
            pubkeys_by_address[owner_address] = [owner]

    state_returns = state_accessor.get_state(
        state,
        [
            addresser.make_role_admins_address(role_id=new_role.role_id, user_id=a)
            for a in new_role.admins
        ]
        + [
            addresser.make_role_owners_address(role_id=new_role.role_id, user_id=o)
            for o in new_role.owners
        ],
    )

    for addr, pubkeys in pubkeys_by_address.items():
        try:
            state_entry = state_accessor.get_state_entry(state_returns, addr)
            container = role_state_pb2.RoleRelationshipContainer()
            container.ParseFromString(state_entry.data)
        except KeyError:
            container = role_state_pb2.RoleRelationshipContainer()

        message_accessor.add_role_rel_to_container(container, new_role.role_id, pubkeys)

        entries_to_set[addr] = container.SerializeToString()

        state_accessor.set_state(state, entries_to_set)
Example #4
0
def propose_role_action(
    state_entries,
    header,
    payload,
    address,
    proposal_type,
    state,
    related_type="user_id",
):
    try:
        entry = state_accessor.get_state_entry(state_entries, address=address)
        proposal_container = message_accessor.get_prop_container(entry)
    except KeyError:
        proposal_container = proposal_state_pb2.ProposalsContainer()

    proposal = proposal_container.proposals.add()

    proposal.proposal_id = payload.proposal_id
    proposal.object_id = payload.role_id
    proposal.target_id = getattr(payload, related_type)
    proposal.proposal_type = proposal_type
    proposal.status = proposal_state_pb2.Proposal.OPEN
    proposal.opener = header.signer_public_key
    proposal.open_reason = payload.reason
    proposal.metadata = payload.metadata

    state_accessor.set_state(state,
                             {address: proposal_container.SerializeToString()})
Example #5
0
def propose_manager_change(proposal_state_entries, header, user_proposal,
                           state):
    proposal_address = addresser.make_proposal_address(
        user_proposal.user_id, user_proposal.new_manager_id)
    try:

        state_entry = state_accessor.get_state_entry(proposal_state_entries,
                                                     proposal_address)
        proposal_container = message_accessor.get_prop_container(state_entry)

    except KeyError:
        proposal_container = proposal_state_pb2.ProposalsContainer()

    proposal = proposal_container.proposals.add()
    proposal.proposal_id = user_proposal.proposal_id
    proposal.proposal_type = proposal_state_pb2.Proposal.UPDATE_USER_MANAGER
    proposal.object_id = user_proposal.user_id
    proposal.target_id = user_proposal.new_manager_id
    proposal.opener = header.signer_public_key
    proposal.status = proposal_state_pb2.Proposal.OPEN
    proposal.open_reason = user_proposal.reason
    proposal.metadata = user_proposal.metadata

    state_accessor.set_state(
        state, {proposal_address: proposal_container.SerializeToString()})
Example #6
0
def record_decision(state, header, confirm, isApproval):
    """
        Record decisions made and who made it in the proposal object
    """
    on_behalf_id = confirm.on_behalf_id

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

    state_entries = state_accessor.get_state(state, [proposal_address])
    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)

    if isApproval:
        record = proposal.approvals.add()
        record.approver = header.signer_public_key
        record.on_behalf = on_behalf_id
    else:
        record = proposal.rejections.add()
        record.rejector = header.signer_public_key
        record.on_behalf = on_behalf_id

    LOGGER.info(
        "recording decision from {}, on behalf of {} for proposal {}".format(  # pylint: disable=logging-format-interpolation
            header.signer_public_key, confirm.on_behalf_id,
            confirm.proposal_id))

    state_accessor.set_state(
        state, {proposal_address: proposal_container.SerializeToString()})
Example #7
0
def validate_role_task(header, confirm, txn_signer_rel_address, state):
    proposal_address = addresser.make_proposal_address(
        object_id=confirm.role_id, related_id=confirm.task_id
    )

    state_entries = state_accessor.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 = state_accessor.get_state_entry(state_entries, txn_signer_rel_address)
        task_owners_container = message_accessor.get_task_rel_container(entry)
    except KeyError:
        raise InvalidTransaction(
            "Signer {} is not a task owner for task {}".format(
                header.signer_public_key, confirm.task_id
            )
        )

    if not message_accessor.is_in_task_rel_container(
        task_owners_container, confirm.task_id, header.signer_public_key
    ):
        raise InvalidTransaction(
            "Signer {} is not a task owner for task {} no bytes in "
            "state".format(header.signer_public_key, confirm.task_id)
        )
    return state_entries
def validate_task_admin_or_owner(
    header, confirm, txn_signer_rel_address, task_rel_address, state, is_remove
):
    """Validate a [ Confirm | Reject }_____Task[ Admin | Owner } transaction.

    Args:
        header (TransactionHeader): The transaction header protobuf class.:
        confirm: ConfirmAddTaskAdmin, RejectAddTaskAdmin, ...
        txn_signer_rel_address (str): The transaction signer address.
        task_rel_address (str): The task relationship address.
        state (Context): The class responsible for gets and sets of state.
        is_remove (boolean): Determines if task owner is being added or removed.

    Returns:
        (dict of addresses)

    Raises:
        InvalidTransaction
            - The transaction is invalid.
    """

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

    if not is_remove:
        state_entries = state_accessor.get_state(
            state, [txn_signer_rel_address, proposal_address]
        )
    else:
        state_entries = state_accessor.get_state(
            state, [txn_signer_rel_address, task_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 = state_accessor.get_state_entry(state_entries, txn_signer_rel_address)
        task_rel_container = message_accessor.get_task_rel_container(entry)
    except KeyError:
        raise InvalidTransaction(
            "Signer {} does not have the Task permissions "
            "to close the proposal".format(header.signer_public_key)
        )
    if not message_accessor.is_in_task_rel_container(
        task_rel_container, task_id=confirm.task_id, identifier=header.signer_public_key
    ):
        raise InvalidTransaction(
            "Signer {} does not have the Task "
            "permissions to close the "
            "proposal".format(header.signer_public_key)
        )

    return state_entries
Example #9
0
def validate_identifier_is_task(state_entries, identifier, address):
    try:
        container = message_accessor.get_task_container(
            state_accessor.get_state_entry(state_entries, address))

        if not message_accessor.is_in_task_container(container, identifier):
            raise InvalidTransaction("{} is not a task.".format(identifier))
    except KeyError:
        raise InvalidTransaction("{} is not a task".format(identifier))
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 create_task(state_entries, payload, state):
    try:
        entry = state_accessor.get_state_entry(
            state_entries, addresser.task.address(payload.task_id)
        )
        container = message_accessor.get_task_container(entry)

    except KeyError:
        container = task_state_pb2.TaskAttributesContainer()

    task = container.task_attributes.add()

    task.task_id = payload.task_id
    task.name = payload.name
    task.metadata = payload.metadata

    address_values = {}

    pubkeys_by_address = {}
    for pubkey in payload.admins:
        address = addresser.task.admin.address(payload.task_id, pubkey)
        if address in pubkeys_by_address:
            pubkeys_by_address[address].append(pubkey)
        else:
            pubkeys_by_address[address] = [pubkey]

    address_values.update(
        _handle_task_rel_container(
            state_entries=state_entries,
            task_id=payload.task_id,
            pubkeys_by_address=pubkeys_by_address,
        )
    )

    pubkeys_by_address = {}
    for pubkey in payload.owners:
        address = addresser.task.owner.address(payload.task_id, pubkey)
        if address in pubkeys_by_address:
            pubkeys_by_address[address].append(pubkey)
        else:
            pubkeys_by_address[address] = [pubkey]

    address_values.update(
        _handle_task_rel_container(
            state_entries=state_entries,
            task_id=payload.task_id,
            pubkeys_by_address=pubkeys_by_address,
        )
    )

    address_values[
        addresser.task.address(payload.task_id)
    ] = container.SerializeToString()

    state_accessor.set_state(state, address_values)
Example #12
0
def proposal_exists_and_open(state_entries, proposal_address, proposal_id):
    try:
        entry = state_accessor.get_state_entry(state_entries, proposal_address)
    except KeyError:
        # There isn't anything in this state address, so no proposal at all
        return False

    prop_container = message_accessor.get_prop_container(entry)
    for proposal in prop_container.proposals:
        if (proposal.proposal_id == proposal_id
                and proposal.status == proposal_state_pb2.Proposal.OPEN):
            return True
    return False
Example #13
0
def validate_manager_state(create_user, state):
    manager_entries = state_accessor.get_state(
        state, [addresser.user.address(create_user.manager_id)])
    if not manager_entries:
        raise InvalidTransaction("User id {} listed as manager is not "
                                 "in state.".format(create_user.manager_id))

    state_entry = state_accessor.get_state_entry(
        manager_entries, addresser.user.address(create_user.manager_id))
    manager_container = message_accessor.get_user_container(state_entry)
    if not message_accessor.is_in_user_container(manager_container,
                                                 create_user.manager_id):
        raise InvalidTransaction(
            "user id {} listed as manager is not within the User container "
            "in state".format(create_user.manager_id))
Example #14
0
def _handle_task_rel_container(state_entries, task_id, pubkeys_by_address):
    entries_to_set = {}

    for addr, pubkeys in pubkeys_by_address.items():
        try:
            state_entry = state_accessor.get_state_entry(state_entries, addr)
            container = task_state_pb2.TaskRelationshipContainer()
            container.ParseFromString(state_entry.data)
        except KeyError:
            container = task_state_pb2.TaskRelationshipContainer()

        _add_task_rel_to_container(container, task_id, pubkeys)

        entries_to_set[addr] = container.SerializeToString()

    return entries_to_set
Example #15
0
def has_no_open_proposal(state_entries, proposal_address, object_id,
                         related_id, proposal_type):
    try:
        entry = state_accessor.get_state_entry(state_entries, proposal_address)
    except KeyError:
        # There isn't anything in this state address, so no proposal at all
        return True

    prop_container = message_accessor.get_prop_container(entry)
    for proposal in prop_container.proposals:
        if (proposal.object_id == object_id
                and proposal.target_id == related_id
                and proposal.status == proposal_state_pb2.Proposal.OPEN
                and proposal.proposal_type == proposal_type):
            return False
    return True
def validate_create_task_state(state_entries, payload):
    user_validator.validate_list_of_user_are_users(state_entries,
                                                   payload.admins)
    user_validator.validate_list_of_user_are_users(state_entries,
                                                   payload.owners)

    try:
        entry = state_accessor.get_state_entry(
            state_entries, addresser.task.address(payload.task_id))
        container = message_accessor.get_task_container(entry)

        if message_accessor.is_in_task_container(container, payload.task_id):
            raise InvalidTransaction("Task with id {} already in "
                                     "state".format(payload.task_id))
    except KeyError:
        # The task container is not in state, so no at this address.
        pass
Example #17
0
def reject_task_action(state_entries, header, reject, state):
    proposal_address = addresser.make_proposal_address(
        object_id=reject.task_id, related_id=reject.user_id)

    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=reject.proposal_id)

    proposal.status = proposal_state_pb2.Proposal.REJECTED
    proposal.closer = header.signer_public_key
    proposal.close_reason = reject.reason

    address_values = {proposal_address: proposal_container.SerializeToString()}

    state_accessor.set_state(state, address_values)
Example #18
0
def apply_user_confirm(header, payload, state):
    confirm_payload = user_transaction_pb2.ConfirmUpdateUserManager()
    confirm_payload.ParseFromString(payload.content)

    proposal_address = addresser.proposal.address(
        object_id=confirm_payload.user_id, target_id=confirm_payload.manager_id
    )

    proposal_entries = state_accessor.get_state(state, [proposal_address])

    if not proposal_validator.proposal_exists_and_open(
        state_entries=proposal_entries,
        proposal_address=proposal_address,
        proposal_id=confirm_payload.proposal_id,
    ):
        raise InvalidTransaction(
            "Proposal id {} for user {} to update manager to {} does not exist or is not open.".format(
                confirm_payload.proposal_id,
                confirm_payload.user_id,
                confirm_payload.manager_id,
            )
        )

    entry = state_accessor.get_state_entry(proposal_entries, proposal_address)
    proposal_container = message_accessor.get_prop_container(entry)
    proposal = message_accessor.get_prop_from_container(
        container=proposal_container, proposal_id=confirm_payload.proposal_id
    )

    if not proposal.target_id == header.signer_public_key:
        raise InvalidTransaction(
            "Confirm update manager txn signed by {} while "
            "proposal expecting {}".format(header.signer_public_key, proposal.target_id)
        )

    state_change.confirm_manager_change(
        container=proposal_container,
        proposal=proposal,
        closer=header.signer_public_key,
        reason=confirm_payload.reason,
        address=proposal_address,
        user_id=confirm_payload.user_id,
        new_manager_id=confirm_payload.manager_id,
        state=state,
    )
Example #19
0
def reject_role_action(state_entries, header, reject, state, rel_type="user_id"):
    proposal_address = addresser.proposal.address(
        object_id=reject.role_id, target_id=getattr(reject, 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=reject.proposal_id
    )

    proposal.status = proposal_state_pb2.Proposal.REJECTED
    proposal.closer = header.signer_public_key
    proposal.close_reason = reject.reason

    address_values = {proposal_address: proposal_container.SerializeToString()}

    state_accessor.set_state(state, address_values)
Example #20
0
def confirm_manager_change(container, proposal, closer, reason, address,
                           user_id, new_manager_id, state):
    proposal.status = proposal_state_pb2.Proposal.CONFIRMED
    proposal.closer = closer
    proposal.close_reason = reason

    state_accessor.set_state(state, {address: container.SerializeToString()})

    user_address = addresser.make_user_address(user_id)
    state_entries = state_accessor.get_state(state, [user_address])
    state_entry = state_accessor.get_state_entry(state_entries=state_entries,
                                                 address=user_address)
    user_container = message_accessor.get_user_container(state_entry)
    user = message_accessor.get_user_from_container(user_container, user_id)
    user.manager_id = new_manager_id

    state_accessor.set_state(
        state, {user_address: user_container.SerializeToString()})
Example #21
0
def apply_user_reject(header, payload, state):
    reject_payload = user_transaction_pb2.RejectUpdateUserManager()
    reject_payload.ParseFromString(payload.content)

    proposal_address = addresser.proposal.address(
        object_id=reject_payload.user_id, target_id=reject_payload.manager_id
    )

    state_entries = state_accessor.get_state(state, [proposal_address])

    if not proposal_validator.proposal_exists_and_open(
        state_entries=state_entries,
        proposal_address=proposal_address,
        proposal_id=reject_payload.proposal_id,
    ):
        raise InvalidTransaction(
            "Proposal {} is not open or does not "
            "exist".format(reject_payload.proposal_id)
        )

    entry = state_accessor.get_state_entry(state_entries, proposal_address)

    proposal_container = message_accessor.get_prop_container(entry)

    if not reject_payload.manager_id == header.signer_public_key:
        raise InvalidTransaction(
            "Proposal expected closer to be {} while txn "
            "signer was {}".format(reject_payload.manager_id, header.signer_public_key)
        )

    proposal = message_accessor.get_prop_from_container(
        proposal_container, reject_payload.proposal_id
    )

    state_change.reject_state_change(
        container=proposal_container,
        proposal=proposal,
        closer=header.signer_public_key,
        reason=reject_payload.reason,
        address=proposal_address,
        state=state,
    )
def _validate_state_and_return_user(header, user_proposal, state):
    """Validate that 1. There is no other open proposal for the manager change
    2. The user is a User 3. the manager is a User 4. The manager is the
    signer of the transaction.

    Args:
        header (TransactionHeader): The transaction header.
        user_proposal (ProposeUpdateUserManager): The transaction that makes
            the proposal to update the user's manager.
        state (Context): The way to set and get values from state.

    """

    prop_state_entries = _validate_unique_proposal(user_proposal, state)

    user_address = addresser.make_user_address(user_id=user_proposal.user_id)
    user_state_entries = state_accessor.get_state(state, [user_address])
    user_validator.validate_identifier_is_user(
        state_entries=user_state_entries,
        identifier=user_proposal.user_id,
        address=user_address,
    )

    manager_address = addresser.make_user_address(
        user_id=user_proposal.new_manager_id)

    manager_state_entries = state_accessor.get_state(state, [manager_address])

    user_validator.validate_identifier_is_user(
        state_entries=manager_state_entries,
        identifier=user_proposal.new_manager_id,
        address=manager_address,
    )

    user_state_entry = state_accessor.get_state_entry(user_state_entries,
                                                      user_address)

    user_container = message_accessor.get_user_container(user_state_entry)

    _validate_manager_is_signer(header, user_container, user_proposal.user_id)

    return prop_state_entries
Example #23
0
def validate_identifier_is_user(state_entries, identifier, address):
    """Validate that the identifier references a User
    or raise an InvalidTransaction if that user does not exist.

    Args:
        state_entries (list): List of StateEntry as returned from a state get.
        identifier (str): The identifier of the User.
        address (str): The address used to get the user container.

    Raises:
        InvalidTransaction: No user with that identifier exists.
    """

    try:
        container = message_accessor.get_user_container(
            state_accessor.get_state_entry(state_entries, address))
        if not message_accessor.is_in_user_container(container, identifier):
            raise InvalidTransaction("{} is not a user".format(identifier))
    except KeyError:
        raise InvalidTransaction("{} is not a user".format(identifier))
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))
Example #25
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
Example #26
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
Example #27
0
def validate_task_rel_del_proposal(header, propose, rel_address, state):
    """Validates that the User exists, the Task exists, and the User is in
    the Tasks's relationship specified by the rel_address.

    Args:
        header (TransactionHeader): The transaction header.
        propose (ProposeRemoveTask____): The Task Remove relationship proposal
        rel_address (str): The task relationship address.
        state (Context:: The way to communicate to the validator State gets
            and sets.

    Returns:
        (dict of addresses)
    """

    user_address = addresser.make_user_address(propose.user_id)
    task_address = addresser.make_task_attributes_address(propose.task_id)

    proposal_address = addresser.make_proposal_address(
        object_id=propose.task_id, related_id=propose.user_id)

    state_entries = state_accessor.get_state(
        state, [user_address, task_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)

    validate_identifier_is_task(state_entries,
                                identifier=propose.task_id,
                                address=task_address)

    try:
        task_rel_entry = state_accessor.get_state_entry(
            state_entries, rel_address)
        task_rel_container = message_accessor.get_task_rel_container(
            task_rel_entry)

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

        if not message_accessor.is_in_task_rel_container(
                task_rel_container, propose.task_id, propose.user_id):
            raise InvalidTransaction("User {} isn't in the Task {} "
                                     "relationship".format(
                                         propose.user_id, propose.task_id))
    except KeyError:
        raise InvalidTransaction(
            "User {} isn't in the Task {} relationship, "
            "since there isn't a container at the address".format(
                propose.user_id, propose.task_id))

    return state_entries