Ejemplo n.º 1
0
    def test_cleanup_temporary_query_tables(self, mock_connections, mock_databases_data):
        mock_cursor = Mock()
        mock_connection = Mock()
        mock_cursor_ctx_manager = MagicMock()

        mock_cursor_ctx_manager.__enter__.return_value = mock_cursor
        mock_connection.cursor.return_value = mock_cursor_ctx_manager
        mock_connections.__getitem__.return_value = mock_connection
        mock_databases_data.__getitem__.return_value = {
            "USER": "******",
            "NAME": "my_database" "",
        }

        user = UserFactory()
        user.profile.sso_id = (
            "00000000-0000-0000-0000-000000000000"  # yields a short hexdigest of 12b9377c
        )
        user.profile.save()

        # last run 1 day and 1 hour ago so its materialized view should be deleted
        with freeze_time(datetime.utcnow() - timedelta(days=1, hours=1)):
            query_log_1 = QueryLogFactory.create(run_by_user=user)

        # last run 2 hours ago so its materialized view should be kept
        with freeze_time(datetime.utcnow() - timedelta(hours=2)):
            QueryLogFactory.create(run_by_user=user)

        cleanup_temporary_query_tables()

        expected_calls = [
            call("GRANT _user_12b9377c TO postgres"),
            call(f"DROP TABLE IF EXISTS _user_12b9377c._data_explorer_tmp_query_{query_log_1.id}"),
            call("REVOKE _user_12b9377c FROM postgres"),
        ]
        mock_cursor.execute.assert_has_calls(expected_calls)
Ejemplo n.º 2
0
    def test_log_saves_duration(self):
        user = UserFactory()
        q = SimpleQueryFactory()
        res, _ = q.execute_with_logging(user, None, 10, 10000)
        log = QueryLog.objects.first()

        assert log.duration == pytest.approx(res.duration, rel=1e-9)
Ejemplo n.º 3
0
    def test_new_credentials_have_pgaudit_configuration(self):
        ensure_databases_configured().handle()

        user = UserFactory(email="*****@*****.**")
        st = SourceTableFactory(dataset=MasterDataSetFactory.create(
            user_access_type=UserAccessType.REQUIRES_AUTHENTICATION))

        source_tables = source_tables_for_user(user)
        db_role_schema_suffix = db_role_schema_suffix_for_user(user)
        user_creds_to_drop = new_private_database_credentials(
            db_role_schema_suffix,
            source_tables,
            postgres_user(user.email),
            user,
            valid_for=datetime.timedelta(days=1),
        )

        connections[st.database.memorable_name].cursor().execute("COMMIT")

        rolename = user_creds_to_drop[0]["db_user"]
        query = f"SELECT rolname, rolconfig FROM pg_roles WHERE rolname = '{rolename}';"

        with connections[st.database.memorable_name].cursor() as cursor:
            cursor.execute(query)
            results = cursor.fetchall()
            assert "pgaudit.log=ALL" in results[0][1]
            assert "pgaudit.log_catalog=off" in results[0][1]
Ejemplo n.º 4
0
 def test_cannot_open_playground_with_another_users_query(
         self, staff_client):
     other_user = UserFactory(email='*****@*****.**')
     query = SimpleQueryFactory(sql="select 1;", created_by_user=other_user)
     resp = staff_client.get('%s?query_id=%s' %
                             (reverse("explorer:index"), query.id))
     assert resp.status_code == 404
Ejemplo n.º 5
0
    def test_cannot_view_another_users_query(self, staff_user, staff_client):
        other_user = UserFactory(email="*****@*****.**")
        other_query = SimpleQueryFactory(created_by_user=other_user)

        resp = staff_client.get(
            reverse("explorer:query_detail", kwargs={"query_id": other_query.id})
        )
        assert resp.status_code == 404
Ejemplo n.º 6
0
    def test_user_can_only_see_their_own_queries_on_log_page(self, staff_user, staff_client):
        other_user = UserFactory(email="*****@*****.**")
        QueryLogFactory(sql="select 1234", run_by_user=other_user)
        QueryLogFactory(sql="select 9876", run_by_user=staff_user)

        resp = staff_client.get(reverse("explorer:explorer_logs"))

        assert "select 9876" in resp.content.decode(resp.charset)
        assert "select 1234" not in resp.content.decode(resp.charset)
Ejemplo n.º 7
0
    def test_cannot_post_to_another_users_query(self, staff_client):
        other_user = UserFactory(email="*****@*****.**")
        query = SimpleQueryFactory(sql="select 1;", created_by_user=other_user)

        resp = staff_client.post(
            reverse("explorer:index") + f"?query_id={query.id}",
            {"title": "test", "sql": "select 1+3400;", "action": "save"},
        )
        assert resp.status_code == 404
Ejemplo n.º 8
0
    def test_cant_query_with_unregistered_connection(self):
        from dataworkspace.apps.explorer.utils import (  # pylint: disable=import-outside-toplevel
            InvalidExplorerConnectionException, )

        user = UserFactory()
        q = SimpleQueryFactory.create(sql="select '$$foo:bar$$', '$$qux$$';",
                                      connection='not_registered')
        with pytest.raises(InvalidExplorerConnectionException):
            q.execute(user, None, 10, 10000)
Ejemplo n.º 9
0
 def test_query_owned_by_other_user(self, staff_user, staff_client):
     QueryLogFactory(sql="select 123", run_by_user=staff_user)
     query_log = QueryLogFactory(
         sql="select 456", run_by_user=UserFactory(email='*****@*****.**'))
     resp = staff_client.get(
         reverse('explorer:querylog_results', args=(query_log.id, )))
     assert resp.status_code == 200
     assert (resp.json()['error'] ==
             'Error fetching results. Please try running your query again.')
Ejemplo n.º 10
0
    def setUp(self):
        fetch_query_results_patcher = patch(
            "dataworkspace.apps.explorer.exporters.fetch_query_results")
        mock_fetch_query_results = fetch_query_results_patcher.start()

        self.mock_fetch_query_results = mock_fetch_query_results

        self.user = UserFactory()
        self.request = MagicMock(user=self.user)
        yield
        fetch_query_results_patcher.stop()
Ejemplo n.º 11
0
    def test_deletes_expired_and_unused_users(self):
        ensure_databases_configured().handle()

        user = UserFactory(email='*****@*****.**')
        st = SourceTableFactory(
            dataset=MasterDataSetFactory.create(
                user_access_type='REQUIRES_AUTHENTICATION'
            )
        )

        source_tables = source_tables_for_user(user)
        db_role_schema_suffix = db_role_schema_suffix_for_user(user)
        user_creds_to_drop = new_private_database_credentials(
            db_role_schema_suffix,
            source_tables,
            postgres_user(user.email),
            user,
            valid_for=datetime.timedelta(days=31),
        )
        qs_creds_to_drop = new_private_database_credentials(
            db_role_schema_suffix,
            source_tables,
            postgres_user(user.email, suffix='qs'),
            user,
            valid_for=datetime.timedelta(seconds=0),
        )
        qs_creds_to_keep = new_private_database_credentials(
            db_role_schema_suffix,
            source_tables,
            postgres_user(user.email, suffix='qs'),
            user,
            valid_for=datetime.timedelta(minutes=1),
        )

        connections[st.database.memorable_name].cursor().execute('COMMIT')

        # Make sure that `qs_creds_to_drop` has definitely expired
        time.sleep(1)

        with mock.patch('dataworkspace.apps.applications.utils.gevent.sleep'):
            delete_unused_datasets_users()

        with connections[st.database.memorable_name].cursor() as cursor:
            cursor.execute(
                "SELECT usename FROM pg_catalog.pg_user WHERE usename IN %s",
                [
                    (
                        user_creds_to_drop[0]['db_user'],
                        qs_creds_to_drop[0]['db_user'],
                        qs_creds_to_keep[0]['db_user'],
                    )
                ],
            )
            assert cursor.fetchall() == [(qs_creds_to_keep[0]['db_user'],)]
Ejemplo n.º 12
0
    def test_can_only_load_query_log_run_by_current_user(self, staff_user, staff_client):
        user = UserFactory(email="*****@*****.**")
        my_querylog = QueryLogFactory(run_by_user=staff_user)
        other_querylog = QueryLogFactory(run_by_user=user)

        resp = staff_client.get("%s?querylog_id=%s" % (reverse("explorer:index"), my_querylog.id))
        assert resp.status_code == 200
        assert "FOUR" in resp.content.decode(resp.charset)

        resp = staff_client.get(
            "%s?querylog_id=%s" % (reverse("explorer:index"), other_querylog.id)
        )
        assert resp.status_code == 404
Ejemplo n.º 13
0
    def test_cannot_download_someone_elses_querylog(self, staff_user,
                                                    staff_client):
        other_user = UserFactory(email='*****@*****.**')
        my_querylog = QueryLogFactory(sql="select 1,2", run_by_user=other_user)
        create_temporary_results_table(my_querylog)

        url = (reverse(
            "explorer:download_querylog",
            kwargs=dict(querylog_id=my_querylog.id),
        ) + '?format=json')

        response = staff_client.get(url)
        assert response.status_code == 404
Ejemplo n.º 14
0
    def setUp(self):
        self.mock_cursor = MagicMock()  # pylint: disable=attribute-defined-outside-init
        # Mock the return value of SELECT COUNT(*) FROM {query}
        self.mock_cursor.fetchone.return_value.__getitem__.return_value = 1

        mock_connection = Mock()
        mock_connection.cursor.return_value = self.mock_cursor

        user_explorer_connection_patcher = patch(
            "dataworkspace.apps.explorer.tasks.user_explorer_connection"
        )
        mock_user_explorer_connection = user_explorer_connection_patcher.start()

        mock_user_explorer_connection.return_value.__enter__.return_value = mock_connection

        self.user = UserFactory()
        self.request = MagicMock(user=self.user)
        yield
        user_explorer_connection_patcher.stop()
Ejemplo n.º 15
0
 def test_custom_delimiter(self):
     user = UserFactory()
     q = SimpleQueryFactory(sql='select 1, 2')
     exporter = CSVExporter(user=user, query=q)
     res = exporter.get_output(delim='|')
     assert res == '?column?|?column?\r\n1|2\r\n'