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()})
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()})
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()})
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 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
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 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)
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, )
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)
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 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, )