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
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
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