Ejemplo n.º 1
0
    def test_import_v1_chart_validation(self):
        """Test different validations applied when importing a chart"""
        # metadata.yaml must be present
        contents = {
            "databases/imported_database.yaml":
            yaml.safe_dump(database_config),
            "datasets/imported_dataset.yaml": yaml.safe_dump(dataset_config),
            "charts/imported_chart.yaml": yaml.safe_dump(chart_config),
        }
        command = ImportChartsCommand(contents)
        with pytest.raises(IncorrectVersionError) as excinfo:
            command.run()
        assert str(excinfo.value) == "Missing metadata.yaml"

        # version should be 1.0.0
        contents["metadata.yaml"] = yaml.safe_dump({
            "version":
            "2.0.0",
            "type":
            "SqlaTable",
            "timestamp":
            "2020-11-04T21:27:44.423819+00:00",
        })
        command = ImportChartsCommand(contents)
        with pytest.raises(IncorrectVersionError) as excinfo:
            command.run()
        assert str(excinfo.value) == "Must be equal to 1.0.0."

        # type should be Slice
        contents["metadata.yaml"] = yaml.safe_dump(database_metadata_config)
        command = ImportChartsCommand(contents)
        with pytest.raises(CommandInvalidError) as excinfo:
            command.run()
        assert str(excinfo.value) == "Error importing chart"
        assert excinfo.value.normalized_messages() == {
            "metadata.yaml": {
                "type": ["Must be equal to Slice."]
            }
        }

        # must also validate datasets and databases
        broken_config = database_config.copy()
        del broken_config["database_name"]
        contents["metadata.yaml"] = yaml.safe_dump(chart_metadata_config)
        contents["databases/imported_database.yaml"] = yaml.safe_dump(
            broken_config)
        command = ImportChartsCommand(contents)
        with pytest.raises(CommandInvalidError) as excinfo:
            command.run()
        assert str(excinfo.value) == "Error importing chart"
        assert excinfo.value.normalized_messages() == {
            "databases/imported_database.yaml": {
                "database_name": ["Missing data for required field."],
            }
        }
Ejemplo n.º 2
0
    def test_import_v1_saved_queries_validation(self):
        """Test different validations applied when importing a saved query"""
        # metadata.yaml must be present
        contents = {
            "databases/imported_database.yaml": yaml.safe_dump(database_config),
            "queries/imported_query.yaml": yaml.safe_dump(saved_queries_config),
        }
        command = ImportSavedQueriesCommand(contents)
        with pytest.raises(IncorrectVersionError) as excinfo:
            command.run()
        assert str(excinfo.value) == "Missing metadata.yaml"

        # version should be 1.0.0
        contents["metadata.yaml"] = yaml.safe_dump(
            {
                "version": "2.0.0",
                "type": "SavedQuery",
                "timestamp": "2021-03-30T20:37:54.791187+00:00",
            }
        )
        command = ImportSavedQueriesCommand(contents)
        with pytest.raises(IncorrectVersionError) as excinfo:
            command.run()
        assert str(excinfo.value) == "Must be equal to 1.0.0."

        # type should be a SavedQuery
        contents["metadata.yaml"] = yaml.safe_dump(database_metadata_config)
        command = ImportSavedQueriesCommand(contents)
        with pytest.raises(CommandInvalidError) as excinfo:
            command.run()
        assert str(excinfo.value) == "Error importing saved_queries"
        assert excinfo.value.normalized_messages() == {
            "metadata.yaml": {"type": ["Must be equal to SavedQuery."]}
        }

        # must also validate databases
        broken_config = database_config.copy()
        del broken_config["database_name"]
        contents["metadata.yaml"] = yaml.safe_dump(saved_queries_metadata_config)
        contents["databases/imported_database.yaml"] = yaml.safe_dump(broken_config)
        command = ImportSavedQueriesCommand(contents)
        with pytest.raises(CommandInvalidError) as excinfo:
            command.run()
        assert str(excinfo.value) == "Error importing saved_queries"
        assert excinfo.value.normalized_messages() == {
            "databases/imported_database.yaml": {
                "database_name": ["Missing data for required field."],
            }
        }
Ejemplo n.º 3
0
    def test_import_database_masked_password_provided(self):
        """
        Database API: Test import database with masked password provided
        """
        self.login(username="******")
        uri = "api/v1/database/import/"

        masked_database_config = database_config.copy()
        masked_database_config[
            "sqlalchemy_uri"] = "postgresql://*****:*****@host:12345/db"

        buf = BytesIO()
        with ZipFile(buf, "w") as bundle:
            with bundle.open("database_export/metadata.yaml", "w") as fp:
                fp.write(yaml.safe_dump(database_metadata_config).encode())
            with bundle.open(
                    "database_export/databases/imported_database.yaml",
                    "w") as fp:
                fp.write(yaml.safe_dump(masked_database_config).encode())
        buf.seek(0)

        form_data = {
            "formData": (buf, "database_export.zip"),
            "passwords":
            json.dumps({"databases/imported_database.yaml": "SECRET"}),
        }
        rv = self.client.post(uri,
                              data=form_data,
                              content_type="multipart/form-data")
        response = json.loads(rv.data.decode("utf-8"))

        assert rv.status_code == 200
        assert response == {"message": "OK"}

        database = (db.session.query(Database).filter_by(
            uuid=database_config["uuid"]).one())
        assert database.database_name == "imported_database"
        assert (database.sqlalchemy_uri ==
                "postgresql://*****:*****@host:12345/db")
        assert database.password == "SECRET"

        db.session.delete(database)
        db.session.commit()
Ejemplo n.º 4
0
 def test_import_v1_database_masked_password(self):
     """Test that database imports with masked passwords are rejected"""
     masked_database_config = database_config.copy()
     masked_database_config[
         "sqlalchemy_uri"
     ] = "postgresql://*****:*****@host:12345/db"
     contents = {
         "metadata.yaml": yaml.safe_dump(database_metadata_config),
         "databases/imported_database.yaml": yaml.safe_dump(masked_database_config),
     }
     command = ImportDatabasesCommand(contents)
     with pytest.raises(CommandInvalidError) as excinfo:
         command.run()
     assert str(excinfo.value) == "Error importing database"
     assert excinfo.value.normalized_messages() == {
         "databases/imported_database.yaml": {
             "_schema": ["Must provide a password for the database"]
         }
     }
Ejemplo n.º 5
0
    def test_import_database_masked_password(self):
        """
        Database API: Test import database with masked password
        """
        self.login(username="******")
        uri = "api/v1/database/import/"

        masked_database_config = database_config.copy()
        masked_database_config[
            "sqlalchemy_uri"] = "postgresql://*****:*****@host:12345/db"

        buf = BytesIO()
        with ZipFile(buf, "w") as bundle:
            with bundle.open("database_export/metadata.yaml", "w") as fp:
                fp.write(yaml.safe_dump(database_metadata_config).encode())
            with bundle.open(
                    "database_export/databases/imported_database.yaml",
                    "w") as fp:
                fp.write(yaml.safe_dump(masked_database_config).encode())
            with bundle.open("database_export/datasets/imported_dataset.yaml",
                             "w") as fp:
                fp.write(yaml.safe_dump(dataset_config).encode())
        buf.seek(0)

        form_data = {
            "formData": (buf, "database_export.zip"),
        }
        rv = self.client.post(uri,
                              data=form_data,
                              content_type="multipart/form-data")
        response = json.loads(rv.data.decode("utf-8"))

        assert rv.status_code == 422
        assert response == {
            "message": {
                "databases/imported_database.yaml": {
                    "_schema": ["Must provide a password for the database"]
                }
            }
        }
    def test_import_v1_database_multiple(self):
        """Test that a database can be imported multiple times"""
        num_databases = db.session.query(Database).count()

        contents = {
            "databases/imported_database.yaml": yaml.safe_dump(database_config),
            "metadata.yaml": yaml.safe_dump(database_metadata_config),
        }
        command = ImportDatabasesCommand(contents)

        # import twice
        command.run()
        command.run()

        database = (
            db.session.query(Database).filter_by(uuid=database_config["uuid"]).one()
        )
        assert database.allow_csv_upload

        # update allow_csv_upload to False
        new_config = database_config.copy()
        new_config["allow_csv_upload"] = False
        contents = {
            "databases/imported_database.yaml": yaml.safe_dump(new_config),
            "metadata.yaml": yaml.safe_dump(database_metadata_config),
        }
        command = ImportDatabasesCommand(contents)
        command.run()

        database = (
            db.session.query(Database).filter_by(uuid=database_config["uuid"]).one()
        )
        assert not database.allow_csv_upload

        # test that only one database was created
        new_num_databases = db.session.query(Database).count()
        assert new_num_databases == num_databases + 1

        db.session.delete(database)
        db.session.commit()