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 = get_state(state, [txn_signer_rel_address, proposal_address]) if not 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) task_owners_container = return_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 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_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) """ 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 = get_state(state, [user_address, task_address, proposal_address, rel_address]) validate_identifier_is_user(state_entries, identifier=propose.user_id, address=user_address) user_entry = get_state_entry(state_entries, user_address) user = get_user_from_container( return_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_task(state_entries, identifier=propose.task_id, address=task_address) try: task_admins_entry = get_state_entry(state_entries, rel_address) task_rel_container = return_task_rel_container(task_admins_entry) if is_in_task_rel_container( task_rel_container, propose.task_id, propose.user_id): raise InvalidTransaction( "User {} is already in the Role {} " "relationship".format(propose.user_id, propose.task_id)) except KeyError: # The task rel container doesn't exist so no task relationship exists pass return state_entries
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: (list of StateEntry) """ 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 = get_state( state, [user_address, task_address, proposal_address, rel_address]) validate_identifier_is_user(state_entries, identifier=propose.user_id, address=user_address) user_entry = get_state_entry(state_entries, user_address) user = get_user_from_container(return_user_container(user_entry), propose.user_id) if header.signer_pubkey not in [user.user_id, user.manager_id]: raise InvalidTransaction( "Txn signer {} is not the user {} or the user's manager {}".format( header.signer_pubkey, user.user_id, user.manager_id)) validate_identifier_is_task(state_entries, identifier=propose.task_id, address=task_address) try: task_rel_entry = get_state_entry(state_entries, rel_address) task_rel_container = return_task_rel_container(task_rel_entry) if not 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
def handle_confirm(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 = get_state_entry(state_entries, proposal_address) proposal_container = return_prop_container(proposal_entry) proposal = 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 = get_state_entry(state_entries, task_rel_address) task_rel_container = return_task_rel_container(task_rel_entry) except KeyError: task_rel_container = task_state_pb2.TaskRelationshipContainer() try: task_rel = 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() set_state(state, address_values)
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 = get_state(state, [txn_signer_rel_address, proposal_address]) else: state_entries = get_state( state, [txn_signer_rel_address, task_rel_address, proposal_address]) if not 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) task_rel_container = return_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 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
def handle_confirm_add(state_entries, header, confirm, task_rel_address, state): proposal_address = addresser.make_proposal_address( object_id=confirm.task_id, related_id=confirm.user_id) proposal_entry = get_state_entry(state_entries, proposal_address) proposal_container = return_prop_container(proposal_entry) proposal = 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 = get_state_entry(state_entries, task_rel_address) task_rel_container = return_task_rel_container(task_rel_entry) except KeyError: task_rel_container = task_state_pb2.TaskRelationshipContainer() try: task_rel = 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 task_rel.identifiers.append(confirm.user_id) address_values[task_rel_address] = task_rel_container.SerializeToString() set_state(state, address_values)
def validate_task_admin_or_owner(header, confirm, txn_signer_rel_address, state): """Validate a [ Confirm | Reject }_____Task[ Admin | Owner } transaction. Args: header (TransactionHeader): The transaction header protobuf class.: confirm: ConfirmAddTaskAdmin, RejectAddTaskAdmin, ... state (Context): The class responsible for gets and sets of state. Returns: (list of StateEntry) """ proposal_address = addresser.make_proposal_address( object_id=confirm.task_id, related_id=confirm.user_id) state_entries = get_state(state, [txn_signer_rel_address, proposal_address]) if not 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) task_rel_container = return_task_rel_container(entry) except KeyError: raise InvalidTransaction( "Signer {} does not have the Task permissions " "to close the proposal".format(header.signer_pubkey)) if not is_in_task_rel_container(task_rel_container, task_id=confirm.task_id, identifier=header.signer_pubkey): raise InvalidTransaction("Signer {} does not have the Task " "permissions to close the " "proposal".format(header.signer_pubkey)) return state_entries