def test_json_0_5_assertion_input(self): assertion_data = json.dumps(self.assertion_data) state = INITIAL_STATE action = store_input(assertion_data) state = main_reducer(state, action) self.assertEqual(state['input']['value'], assertion_data) task_meta = add_task(DETECT_INPUT_TYPE) result, message, actions = run_task(state, task_meta) self.assertTrue(result, "Task completes successfully") self.assertIn(REPORT_MESSAGE, [a.get('type') for a in actions])
def test_json_1_0_assertion_input(self): assertion_data = test_components['1_0_basic_assertion'] state = INITIAL_STATE action = store_input(assertion_data) state = main_reducer(state, action) self.assertEqual(state['input']['value'], assertion_data) task_meta = add_task(DETECT_INPUT_TYPE) result, message, actions = run_task(state, task_meta) self.assertTrue(result) self.assertIn(SET_VALIDATION_SUBJECT, [a.get('type') for a in actions]) self.assertIn(FETCH_HTTP_NODE, [a.get('name') for a in actions])
def test_extension_discovered_jsonld_compact(self): """ Ensure an extension node is properly discovered and that the task runs without error. """ node = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': 'http://example.com/1', 'type': 'Assertion', 'schema:location': { '@context': GeoLocation.context_url, 'type': ['Extension', 'extensions:GeoCoordinates'], 'description': 'That place in the woods where we built the fort', 'schema:geo': { 'schema:latitude': 44.580900, 'schema:longitude': -123.301815 } } } state = INITIAL_STATE set_up_context_mock() responses.add( responses.GET, GeoLocation.context_url, body=json.dumps(GeoLocation.context_json), status=200, content_type='application/ld+json') schema_url = 'https://w3id.org/openbadges/extensions/geoCoordinatesExtension/schema.json' responses.add( responses.GET, schema_url, body=json.dumps(GeoLocation.validation_schema[schema_url]), status=200, content_type='application/ld+json') compact_task = add_task( JSONLD_COMPACT_DATA, data=json.dumps(node), jsonld_options=jsonld_no_cache, context_urls=[GeoLocation.context_url] ) result, message, actions = task_named(JSONLD_COMPACT_DATA)(state, compact_task) self.assertTrue(result, "JSON-LD Compact is successful.") self.assertIn(VALIDATE_EXTENSION_NODE, [i.get('name') for i in actions], "Validation task queued.") state = main_reducer(state, actions[0]) # ADD_NODE validate_task = [i for i in actions if i.get('name') == VALIDATE_EXTENSION_NODE][0] self.assertIsNotNone(validate_task['node_json']) result, message, actions = task_named(VALIDATE_EXTENSION_NODE)(state, validate_task) self.assertTrue(result, "Validation task is successful.")
def test_input_json_bad_0_5(self): input_data = { "recipient": "sha256$ef1253755797c2a3dfd3ab455a7a2080cb9160f2f1fbbf99c475347af1ecc598", "issued_on": "2012-12-28", "badge": { "name": "Completed Rails for Zombies Redux", "image": "https://d1ffx7ull4987f.cloudfront.net/images/achievements/large_badge/133/completed-rails-for-zombies-redux-0f73c361c3d5070ca2fa7951e65cbf39.png", "description": "Awarded for the completion of Rails for Zombies Redux", "version": "0.5.0", "criteria": "https://www.codeschool.com/users/mrmickca/badges/133", "issuer": { "origin": "http://www.codeschool.com", "org": None, "contact": None, "name": "Code School" } }, "salt": "6abf7e9504d73363bdcf9336056f5235", } input_string = json.dumps(input_data) state = INITIAL_STATE state['input']['value'] = input_string task_meta = add_task(DETECT_INPUT_TYPE) result, message, actions = detect_input_type(state, task_meta) self.assertTrue(result) self.assertEqual(actions[0]['input_type'], 'json') self.assertEqual(actions[1]['messageLevel'], MESSAGE_LEVEL_ERROR) # 1.0 style hosted JSON input input_data['verify'] = { "url": "http://example.org/assertion/1", "type": "hosted" } input_data['badge'] = 'http://example.org/badge/1' input_string = json.dumps(input_data) state['input']['value'] = input_string result, message, actions = detect_input_type(state, task_meta) self.assertTrue(result) self.assertEqual(actions[0]['type'], STORE_INPUT) self.assertEqual(actions[0]['input'], input_data['verify']['url']) self.assertEqual(actions[1]['input_type'], 'url') self.assertEqual(actions[2]['url'], input_data['verify']['url']) # FETCH_HTTP_NODE self.assertEqual(actions[3]['node_id'], input_data['verify']['url']) # SET_VALIDATION_SUBJECT
def test_fetch_task_handles_potential_baked_input(self): set_up_context_mock() assertion_url = 'http://example.org/assertion/1' image_url = 'http://example.org/image' with open( os.path.join(os.path.dirname(__file__), 'testfiles', 'public_domain_heart.png'), 'rb') as f: baked_file = bake(f, assertion_url) responses.add(responses.GET, image_url, body=baked_file.read(), status=200, content_type='image/png') task = add_task(FETCH_HTTP_NODE, url=image_url, is_potential_baked_input=True) result, message, actions = run_task({}, task) self.assertTrue(result) store_resource_action = [ a for a in actions if a.get('type') == STORE_ORIGINAL_RESOURCE ][0] process_baked_input_action = [ a for a in actions if a.get('name') == PROCESS_BAKED_RESOURCE ][0] self.assertEqual(store_resource_action.get('node_id'), image_url) self.assertEqual(process_baked_input_action.get('node_id'), image_url) task = add_task(FETCH_HTTP_NODE, url=image_url, is_potential_baked_input=False) result, message, actions = run_task({}, task) self.assertTrue(result)
def test_validate_related_language(self): assertion = { 'type': 'Assertion', 'id': 'http://example.com/assertion', 'verification': { 'type': 'HostedBadge' }, 'badge': 'http://example.com/badgeclass' } badgeclass = { 'id': 'http://example.com/badgeclass', 'type': 'BadgeClass', '@language': 'es', 'issuer': 'http://example.com/issuer', 'related': { 'id': 'http://example.com/other_badgeclass', '@language': 'en-US' }, 'name': 'Insignia Pronto' } state = {'graph': [assertion, badgeclass]} task_meta = add_task(DETECT_AND_VALIDATE_NODE_CLASS, node_id=badgeclass['id']) result, message, actions = run_task(state, task_meta) self.assertTrue(result) language_task = [ t for t in actions if t.get('prop_name') == '@language' ][0] r, _, __ = run_task(state, language_task) self.assertTrue(r, "The BadgeClass's language property is valid.") related_task = [t for t in actions if t.get('prop_name') == 'related'][0] result, message, actions = run_task(state, related_task) self.assertTrue( result, "The related property is valid and queues up task discovery for embedded node" ) result, message, actions = run_task(state, actions[0]) self.assertTrue( result, "Some tasks are discovered to validate the related node.") self.assertEqual(len(actions), 2, "There are only tasks for 'id' and '@language'.") for a in actions: r, _, __ = run_task(state, a) self.assertTrue(r, "Related node property validation is successful.")
def test_can_verify_jws(self): task_meta = add_task(VERIFY_JWS, data=self.signed_assertion, node_id=self.assertion_data['id']) success, message, actions = verify_jws_signature(self.state, task_meta) print("TEST CAN VERIFY JWS : success:") print(success) print("TEST CAN VERIFY JWS : message:") print(message) print("TEST CAN VERIFY JWS : actions:") print(actions) self.assertTrue(success) self.assertEqual(len(actions), 2) # Construct an invalid signature by adding to payload after signing, one theoretical attack. header = {'alg': 'RS256'} signature = jws.sign(header, self.assertion_data, self.private_key) self.assertion_data['evidence'] = 'http://hahafakeinserteddata.com' encoded_separator = '.' if sys.version[:3] < '3': encoded_header = b64encode(json.dumps(header)) encoded_payload = b64encode(json.dumps(self.assertion_data)) else: encoded_separator = '.'.encode() encoded_header = b64encode(json.dumps(header).encode()) encoded_payload = b64encode(json.dumps(self.assertion_data).encode()) self.signed_assertion = encoded_separator.join((encoded_header, encoded_payload, signature)) task_meta = add_task(VERIFY_JWS, data=self.signed_assertion, node_id=self.assertion_data['id']) success, message, actions = verify_jws_signature(self.state, task_meta) self.assertFalse(success) self.assertEqual(len(actions), 2)
def test_basic_http_fetch_task(self): url = 'http://example.com/assertionmaybe' responses.add(responses.GET, url, body=test_components['2_0_basic_assertion'], status=200, content_type='application/ld+json') task = add_task(FETCH_HTTP_NODE, url=url) success, message, actions = fetch_http_node({}, task) self.assertTrue(success) self.assertEqual(len(actions), 2) self.assertEqual(actions[0]['type'], STORE_ORIGINAL_RESOURCE) self.assertEqual(actions[1]['name'], INTAKE_JSON)
def test_input_type_detection(self): state = INITIAL_STATE.copy() url = 'http://example.org/assertion/1' state['input'] = {'value': url} task_meta = add_task(DETECT_INPUT_TYPE) result, message, actions = detect_input_type(state, task_meta) fetch_action = [ a for a in actions if a.get('name') == FETCH_HTTP_NODE ][0] set_action = [ a for a in actions if a.get('type') == SET_VALIDATION_SUBJECT ][0] self.assertTrue(fetch_action.get('is_potential_baked_input')) self.assertEqual(set_action.get('node_id'), url) task_meta = add_task(DETECT_INPUT_TYPE, is_potential_baked_input=False) result, message, actions = detect_input_type(state, task_meta) self.assertTrue(result) fetch_action = [ a for a in actions if a.get('name') == FETCH_HTTP_NODE ][0] self.assertFalse(fetch_action.get('is_potential_baked_input'))
def test_node_has_id_different_from_fetch_url(self): set_up_context_mock() first_url = 'http://example.org/url1' second_url = 'http://example.org/url2' node_data = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': first_url, 'name': 'Some Badge' } responses.add(responses.GET, first_url, json=node_data) responses.add(responses.GET, second_url, json=node_data) task = add_task(FETCH_HTTP_NODE, url=second_url) state = {'graph': []} result, message, actions = run_task(state, task) self.assertTrue(result) self.assertEqual(len(actions), 2) self.assertEqual(actions[1]['name'], INTAKE_JSON) result, message, actions = run_task(state, actions[1]) # INTAKE_JSON self.assertTrue(result) self.assertEqual(len(actions), 2) self.assertEqual(actions[1]['name'], JSONLD_COMPACT_DATA) result, message, actions = run_task(state, actions[1]) # JSONLD_COMPACT_DATA self.assertTrue(result) self.assertEqual(len(actions), 3) self.assertEqual(actions[2]['name'], FETCH_HTTP_NODE) self.assertEqual(actions[2]['url'], first_url) self.assertEqual(actions[0]['messageLevel'], MESSAGE_LEVEL_WARNING) # Pass 2: re-run FETCH_HTTP_NODE result, message, actions = run_task(state, actions[2]) self.assertTrue(result) result, message, actions = run_task(state, actions[1]) # INTAKE_JSON self.assertTrue(result) result, message, actions = run_task(state, actions[1]) # JSONLD_COMPACT_DATA self.assertTrue(result) self.assertEqual(len(actions), 2) self.assertEqual(actions[0]['type'], ADD_NODE) self.assertEqual(actions[1]['name'], DETECT_AND_VALIDATE_NODE_CLASS)
def test_report_message_on_unknown_extension(self): first_node = { 'id': 'http://example.org/assertion', 'extensions:exampleExtension': '_:b0', 'evidence': '_:b1' } extension = { 'id': '_:b0', 'type': ['Extension', 'extensions:UnknownExtension'], 'schema:unknownProperty': 'I\'m a property, short and sweet' } state = {'graph': [first_node, extension]} task_meta = add_task(VALIDATE_EXTENSION_NODE, node_id=extension['id']) result, message, actions = validate_extension_node(state, task_meta) self.assertFalse(result, "An unknown extension will fail for now.")
def validate_language_prop_basic(self): badgeclass = { 'id': 'http://example.org/badgeclass', '@language': 'en-US' } state = {'graph': [badgeclass]} task = add_task(VALIDATE_EXPECTED_NODE_CLASS, node_id=badgeclass['id'], expected_class=OBClasses.BadgeClass) result, message, actions = run_task(state, task) self.assertTrue(result) l_actions = [a for a in actions if a.get('prop_name') == '@language'] self.assertEqual(len(l_actions), 1) result, message, actions = run_task(state, l_actions[0]) self.assertTrue(result)
def test_svg_fetch_with_complex_mimetype(self): url = 'http://example.com/circle' svg_circle = u'<svg height="100" width="100"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" ' \ u'fill="red" /></svg>' responses.add(responses.GET, url, body=svg_circle, status=200, content_type='image/svg+xml; charset=utf-8') task = add_task(FETCH_HTTP_NODE, url=url) success, message, actions = fetch_http_node({}, task) self.assertTrue(success) self.assertEqual(len(actions), 1) self.assertEqual(actions[0]['type'], STORE_ORIGINAL_RESOURCE)
def test_can_detect_and_upgrade_v_0_5(self): assertion_data = self.assertion_data state = INITIAL_STATE task = add_task(INTAKE_JSON, data=json.dumps(assertion_data), node_id='http://example.org/assertion') result, message, actions = run_task(state, task) self.assertTrue(result) version_action = [a for a in actions if a.get('type') == SET_OPENBADGES_VERSION][0] self.assertEqual(version_action['version'], '0.5') upgrade_action = [a for a in actions if a.get('name') == UPGRADE_0_5_NODE][0] result, message, actions = run_task(state, upgrade_action) self.assertTrue(result) self.assertEqual(len(actions), 2) self.assertEqual(actions[0]['name'], JSONLD_COMPACT_DATA)
def test_node_json_validation(self): node = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': 'http://example.com/1', 'type': 'Assertion', 'schema:location': { '@context': 'https://w3id.org/openbadges/extensions/geoCoordinatesExtension/context.json', 'type': ['Extension', 'extensions:GeoCoordinates'], 'description': 'That place in the woods where we built the fort', 'schema:geo': { 'schema:latitude': 44.580900, 'schema:longitude': -123.301815 } } } loader = CachableDocumentLoader(use_cache=True) loader.session.cache.remove_old_entries(datetime.datetime.utcnow()) loader.contexts = set() options = {'jsonld_options': {'documentLoader': loader}} set_up_context_mock() loader(OPENBADGES_CONTEXT_V2_URI) schema_url = list(GeoLocation.validation_schema)[0] responses.add(responses.GET, GeoLocation.context_url, status=200, json=GeoLocation.context_json) loader(GeoLocation.context_url) responses.add(responses.GET, schema_url, status=200, json=GeoLocation.validation_schema[schema_url]) loader.session.get(schema_url) state = INITIAL_STATE task = add_task( INTAKE_JSON, data=json.dumps(node), node_id=node['id']) result, message, actions = task_named(INTAKE_JSON)(state, task, **options) state = main_reducer(state, actions[0]) result, message, actions = task_named(actions[1]['name'])( state, actions[1], **options) # JSONLD_COMPACT_DATE state = main_reducer(state, actions[0]) # ADD_NODE task_meta = actions[1] # VALIDATE_EXTENSION_NODE result, message, actions = validate_extension_node(state, task_meta) self.assertTrue(result, "A valid expression of the extension should pass") self.assertIn('validated on node', message) self.assertEqual(len(actions), 0) del state['graph'][0]['schema:location']['schema:geo']['schema:latitude'] result, message, actions = validate_extension_node(state, task_meta) self.assertFalse(result, "A required property not present should be detected by JSON-schema.")
def test_upgrade_1_1_issuer(self): setUpContextCache() data = json.loads(test_components['1_1_basic_issuer']) data['type'] = 'IssuerOrg' # Test alias that was accepted in v1.1 context json_data = json.dumps(data) state = INITIAL_STATE task = add_task(INTAKE_JSON, node_id='https://example.org/organization.json', data=json_data) result, message, actions = task_named(INTAKE_JSON)(state, task) for action in actions: state = main_reducer(state, action) for task in state.get('tasks'): result, message, actions = task_named(task['name'])(state, task) for action in actions: state = main_reducer(state, action) self.assertTrue(result) self.assertEqual(state['graph'][0]['type'], OBClasses.Issuer)
def test_upgrade_1_1_assertion(self): setUpContextCache() json_data = test_components['1_1_basic_assertion'] state = INITIAL_STATE task = add_task( INTAKE_JSON, node_id='https://example.org/beths-robotics-badge.json', data=json_data) result, message, actions = task_named(INTAKE_JSON)(state, task) for action in actions: state = main_reducer(state, action) for task in state.get('tasks'): result, message, actions = task_named(task['name'])(state, task) for action in actions: state = main_reducer(state, action) result, message, actions = task_named(UPGRADE_1_1_NODE)(state, task) self.assertTrue(result) self.assertEqual(len(actions), 0) # Test timestamp upgrading state['graph'][0]['issuedOn'] = 1500423730 result, message, actions = task_named(UPGRADE_1_1_NODE)(state, task) self.assertTrue(result) self.assertEqual(len(actions), 1) self.assertEqual(actions[0]['data']['issuedOn'], '2017-07-19T00:22:10+00:00') self.assertEqual(len(actions[0]['data'].keys()), 1, "There is a patch made of one prop") state['graph'][0]['issuedOn'] = '1500423730.5' result, message, actions = task_named(UPGRADE_1_1_NODE)(state, task) self.assertTrue(result) self.assertEqual(len(actions), 1) state = main_reducer(state, actions[0]) state['graph'][0]['issuedOn'] = '2016-05-15' result, message, actions = task_named(UPGRADE_1_1_NODE)(state, task) self.assertTrue(result) self.assertEqual(len(actions), 1) state = main_reducer(state, actions[0])
def test_profile_with_multiple_emails(self): recipient_profile = {'id': '_:b0', 'email': ['*****@*****.**', '*****@*****.**']} assertion = { 'id': 'http://example.org', 'type': 'Assertion', 'recipient': '_:b1' } identity_object = { 'id': '_:b1', 'type': 'email', 'hashed': False, 'identity': '*****@*****.**' } state = {'graph': [recipient_profile, assertion, identity_object]} task_meta = add_task(VERIFY_RECIPIENT_IDENTIFIER, node_id='_:b0') result, message, actions = verify_recipient_against_trusted_profile(state, task_meta) self.assertTrue(result) self.assertIn('*****@*****.**', message)
def test_claim_property_validation(self): self.set_up_resources() state = {'graph': [self.endorsement]} task_meta = add_task(VALIDATE_EXPECTED_NODE_CLASS, node_id=self.endorsement['id'], prop_name='claim', expected_class=OBClasses.Endorsement) result, message, actions = run_task(state, task_meta) self.assertTrue(result) claim_action = [a for a in actions if a.get('prop_name') == 'claim'][0] result, message, actions = run_task(state, claim_action) self.assertTrue(result) self.assertEqual(len(actions), 1) result, message, actions = run_task(state, actions[0]) self.assertTrue(result) self.assertEqual(len(actions), 3)
def test_can_print_exception(self): state = INITIAL_STATE.copy() # Create a state that will trigger an exception state['graph'] = [AttributeError("Haha this isn't a dict!")] task = add_task(VALIDATE_PROPERTY, node_id='http://example.org/1', prop_name='turnips', prop_type=ValueTypes.TEXT) store = create_store(main_reducer, state) store.dispatch(task) call_task(task_named(VALIDATE_PROPERTY), store.get_state()['tasks'][0], store) state = store.get_state() self.assertEqual(len(state['tasks']), 1, 'There is one task in state.') task = state['tasks'][0] self.assertFalse(task['success']) self.assertIn('AttributeError:', task['result'], "assert an AttributeError is formatted as the message.")
def test_profile_with_salted_hashed_email(self): recipient_profile = {'id': '_:b0', 'email': '*****@*****.**'} assertion = { 'id': 'http://example.org', 'type': 'Assertion', 'recipient': '_:b1' } identity_object = { 'id': '_:b1', 'type': 'email', 'hashed': True, 'salt': 'Maldon', 'identity': 'sha256$' + hashlib.sha256(recipient_profile['email'].encode('utf8') + 'Maldon'.encode('utf8')).hexdigest() } state = {'graph': [recipient_profile, assertion, identity_object]} task_meta = add_task(VERIFY_RECIPIENT_IDENTIFIER, node_id='_:b0') result, message, actions = verify_recipient_against_trusted_profile(state, task_meta) self.assertTrue(result) self.assertIn('*****@*****.**', message)
def test_reduce_compacted_output(self): self.setUpContextCache() data = { "@context": { "thing_we_call_you_by": "http://schema.org/name" }, "thing_we_call_you_by": "Test Data" } task = add_task(JSONLD_COMPACT_DATA, data=json.dumps(data), node_id='_:b100') result, message, actions = jsonld_compact_data({}, task) state = graph_reducer([], actions[0]) self.assertEqual(len(state), 1, "Node should be added to graph") self.assertEqual(state[0]['name'], data['thing_we_call_you_by']) self.assertEqual(state[0].get('id'), '_:b100', "Node should have a blank id assigned")
def test_upgrade_1_0_assertion(self): json_data = test_components['1_0_basic_assertion'] state = INITIAL_STATE task = add_task(INTAKE_JSON, node_id='http://a.com/instance', data=json_data) result, message, actions = task_named(INTAKE_JSON)(state, task) for action in actions: state = main_reducer(state, action) task = state.get('tasks')[0] result, message, actions = task_named(task['name'])(state, task) self.assertTrue(result) self.assertEqual(len(actions), 2) for action in actions: state = main_reducer(state, action) self.assertEqual(len(state.get('tasks')), 3) modified_data = json.loads(state.get('tasks')[1]['data']) self.assertEqual(modified_data['@context'], OPENBADGES_CONTEXT_V1_URI) self.assertEqual(modified_data['id'], modified_data['verify']['url']) self.assertEqual(modified_data['type'], OBClasses.Assertion)
def test_can_detect_and_upgrade_v_0_5(self): assertion_data = { "recipient": "sha256$a4a934a0bfc882a34a3e71650e40789453b2db9799a51a2d084a64caadd72397", "salt": "2e2bad0df9e11272ffbcee86e4c7edd4", "issued_on": "2017-01-01", "badge": { "name": "Test Badge for [email protected]", "image": "http://example.org/image", "description": "Awarded using the php example codebase", "criteria": "http://example.org/criteria", "issuer": { "origin": "example.org", "name": "Test Issuer", "org": None, "contact": None } } } state = INITIAL_STATE task = add_task(INTAKE_JSON, data=json.dumps(assertion_data), node_id='http://example.org/assertion') result, message, actions = run_task(state, task) self.assertTrue(result) version_action = [ a for a in actions if a.get('type') == SET_OPENBADGES_VERSION ][0] self.assertEqual(version_action['version'], '0.5') upgrade_action = [ a for a in actions if a.get('name') == UPGRADE_0_5_NODE ][0] result, message, actions = run_task(state, upgrade_action) self.assertTrue(result) self.assertEqual(len(actions), 2) self.assertEqual(actions[0]['name'], JSONLD_COMPACT_DATA)
def test_upgrade_1_1_badgeclass(self): setUpContextCache() json_data = test_components['1_1_basic_badgeclass'] state = INITIAL_STATE task = add_task(INTAKE_JSON, node_id='https://example.org/robotics-badge.json', data=json_data) result, message, actions = task_named(INTAKE_JSON)(state, task) for action in actions: state = main_reducer(state, action) for task in state.get('tasks'): result, message, actions = task_named(task['name'])(state, task) for action in actions: state = main_reducer(state, action) # Test criteria class upgrade state['graph'][0]['alignment'] = { 'url': 'http://somewhere.overtherainbow.net/wayuphigh', 'name': "Knowledge of children's songs" } result, message, actions = task_named(UPGRADE_1_1_NODE)(state, task) self.assertTrue(result) self.assertEqual(len(actions), 1)
def test_queue_validation_on_unknown_extension(self): set_up_context_mock() self.set_up_test_extension() first_node_json = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': 'http://example.org/assertion', 'extensions:exampleExtension': { '@context': self.extension_context_url, 'type': ['Extension', 'extensions:UnknownExtension'], 'unknownProperty': 'I\'m a property, short and sweet' }, 'evidence': 'http://example.org/evidence' } state = INITIAL_STATE task_meta = add_task(INTAKE_JSON, data=json.dumps(first_node_json), node_id=first_node_json['id']) result, message, actions = task_named(INTAKE_JSON)(state, task_meta) for action in actions: state = main_reducer(state, action) # Compact JSON result, message, actions = task_named(state['tasks'][0]['name'])( state, state['tasks'][0]) self.assertEqual(len(actions), 3) state = main_reducer(state, actions[0]) validation_action = actions[1] result, message, actions = validate_extension_node( state, validation_action) self.assertTrue(result)
def load_mocks(self): loader = CachableDocumentLoader(use_cache=True) loader.session.cache.remove_old_entries(datetime.datetime.utcnow()) loader.contexts = set() self.options = {'jsonld_options': {'documentLoader': loader}} set_up_context_mock() loader(OPENBADGES_CONTEXT_V2_URI) schema_url = list(ExampleExtension.validation_schema)[0] responses.add(responses.GET, ExampleExtension.context_url, status=200, json=ExampleExtension.context_json) loader(ExampleExtension.context_url) responses.add(responses.GET, schema_url, status=200, json=ExampleExtension.validation_schema[schema_url]) loader.session.get(schema_url) self.state = INITIAL_STATE task = add_task( INTAKE_JSON, data=json.dumps(self.first_node), node_id=self.first_node['id']) result, message, actions = task_named(INTAKE_JSON)(self.state, task, **self.options) self.state = main_reducer(self.state, actions[0]) result, message, actions = task_named(actions[1]['name'])( self.state, actions[1], **self.options) # JSONLD_COMPACT_DATE self.state = main_reducer(self.state, actions[0]) # ADD_NODE self.validation_task = actions[1] # VALIDATE_EXTENSION_NODE
def test_compact_node(self): self.setUpContextCache() data = """{ "@context": {"thing_we_call_you_by": "http://schema.org/name"}, "thing_we_call_you_by": "Test Data" }""" task = add_task(JSONLD_COMPACT_DATA, data=data, node_id='http://example.com/1') result, message, actions = jsonld_compact_data({}, task) self.assertTrue(result, "JSON-LD Compaction should be successful.") self.assertEqual(message, "Successfully compacted node http://example.com/1") self.assertEqual( len(actions), 2, "Should queue up add_node and add_task for type detection") self.assertEqual( actions[0]['data']['name'], "Test Data", "Node should be compacted into OB Context and use OB property names." )
def test_unknown_identity_type(self): recipient_profile = {'id': '_:b0', 'schema:duns': '999999999'} assertion = { 'id': 'http://example.org', 'type': 'Assertion', 'recipient': '_:b1' } identity_object = { 'id': '_:b1', 'type': 'schema:duns', 'hashed': True, 'salt': 'HimalayanPink', 'identity': 'sha256$' + hashlib.sha256( recipient_profile['schema:duns'].encode('utf8') + 'HimalayanPink'.encode('utf8')).hexdigest() } state = {'graph': [recipient_profile, assertion, identity_object]} task_meta = add_task(VERIFY_RECIPIENT_IDENTIFIER, node_id='_:b0') result, message, actions = verify_recipient_against_trusted_profile(state, task_meta) self.assertTrue(result) self.assertIn(recipient_profile['schema:duns'], message) self.assertEqual(len(actions), 2) self.assertIn('schema:duns', actions[0]['message'], "Non-standard identifier reported")
def test_queue_validation_on_unknown_extension(self): set_up_context_mock() extension_schema = { "$schema": "http://json-schema.org/draft-04/schema#", "title": "1.1 Open Badge Example Extension for testing: Unknown Extension", "description": "An extension that allows you to add a single string unknownProperty to an extension object for unknown reasons.", "type": "object", "properties": { "unknownProperty": { "type": "string" } }, "required": ["unknownProperty"] } extension_schema_url = 'http://example.org/unkownSchema' extension_context = { '@context': { "obi": "https://w3id.org/openbadges#", "extensions": "https://w3id.org/openbadges/extensions#", 'unknownProperty': 'http://schema.org/unknownProperty' }, "obi:validation": [ { "obi:validatesType": "extensions:UnknownExtension", "obi:validationSchema": extension_schema_url } ] } extension_context_url = 'http://example.org/unknownExtensionContext' first_node_json = { '@context': OPENBADGES_CONTEXT_V2_URI, 'id': 'http://example.org/assertion', 'extensions:exampleExtension': { '@context': extension_context_url, 'type': ['Extension', 'extensions:UnknownExtension'], 'unknownProperty': 'I\'m a property, short and sweet' }, 'evidence': 'http://example.org/evidence' } responses.add( responses.GET, extension_context_url, json=extension_context ) responses.add( responses.GET, extension_schema_url, json=extension_schema ) state = INITIAL_STATE task_meta = add_task( INTAKE_JSON, data=json.dumps(first_node_json), node_id=first_node_json['id']) result, message, actions = task_named(INTAKE_JSON)(state, task_meta) for action in actions: state = main_reducer(state, action) # Compact JSON result, message, actions = task_named(state['tasks'][0]['name'])(state, state['tasks'][0]) self.assertEqual(len(actions), 3) state = main_reducer(state, actions[0]) validation_action = actions[1] result, message, actions = validate_extension_node(state, validation_action) self.assertTrue(result)