def setUp(self):
        # Start container
        self._start_container()
        self.container.start_rel_from_url('res/deploy/r2coi.yml')

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient(node=self.container.node)

        log.debug('stopping Gateway web server')
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(app)
    def setUp(self):

        DMTestCase.setUp(self)

        # clients needed (NOTE:most inherited from DMTestCase)
        self.object_store = self.container.object_store
        self.service_gateway_service = ServiceGatewayServiceClient(
            node=self.container.node)
        self.parameter_helper = self.ph  # rename so know exactly what it is below

        # create a TestApp instance against the ServiceGatewayService
        self.testapp = TestApp(service_gateway_app)
    def setUp(self):
        # Start container
        self._start_container()
        self.container.start_rel_from_url("res/deploy/r2deploy.yml")

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient()

        log.debug("stopping Gateway web server")
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(service_gateway_app)
    def setUp(self):
        # Start container
        self._start_container()

        # Establish endpoint with container
        container_client = ContainerAgentClient(node=self.container.node, name=self.container.name)
        container_client.start_rel_from_url('res/deploy/r2coi.yml')

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient(node=self.container.node)

        log.debug('stopping Gateway web server')
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(app)
class TestServiceGatewayServiceInt(IonIntegrationTestCase):
    def setUp(self):
        # Start container
        self._start_container()
        self.container.start_rel_from_url("res/deploy/r2deploy.yml")

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient()

        log.debug("stopping Gateway web server")
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(service_gateway_app)

    def tearDown(self):
        self._stop_container()

    # Common SGS Response header check
    def check_response_headers(self, response):
        self.assertEqual(response.content_type, "application/json")
        self.assertEqual(len(response.json), 1)
        self.assertIn("data", response.json)

    def test_list_resource_types(self):
        response = self.test_app.get("/ion-service/list_resource_types")

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        expected_type_list = getextends("Resource")

        self.assertEqual(len(response.json["data"][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json["data"][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get("/ion-service/list_resource_types?type=InformationResource")

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        expected_type_list = getextends("InformationResource")

        self.assertEqual(len(response.json["data"][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json["data"][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get("/ion-service/list_resource_types?type=TaskableResource")

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        expected_type_list = getextends("TaskableResource")

        self.assertEqual(len(response.json["data"][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json["data"][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get("/ion-service/list_resource_types?type=MyFakeResource")

        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json["data"])
        self.assertIn("KeyError", response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_EXCEPTION])
        self.assertIn("MyFakeResource", response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def create_data_product_resource(self):
        geospatial_bounds = {
            "geospatial_latitude_limit_north": 1.0,
            "geospatial_latitude_limit_south": 1.0,
            "geospatial_longitude_limit_east": 1.0,
            "geospatial_longitude_limit_west": 1.0,
            "geospatial_vertical_min": 1.0,
            "geospatial_vertical_max": 1.0,
        }
        data_product_create_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "create",
                "params": {
                    "object": {
                        "type_": "DataProduct",
                        "lcstate": "DRAFT",
                        "description": DATA_PRODUCT_DESCRIPTION,
                        "name": DATA_PRODUCT_NAME,
                        "geospatial_bounds": geospatial_bounds,
                    }
                },
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/create", {"payload": simplejson.dumps(data_product_create_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        data_product_id = convert_unicode(response_data[0])
        return data_product_id

    def create_data_product_resource_full(self):
        geospatial_bounds = {
            "geospatial_latitude_limit_north": 1.0,
            "geospatial_latitude_limit_south": 1.0,
            "geospatial_longitude_limit_east": 1.0,
            "geospatial_longitude_limit_west": 1.0,
            "geospatial_vertical_min": 1.0,
            "geospatial_vertical_max": 1.0,
        }

        # create a paramter dictionary the a stream definition for this data product
        DICTIONARY_NAME = "ctd_parsed_param_dict"
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name="
            + convert_unicode(DICTIONARY_NAME)
            + "&id_only=True&user_id=123abc456"
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        param_dictionary_id = convert_unicode(response_data[0])
        test = str(param_dictionary_id[0])
        log.debug("create_data_product_resource_full  param_dictionary_id:  %s", param_dictionary_id)
        log.debug("create_data_product_resource_full  test:  %s", test)

        response = self.test_app.get(
            "/ion-service/pubsub_management/create_stream_definition?name=CTDData&parameter_dictionary_id="
            + convert_unicode(param_dictionary_id[0])
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        log.debug("create_data_product_resource_full   response_data:  %s", response_data)
        stream_definition_id = convert_unicode(response_data)
        log.debug("create_data_product_resource_full  stream_definition_id:  %s", stream_definition_id)

        data_product_create_request = {
            "serviceRequest": {
                "serviceName": "data_product_management",
                "serviceOp": "create_data_product",
                "params": {
                    "data_product": {
                        "type_": "DataProduct",
                        "lcstate": "DRAFT",
                        "description": DATA_PRODUCT_DESCRIPTION,
                        "name": DATA_PRODUCT_NAME,
                        "geospatial_bounds": geospatial_bounds,
                    },
                    "stream_definition_id": stream_definition_id,
                },
            }
        }

        response = self.test_app.post(
            "/ion-service/data_product_management/create_data_product",
            {"payload": simplejson.dumps(data_product_create_request)},
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        log.debug("create_data_product_resource_full  create_data_product response_data:  %s", response_data)
        # self.assertEqual(len(response_data), 2 )
        data_product_id = convert_unicode(response_data)
        return data_product_id

    def delete_data_product_resource(self, data_product_id):
        data_product_delete_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "delete",
                "params": {"object_id": data_product_id},
            }
        }
        response = self.test_app.post(
            "/ion-service/resource_registry/delete", {"payload": simplejson.dumps(data_product_delete_request)}
        )
        self.check_response_headers(response)
        return response

    def create_policy_resource(self):
        policy_create_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "create",
                "params": {
                    "object": {
                        "definition": {},
                        "name": POLICY_NAME,
                        "description": POLICY_DESCRIPTION,
                        "lcstate": "DRAFT",
                        "required": True,
                        "enabled": True,
                        "type_": "Policy",
                        "policy_type": {
                            "policy_rule": POLICY_RULE,
                            "service_name": "user_notification",
                            "type_": "ServiceAccessPolicy",
                        },
                    }
                },
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/create", {"payload": simplejson.dumps(policy_create_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        policy_id = convert_unicode(response_data[0])
        return policy_id

    @attr("SMOKE")
    def test_anonymous_resource_registry_operations_through_gateway(self):
        """
        This test ensures that requests make through the service gateway through messaging to the Resource Registry and
        back; including the support of unicode characters.
        """
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name="
            + convert_unicode(DATA_PRODUCT_NAME)
            + "&id_only=True&user_id=123abc456"
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        data_product_id = self.create_data_product_resource()

        data_product_read_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "read",
                "params": {"object_id": data_product_id},
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/read", {"payload": simplejson.dumps(data_product_read_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        data_product_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])

        # Verify the the name and description fields containing unicode characters match all the way through couch and the messaging
        self.assertEqual(data_product_obj["name"], convert_unicode(DATA_PRODUCT_NAME))
        self.assertEqual(data_product_obj["description"], convert_unicode(DATA_PRODUCT_DESCRIPTION))

        updated_description_text = data_product_obj["description"] + "---Updated!!"

        # modify some fields in the data for testing update
        data_product_obj["description"] = updated_description_text

        data_product_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {"object": data_product_obj},
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/update", {"payload": simplejson.dumps(data_product_update_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        response = self.test_app.post(
            "/ion-service/resource_registry/read", {"payload": simplejson.dumps(data_product_read_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        updated_data_product_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])
        self.assertEqual(updated_data_product_obj["description"], updated_description_text)

        differ = DictDiffer(updated_data_product_obj, data_product_obj)
        self.assertEqual(
            len(differ.changed()), 2
        )  # Only the _rev and ts_updated fields should be different after an update

        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=" + convert_unicode(DATA_PRODUCT_NAME) + "&id_only=True"
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 1)

        response = self.delete_data_product_resource(data_product_id)
        self.assertIsNone(response.json["data"][GATEWAY_RESPONSE])

        response = self.test_app.post(
            "/ion-service/resource_registry/read", {"payload": simplejson.dumps(data_product_read_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json["data"])
        self.assertIn("does not exist", response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])

        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=" + convert_unicode(DATA_PRODUCT_NAME) + "&id_only=True"
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        response = self.delete_data_product_resource(data_product_id)
        self.assertIn(GATEWAY_ERROR, response.json["data"])
        self.assertIn("does not exist", response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

        # Now try creating a policy object which has an internal object of a different type
        policy_id = self.create_policy_resource()

        policy_read_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "read",
                "params": {"object_id": policy_id},
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/read", {"payload": simplejson.dumps(policy_read_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        policy_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])

        # Verify the the name and description fields containing unicode characters match all the way through couch and the messaging
        self.assertEqual(policy_obj["name"], convert_unicode(POLICY_NAME))
        self.assertEqual(policy_obj["description"], convert_unicode(POLICY_DESCRIPTION))
        self.assertEqual(policy_obj["policy_type"]["policy_rule"], convert_unicode(POLICY_RULE))

        updated_policy_rule = policy_obj["policy_type"]["policy_rule"] + "---Updated!!"

        # modify some fields in the data for testing update
        policy_obj["policy_type"]["policy_rule"] = updated_policy_rule

        policy_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {"object": policy_obj},
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/update", {"payload": simplejson.dumps(policy_update_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        response = self.test_app.post(
            "/ion-service/resource_registry/read", {"payload": simplejson.dumps(policy_read_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        updated_policy_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])
        self.assertEqual(updated_policy_obj["policy_type"]["policy_rule"], updated_policy_rule)

        # Now testing the generic get_resource_extension with optional user_id parameter

        response = self.test_app.get("/ion-service/resource_registry/find_resources?name=ionsystem")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]

        actor_id = response_data[0][0]["_id"]

        response = self.test_app.get(
            "/ion-service/resource_registry/get_resource_extension?resource_id="
            + actor_id
            + "&resource_extension=TestExtendedInformationResource"
        )
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(convert_unicode(response_data["user_id"]), "")

        response = self.test_app.get(
            "/ion-service/resource_registry/get_resource_extension?resource_id="
            + actor_id
            + "&resource_extension=TestExtendedInformationResource&user_id=123abc456"
        )
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(convert_unicode(response_data["user_id"]), "123abc456")

    def test_non_anonymous_resource_registry_operations_through_gateway(self):
        id_client = IdentityManagementServiceClient()

        actor_id, valid_until, registered = id_client.signon(USER1_CERTIFICATE, True)

        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=" + actor_id
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        id_client.delete_actor_identity(actor_id)

    def test_non_anonymous_resource_registry_operations_with_token(self):
        rr = self.container.resource_registry
        id_client = IdentityManagementServiceClient()

        create_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "create",
                "params": {"object": {"name": "Instrument1", "type_": "InstrumentDevice"}},
            }
        }

        # Create without actor
        response = self.test_app.post(
            "/ion-service/resource_registry/create", {"payload": simplejson.dumps(create_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertGreaterEqual(len(response_data[0]), 20)  # This is a resource_id
        inst_id = str(response_data[0])

        inst_obj = rr.read(inst_id)
        self.assertEquals(inst_obj.type_, RT.InstrumentDevice)
        self.assertEquals(inst_obj.name, "Instrument1")
        self.assertEquals(inst_obj.visibility, ResourceVisibilityEnum.PUBLIC)

        act_objs, assocs = rr.find_objects(inst_id, PRED.hasOwner, RT.ActorIdentity, id_only=False)
        self.assertEquals(len(act_objs), 0)

        # Anonymous query shows PUBLIC visibility resource anymore
        response = self.test_app.get("/ion-service/resource_registry/find_resources?name=Instrument1&id_only=True")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 1)
        self.assertEqual(len(response_data[1]), 1)
        self.assertEqual(response_data[0][0], inst_id)

        inst_obj.visibility = ResourceVisibilityEnum.OWNER
        rr.update(inst_obj)

        # Now the anonymous query should not show the resource anymore
        response = self.test_app.get("/ion-service/resource_registry/find_resources?name=Instrument1&id_only=True")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        rr.delete(inst_id)

        # Create with actor
        actor_id, valid_until, registered = id_client.signon(USER1_CERTIFICATE, True)

        create_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "create",
                "requester": actor_id,
                "params": {
                    "object": {
                        "name": "Instrument1",
                        "type_": "InstrumentDevice",
                        "visibility": ResourceVisibilityEnum.OWNER,
                    }
                },
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/create", {"payload": simplejson.dumps(create_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertGreaterEqual(len(response_data[0]), 20)  # This is a resource_id
        inst_id = str(response_data[0])

        inst_obj = rr.read(inst_id)
        self.assertEquals(inst_obj.type_, RT.InstrumentDevice)
        self.assertEquals(inst_obj.name, "Instrument1")
        self.assertEquals(inst_obj.visibility, ResourceVisibilityEnum.OWNER)

        act_objs, assocs = rr.find_objects(inst_id, PRED.hasOwner, RT.ActorIdentity, id_only=False)
        self.assertEquals(len(act_objs), 1)
        self.assertEquals(act_objs[0]._id, actor_id)

        # Anonymous query should not show the resource anymore
        response = self.test_app.get("/ion-service/resource_registry/find_resources?name=Instrument1&id_only=True")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        # Authenticated request with owner shows resource
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=Instrument1&id_only=True&requester=" + actor_id
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 1)
        self.assertEqual(len(response_data[1]), 1)
        self.assertEqual(response_data[0][0], inst_id)

        token_str = id_client.create_authentication_token(actor_id, validity=2)

        # Request with authentication token for owner shows resource
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=Instrument1&id_only=True&authtoken=" + token_str
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 1)
        self.assertEqual(len(response_data[1]), 1)
        self.assertEqual(response_data[0][0], inst_id)

        gevent.sleep(2.1)

        # Request with expired authentication token for owner does not show resource (no error though)
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=Instrument1&id_only=True&authtoken=" + token_str
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        # Request with valid authentication token for different user does not show resource
        actor_id2, _ = rr.create(IonObject(RT.ActorIdentity, name="Actor2"))
        token_str2 = id_client.create_authentication_token(actor_id2, validity=2)

        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=Instrument1&id_only=True&authtoken=" + token_str2
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        token_str3 = id_client.create_authentication_token(actor_id, validity=2)

        # Request with new authentication token for owner shows resource
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=Instrument1&id_only=True&authtoken=" + token_str3
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 1)
        self.assertEqual(len(response_data[1]), 1)
        self.assertEqual(response_data[0][0], inst_id)

        id_client.invalidate_authentication_token(token_str3)

        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=Instrument1&id_only=True&authtoken=" + token_str3
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        # Cleanup
        rr.delete(inst_id)
        rr.delete(actor_id2)
        id_client.delete_actor_identity(actor_id)

    def test_get_resource_schema(self):
        response = self.test_app.get("/ion-service/resource_type_schema/Org")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        org_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(org_obj, dict))
        self.assertIn("object", org_obj)
        self.assertIn("schemas", org_obj)
        self.assertIn("Org", org_obj["schemas"])
        self.assertIn("OrgTypeEnum", org_obj["schemas"])
        self.assertIn("Institution", org_obj["schemas"])

        response = self.test_app.get("/ion-service/resource_type_schema/InstrumentModel")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        model_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(org_obj, dict))
        self.assertIn("object", model_obj)
        self.assertIn("schemas", model_obj)
        self.assertIn("InstrumentModel", model_obj["schemas"])
        self.assertIn("PrimaryInterface", model_obj["schemas"])

        response = self.test_app.get("/ion-service/resource_type_schema/DataProduct")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        data_product_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(data_product_obj, dict))
        self.assertIn("object", data_product_obj)
        self.assertIn("schemas", data_product_obj)
        self.assertIn("DataProduct", data_product_obj["schemas"])
        self.assertIn("GeospatialBounds", data_product_obj["schemas"])
        self.assertIn("GeospatialCoordinateReferenceSystem", data_product_obj["schemas"])

        response = self.test_app.get("/ion-service/resource_type_schema/DataProduct123")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json["data"])
        self.assertIn("No matching class found", response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def test_get_resource(self):
        data_product_id = self.create_data_product_resource()

        response = self.test_app.get("/ion-resources/resource/" + data_product_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertNotIn("does not exist", response_data)

        data_product_obj = convert_unicode(response_data)
        self.assertEqual(data_product_id, data_product_obj["_id"])

        self.delete_data_product_resource(data_product_id)

    def test_list_resources_by_type(self):
        data_product_id = self.create_data_product_resource()

        response = self.test_app.get("/ion-resources/find_resources/DataProduct")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 1)

        data_product_obj = convert_unicode(response_data[0])
        self.assertEqual(data_product_id, data_product_obj["_id"])

        self.delete_data_product_resource(data_product_id)

    def test_list_org_roles(self):
        response = self.test_app.get("/ion-service/resource_registry/find_resources?name=ionsystem")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]

        actor_id = response_data[0][0]["_id"]
        response = self.test_app.get("/ion-service/org_roles/" + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]

        self.assertIn("ION", response_data)
        self.assertEqual(len(response_data["ION"]), 3)
        self.assertIn("ION_MANAGER", response_data["ION"])
        self.assertIn("ORG_MANAGER", response_data["ION"])
        self.assertIn("ORG_MEMBER", response_data["ION"])

    def test_user_role_cache(self):
        # Create a user
        id_client = IdentityManagementServiceClient()

        actor_id, valid_until, registered = id_client.signon(USER1_CERTIFICATE, True)

        # Make a request with this new user  to get it into the cache
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=" + actor_id
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        # Check the contents of the user role cache for this user
        service_gateway_user_role_cache = self.container.proc_manager.procs_by_name["service_gateway"].user_role_cache
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn("ION", role_header)
        self.assertEqual(len(role_header["ION"]), 1)
        self.assertIn("ORG_MEMBER", role_header["ION"])

        org_client = OrgManagementServiceClient()

        ion_org = org_client.find_org()
        manager_role = org_client.find_org_role_by_name(org_id=ion_org._id, role_name="ORG_MANAGER")

        org_client.grant_role(org_id=ion_org._id, actor_id=actor_id, role_name="ORG_MANAGER")

        # Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        # The user should be evicted from the cache due to a change in roles
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), False)

        # Do it again to check for new roles
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=" + actor_id
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        # Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn("ION", role_header)
        self.assertEqual(len(role_header["ION"]), 2)
        self.assertIn("ORG_MEMBER", role_header["ION"])
        self.assertIn("ORG_MANAGER", role_header["ION"])

        # Now flush the user_role_cache and make sure it was flushed
        event_publisher = EventPublisher()
        event_publisher.publish_event(event_type=OT.UserRoleCacheResetEvent)

        # Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), False)
        self.assertEqual(service_gateway_user_role_cache.size(), 0)

        # Change the role once again and see if it is there again
        org_client.revoke_role(org_id=ion_org._id, actor_id=actor_id, role_name="ORG_MANAGER")

        # Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        # The user should still not be there
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), False)

        # Do it again to check for new roles
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=" + actor_id
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        # Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn("ION", role_header)
        self.assertEqual(len(role_header["ION"]), 1)
        self.assertIn("ORG_MEMBER", role_header["ION"])

        id_client.delete_actor_identity(actor_id)

    def test_data_provenance_retrieve(self):
        data_product_id = self.create_data_product_resource_full()
        get_parameter_provenance_visualization_image_request = {
            "serviceRequest": {
                "serviceName": "service_gateway",
                "serviceOp": "get_parameter_provenance_visualization_image",
                "params": {"data_product_id": data_product_id, "parameter_name": "temp"},
            }
        }

        # call the gateway service intermeditary operation to get the image from the data product mgmt svc
        response = self.test_app.post(
            "/ion-service/get_parameter_provenance_visualization_image",
            {"payload": simplejson.dumps(get_parameter_provenance_visualization_image_request)},
        )
        # log.debug('test_data_provenance_retrieve  response:  %s', response)

        self.assertIsNotNone(response)
class TestServiceGatewayServiceInt(IonIntegrationTestCase):

    def setUp(self):
        # Start container
        self._start_container()
        self.container.start_rel_from_url('res/deploy/r2coi.yml')

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient(node=self.container.node)

        log.debug('stopping Gateway web server')
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(app)

    def tearDown(self):
        self._stop_container()

    #Common SGS Response header check
    def check_response_headers(self, response):
        self.assertEqual(response.content_type, "application/json")
        self.assertEqual(len(response.json), 1)
        self.assertIn('data',response.json)

    def test_list_resource_types(self):

        response = self.test_app.get('/ion-service/list_resource_types')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('Resource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=InformationResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('InformationResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=TaskableResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('TaskableResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=MyFakeResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('KeyError', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_EXCEPTION])
        self.assertIn('MyFakeResource', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def create_data_product_resource(self):

        data_product_create_request = {  "serviceRequest": {
            "serviceName": "resource_registry",
            "serviceOp": "create",
            "params": {
                "object": {
                    "type_": "DataProduct",
                    "provider_project": "Integration Test",
                    "lcstate": "DRAFT",
                    "description": "A test data product",
                    "name": "TestDataProduct",
                    "contact": {
                        "name": "Test User",
                        "phone": "858-555-1212",
                        "city": "San Diego",
                        "postalcode": "92093"
                    }
                }
            }
        }
        }

        response = self.test_app.post('/ion-service/resource_registry/create', {'payload': json.dumps(data_product_create_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2 )
        data_product_id = convert_unicode(response_data[0])
        return data_product_id


    def delete_data_product_resource(self, data_product_id):

        data_product_delete_request = {  "serviceRequest": {
            "serviceName": "resource_registry",
            "serviceOp": "delete",
            "params": {
                "object_id": data_product_id
            }
        }
        }
        response = self.test_app.post('/ion-service/resource_registry/delete', {'payload': simplejson.dumps(data_product_delete_request) })
        self.check_response_headers(response)
        return response


    def test_resource_registry_operations_through_gateway(self):


        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 0 )

        data_product_id = self.create_data_product_resource()

        data_product_read_request = {  "serviceRequest": {
                                    "serviceName": "resource_registry",
                                    "serviceOp": "read",
                                    "params": {
                                        "object_id": data_product_id
                                            }
                                        }
                                    }

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])

        #modify some fields in the data for testing update
        data_product_obj['description'] = 'An updated description for test data'
        data_product_obj['contact']['postalcode'] = '12345'

        data_product_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {
                    "object": data_product_obj
                }
            }
        }

        response = self.test_app.post('/ion-service/resource_registry/update', {'payload': simplejson.dumps(data_product_update_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        updated_data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertEqual(updated_data_product_obj['description'], 'An updated description for test data', )
        self.assertEqual(updated_data_product_obj['contact']['postalcode'], '12345')

        differ = DictDiffer(updated_data_product_obj, data_product_obj)
        self.assertEqual(len(differ.changed()), 2)  # Only the _rev and ts_updated fields should be different after an update

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 1 )

        response = self.delete_data_product_resource(data_product_id)
        self.assertIsNone(response.json['data'][GATEWAY_RESPONSE])

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('does not exist', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 0 )

        response = self.delete_data_product_resource(data_product_id)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('does not exist', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def test_get_resource_schema(self):

        response = self.test_app.get('/ion-service/resource_type_schema/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(data_product_obj, dict))

        response = self.test_app.get('/ion-service/resource_type_schema/DataProduct123')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('No matching class found', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])



    def test_get_resource(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get('/ion-service/rest/resource/' + data_product_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertNotIn('does not exist', response_data)

        data_product_obj = convert_unicode(response_data)
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)

    def test_list_resources_by_type(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get('/ion-service/rest/find_resources/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),1 )

        data_product_obj = convert_unicode(response_data[0])
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)
class TestServiceGatewayServiceInt(IonIntegrationTestCase):
    def setUp(self):
        # Start container
        self._start_container()
        self.container.start_rel_from_url("res/deploy/r2deploy.yml")

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient(node=self.container.node)

        log.debug("stopping Gateway web server")
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(service_gateway_app)

    def tearDown(self):
        self._stop_container()

    # Common SGS Response header check
    def check_response_headers(self, response):
        self.assertEqual(response.content_type, "application/json")
        self.assertEqual(len(response.json), 1)
        self.assertIn("data", response.json)

    def test_list_resource_types(self):

        response = self.test_app.get("/ion-service/list_resource_types")

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        expected_type_list = getextends("Resource")

        self.assertEqual(len(response.json["data"][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json["data"][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get("/ion-service/list_resource_types?type=InformationResource")

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        expected_type_list = getextends("InformationResource")

        self.assertEqual(len(response.json["data"][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json["data"][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get("/ion-service/list_resource_types?type=TaskableResource")

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        expected_type_list = getextends("TaskableResource")

        self.assertEqual(len(response.json["data"][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json["data"][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get("/ion-service/list_resource_types?type=MyFakeResource")

        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json["data"])
        self.assertIn("KeyError", response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_EXCEPTION])
        self.assertIn("MyFakeResource", response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def create_data_product_resource(self):

        geospatial_bounds = {
            "geospatial_latitude_limit_north": 1.0,
            "geospatial_latitude_limit_south": 1.0,
            "geospatial_longitude_limit_east": 1.0,
            "geospatial_longitude_limit_west": 1.0,
            "geospatial_vertical_min": 1.0,
            "geospatial_vertical_max": 1.0,
        }
        data_product_create_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "create",
                "params": {
                    "object": {
                        "type_": "DataProduct",
                        "lcstate": "DRAFT",
                        "description": DATA_PRODUCT_DESCRIPTION,
                        "name": DATA_PRODUCT_NAME,
                        "geospatial_bounds": geospatial_bounds,
                        "temporal_domain": TEMPORAL_DOMAIN,
                    }
                },
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/create", {"payload": simplejson.dumps(data_product_create_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        data_product_id = convert_unicode(response_data[0])
        return data_product_id

    def delete_data_product_resource(self, data_product_id):

        data_product_delete_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "delete",
                "params": {"object_id": data_product_id},
            }
        }
        response = self.test_app.post(
            "/ion-service/resource_registry/delete", {"payload": simplejson.dumps(data_product_delete_request)}
        )
        self.check_response_headers(response)
        return response

    def create_policy_resource(self):

        policy_create_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "create",
                "params": {
                    "object": {
                        "definition": {},
                        "name": POLICY_NAME,
                        "description": POLICY_DESCRIPTION,
                        "lcstate": "DRAFT",
                        "required": True,
                        "enabled": True,
                        "type_": "Policy",
                        "policy_type": {
                            "policy_rule": POLICY_RULE,
                            "service_name": "user_notification",
                            "type_": "ServiceAccessPolicy",
                        },
                    }
                },
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/create", {"payload": simplejson.dumps(policy_create_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        policy_id = convert_unicode(response_data[0])
        return policy_id

    @attr("SMOKE")
    def test_anonymous_resource_registry_operations_through_gateway(self):
        """
        This test ensures that requests make through the service gateway through messaging to the Resource Registry and
        back; including the support of unicode characters.
        @return:
        """

        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name="
            + convert_unicode(DATA_PRODUCT_NAME)
            + "&id_only=True&user_id=123abc456"
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        data_product_id = self.create_data_product_resource()

        data_product_read_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "read",
                "params": {"object_id": data_product_id},
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/read", {"payload": simplejson.dumps(data_product_read_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        data_product_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])

        # Verify the the name and description fields containing unicode characters match all the way through couch and the messaging
        self.assertEqual(data_product_obj["name"], convert_unicode(DATA_PRODUCT_NAME))
        self.assertEqual(data_product_obj["description"], convert_unicode(DATA_PRODUCT_DESCRIPTION))

        updated_description_text = data_product_obj["description"] + "---Updated!!"

        # modify some fields in the data for testing update
        data_product_obj["description"] = updated_description_text

        data_product_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {"object": data_product_obj},
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/update", {"payload": simplejson.dumps(data_product_update_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        response = self.test_app.post(
            "/ion-service/resource_registry/read", {"payload": simplejson.dumps(data_product_read_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        updated_data_product_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])
        self.assertEqual(updated_data_product_obj["description"], updated_description_text)

        differ = DictDiffer(updated_data_product_obj, data_product_obj)
        self.assertEqual(
            len(differ.changed()), 2
        )  # Only the _rev and ts_updated fields should be different after an update

        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=" + convert_unicode(DATA_PRODUCT_NAME) + "&id_only=True"
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 1)

        response = self.delete_data_product_resource(data_product_id)
        self.assertIsNone(response.json["data"][GATEWAY_RESPONSE])

        response = self.test_app.post(
            "/ion-service/resource_registry/read", {"payload": simplejson.dumps(data_product_read_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json["data"])
        self.assertIn("does not exist", response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])

        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=" + convert_unicode(DATA_PRODUCT_NAME) + "&id_only=True"
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        response = self.delete_data_product_resource(data_product_id)
        self.assertIn(GATEWAY_ERROR, response.json["data"])
        self.assertIn("does not exist", response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

        # Now try creating a policy object which has an internal object of a different type
        policy_id = self.create_policy_resource()

        policy_read_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "read",
                "params": {"object_id": policy_id},
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/read", {"payload": simplejson.dumps(policy_read_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        policy_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])

        # Verify the the name and description fields containing unicode characters match all the way through couch and the messaging
        self.assertEqual(policy_obj["name"], convert_unicode(POLICY_NAME))
        self.assertEqual(policy_obj["description"], convert_unicode(POLICY_DESCRIPTION))
        self.assertEqual(policy_obj["policy_type"]["policy_rule"], convert_unicode(POLICY_RULE))

        updated_policy_rule = policy_obj["policy_type"]["policy_rule"] + "---Updated!!"

        # modify some fields in the data for testing update
        policy_obj["policy_type"]["policy_rule"] = updated_policy_rule

        policy_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {"object": policy_obj},
            }
        }

        response = self.test_app.post(
            "/ion-service/resource_registry/update", {"payload": simplejson.dumps(policy_update_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        response = self.test_app.post(
            "/ion-service/resource_registry/read", {"payload": simplejson.dumps(policy_read_request)}
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        updated_policy_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])
        self.assertEqual(updated_policy_obj["policy_type"]["policy_rule"], updated_policy_rule)

        # Now testing the generic get_resource_extension with optional user_id parameter

        response = self.test_app.get("/ion-service/resource_registry/find_resources?name=ionsystem")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]

        actor_id = response_data[0][0]["_id"]

        response = self.test_app.get(
            "/ion-service/resource_registry/get_resource_extension?resource_id="
            + actor_id
            + "&resource_extension=TestExtendedInformationResource"
        )
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(convert_unicode(response_data["user_id"]), "")

        response = self.test_app.get(
            "/ion-service/resource_registry/get_resource_extension?resource_id="
            + actor_id
            + "&resource_extension=TestExtendedInformationResource&user_id=123abc456"
        )
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(convert_unicode(response_data["user_id"]), "123abc456")

    def test_non_anonymous_resource_registry_operations_through_gateway(self):

        id_client = IdentityManagementServiceClient(node=self.container.node)

        actor_id, valid_until, registered = id_client.signon(USER1_CERTIFICATE, True)

        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=" + actor_id
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        id_client.delete_actor_identity(actor_id)

    def test_get_resource_schema(self):

        response = self.test_app.get("/ion-service/resource_type_schema/Org")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        org_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(org_obj, dict))
        self.assertIn("object", org_obj)
        self.assertIn("schemas", org_obj)
        self.assertIn("Org", org_obj["schemas"])
        self.assertIn("OrgTypeEnum", org_obj["schemas"])
        self.assertIn("Institution", org_obj["schemas"])

        response = self.test_app.get("/ion-service/resource_type_schema/InstrumentModel")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        model_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(org_obj, dict))
        self.assertIn("object", model_obj)
        self.assertIn("schemas", model_obj)
        self.assertIn("InstrumentModel", model_obj["schemas"])
        self.assertIn("PrimaryInterface", model_obj["schemas"])

        response = self.test_app.get("/ion-service/resource_type_schema/DataProduct")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        data_product_obj = convert_unicode(response.json["data"][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(data_product_obj, dict))
        self.assertIn("object", data_product_obj)
        self.assertIn("schemas", data_product_obj)
        self.assertIn("DataProduct", data_product_obj["schemas"])
        self.assertIn("GeospatialBounds", data_product_obj["schemas"])
        self.assertIn("GeospatialCoordinateReferenceSystem", data_product_obj["schemas"])

        response = self.test_app.get("/ion-service/resource_type_schema/DataProduct123")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json["data"])
        self.assertIn("No matching class found", response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json["data"][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def test_get_resource(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get("/ion-resources/resource/" + data_product_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertNotIn("does not exist", response_data)

        data_product_obj = convert_unicode(response_data)
        self.assertEqual(data_product_id, data_product_obj["_id"])

        self.delete_data_product_resource(data_product_id)

    def test_list_resources_by_type(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get("/ion-resources/find_resources/DataProduct")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 1)

        data_product_obj = convert_unicode(response_data[0])
        self.assertEqual(data_product_id, data_product_obj["_id"])

        self.delete_data_product_resource(data_product_id)

    def test_list_org_roles(self):

        response = self.test_app.get("/ion-service/resource_registry/find_resources?name=ionsystem")
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]

        actor_id = response_data[0][0]["_id"]
        response = self.test_app.get("/ion-service/org_roles/" + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])
        response_data = response.json["data"][GATEWAY_RESPONSE]

        self.assertIn("ION", response_data)
        self.assertEqual(len(response_data["ION"]), 3)
        self.assertIn("ION_MANAGER", response_data["ION"])
        self.assertIn("ORG_MANAGER", response_data["ION"])
        self.assertIn("ORG_MEMBER", response_data["ION"])

    def test_user_role_cache(self):

        # Create a user
        id_client = IdentityManagementServiceClient(node=self.container.node)

        actor_id, valid_until, registered = id_client.signon(USER1_CERTIFICATE, True)

        # Make a request with this new user  to get it into the cache
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=" + actor_id
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        # Check the contents of the user role cache for this user
        service_gateway_user_role_cache = self.container.proc_manager.procs_by_name["service_gateway"].user_role_cache
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn("ION", role_header)
        self.assertEqual(len(role_header["ION"]), 1)
        self.assertIn("ORG_MEMBER", role_header["ION"])

        org_client = OrgManagementServiceClient(node=self.container.node)

        ion_org = org_client.find_org()
        manager_role = org_client.find_org_role_by_name(org_id=ion_org._id, role_name="ORG_MANAGER")

        org_client.grant_role(org_id=ion_org._id, actor_id=actor_id, role_name="ORG_MANAGER")

        # Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        # The user should be evicted from the cache due to a change in roles
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), False)

        # Do it again to check for new roles
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=" + actor_id
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        # Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn("ION", role_header)
        self.assertEqual(len(role_header["ION"]), 2)
        self.assertIn("ORG_MEMBER", role_header["ION"])
        self.assertIn("ORG_MANAGER", role_header["ION"])

        # Now flush the user_role_cache and make sure it was flushed
        event_publisher = EventPublisher()
        event_publisher.publish_event(event_type=OT.UserRoleCacheResetEvent)

        # Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), False)
        self.assertEqual(service_gateway_user_role_cache.size(), 0)

        # Change the role once again and see if it is there again
        org_client.revoke_role(org_id=ion_org._id, actor_id=actor_id, role_name="ORG_MANAGER")

        # Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        # The user should still not be there
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), False)

        # Do it again to check for new roles
        response = self.test_app.get(
            "/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=" + actor_id
        )
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json["data"])

        # Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn("ION", role_header)
        self.assertEqual(len(role_header["ION"]), 1)
        self.assertIn("ORG_MEMBER", role_header["ION"])

        id_client.delete_actor_identity(actor_id)
class TestServiceGatewayServiceInt(IonIntegrationTestCase):

    def setUp(self):
        # Start container
        self._start_container()
        self.container.start_rel_from_url('res/deploy/r2deploy.yml')

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient(node=self.container.node)

        log.debug('stopping Gateway web server')
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(service_gateway_app)

    def tearDown(self):
        self._stop_container()

    #Common SGS Response header check
    def check_response_headers(self, response):
        self.assertEqual(response.content_type, "application/json")
        self.assertEqual(len(response.json), 1)
        self.assertIn('data',response.json)

    def test_list_resource_types(self):

        response = self.test_app.get('/ion-service/list_resource_types')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('Resource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=InformationResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('InformationResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=TaskableResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('TaskableResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=MyFakeResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('KeyError', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_EXCEPTION])
        self.assertIn('MyFakeResource', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])


    def create_data_product_resource(self):

        geospatial_bounds = {
            "geospatial_latitude_limit_north": 1.0,
            "geospatial_latitude_limit_south": 1.0,
            "geospatial_longitude_limit_east": 1.0,
            "geospatial_longitude_limit_west": 1.0,
            "geospatial_vertical_min": 1.0,
            "geospatial_vertical_max": 1.0
        }
        data_product_create_request = {  "serviceRequest": {
            "serviceName": "resource_registry",
            "serviceOp": "create",
            "params": {
                "object": {
                    "type_": "DataProduct",
                    "lcstate": "DRAFT",
                    "description": DATA_PRODUCT_DESCRIPTION,
                    "name": DATA_PRODUCT_NAME,
                    'geospatial_bounds': geospatial_bounds,
                    'temporal_domain': TEMPORAL_DOMAIN
                }
            }
        }
        }

        response = self.test_app.post('/ion-service/resource_registry/create', {'payload': simplejson.dumps(data_product_create_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2 )
        data_product_id = convert_unicode(response_data[0])
        return data_product_id


    def create_data_product_resource_full(self):

        geospatial_bounds = {
            "geospatial_latitude_limit_north": 1.0,
            "geospatial_latitude_limit_south": 1.0,
            "geospatial_longitude_limit_east": 1.0,
            "geospatial_longitude_limit_west": 1.0,
            "geospatial_vertical_min": 1.0,
            "geospatial_vertical_max": 1.0
        }

        #create a paramter dictionary the a stream definition for this data product
        DICTIONARY_NAME='ctd_parsed_param_dict'
        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=' + convert_unicode(DICTIONARY_NAME) + '&id_only=True&user_id=123abc456')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        param_dictionary_id = convert_unicode(response_data[0])
        test = str(param_dictionary_id[0])
        log.debug('create_data_product_resource_full  param_dictionary_id:  %s', param_dictionary_id)
        log.debug('create_data_product_resource_full  test:  %s', test)


        response = self.test_app.get('/ion-service/pubsub_management/create_stream_definition?name=CTDData&parameter_dictionary_id='+ convert_unicode(param_dictionary_id[0]))
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        log.debug('create_data_product_resource_full   response_data:  %s', response_data)
        stream_definition_id = convert_unicode(response_data)
        log.debug('create_data_product_resource_full  stream_definition_id:  %s', stream_definition_id)


        data_product_create_request = {  "serviceRequest": {
            "serviceName": "data_product_management",
            "serviceOp": "create_data_product",
            "params": {
                "data_product": {
                    "type_": "DataProduct",
                    "lcstate": "DRAFT",
                    "description": DATA_PRODUCT_DESCRIPTION,
                    "name": DATA_PRODUCT_NAME,
                    'geospatial_bounds': geospatial_bounds,
                    'temporal_domain': TEMPORAL_DOMAIN
                },
                "stream_definition_id": stream_definition_id
            }
        }
        }

        response = self.test_app.post('/ion-service/data_product_management/create_data_product', {'payload': simplejson.dumps(data_product_create_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        log.debug('create_data_product_resource_full  create_data_product response_data:  %s', response_data)
        #self.assertEqual(len(response_data), 2 )
        data_product_id = convert_unicode(response_data)
        return data_product_id


    def delete_data_product_resource(self, data_product_id):

        data_product_delete_request = {  "serviceRequest": {
            "serviceName": "resource_registry",
            "serviceOp": "delete",
            "params": {
                "object_id": data_product_id
            }
        }
        }
        response = self.test_app.post('/ion-service/resource_registry/delete', {'payload': simplejson.dumps(data_product_delete_request) })
        self.check_response_headers(response)
        return response

    def create_policy_resource(self):


        policy_create_request = {  "serviceRequest": {
            "serviceName": "resource_registry",
            "serviceOp": "create",
            "params": {
                "object": {
                    "definition": {},
                    "name": POLICY_NAME,
                    "description": POLICY_DESCRIPTION,
                    "lcstate": "DRAFT",
                    "required": True,
                    "enabled": True,
                    "type_": "Policy",
                    "policy_type": {
                        "policy_rule" : POLICY_RULE,
                        "service_name": "user_notification",
                        "type_": "ServiceAccessPolicy"
                    }
                }

            }
        }
        }

        response = self.test_app.post('/ion-service/resource_registry/create', {'payload': simplejson.dumps(policy_create_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2 )
        policy_id = convert_unicode(response_data[0])
        return policy_id



    @attr('SMOKE')
    def test_anonymous_resource_registry_operations_through_gateway(self):
        """
        This test ensures that requests make through the service gateway through messaging to the Resource Registry and
        back; including the support of unicode characters.
        @return:
        """

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=' + convert_unicode(DATA_PRODUCT_NAME) + '&id_only=True&user_id=123abc456')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 0 )

        data_product_id = self.create_data_product_resource()

        data_product_read_request = {  "serviceRequest": {
                                    "serviceName": "resource_registry",
                                    "serviceOp": "read",
                                    "params": {
                                        "object_id": data_product_id
                                            }
                                        }
                                    }

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])


        #Verify the the name and description fields containing unicode characters match all the way through couch and the messaging
        self.assertEqual(data_product_obj['name'], convert_unicode(DATA_PRODUCT_NAME))
        self.assertEqual(data_product_obj['description'], convert_unicode(DATA_PRODUCT_DESCRIPTION))

        updated_description_text = data_product_obj['description'] + '---Updated!!'

        #modify some fields in the data for testing update
        data_product_obj['description'] = updated_description_text

        data_product_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {
                    "object": data_product_obj
                }
            }
        }

        response = self.test_app.post('/ion-service/resource_registry/update', {'payload': simplejson.dumps(data_product_update_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        updated_data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertEqual(updated_data_product_obj['description'], updated_description_text )

        differ = DictDiffer(updated_data_product_obj, data_product_obj)
        self.assertEqual(len(differ.changed()), 2)  # Only the _rev and ts_updated fields should be different after an update

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=' + convert_unicode(DATA_PRODUCT_NAME) + '&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 1 )

        response = self.delete_data_product_resource(data_product_id)
        self.assertIsNone(response.json['data'][GATEWAY_RESPONSE])

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('does not exist', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=' + convert_unicode(DATA_PRODUCT_NAME) + '&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 0 )

        response = self.delete_data_product_resource(data_product_id)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('does not exist', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])


        #Now try creating a policy object which has an internal object of a different type
        policy_id = self.create_policy_resource()

        policy_read_request = {  "serviceRequest": {
            "serviceName": "resource_registry",
            "serviceOp": "read",
            "params": {
                "object_id": policy_id
            }
        }
        }

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(policy_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        policy_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])

        #Verify the the name and description fields containing unicode characters match all the way through couch and the messaging
        self.assertEqual(policy_obj['name'], convert_unicode(POLICY_NAME))
        self.assertEqual(policy_obj['description'], convert_unicode(POLICY_DESCRIPTION))
        self.assertEqual(policy_obj['policy_type']['policy_rule'], convert_unicode(POLICY_RULE))


        updated_policy_rule = policy_obj['policy_type']['policy_rule'] + '---Updated!!'

        #modify some fields in the data for testing update
        policy_obj['policy_type']['policy_rule'] = updated_policy_rule

        policy_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {
                    "object": policy_obj
                }
            }
        }

        response = self.test_app.post('/ion-service/resource_registry/update', {'payload': simplejson.dumps(policy_update_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(policy_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        updated_policy_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertEqual(updated_policy_obj['policy_type']['policy_rule'], updated_policy_rule )


        #Now testing the generic get_resource_extension with optional user_id parameter

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=ionsystem')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]

        actor_id = response_data[0][0]['_id']

        response = self.test_app.get('/ion-service/resource_registry/get_resource_extension?resource_id=' + actor_id + '&resource_extension=TestExtendedInformationResource')
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(convert_unicode(response_data['user_id']), '')

        response = self.test_app.get('/ion-service/resource_registry/get_resource_extension?resource_id=' + actor_id + '&resource_extension=TestExtendedInformationResource&user_id=123abc456')
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(convert_unicode(response_data['user_id']), '123abc456')



    def test_non_anonymous_resource_registry_operations_through_gateway(self):

        id_client = IdentityManagementServiceClient(node=self.container.node)

        actor_id, valid_until, registered = id_client.signon(USER1_CERTIFICATE, True)

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 0 )

        id_client.delete_actor_identity(actor_id)


    def test_get_resource_schema(self):

        response = self.test_app.get('/ion-service/resource_type_schema/Org')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        org_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(org_obj, dict))
        self.assertIn('object', org_obj)
        self.assertIn('schemas', org_obj)
        self.assertIn('Org', org_obj['schemas'])
        self.assertIn('OrgTypeEnum', org_obj['schemas'])
        self.assertIn('Institution', org_obj['schemas'])

        response = self.test_app.get('/ion-service/resource_type_schema/InstrumentModel')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        model_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(org_obj, dict))
        self.assertIn('object', model_obj)
        self.assertIn('schemas', model_obj)
        self.assertIn('InstrumentModel', model_obj['schemas'])
        self.assertIn('PrimaryInterface', model_obj['schemas'])


        response = self.test_app.get('/ion-service/resource_type_schema/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(data_product_obj, dict))
        self.assertIn('object', data_product_obj)
        self.assertIn('schemas', data_product_obj)
        self.assertIn('DataProduct', data_product_obj['schemas'])
        self.assertIn('GeospatialBounds', data_product_obj['schemas'])
        self.assertIn('GeospatialCoordinateReferenceSystem', data_product_obj['schemas'])

        response = self.test_app.get('/ion-service/resource_type_schema/DataProduct123')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('No matching class found', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])



    def test_get_resource(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get('/ion-resources/resource/' + data_product_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertNotIn('does not exist', response_data)

        data_product_obj = convert_unicode(response_data)
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)

    def test_list_resources_by_type(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get('/ion-resources/find_resources/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),1 )

        data_product_obj = convert_unicode(response_data[0])
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)

    def test_list_org_roles(self):

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=ionsystem')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]

        actor_id = response_data[0][0]['_id']
        response = self.test_app.get('/ion-service/org_roles/' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]

        self.assertIn('ION', response_data)
        self.assertEqual(len(response_data['ION']), 3)
        self.assertIn('ION_MANAGER', response_data['ION'])
        self.assertIn('ORG_MANAGER', response_data['ION'])
        self.assertIn('ORG_MEMBER', response_data['ION'])

    def test_user_role_cache(self):


        #Create a user
        id_client = IdentityManagementServiceClient(node=self.container.node)

        actor_id, valid_until, registered = id_client.signon(USER1_CERTIFICATE, True)

        #Make a request with this new user  to get it into the cache
        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        service_gateway_user_role_cache = self.container.proc_manager.procs_by_name['service_gateway'].user_role_cache
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 1)
        self.assertIn('ORG_MEMBER', role_header['ION'])

        org_client = OrgManagementServiceClient(node=self.container.node)

        ion_org = org_client.find_org()
        manager_role = org_client.find_org_role_by_name(org_id=ion_org._id, role_name='ORG_MANAGER')

        org_client.grant_role(org_id=ion_org._id, actor_id=actor_id, role_name='ORG_MANAGER')

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        #The user should be evicted from the cache due to a change in roles
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), False)

        #Do it again to check for new roles
        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 2)
        self.assertIn('ORG_MEMBER', role_header['ION'])
        self.assertIn('ORG_MANAGER', role_header['ION'])

        #Now flush the user_role_cache and make sure it was flushed
        event_publisher = EventPublisher()
        event_publisher.publish_event(event_type=OT.UserRoleCacheResetEvent)

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), False)
        self.assertEqual(service_gateway_user_role_cache.size(), 0)

        #Change the role once again and see if it is there again
        org_client.revoke_role(org_id=ion_org._id, actor_id=actor_id, role_name='ORG_MANAGER')

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        #The user should still not be there
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), False)

        #Do it again to check for new roles
        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id), True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 1)
        self.assertIn('ORG_MEMBER', role_header['ION'])

        id_client.delete_actor_identity(actor_id)


    def test_data_provenance_retrieve(self):

        data_product_id = self.create_data_product_resource_full()
        get_parameter_provenance_visualization_image_request = {  "serviceRequest": {
            "serviceName": "service_gateway",
            "serviceOp": "get_parameter_provenance_visualization_image",
            "params": {
                "data_product_id": data_product_id,
                "parameter_name" : "temp"
            }
        }
        }

        #call the gateway service intermeditary operation to get the image from the data product mgmt svc
        response = self.test_app.post('/ion-service/get_parameter_provenance_visualization_image', {'payload': simplejson.dumps(get_parameter_provenance_visualization_image_request) })
        #log.debug('test_data_provenance_retrieve  response:  %s', response)

        self.assertIsNotNone(response)
class TestServiceGatewayServiceInt(IonIntegrationTestCase):

    def setUp(self):
        # Start container
        self._start_container()
        self.container.start_rel_from_url('res/deploy/r2coi.yml')

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient(node=self.container.node)

        log.debug('stopping Gateway web server')
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(service_gateway_app)

    def tearDown(self):
        self._stop_container()

    #Common SGS Response header check
    def check_response_headers(self, response):
        self.assertEqual(response.content_type, "application/json")
        self.assertEqual(len(response.json), 1)
        self.assertIn('data',response.json)

    def test_list_resource_types(self):

        response = self.test_app.get('/ion-service/list_resource_types')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('Resource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=InformationResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('InformationResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=TaskableResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('TaskableResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=MyFakeResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('KeyError', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_EXCEPTION])
        self.assertIn('MyFakeResource', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def create_data_product_resource(self):

        data_product_create_request = {  "serviceRequest": {
            "serviceName": "resource_registry",
            "serviceOp": "create",
            "params": {
                "object": {
                    "type_": "DataProduct",
                    "lcstate": "DRAFT",
                    "description": "A test data product",
                    "name": "TestDataProduct"
                }
            }
        }
        }

        response = self.test_app.post('/ion-service/resource_registry/create', {'payload': json.dumps(data_product_create_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2 )
        data_product_id = convert_unicode(response_data[0])
        return data_product_id


    def delete_data_product_resource(self, data_product_id):

        data_product_delete_request = {  "serviceRequest": {
            "serviceName": "resource_registry",
            "serviceOp": "delete",
            "params": {
                "object_id": data_product_id
            }
        }
        }
        response = self.test_app.post('/ion-service/resource_registry/delete', {'payload': simplejson.dumps(data_product_delete_request) })
        self.check_response_headers(response)
        return response


    @attr('SMOKE')
    def test_anonymous_resource_registry_operations_through_gateway(self):


        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 0 )

        data_product_id = self.create_data_product_resource()

        data_product_read_request = {  "serviceRequest": {
                                    "serviceName": "resource_registry",
                                    "serviceOp": "read",
                                    "params": {
                                        "object_id": data_product_id
                                            }
                                        }
                                    }

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])

        #modify some fields in the data for testing update
        data_product_obj['description'] = 'An updated description for test data'

        data_product_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {
                    "object": data_product_obj
                }
            }
        }

        response = self.test_app.post('/ion-service/resource_registry/update', {'payload': simplejson.dumps(data_product_update_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        updated_data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertEqual(updated_data_product_obj['description'], 'An updated description for test data', )

        differ = DictDiffer(updated_data_product_obj, data_product_obj)
        self.assertEqual(len(differ.changed()), 2)  # Only the _rev and ts_updated fields should be different after an update

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 1 )

        response = self.delete_data_product_resource(data_product_id)
        self.assertIsNone(response.json['data'][GATEWAY_RESPONSE])

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('does not exist', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 0 )

        response = self.delete_data_product_resource(data_product_id)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('does not exist', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def test_non_anonymous_resource_registry_operations_through_gateway(self):

        id_client = IdentityManagementServiceClient(node=self.container.node)

        actor_id, valid_until, registered = id_client.signon(USER1_CERTIFICATE, True)

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 0 )

        id_client.delete_actor_identity(actor_id)


    def test_get_resource_schema(self):

        response = self.test_app.get('/ion-service/resource_type_schema/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(data_product_obj, dict))

        response = self.test_app.get('/ion-service/resource_type_schema/DataProduct123')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('No matching class found', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])



    def test_get_resource(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get('/ion-service/rest/resource/' + data_product_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertNotIn('does not exist', response_data)

        data_product_obj = convert_unicode(response_data)
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)

    def test_list_resources_by_type(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get('/ion-service/rest/find_resources/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),1 )

        data_product_obj = convert_unicode(response_data[0])
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)

    def test_list_org_roles(self):

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=ionsystem')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]

        actor_id = response_data[0][0]['_id']
        response = self.test_app.get('/ion-service/org_roles/' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]

        self.assertIn('ION', response_data)
        self.assertEqual(len(response_data['ION']), 3)
        self.assertIn('ION_MANAGER', response_data['ION'])
        self.assertIn('ORG_MANAGER', response_data['ION'])
        self.assertIn('ORG_MEMBER', response_data['ION'])

    def test_user_role_cache(self):


        #Create a user
        id_client = IdentityManagementServiceClient(node=self.container.node)

        actor_id, valid_until, registered = id_client.signon(USER1_CERTIFICATE, True)

        #Make a request with this new user  to get it into the cache
        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        service_gateway_user_cache = self.container.proc_manager.procs_by_name['service_gateway'].user_data_cache
        self.assertEqual(service_gateway_user_cache.has_key(actor_id), True)

        role_header = service_gateway_user_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 1)
        self.assertIn('ORG_MEMBER', role_header['ION'])

        org_client = OrgManagementServiceClient(node=self.container.node)

        ion_org = org_client.find_org()
        manager_role = org_client.find_org_role_by_name(org_id=ion_org._id, role_name='ORG_MANAGER')

        org_client.grant_role(org_id=ion_org._id, user_id=actor_id, role_name='ORG_MANAGER')

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        #The user should be evicted from the cache due to a change in roles
        self.assertEqual(service_gateway_user_cache.has_key(actor_id), False)

        #Do it again to check for new roles
        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_cache.has_key(actor_id), True)

        role_header = service_gateway_user_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 2)
        self.assertIn('ORG_MEMBER', role_header['ION'])
        self.assertIn('ORG_MANAGER', role_header['ION'])

        #Now flush the user_role_cache and make sure it was flushed
        event_publisher = EventPublisher()
        event_publisher.publish_event(event_type=OT.UserRoleCacheResetEvent)

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        self.assertEqual(service_gateway_user_cache.has_key(actor_id), False)
        self.assertEqual(service_gateway_user_cache.size(), 0)

        #Change the role once again and see if it is there again
        org_client.revoke_role(org_id=ion_org._id, user_id=actor_id, role_name='ORG_MANAGER')

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        #The user should still not be there
        self.assertEqual(service_gateway_user_cache.has_key(actor_id), False)

        #Do it again to check for new roles
        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester=' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_cache.has_key(actor_id), True)

        role_header = service_gateway_user_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 1)
        self.assertIn('ORG_MEMBER', role_header['ION'])

        id_client.delete_actor_identity(actor_id)
class TestServiceGatewayServiceInt(IonIntegrationTestCase):

    def setUp(self):
        # Start container
        self._start_container()
        self.container.start_rel_from_url('res/deploy/r2coi.yml')

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient(node=self.container.node)

        log.debug('stopping Gateway web server')
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(app)

    def tearDown(self):
        self._stop_container()

    #Common SGS Response header check
    def check_response_headers(self, response):
        self.assertEqual(response.content_type, "application/json")
        self.assertEqual(len(response.json), 1)
        self.assertIn('data',response.json)

    def test_list_resource_types(self):

        response = self.test_app.get('/ion-service/list_resource_types')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('Resource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=InformationResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('InformationResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=TaskableResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('TaskableResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]), len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get('/ion-service/list_resource_types?type=MyFakeResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('KeyError', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_EXCEPTION])
        self.assertIn('MyFakeResource', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def create_data_product_resource(self):

        data_product_create_request = {  "serviceRequest": {
            "serviceName": "resource_registry",
            "serviceOp": "create",
            "params": {
                "object": {
                    "type_": "DataProduct",
                    "provider_project": "Integration Test",
                    "lcstate": "DRAFT",
                    "description": "A test data product",
                    "name": "TestDataProduct",
                    "contact": {
                        "name": "Test User",
                        "phone": "858-555-1212",
                        "city": "San Diego",
                        "postalcode": "92093"
                    }
                }
            }
        }
        }

        response = self.test_app.post('/ion-service/resource_registry/create', {'payload': json.dumps(data_product_create_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2 )
        data_product_id = convert_unicode(response_data[0])
        return data_product_id


    def delete_data_product_resource(self, data_product_id):

        data_product_delete_request = {  "serviceRequest": {
            "serviceName": "resource_registry",
            "serviceOp": "delete",
            "params": {
                "object_id": data_product_id
            }
        }
        }
        response = self.test_app.post('/ion-service/resource_registry/delete', {'payload': simplejson.dumps(data_product_delete_request) })
        self.check_response_headers(response)
        return response


    def test_resource_registry_operations_through_gateway(self):


        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 0 )

        data_product_id = self.create_data_product_resource()

        data_product_read_request = {  "serviceRequest": {
                                    "serviceName": "resource_registry",
                                    "serviceOp": "read",
                                    "params": {
                                        "object_id": data_product_id
                                            }
                                        }
                                    }

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])

        #modify some fields in the data for testing update
        data_product_obj['description'] = 'An updated description for test data'
        data_product_obj['contact']['postalcode'] = '12345'

        data_product_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {
                    "object": data_product_obj
                }
            }
        }

        response = self.test_app.post('/ion-service/resource_registry/update', {'payload': simplejson.dumps(data_product_update_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        updated_data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertEqual(updated_data_product_obj['description'], 'An updated description for test data', )
        self.assertEqual(updated_data_product_obj['contact']['postalcode'], '12345')

        differ = DictDiffer(updated_data_product_obj, data_product_obj)
        self.assertEqual(len(differ.changed()), 2)  # Only the _rev and ts_updated fields should be different after an update

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 1 )

        response = self.delete_data_product_resource(data_product_id)
        self.assertIsNone(response.json['data'][GATEWAY_RESPONSE])

        response = self.test_app.post('/ion-service/resource_registry/read', {'payload': simplejson.dumps(data_product_read_request) })
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('does not exist', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])

        response = self.test_app.get('/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),2 )
        self.assertEqual(len(response_data[0]), 0 )

        response = self.delete_data_product_resource(data_product_id)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('does not exist', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def test_get_resource_schema(self):

        response = self.test_app.get('/ion-service/resource_type_schema/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        data_product_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(data_product_obj, dict))

        response = self.test_app.get('/ion-service/resource_type_schema/DataProduct123')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn('No matching class found', response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])



    def test_get_resource(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get('/ion-service/rest/resource/' + data_product_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertNotIn('does not exist', response_data)

        data_product_obj = convert_unicode(response_data)
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)

    def test_list_resources_by_type(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get('/ion-service/rest/find_resources/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data),1 )

        data_product_obj = convert_unicode(response_data[0])
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)
class TestServiceGatewayServiceInt(IonIntegrationTestCase):
    def setUp(self):
        # Start container
        self._start_container()
        self.container.start_rel_from_url('res/deploy/r2coi.yml')

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient(
            node=self.container.node)

        log.debug('stopping Gateway web server')
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(service_gateway_app)

    def tearDown(self):
        self._stop_container()

    #Common SGS Response header check
    def check_response_headers(self, response):
        self.assertEqual(response.content_type, "application/json")
        self.assertEqual(len(response.json), 1)
        self.assertIn('data', response.json)

    def test_list_resource_types(self):

        response = self.test_app.get('/ion-service/list_resource_types')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('Resource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]),
                         len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get(
            '/ion-service/list_resource_types?type=InformationResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('InformationResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]),
                         len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get(
            '/ion-service/list_resource_types?type=TaskableResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('TaskableResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]),
                         len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get(
            '/ion-service/list_resource_types?type=MyFakeResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn(
            'KeyError',
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_EXCEPTION])
        self.assertIn(
            'MyFakeResource',
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def create_data_product_resource(self):

        data_product_create_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "create",
                "params": {
                    "object": {
                        "type_": "DataProduct",
                        "lcstate": "DRAFT",
                        "description": DATA_PRODUCT_DESCRIPTION,
                        "name": DATA_PRODUCT_NAME
                    }
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/resource_registry/create',
            {'payload': simplejson.dumps(data_product_create_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        data_product_id = convert_unicode(response_data[0])
        return data_product_id

    def delete_data_product_resource(self, data_product_id):

        data_product_delete_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "delete",
                "params": {
                    "object_id": data_product_id
                }
            }
        }
        response = self.test_app.post(
            '/ion-service/resource_registry/delete',
            {'payload': simplejson.dumps(data_product_delete_request)})
        self.check_response_headers(response)
        return response

    @attr('SMOKE')
    def test_anonymous_resource_registry_operations_through_gateway(self):
        """
        This test ensures that requests make through the service gateway through messaging to the Resource Registry and
        back; including the support of unicode characters.
        @return:
        """

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=' +
            convert_unicode(DATA_PRODUCT_NAME) + '&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        data_product_id = self.create_data_product_resource()

        data_product_read_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "read",
                "params": {
                    "object_id": data_product_id
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/resource_registry/read',
            {'payload': simplejson.dumps(data_product_read_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        data_product_obj = convert_unicode(
            response.json['data'][GATEWAY_RESPONSE])

        #Verify the the name and description fields containing unicode characters match all the way through couch and the messaging
        self.assertEqual(data_product_obj['name'],
                         convert_unicode(DATA_PRODUCT_NAME))
        self.assertEqual(data_product_obj['description'],
                         convert_unicode(DATA_PRODUCT_DESCRIPTION))

        updated_description_text = data_product_obj[
            'description'] + '---Updated!!'

        #modify some fields in the data for testing update
        data_product_obj['description'] = updated_description_text

        data_product_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {
                    "object": data_product_obj
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/resource_registry/update',
            {'payload': simplejson.dumps(data_product_update_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response = self.test_app.post(
            '/ion-service/resource_registry/read',
            {'payload': simplejson.dumps(data_product_read_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        updated_data_product_obj = convert_unicode(
            response.json['data'][GATEWAY_RESPONSE])
        self.assertEqual(updated_data_product_obj['description'],
                         updated_description_text)

        differ = DictDiffer(updated_data_product_obj, data_product_obj)
        self.assertEqual(
            len(differ.changed()), 2
        )  # Only the _rev and ts_updated fields should be different after an update

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=' +
            convert_unicode(DATA_PRODUCT_NAME) + '&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 1)

        response = self.delete_data_product_resource(data_product_id)
        self.assertIsNone(response.json['data'][GATEWAY_RESPONSE])

        response = self.test_app.post(
            '/ion-service/resource_registry/read',
            {'payload': simplejson.dumps(data_product_read_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn(
            'does not exist',
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=' +
            convert_unicode(DATA_PRODUCT_NAME) + '&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        response = self.delete_data_product_resource(data_product_id)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn(
            'does not exist',
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def test_non_anonymous_resource_registry_operations_through_gateway(self):

        id_client = IdentityManagementServiceClient(node=self.container.node)

        actor_id, valid_until, registered = id_client.signon(
            USER1_CERTIFICATE, True)

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester='
            + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        id_client.delete_actor_identity(actor_id)

    def test_get_resource_schema(self):

        response = self.test_app.get('/ion-service/resource_type_schema/Org')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        org_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(org_obj, dict))
        self.assertIn('object', org_obj)
        self.assertIn('schemas', org_obj)
        self.assertIn('Org', org_obj['schemas'])
        self.assertIn('OrgTypeEnum', org_obj['schemas'])
        self.assertIn('Institution', org_obj['schemas'])

        response = self.test_app.get(
            '/ion-service/resource_type_schema/InstrumentModel')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        model_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(org_obj, dict))
        self.assertIn('object', model_obj)
        self.assertIn('schemas', model_obj)
        self.assertIn('InstrumentModel', model_obj['schemas'])
        self.assertIn('PrimaryInterface', model_obj['schemas'])

        response = self.test_app.get(
            '/ion-service/resource_type_schema/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        data_product_obj = convert_unicode(
            response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(data_product_obj, dict))
        self.assertIn('object', data_product_obj)
        self.assertIn('schemas', data_product_obj)
        self.assertIn('DataProduct', data_product_obj['schemas'])
        self.assertIn('GeospatialBounds', data_product_obj['schemas'])
        self.assertIn('GeospatialCoordinateReferenceSystem',
                      data_product_obj['schemas'])

        response = self.test_app.get(
            '/ion-service/resource_type_schema/DataProduct123')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn(
            'No matching class found',
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def test_get_resource(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get('/ion-resources/resource/' +
                                     data_product_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertNotIn('does not exist', response_data)

        data_product_obj = convert_unicode(response_data)
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)

    def test_list_resources_by_type(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get(
            '/ion-resources/find_resources/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 1)

        data_product_obj = convert_unicode(response_data[0])
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)

    def test_list_org_roles(self):

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=ionsystem')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]

        actor_id = response_data[0][0]['_id']
        response = self.test_app.get('/ion-service/org_roles/' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]

        self.assertIn('ION', response_data)
        self.assertEqual(len(response_data['ION']), 3)
        self.assertIn('ION_MANAGER', response_data['ION'])
        self.assertIn('ORG_MANAGER', response_data['ION'])
        self.assertIn('ORG_MEMBER', response_data['ION'])

    def test_user_role_cache(self):

        #Create a user
        id_client = IdentityManagementServiceClient(node=self.container.node)

        actor_id, valid_until, registered = id_client.signon(
            USER1_CERTIFICATE, True)

        #Make a request with this new user  to get it into the cache
        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester='
            + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        service_gateway_user_cache = self.container.proc_manager.procs_by_name[
            'service_gateway'].user_data_cache
        self.assertEqual(service_gateway_user_cache.has_key(actor_id), True)

        role_header = service_gateway_user_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 1)
        self.assertIn('ORG_MEMBER', role_header['ION'])

        org_client = OrgManagementServiceClient(node=self.container.node)

        ion_org = org_client.find_org()
        manager_role = org_client.find_org_role_by_name(
            org_id=ion_org._id, role_name='ORG_MANAGER')

        org_client.grant_role(org_id=ion_org._id,
                              user_id=actor_id,
                              role_name='ORG_MANAGER')

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        #The user should be evicted from the cache due to a change in roles
        self.assertEqual(service_gateway_user_cache.has_key(actor_id), False)

        #Do it again to check for new roles
        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester='
            + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_cache.has_key(actor_id), True)

        role_header = service_gateway_user_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 2)
        self.assertIn('ORG_MEMBER', role_header['ION'])
        self.assertIn('ORG_MANAGER', role_header['ION'])

        #Now flush the user_role_cache and make sure it was flushed
        event_publisher = EventPublisher()
        event_publisher.publish_event(event_type=OT.UserRoleCacheResetEvent)

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        self.assertEqual(service_gateway_user_cache.has_key(actor_id), False)
        self.assertEqual(service_gateway_user_cache.size(), 0)

        #Change the role once again and see if it is there again
        org_client.revoke_role(org_id=ion_org._id,
                               user_id=actor_id,
                               role_name='ORG_MANAGER')

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        #The user should still not be there
        self.assertEqual(service_gateway_user_cache.has_key(actor_id), False)

        #Do it again to check for new roles
        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester='
            + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_cache.has_key(actor_id), True)

        role_header = service_gateway_user_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 1)
        self.assertIn('ORG_MEMBER', role_header['ION'])

        id_client.delete_actor_identity(actor_id)
class TestServiceGatewayServiceInt(IonIntegrationTestCase):
    def setUp(self):
        # Start container
        self._start_container()
        self.container.start_rel_from_url('res/deploy/r2deploy.yml')

        # Now create client to service
        self.service_gateway_service = ServiceGatewayServiceClient(
            node=self.container.node)

        log.debug('stopping Gateway web server')
        # Stop the web server as it is not needed.
        self.service_gateway_service.stop_service()

        self.test_app = TestApp(service_gateway_app)

    def tearDown(self):
        self._stop_container()

    #Common SGS Response header check
    def check_response_headers(self, response):
        self.assertEqual(response.content_type, "application/json")
        self.assertEqual(len(response.json), 1)
        self.assertIn('data', response.json)

    def test_list_resource_types(self):

        response = self.test_app.get('/ion-service/list_resource_types')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('Resource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]),
                         len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get(
            '/ion-service/list_resource_types?type=InformationResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('InformationResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]),
                         len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get(
            '/ion-service/list_resource_types?type=TaskableResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        expected_type_list = getextends('TaskableResource')

        self.assertEqual(len(response.json['data'][GATEWAY_RESPONSE]),
                         len(expected_type_list))

        result_set = set(response.json['data'][GATEWAY_RESPONSE])
        expected_type_set = set(expected_type_list)

        intersect_result = expected_type_set.intersection(result_set)
        self.assertEqual(len(intersect_result), len(expected_type_list))

        response = self.test_app.get(
            '/ion-service/list_resource_types?type=MyFakeResource')

        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn(
            'KeyError',
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_EXCEPTION])
        self.assertIn(
            'MyFakeResource',
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def create_data_product_resource(self):

        geospatial_bounds = {
            "geospatial_latitude_limit_north": 1.0,
            "geospatial_latitude_limit_south": 1.0,
            "geospatial_longitude_limit_east": 1.0,
            "geospatial_longitude_limit_west": 1.0,
            "geospatial_vertical_min": 1.0,
            "geospatial_vertical_max": 1.0
        }
        data_product_create_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "create",
                "params": {
                    "object": {
                        "type_": "DataProduct",
                        "lcstate": "DRAFT",
                        "description": DATA_PRODUCT_DESCRIPTION,
                        "name": DATA_PRODUCT_NAME,
                        'geospatial_bounds': geospatial_bounds,
                        'temporal_domain': TEMPORAL_DOMAIN
                    }
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/resource_registry/create',
            {'payload': simplejson.dumps(data_product_create_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        data_product_id = convert_unicode(response_data[0])
        return data_product_id

    def create_data_product_resource_full(self):

        geospatial_bounds = {
            "geospatial_latitude_limit_north": 1.0,
            "geospatial_latitude_limit_south": 1.0,
            "geospatial_longitude_limit_east": 1.0,
            "geospatial_longitude_limit_west": 1.0,
            "geospatial_vertical_min": 1.0,
            "geospatial_vertical_max": 1.0
        }

        #create a paramter dictionary the a stream definition for this data product
        DICTIONARY_NAME = 'ctd_parsed_param_dict'
        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=' +
            convert_unicode(DICTIONARY_NAME) +
            '&id_only=True&user_id=123abc456')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        param_dictionary_id = convert_unicode(response_data[0])
        test = str(param_dictionary_id[0])
        log.debug(
            'create_data_product_resource_full  param_dictionary_id:  %s',
            param_dictionary_id)
        log.debug('create_data_product_resource_full  test:  %s', test)

        response = self.test_app.get(
            '/ion-service/pubsub_management/create_stream_definition?name=CTDData&parameter_dictionary_id='
            + convert_unicode(param_dictionary_id[0]))
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        log.debug('create_data_product_resource_full   response_data:  %s',
                  response_data)
        stream_definition_id = convert_unicode(response_data)
        log.debug(
            'create_data_product_resource_full  stream_definition_id:  %s',
            stream_definition_id)

        data_product_create_request = {
            "serviceRequest": {
                "serviceName": "data_product_management",
                "serviceOp": "create_data_product",
                "params": {
                    "data_product": {
                        "type_": "DataProduct",
                        "lcstate": "DRAFT",
                        "description": DATA_PRODUCT_DESCRIPTION,
                        "name": DATA_PRODUCT_NAME,
                        'geospatial_bounds': geospatial_bounds,
                        'temporal_domain': TEMPORAL_DOMAIN
                    },
                    "stream_definition_id": stream_definition_id
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/data_product_management/create_data_product',
            {'payload': simplejson.dumps(data_product_create_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        log.debug(
            'create_data_product_resource_full  create_data_product response_data:  %s',
            response_data)
        #self.assertEqual(len(response_data), 2 )
        data_product_id = convert_unicode(response_data)
        return data_product_id

    def delete_data_product_resource(self, data_product_id):

        data_product_delete_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "delete",
                "params": {
                    "object_id": data_product_id
                }
            }
        }
        response = self.test_app.post(
            '/ion-service/resource_registry/delete',
            {'payload': simplejson.dumps(data_product_delete_request)})
        self.check_response_headers(response)
        return response

    def create_policy_resource(self):

        policy_create_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "create",
                "params": {
                    "object": {
                        "definition": {},
                        "name": POLICY_NAME,
                        "description": POLICY_DESCRIPTION,
                        "lcstate": "DRAFT",
                        "required": True,
                        "enabled": True,
                        "type_": "Policy",
                        "policy_type": {
                            "policy_rule": POLICY_RULE,
                            "service_name": "user_notification",
                            "type_": "ServiceAccessPolicy"
                        }
                    }
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/resource_registry/create',
            {'payload': simplejson.dumps(policy_create_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        policy_id = convert_unicode(response_data[0])
        return policy_id

    @attr('SMOKE')
    def test_anonymous_resource_registry_operations_through_gateway(self):
        """
        This test ensures that requests make through the service gateway through messaging to the Resource Registry and
        back; including the support of unicode characters.
        @return:
        """

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=' +
            convert_unicode(DATA_PRODUCT_NAME) +
            '&id_only=True&user_id=123abc456')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        data_product_id = self.create_data_product_resource()

        data_product_read_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "read",
                "params": {
                    "object_id": data_product_id
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/resource_registry/read',
            {'payload': simplejson.dumps(data_product_read_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        data_product_obj = convert_unicode(
            response.json['data'][GATEWAY_RESPONSE])

        #Verify the the name and description fields containing unicode characters match all the way through couch and the messaging
        self.assertEqual(data_product_obj['name'],
                         convert_unicode(DATA_PRODUCT_NAME))
        self.assertEqual(data_product_obj['description'],
                         convert_unicode(DATA_PRODUCT_DESCRIPTION))

        updated_description_text = data_product_obj[
            'description'] + '---Updated!!'

        #modify some fields in the data for testing update
        data_product_obj['description'] = updated_description_text

        data_product_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {
                    "object": data_product_obj
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/resource_registry/update',
            {'payload': simplejson.dumps(data_product_update_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response = self.test_app.post(
            '/ion-service/resource_registry/read',
            {'payload': simplejson.dumps(data_product_read_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        updated_data_product_obj = convert_unicode(
            response.json['data'][GATEWAY_RESPONSE])
        self.assertEqual(updated_data_product_obj['description'],
                         updated_description_text)

        differ = DictDiffer(updated_data_product_obj, data_product_obj)
        self.assertEqual(
            len(differ.changed()), 2
        )  # Only the _rev and ts_updated fields should be different after an update

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=' +
            convert_unicode(DATA_PRODUCT_NAME) + '&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 1)

        response = self.delete_data_product_resource(data_product_id)
        self.assertIsNone(response.json['data'][GATEWAY_RESPONSE])

        response = self.test_app.post(
            '/ion-service/resource_registry/read',
            {'payload': simplejson.dumps(data_product_read_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn(
            'does not exist',
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=' +
            convert_unicode(DATA_PRODUCT_NAME) + '&id_only=True')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        response = self.delete_data_product_resource(data_product_id)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn(
            'does not exist',
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

        #Now try creating a policy object which has an internal object of a different type
        policy_id = self.create_policy_resource()

        policy_read_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "read",
                "params": {
                    "object_id": policy_id
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/resource_registry/read',
            {'payload': simplejson.dumps(policy_read_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        policy_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])

        #Verify the the name and description fields containing unicode characters match all the way through couch and the messaging
        self.assertEqual(policy_obj['name'], convert_unicode(POLICY_NAME))
        self.assertEqual(policy_obj['description'],
                         convert_unicode(POLICY_DESCRIPTION))
        self.assertEqual(policy_obj['policy_type']['policy_rule'],
                         convert_unicode(POLICY_RULE))

        updated_policy_rule = policy_obj['policy_type'][
            'policy_rule'] + '---Updated!!'

        #modify some fields in the data for testing update
        policy_obj['policy_type']['policy_rule'] = updated_policy_rule

        policy_update_request = {
            "serviceRequest": {
                "serviceName": "resource_registry",
                "serviceOp": "update",
                "params": {
                    "object": policy_obj
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/resource_registry/update',
            {'payload': simplejson.dumps(policy_update_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response = self.test_app.post(
            '/ion-service/resource_registry/read',
            {'payload': simplejson.dumps(policy_read_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        updated_policy_obj = convert_unicode(
            response.json['data'][GATEWAY_RESPONSE])
        self.assertEqual(updated_policy_obj['policy_type']['policy_rule'],
                         updated_policy_rule)

        #Now testing the generic get_resource_extension with optional user_id parameter

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=ionsystem')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]

        actor_id = response_data[0][0]['_id']

        response = self.test_app.get(
            '/ion-service/resource_registry/get_resource_extension?resource_id='
            + actor_id + '&resource_extension=TestExtendedInformationResource')
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(convert_unicode(response_data['user_id']), '')

        response = self.test_app.get(
            '/ion-service/resource_registry/get_resource_extension?resource_id='
            + actor_id +
            '&resource_extension=TestExtendedInformationResource&user_id=123abc456'
        )
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(convert_unicode(response_data['user_id']),
                         '123abc456')

    def test_non_anonymous_resource_registry_operations_through_gateway(self):

        id_client = IdentityManagementServiceClient(node=self.container.node)

        actor_id, valid_until, registered = id_client.signon(
            USER1_CERTIFICATE, True)

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester='
            + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 2)
        self.assertEqual(len(response_data[0]), 0)

        id_client.delete_actor_identity(actor_id)

    def test_get_resource_schema(self):

        response = self.test_app.get('/ion-service/resource_type_schema/Org')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        org_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(org_obj, dict))
        self.assertIn('object', org_obj)
        self.assertIn('schemas', org_obj)
        self.assertIn('Org', org_obj['schemas'])
        self.assertIn('OrgTypeEnum', org_obj['schemas'])
        self.assertIn('Institution', org_obj['schemas'])

        response = self.test_app.get(
            '/ion-service/resource_type_schema/InstrumentModel')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        model_obj = convert_unicode(response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(org_obj, dict))
        self.assertIn('object', model_obj)
        self.assertIn('schemas', model_obj)
        self.assertIn('InstrumentModel', model_obj['schemas'])
        self.assertIn('PrimaryInterface', model_obj['schemas'])

        response = self.test_app.get(
            '/ion-service/resource_type_schema/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        data_product_obj = convert_unicode(
            response.json['data'][GATEWAY_RESPONSE])
        self.assertTrue(isinstance(data_product_obj, dict))
        self.assertIn('object', data_product_obj)
        self.assertIn('schemas', data_product_obj)
        self.assertIn('DataProduct', data_product_obj['schemas'])
        self.assertIn('GeospatialBounds', data_product_obj['schemas'])
        self.assertIn('GeospatialCoordinateReferenceSystem',
                      data_product_obj['schemas'])

        response = self.test_app.get(
            '/ion-service/resource_type_schema/DataProduct123')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_ERROR, response.json['data'])
        self.assertIn(
            'No matching class found',
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_MESSAGE])
        self.assertIsNotNone(
            response.json['data'][GATEWAY_ERROR][GATEWAY_ERROR_TRACE])

    def test_get_resource(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get('/ion-resources/resource/' +
                                     data_product_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertNotIn('does not exist', response_data)

        data_product_obj = convert_unicode(response_data)
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)

    def test_list_resources_by_type(self):

        data_product_id = self.create_data_product_resource()

        response = self.test_app.get(
            '/ion-resources/find_resources/DataProduct')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        self.assertEqual(len(response_data), 1)

        data_product_obj = convert_unicode(response_data[0])
        self.assertEqual(data_product_id, data_product_obj['_id'])

        self.delete_data_product_resource(data_product_id)

    def test_list_org_roles(self):

        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=ionsystem')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]

        actor_id = response_data[0][0]['_id']
        response = self.test_app.get('/ion-service/org_roles/' + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]

        self.assertIn('ION', response_data)
        self.assertEqual(len(response_data['ION']), 3)
        self.assertIn('ION_MANAGER', response_data['ION'])
        self.assertIn('ORG_MANAGER', response_data['ION'])
        self.assertIn('ORG_MEMBER', response_data['ION'])

    def test_user_role_cache(self):

        #Create a user
        id_client = IdentityManagementServiceClient(node=self.container.node)

        actor_id, valid_until, registered = id_client.signon(
            USER1_CERTIFICATE, True)

        #Make a request with this new user  to get it into the cache
        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester='
            + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        service_gateway_user_role_cache = self.container.proc_manager.procs_by_name[
            'service_gateway'].user_role_cache
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id),
                         True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 1)
        self.assertIn('ORG_MEMBER', role_header['ION'])

        org_client = OrgManagementServiceClient(node=self.container.node)

        ion_org = org_client.find_org()
        manager_role = org_client.find_org_role_by_name(
            org_id=ion_org._id, role_name='ORG_MANAGER')

        org_client.grant_role(org_id=ion_org._id,
                              actor_id=actor_id,
                              role_name='ORG_MANAGER')

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        #The user should be evicted from the cache due to a change in roles
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id),
                         False)

        #Do it again to check for new roles
        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester='
            + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id),
                         True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 2)
        self.assertIn('ORG_MEMBER', role_header['ION'])
        self.assertIn('ORG_MANAGER', role_header['ION'])

        #Now flush the user_role_cache and make sure it was flushed
        event_publisher = EventPublisher()
        event_publisher.publish_event(event_type=OT.UserRoleCacheResetEvent)

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id),
                         False)
        self.assertEqual(service_gateway_user_role_cache.size(), 0)

        #Change the role once again and see if it is there again
        org_client.revoke_role(org_id=ion_org._id,
                               actor_id=actor_id,
                               role_name='ORG_MANAGER')

        #Just allow some time for event processing on slower platforms
        gevent.sleep(2)

        #The user should still not be there
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id),
                         False)

        #Do it again to check for new roles
        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=TestDataProduct&id_only=True&requester='
            + actor_id)
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])

        #Check the contents of the user role cache for this user
        self.assertEqual(service_gateway_user_role_cache.has_key(actor_id),
                         True)

        role_header = service_gateway_user_role_cache.get(actor_id)
        self.assertIn('ION', role_header)
        self.assertEqual(len(role_header['ION']), 1)
        self.assertIn('ORG_MEMBER', role_header['ION'])

        id_client.delete_actor_identity(actor_id)

    def test_data_provenance_retrieve(self):

        data_product_id = self.create_data_product_resource_full()
        get_parameter_provenance_visualization_image_request = {
            "serviceRequest": {
                "serviceName": "service_gateway",
                "serviceOp": "get_parameter_provenance_visualization_image",
                "params": {
                    "data_product_id": data_product_id,
                    "parameter_name": "temp"
                }
            }
        }

        #call the gateway service intermeditary operation to get the image from the data product mgmt svc
        response = self.test_app.post(
            '/ion-service/get_parameter_provenance_visualization_image', {
                'payload':
                simplejson.dumps(
                    get_parameter_provenance_visualization_image_request)
            })
        #log.debug('test_data_provenance_retrieve  response:  %s', response)

        self.assertIsNotNone(response)