예제 #1
0
    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])
예제 #2
0
    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.")
예제 #4
0
    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
예제 #5
0
    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)
예제 #6
0
    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.")
예제 #7
0
    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)
예제 #8
0
    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)
예제 #9
0
    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'))
예제 #10
0
    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)
예제 #11
0
    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.")
예제 #12
0
    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)
예제 #13
0
    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)
예제 #14
0
    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.")
예제 #16
0
    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])
예제 #18
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)
예제 #19
0
    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)
예제 #20
0
    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.")
예제 #21
0
    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)
예제 #22
0
    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")
예제 #23
0
    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)
예제 #25
0
    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)
예제 #26
0
    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
예제 #28
0
    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."
        )
예제 #29
0
    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)