def confirm_remove_task_admins(txn_key, batch_key, proposal_id, task_id, user_id, reason): confirm_payload = task_transaction_pb2.ConfirmRemoveTaskAdmin( proposal_id=proposal_id, task_id=task_id, user_id=user_id, reason=reason) inputs = [ addresser.make_task_admins_address(task_id, txn_key.public_key), addresser.make_task_admins_address(task_id, user_id), addresser.make_proposal_address(task_id, user_id), ] outputs = [ addresser.make_proposal_address(task_id, user_id), addresser.make_task_admins_address(task_id, user_id), ] rbac_payload = rbac_payload_pb2.RBACPayload( content=confirm_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CONFIRM_REMOVE_TASK_ADMINS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def test_generated_task_admin_addr(self): """Tests the task admin address creation function as well as the address_is function. """ task_id = uuid4().hex admin_id = uuid4().hex address = addresser.make_task_admins_address(task_id, admin_id) self.assertEqual( len(address), addresser.ADDRESS_LENGTH, "The address is 70 characters" ) self.assertTrue( addresser.is_address(address), "The address is 70 character hexidecimal" ) self.assertTrue( addresser.namespace_ok(address), "The address has correct namespace prefix" ) self.assertTrue( addresser.is_family_address(address), "The address is 70 character hexidecimal with family prefix", ) self.assertEqual( addresser.address_is(address), AddressSpace.TASKS_ADMINS, "The address created must be a Task Attributes address.", )
def propose_add_task_admins( txn_key, batch_key, proposal_id, task_id, user_id, reason, metadata ): propose_payload = task_transaction_pb2.ProposeAddTaskAdmin( proposal_id=proposal_id, task_id=task_id, user_id=user_id, reason=reason, metadata=metadata, ) inputs = [ addresser.make_user_address(user_id), addresser.make_task_admins_address(task_id=task_id, user_id=user_id), addresser.make_proposal_address(task_id, user_id), addresser.make_task_attributes_address(task_id), ] outputs = [addresser.make_proposal_address(task_id, user_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=propose_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.PROPOSE_ADD_TASK_ADMINS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def test_determine_task_admin_addr(self): """Tests that a specific task_id and admin_id generates the expected task admin address, and thus is probably deterministic. """ task_id = "99968acb8f1a48b3a4bc21e2cd252e67" admin_id = "966ab67317234df489adb4bc1f517b88" expected_address = "9f44481e326a1713a905b26359fc8d\ a2817c1a5f67de6f464701f0c10042da345d2848" address = addresser.make_task_admins_address(task_id, admin_id) self.assertEqual(len(address), addresser.ADDRESS_LENGTH, "The address is 70 characters") self.assertTrue(addresser.is_address(address), "The address is 70 character hexidecimal") self.assertTrue(addresser.namespace_ok(address), "The address has correct namespace prefix") self.assertTrue( addresser.is_family_address(address), "The address is 70 character hexidecimal with family prefix", ) self.assertEqual(address, expected_address, "The address is the one we expected it to be") self.assertEqual( addresser.address_is(address), AddressSpace.TASKS_ADMINS, "The address created must be a Task Attributes address.", )
def apply_confirm(header, payload, state, is_remove=False): """Apply the (Add | Remove) TaskAdmins transaction. Args: header (TransactionHeader): The protobuf TransactionHeader. payload (RBACPayload): The protobuf RBACPayload. state (Context): The class that handles state gets and sets. is_remove (boolean): Determines if task admin is being added or removed. Raises: InvalidTransaction: - The transaction is invalid. """ if not is_remove: confirm_payload = task_transaction_pb2.ConfirmAddTaskAdmin() else: confirm_payload = task_transaction_pb2.ConfirmRemoveTaskAdmin() confirm_payload.ParseFromString(payload.content) task_admins_address = addresser.make_task_admins_address( task_id=confirm_payload.task_id, user_id=confirm_payload.user_id ) txn_signer_admin_address = addresser.make_task_admins_address( task_id=confirm_payload.task_id, user_id=header.signer_public_key ) state_entries = task_validator.validate_task_admin_or_owner( header=header, confirm=confirm_payload, txn_signer_rel_address=txn_signer_admin_address, task_rel_address=task_admins_address, state=state, is_remove=is_remove, ) state_change.confirm_task_action( state_entries=state_entries, header=header, confirm=confirm_payload, task_rel_address=task_admins_address, state=state, is_remove=is_remove, )
def create_task(state_entries, payload, state): try: entry = state_accessor.get_state_entry( state_entries, addresser.make_task_attributes_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.make_task_admins_address(task_id=payload.task_id, user_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.make_task_owners_address(task_id=payload.task_id, user_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.make_task_attributes_address( payload.task_id)] = container.SerializeToString() state_accessor.set_state(state, address_values)
def test_task_addresses(self): """Tests the Task address creation functions as well as the address_is function. Notes: 1. Create an address of a particular type: - Task Attributes - Task Owners - Task Admins 2. Assert that address_is returns the correct address type. """ task_address = addresser.make_task_attributes_address(uuid4().hex) self.assertEqual(len(task_address), 70, "The address is a well-formed address.") self.assertEqual( addresser.address_is(task_address), AddressSpace.TASKS_ATTRIBUTES, "The Task Attributes address created must be " "found to be a Task Attributes address.", ) task_owners_address = addresser.make_task_owners_address( task_id=uuid4().hex, user_id=uuid4().hex ) self.assertEqual( len(task_owners_address), 70, "The address is a well-formed address." ) self.assertEqual( addresser.address_is(task_owners_address), AddressSpace.TASKS_OWNERS, "The Task Owners address created must be " "found to be a Task Owners address.", ) task_admins_address = addresser.make_task_admins_address( task_id=uuid4().hex, user_id=uuid4().hex ) self.assertEqual( len(task_admins_address), 70, "The address is a well-formed address." ) self.assertEqual( addresser.address_is(task_admins_address), AddressSpace.TASKS_ADMINS, "The Task Admins address created must be " "found to be a Task Admins address.", )
def apply_propose_remove(header, payload, state): """Apply the ProposeRemoveTaskAdmins transaction. Args: header (TransactionHeader): The protobuf TransactionHeader. payload (RBACPayload): The protobuf RBACPayload. state (Context): The class that handles state gets and sets. Raises InvalidTransaction: - The transaction is invalid. """ propose_payload = task_transaction_pb2.ProposeRemoveTaskAdmin() propose_payload.ParseFromString(payload.content) task_admins_address = addresser.make_task_admins_address( task_id=propose_payload.task_id, user_id=propose_payload.user_id ) proposal_address = addresser.make_proposal_address( propose_payload.task_id, propose_payload.user_id ) state_entries = task_validator.validate_task_rel_del_proposal( header=header, propose=propose_payload, rel_address=task_admins_address, state=state, ) if not proposal_validator.has_no_open_proposal( state_entries=state_entries, object_id=propose_payload.task_id, related_id=propose_payload.user_id, proposal_address=proposal_address, proposal_type=proposal_state_pb2.Proposal.REMOVE_TASK_ADMINS, ): raise InvalidTransaction( "There is already an open proposal for REMOVE_TASK_ADMINS " "with task id {} and user id {}".format( propose_payload.task_id, propose_payload.user_id ) ) state_change.propose_task_action( state_entries=state_entries, header=header, payload=propose_payload, address=proposal_address, proposal_type=proposal_state_pb2.Proposal.REMOVE_TASK_ADMINS, state=state, )
def create_task(txn_key, batch_key, task_id, task_name, admins, owners, metadata): create_payload = task_transaction_pb2.CreateTask(task_id=task_id, name=task_name) create_payload.admins.extend(admins) inputs = [ addresser.make_task_attributes_address(task_id=task_id), addresser.make_sysadmin_members_address(txn_key.public_key), ] inputs.extend([addresser.make_user_address(user_id=u) for u in admins]) inputs.extend( [addresser.make_task_admins_address(task_id, u) for u in admins]) outputs = [addresser.make_task_attributes_address(task_id=task_id)] outputs.extend( [addresser.make_task_admins_address(task_id, u) for u in admins]) if owners: create_payload.owners.extend(owners) inputs.extend([addresser.make_user_address(user_id=u) for u in owners]) inputs.extend( [addresser.make_task_owners_address(task_id, u) for u in owners]) outputs.extend( [addresser.make_task_owners_address(task_id, u) for u in owners]) rbac_payload = rbac_payload_pb2.RBACPayload( content=create_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CREATE_TASK, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def reject_add_task_owners(txn_key, batch_key, proposal_id, task_id, user_id, reason): reject = task_transaction_pb2.RejectAddTaskOwner( proposal_id=proposal_id, task_id=task_id, user_id=user_id, reason=reason ) inputs = [ addresser.make_proposal_address(task_id, user_id), addresser.make_task_admins_address(task_id, txn_key.public_key), ] outputs = [addresser.make_proposal_address(task_id, user_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=reject.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.REJECT_ADD_TASK_OWNERS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def apply_reject(header, payload, state): reject_payload = task_transaction_pb2.RejectAddTaskOwner() reject_payload.ParseFromString(payload.content) txn_signer_admin_address = addresser.make_task_admins_address( task_id=reject_payload.task_id, user_id=header.signer_public_key) state_entries = task_validator.validate_task_admin_or_owner( header=header, confirm=reject_payload, txn_signer_rel_address=txn_signer_admin_address, task_rel_address="", state=state, is_remove=False, ) state_change.reject_task_action(state_entries, header, reject_payload, state)
def new_task(payload, state): create_payload = task_transaction_pb2.CreateTask() create_payload.ParseFromString(payload.content) addresses = [ addresser.make_task_attributes_address(create_payload.task_id) ] if not create_payload.admins: raise InvalidTransaction("New tasks must have administrators.") if not create_payload.owners: raise InvalidTransaction("New tasks must have owners.") if create_payload.admins: addresses.extend( [addresser.make_user_address(u) for u in create_payload.admins]) addresses.extend([ addresser.make_task_admins_address(task_id=create_payload.task_id, user_id=u) for u in create_payload.admins ]) if create_payload.owners: addresses.extend( [addresser.make_user_address(u) for u in create_payload.owners]) addresses.extend([ addresser.make_task_owners_address(create_payload.task_id, user_id=u) for u in create_payload.owners ]) state_entries = state_accessor.get_state(state, addresses) task_validator.validate_create_task_state(state_entries=state_entries, payload=create_payload) create_task(state_entries, create_payload, state)