Example #1
0
    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_can_detect_v1_based_on_context(self):
        json_data = test_components['1_1_basic_assertion']
        state = INITIAL_STATE

        task = add_task(INTAKE_JSON, data=json_data)
        result, message, actions = task_named(task['name'])(state, task)
        self.assertTrue(result)
        self.assertEqual(actions[2]['name'], UPGRADE_1_1_NODE)

        json_data = test_components['1_1_basic_badgeclass']
        task['data'] = json_data
        result, message, actions = task_named(task['name'])(state, task)
        self.assertTrue(result)
        self.assertEqual(actions[2]['name'], UPGRADE_1_1_NODE)

        json_data = test_components['1_1_basic_issuer']
        task['data'] = json_data
        result, message, actions = task_named(task['name'])(state, task)
        self.assertTrue(result)
        self.assertEqual(actions[2]['name'], UPGRADE_1_1_NODE)

        json_data = test_components['1_0_basic_issuer']
        task['data'] = json_data
        result, message, actions = task_named(task['name'])(state, task)
        self.assertTrue(result)
        self.assertEqual(actions[1]['name'], UPGRADE_1_0_NODE)
Example #3
0
    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_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 test_upgrade_1_1_badgeclass_with_multiple_alignments(self):
        setUpContextCache()
        data = json.loads(test_components['1_1_basic_badgeclass'])
        data['alignment'] = [{
            'name': 'Target 1 Name',
            'description': 'Target 1 Description',
            'url': 'http://example.org/target-1'
        }, {
            'name': 'Target 2 Name',
            'url': 'http://example.org/target-2'
        }]
        state = INITIAL_STATE
        task = add_task(INTAKE_JSON,
                        node_id='https://example.org/robotics-badge.json',
                        data=json.dumps(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 alignment object upgrades
        self.assertEqual(len(state['graph'][0]['alignment']), 2)
        self.assertEqual(state['graph'][0]['alignment'][0]['targetUrl'],
                         data['alignment'][0]['url'])
Example #6
0
    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.")
Example #7
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)
Example #8
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)
Example #9
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)
Example #10
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.")
    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_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)
    def test_validate_badgeclass_image_formats(self):
        session = CachedSession(backend='memory', expire_after=100000)
        loader = CachableDocumentLoader(use_cache=True, session=session)
        options = {
            'jsonld_options': {'documentLoader': loader}
        }
        image_url = 'http://example.org/awesomebadge.png'
        badgeclass = {
            'id': 'http://example.org/badgeclass',
            'name': 'Awesome badge',
            'image': image_url
        }
        state = {'graph': [badgeclass]}

        with open(os.path.join(os.path.dirname(__file__), 'testfiles', 'public_domain_heart.png'), 'rb') as f:
            responses.add(responses.GET, badgeclass['image'], body=f.read(), content_type='image/png')
        response = session.get(badgeclass['image'])
        self.assertEqual(response.status_code, 200)

        task_meta = add_task(
            VALIDATE_EXPECTED_NODE_CLASS, node_id=badgeclass['id'], expected_class=OBClasses.BadgeClass)

        result, message, actions = task_named(VALIDATE_EXPECTED_NODE_CLASS)(state, task_meta, **options)
        self.assertTrue(result)

        image_task = [a for a in actions if a.get('prop_name') == 'image'][0]
        class_image_validation_task = [a for a in actions if a.get('name') == IMAGE_VALIDATION][0]
        result, message, actions = task_named(image_task['name'])(state, image_task, **options)
        self.assertTrue(result)
        self.assertEqual(len(actions), 0)

        result, message, actions = task_named(class_image_validation_task['name'])(
            state, class_image_validation_task, **options)
        self.assertTrue(result)
        self.assertEqual(len(actions), 1)
        # self.assertEqual(actions[0]['name'], STORE_ORIGINAL_RESOURCE)

        # Case 2: Embedded image document
        badgeclass['image'] = {
            'id': 'http://example.org/awesomebadge.png',
            'author': 'http://someoneelse.org/1',
            'caption': 'A hexagon with attitude'
        }

        # Validate BadgeClass, queuing the image node validation task
        result, message, actions = task_named(image_task['name'])(state, image_task, **options)
        self.assertTrue(result)
        self.assertEqual(len(actions), 1, "Image node validation task queued")

        # Run image node task discovery
        next_task = actions[0]
        result, message, actions = task_named(next_task['name'])(state, next_task, **options)
        self.assertTrue(result)

        # Run validation task for the Image node
        next_task = [a for a in actions if a.get('name') == IMAGE_VALIDATION][0]
        result, message, actions = task_named(next_task['name'])(state, next_task, **options)
        self.assertTrue(result)

        # Store image data
        next_task = actions[0]
        self.assertEqual(next_task['type'], STORE_ORIGINAL_RESOURCE)
        new_state = input_reducer({}, next_task)
        self.assertTrue(new_state['original_json'][image_url].startswith('data:'), "Data is stored in the expected spot.")