def test_get_user_secrets(self):
        """Vanilla test case for get_user_secrets

        Utility function for reading user secrets from configured location
        """
        # Setting up config object
        tc = UtilsTestConfig()

        with tempfile.NamedTemporaryFile(mode="w", suffix=".json") as temp_secrets_file, \
                tempfile.NamedTemporaryFile(mode="w", suffix=".json") as temp_user_secrets_file:
            json.dump(self.test_secrets, temp_secrets_file)
            json.dump(self.test_user_secrets, temp_user_secrets_file)
            temp_secrets_file.flush()
            temp_user_secrets_file.flush()

            tc.SECRETS_FILE = temp_secrets_file.name
            tc.USER_SECRETS_FILE = temp_user_secrets_file.name  # *not* reusing the temp file
            tc.USER_SECRETS_SALT_KEY = self.test_secret_key
            current_app.config.from_object(tc)
            util.flush_caches()

            util.get_secrets(flush_cache=True)
            util.get_user_secrets(flush_cache=True)
            util.secure_mode(flush_cache=True)
            user_secrets = util.get_user_secrets()

        self.assertDictEqual(user_secrets, self.test_user_secrets,
                             "User secrets not loaded correctly")
    def test_get_secrets(self):
        """Vanilla test case for get_secrets

        Utility function for reading secrets from configured location
        """
        # Setting up config object
        tc = UtilsTestConfig()

        with tempfile.NamedTemporaryFile(mode="w",
                                         suffix=".json") as temp_secrets_file:
            json.dump(self.test_secrets, temp_secrets_file)
            temp_secrets_file.flush()

            tc.SECRETS_FILE = temp_secrets_file.name
            current_app.config.from_object(tc)
            util.flush_caches()

            secrets = util.get_secrets()
            secrets2 = util.get_secrets()
            secrets3 = util.get_secrets(flush_cache=True)

        self.assertDictEqual(
            secrets, self.test_secrets,
            "get_secrets not reading secrets from configured location")

        # Checking that cache (and its flush) is working as expected
        self.assertIs(secrets, secrets2,
                      "get_secrets cache is not working as expected")
        self.assertIsNot(secrets, secrets3,
                         "get_secrets cache flush is not happening")
    def setUp(self) -> None:
        credentials = base64.b64encode(b"test_user:test_password").decode('utf-8')
        self.authorisation_headers = {"Authorization": "Basic {}".format(credentials)}

        # Setting up the GeoLookup data files
        tc = GeoLookupTestConfig()

        self.temp_dir = tempfile.TemporaryDirectory()
        tc.GEOLOOKUP_DATASET_DIR = self.temp_dir.name

        temp_geojson = {
            "type": "FeatureCollection",
            "features": [{
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    "coordinates": [0.0, 0.0]
                },
                "properties": {
                    "temp_id": "centre_of_the_world"
                }}]
        }
        temp_layer_file_path = self.temp_dir.name + "temp_layer.geojson"
        with open(temp_layer_file_path, "w") as temp_layer_file:
            json.dump(temp_geojson, temp_layer_file)

        tc.GEOLOOKUP_DATASET_CONFIG = {
            "temp_layer": (temp_layer_file.name, "temp_id")
        }
        current_app.config.from_object(tc)
        util.flush_caches()
Esempio n. 4
0
 def setUp(self) -> None:
     credentials = base64.b64encode(b"test_user:test_password").decode(
         'utf-8')
     self.authorisation_headers = {
         "Authorization": "Basic {}".format(credentials)
     }
     current_app.config.from_object(ScrubTestConfig)
     util.flush_caches()
    def test_configurable_geocoders(self):
        """Testing get_geocoders sets up a configurable geocoder correctly.
        This test does double duty, as the config mechanism is shared with get_scrubbers.

        Configurable geocoders are geocoders that need additional config (e.g. secrets)
        """
        # Setting up config object
        tc = UtilsTestConfig()

        random_value = random.random()
        tc.SOME_RANDOM_VALUE = random_value
        tc.GEOCODERS = ((test_geocode_controller.MockGeocoder, {
            "proxy_url": [config.ConfigNamespace.CONFIG, "SOME_RANDOM_VALUE"]
        }), (test_geocode_controller.MockGeocoder, {
            "proxy_url":
            [config.ConfigNamespace.SECRETS, self.test_secret_key]
        }), (test_geocode_controller.MockGeocoder, {
            "proxy_url":
            [config.ConfigNamespace.CONFIG, "SOME_OTHER_RANDOM_VALUE"]
        }))

        # Setting secrets values
        with tempfile.NamedTemporaryFile(mode="w",
                                         suffix=".json") as temp_secrets_file:
            json.dump(self.test_secrets, temp_secrets_file)
            temp_secrets_file.flush()

            tc.SECRETS_FILE = temp_secrets_file.name
            tc.USER_SECRETS_FILE = temp_secrets_file.name  # reusing the temp file
            tc.USER_SECRETS_SALT_KEY = self.test_secret_key

            # Actually configuring the app
            current_app.config.from_object(tc)
            util.flush_caches()

            # Testing the configuration from config namespace works
            gc, *_ = util.get_geocoders(flush_cache=True)
            self.assertIsInstance(
                gc, test_geocode_controller.MockGeocoder,
                "Configurable geocoder using config namespace not being returned"
            )
            self.assertEqual(
                gc.proxy_url, random_value,
                "Configurable geocoder using config namespace not being configured correctly"
            )

            _, gc2, *_ = util.get_geocoders()
            self.assertIsInstance(
                gc, test_geocode_controller.MockGeocoder,
                "Configurable geocoder using secrets namespace not being returned"
            )
            self.assertEqual(
                gc2.proxy_url, self.test_secret_value,
                "Configurable geocoder using secrets namespace not being configured correctly"
            )

            self.assertEqual(len(util.get_geocoders(flush_cache=True)), 2,
                             "Wrong number of geocoders being returned")
    def test_secure_auth(self):
        """Tests for auth in secure mode

        Service should only allow valid usernames to call
        """
        # Setting up config object
        tc = AuthorizationTestConfig()

        with tempfile.NamedTemporaryFile(mode="w", suffix=".json") as temp_secrets_file, \
                tempfile.NamedTemporaryFile(mode="w", suffix=".json") as temp_user_secrets_file:
            json.dump(self.test_secrets, temp_secrets_file)
            json.dump(self.test_user_secrets, temp_user_secrets_file)
            temp_secrets_file.flush()
            temp_user_secrets_file.flush()

            tc.SECRETS_FILE = temp_secrets_file.name
            tc.USER_SECRETS_FILE = temp_user_secrets_file.name
            tc.USER_SECRETS_SALT_KEY = self.test_secret_key

            current_app.config.from_object(tc)
            util.flush_caches()

            current_app.logger.info(f"**Happy Case Test**")
            query_string = [('address', 'address_example')]
            # Testing the happy case
            response = self.client.open(
                '/v1/scrub',
                method='GET',
                query_string=query_string,
                headers=self.authorisation_headers
            )
            self.assert200(response,
                           'Response body is : ' + response.data.decode('utf-8'))

            # Testing the unhappy case (no creds)
            current_app.logger.info(f"**Unhappy Case Test**")
            response2 = self.client.open(
                '/v1/scrub',
                method='GET',
                query_string=query_string,
            )
            self.assert401(response2,
                           'Response body is : ' + response2.data.decode('utf-8'))

            # Testing the unhappy case (bad creds)
            current_app.logger.info(f"**Unhappy Case Test 2**")
            credentials = base64.b64encode(b"Fanny:your aunt").decode('utf-8')
            authorisation_headers2 = {"Authorization": "Basic {}".format(credentials)}

            response3 = self.client.open(
                '/v1/scrub',
                method='GET',
                query_string=query_string,
                headers=authorisation_headers2
            )
            self.assert401(response3,
                           'Response body is : ' + response3.data.decode('utf-8'))
Esempio n. 7
0
    def test_geocode(self):
        """Vanilla test case for geocode

        Translate a free form address into a spatial coordinate
        """
        tc = GeocoderTestConfig()
        tc.GEOCODERS = [
            (
                MockGeocoder, {}
            ),
        ]
        current_app.config.from_object(tc)
        util.flush_caches()

        query_string = [('address', 'address_example')]
        response = self.client.open(
            '/v1/geocode',
            method='GET',
            query_string=query_string,
            headers=self.authorisation_headers
        )
        self.assert200(response,
                       'Response body is : ' + response.data.decode('utf-8'))

        # Asserting that we get back the results we expect
        data_dict = json.loads(response.data)
        self.assertIn("results", data_dict)
        results = data_dict["results"]
        self.assertEqual(2, len(data_dict["results"]), "Geocoder is not returning the expected number of test results")

        # Inspecting the result itself
        result, *_ = results
        self.assertEqual(result["geocoder_id"], MockGeocoder.__name__, "Geocode ID not mapped through correctly")
        self.assertEqual(result["confidence"], 1, "Geocoder confidence not mapped through correctly")
        result_dict = json.loads(result["geocoded_value"])
        self.assertDictEqual(
            {"features": [
                {"geometry": {"coordinates": [0.000, 0.0001], "type": "Point"},
                 "properties": {"address": "address_example"}, "type": "Feature"}],
                "type": "FeatureCollection"},
            result_dict,
            "Geocoded value not mapped through correctly"
        )

        # Inspecting the second result (the combined result)
        *_, result2 = results
        result_dict2 = json.loads(result2["geocoded_value"])
        self.assertDictEqual(
            {"features": [
                {"geometry": {"coordinates": [0.0, 0.0001], "type": "Point"},
                 "properties": {"geocoders": ["MockGeocoder"]}, "type": "Feature"}],
                "type": "FeatureCollection"},
            result_dict2,
            "Combined geocoded value not mapped through correctly"

        )
    def setUp(self) -> None:
        self.test_secret_key = "Bob"
        self.test_secret_value = "your uncle"
        self.test_secrets = {self.test_secret_key: self.test_secret_value}

        self.test_user_secrets = {
            '3d224707797b570fe4523f6ff4b9d68be72815d80c19530000919efad9e6cfe2':  # sha256("Bob" + "your uncle")
                '037525e1e2b6f9f169c483caf4aba43bc50885fdb9a2efe023635cd9534999ab'
            # sha256("your uncle" + "your uncle")
        }

        cred_string = f"{self.test_secret_key}:{self.test_secret_value}"
        credentials = base64.b64encode(cred_string.encode('utf-8')).decode('utf-8')
        self.authorisation_headers = {"Authorization": "Basic {}".format(credentials)}
        current_app.logger.debug(f"self.authorisation_headers={self.authorisation_headers}")

        current_app.config.from_object(AuthorizationTestConfig)
        util.flush_caches()
Esempio n. 9
0
    def test_bad_gecode(self):
        """Testing the behaviour around failed geocoding AKA SAD CASE TESTS

        """
        tc = GeocoderTestConfig()
        tc.GEOCODERS = [
            (
                MockGeocoder, {}
            ),
            (
                BadMockGeocoder, {}
            ),
        ]
        current_app.config.from_object(tc)
        util.flush_caches()

        query_string = [('address', 'address_example')]
        response = self.client.open(
            '/v1/geocode',
            method='GET',
            query_string=query_string,
            headers=self.authorisation_headers
        )

        data_dict = json.loads(response.data)
        results = data_dict["results"]
        # For now, the expected behaviour is just to pass through failed geocodes with null values.
        self.assertEqual(3, len(results), "Geocoder is not returning the expected number of test results")

        _, bad_result, _ = results
        self.assertEqual(bad_result["confidence"], 0, "Failed geocoder confidence not mapped through correctly")
        result = json.loads(bad_result["geocoded_value"])
        self.assertIsNone(result, "Failed geocoder not returning a null result")

        *_, combined_result = results
        result_dict = json.loads(combined_result["geocoded_value"])
        self.assertDictEqual(
            {"features": [
                {"geometry": {"coordinates": [0.0, 0.0001], "type": "Point"},
                 "properties": {"geocoders": ["MockGeocoder"]}, "type": "Feature"}],
                "type": "FeatureCollection"},
            result_dict,
            "Combined geocoded value not excluding bad geocoder properly"
        )
    def test_secure_mode(self):
        """Vanilla test case for secure_mode

        Utility function for determining whether the app should start in secure mode
        """
        # Setting up config object
        tc = UtilsTestConfig()

        with tempfile.NamedTemporaryFile(mode="w",
                                         suffix=".json") as temp_secrets_file:
            json.dump(self.test_secrets, temp_secrets_file)
            temp_secrets_file.flush()

            tc.SECRETS_FILE = temp_secrets_file.name
            tc.USER_SECRETS_FILE = temp_secrets_file.name  # reusing the temp file
            tc.USER_SECRETS_SALT_KEY = self.test_secret_key
            current_app.config.from_object(tc)
            util.flush_caches()

            secure_mode = util.secure_mode()

        self.assertTrue(secure_mode, "Secure mode not correctly detected")

        # The user secrets file shouldn't exist at this point
        secure_mode2 = util.secure_mode(flush_cache=True)
        self.assertFalse(
            secure_mode2,
            "Secure mode *shouldn't* be detected because the user secrets doesn't exist"
        )

        # Testing that the salt not existing is
        tc.USER_SECRETS_SALT_KEY = "doesn't-exist"
        current_app.config.from_object(tc)
        util.flush_caches()
        secure_mode2 = util.secure_mode(flush_cache=False)
        self.assertFalse(
            secure_mode2,
            "Secure mode *shouldn't* be detected because the user secrets salt doesn't exist"
        )
    def test_auth_user(self):
        """Vanilla test case for auth_user

        Utility function for confirming that user matches what is in the records
        """
        # Setting up config object
        tc = UtilsTestConfig()

        with tempfile.NamedTemporaryFile(mode="w", suffix=".json") as temp_secrets_file, \
                tempfile.NamedTemporaryFile(mode="w", suffix=".json") as temp_user_secrets_file:
            json.dump(self.test_secrets, temp_secrets_file)
            json.dump(self.test_user_secrets, temp_user_secrets_file)
            temp_secrets_file.flush()
            temp_user_secrets_file.flush()

            tc.SECRETS_FILE = temp_secrets_file.name
            tc.USER_SECRETS_FILE = temp_user_secrets_file.name  # *not* reusing the temp file
            tc.USER_SECRETS_SALT_KEY = self.test_secret_key
            current_app.config.from_object(tc)
            util.flush_caches()

            util.get_secrets(flush_cache=True)
            util.get_user_secrets(flush_cache=True)
            util.secure_mode(flush_cache=True)
            user_auth_check = util.auth_user(self.test_secret_key,
                                             self.test_secret_value)

        self.assertTrue(user_auth_check, "User auth not successful")

        user_auth_check2 = util.auth_user(self.test_secret_key, "blah")
        self.assertFalse(
            user_auth_check2,
            "User auth successful despite the password being wrong!")

        user_auth_check3 = util.auth_user("foo", self.test_secret_value)
        self.assertFalse(
            user_auth_check2,
            "User auth successful despite the username being wrong!")
Esempio n. 12
0
    def test_combined_gecode(self):
        """Testing that combined geocode result is blended into results

        """
        tc = GeocoderTestConfig()
        tc.GEOCODERS = [
            (
                MockGeocoder, {}
            ),
            (
                MockGeocoder2, {}
            ),
        ]
        current_app.config.from_object(tc)
        util.flush_caches()

        query_string = [('address', 'address_example')]
        response = self.client.open(
            '/v1/geocode',
            method='GET',
            query_string=query_string,
            headers=self.authorisation_headers
        )

        data_dict = json.loads(response.data)
        results = data_dict["results"]
        self.assertEqual(3, len(results), "Geocoder is not returning the expected number of test results")

        *_, combined_result = results
        result_dict = json.loads(combined_result["geocoded_value"])
        self.assertDictEqual(
            {"features": [
                {"geometry": {"coordinates": [0.00005, 0.0001], "type": "Point"},
                 "properties": {"geocoders": ["MockGeocoder", "MockGeocoder2"]}, "type": "Feature"}],
                "type": "FeatureCollection"},
            result_dict,
            "Combined geocoded value not mapped through correctly"
        )
    def test_get_geocoders(self):
        """Vanilla test case for get_geocoders

        Utility function for setting up and configuring geocoder objects
        """
        # Setting up config object
        tc = UtilsTestConfig()
        tc.GEOCODERS = ((test_geocode_controller.MockGeocoder, {}), )
        current_app.config.from_object(tc)

        # Testing that we get back an instance of the configured geocoder
        gc, *_ = util.get_geocoders()
        self.assertIsInstance(
            gc, test_geocode_controller.MockGeocoder,
            "config is not plumbing through to get_geocoders correctly")

        # Checking that the cache is working
        gc2, *_ = util.get_geocoders()
        self.assertIs(gc, gc2,
                      "get_geocoders cache is not working as expected")

        # Flushing the cache and checking we get a new geocoder instance
        gc3, *_ = util.get_geocoders(flush_cache=True)
        self.assertIsNot(gc, gc3, "get_geocoders cache flush is not happening")

        # Checking that that the min geocoders check works
        tc = UtilsTestConfig()
        tc.GEOCODERS = []
        tc.GEOCODERS_MIN = 1
        current_app.config.from_object(tc)

        with self.assertRaises(
                AssertionError,
                msg="get_geocoders did not raise an assertion error as expected"
        ):
            util.flush_caches()