diff --git a/api/Dockerfile b/api/Dockerfile index ec4e4568c..297684fdf 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:trixie +FROM debian:bookworm ENV PYTHONUNBUFFERED 1 ENV PYTHONPATH /app/ ENV DEBIAN_FRONTEND noninteractive diff --git a/api/build_runner.sh b/api/build_runner.sh index b8637e619..c256e0757 100755 --- a/api/build_runner.sh +++ b/api/build_runner.sh @@ -7,7 +7,7 @@ set -eu export DEBIAN_FRONTEND=noninteractive -echo 'deb http://deb.debian.org/debian trixie-backports main' \ +echo 'deb http://deb.debian.org/debian bookworm-backports main' \ > /etc/apt/sources.list.d/backports.list # Install ca-certificates and gnupg first diff --git a/api/ooniapi/app.py b/api/ooniapi/app.py index 67105c431..19465a33c 100644 --- a/api/ooniapi/app.py +++ b/api/ooniapi/app.py @@ -2,8 +2,8 @@ import datetime import logging -import os import json +import os import re import sys from collections import deque @@ -33,7 +33,7 @@ APP_DIR = os.path.dirname(__file__) -class JSONEncoderWithDates(json.JSONEncoder): +class FlaskJSONEncoder(json.JSONEncoder): # Special JSON encoder that handles dates def default(self, o): if isinstance(o, datetime.datetime): @@ -177,7 +177,7 @@ def create_app(*args, testmode=False, **kw): from ooniapi import views app = Flask(__name__) - app.json_encoder = JSONEncoderWithDates + app.json_encoder = FlaskJSONEncoder # Order matters init_app(app, testmode=testmode) diff --git a/api/ooniapi/database.py b/api/ooniapi/database.py index d5250a271..7af933923 100644 --- a/api/ooniapi/database.py +++ b/api/ooniapi/database.py @@ -6,7 +6,7 @@ from flask import current_app from sqlalchemy.dialects import postgresql -from sqlalchemy.orm import declarative_base +from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.sql.elements import TextClause from sqlalchemy.sql.selectable import Select diff --git a/api/tests/conftest.py b/api/tests/conftest.py index 2cc59f5f4..4047f6ff8 100644 --- a/api/tests/conftest.py +++ b/api/tests/conftest.py @@ -30,21 +30,8 @@ def app(): @pytest.fixture def client(app): - """ - Overriding the `client` fixture from pytest_flask to fix this bug: - https://github.com/pytest-dev/pytest-flask/issues/42 - """ with app.test_client() as client: - yield client - - # deprecated name _request_ctx_stack and marked as not a bug on issue #42 - #while True: - # top = flask._request_ctx_stack.top - # if top is not None and top.preserved: - # top.pop() - # else: - # break - + return client @pytest.fixture(autouse=True) def disable_rate_limits(app): diff --git a/api/tests/integ/test_integration.py b/api/tests/integ/test_integration.py index 41cc9a079..a2c4bdb71 100644 --- a/api/tests/integ/test_integration.py +++ b/api/tests/integ/test_integration.py @@ -304,7 +304,7 @@ def test_get_measurement_meta_not_found(client): resp = client.get(url) # TODO: is this a bug? assert resp.status_code == 200 - assert resp.json == {} + assert resp.get_json() == {} def FIXME_MISSING_MSMT____test_get_measurement_meta_input_none_from_fp(client): diff --git a/api/tests/integ/test_probe_services.py b/api/tests/integ/test_probe_services.py index 1449b5bcd..81c08057b 100644 --- a/api/tests/integ/test_probe_services.py +++ b/api/tests/integ/test_probe_services.py @@ -31,28 +31,28 @@ def getjson(client, url): response = client.get(url) assert response.status_code == 200 assert response.is_json - return response.json + return response.get_json() def getjsonh(client, url, headers=None): response = client.get(url, headers=headers) assert response.status_code == 200 assert response.is_json - return response.json + return response.get_json() def post(client, url, data): response = client.post(url, data=data) assert response.status_code == 200 assert response.is_json - return response.json + return response.get_json() def postj(client, url, **kw): response = client.post(url, json=kw) assert response.status_code == 200 assert response.is_json - return response.json + return response.get_json() def test_index(client): @@ -231,17 +231,19 @@ def test_register(client): assert len(c["client_id"]) == 132 -def test_register_then_login(client): +def test_register_then_login(client, app): pwd = "HLdywVhzVCNqLvHCfmnMhIXqGmUFMTuYjmuGZhNlRTeIyvxeQTnjVJsiRkutHCSw" c = _register(client) assert "client_id" in c assert len(c["client_id"]) == 132 - tok = ooniapi.auth.decode_jwt(c["client_id"], audience="probe_login") + with app.app_context(): + tok = ooniapi.auth.decode_jwt(c["client_id"], audience="probe_login") client_id = c["client_id"] c = postj(client, "/api/v1/login", username=client_id, password=pwd) - tok = ooniapi.auth.decode_jwt(c["token"], audience="probe_token") - assert tok["registration_time"] is not None + with app.app_context(): + tok = ooniapi.auth.decode_jwt(c["token"], audience="probe_token") + assert tok["registration_time"] is not None # Login with a bogus client id emulating probes before 2022 client_id = "BOGUSBOGUS" @@ -249,8 +251,10 @@ def test_register_then_login(client): r = client.post("/api/v1/login", json=j) assert r.status_code == 200 token = r.json["token"] - tok = ooniapi.auth.decode_jwt(token, audience="probe_token") - assert tok["registration_time"] is None # we don't know the reg. time + + with app.app_context(): + tok = ooniapi.auth.decode_jwt(token, audience="probe_token") + assert tok["registration_time"] is None # we don't know the reg. time # Expect failed login resp = client.post("/api/v1/login", json=dict()) @@ -263,15 +267,16 @@ def test_test_helpers(client): @patch("ooniapi.probe_services._load_json") -def test_psiphon(mock_load_json, client): +def test_psiphon(mock_load_json, client, app): # register and login pwd = "HLdywVhzVCNqLvHCfmnMhIXqGmUFMTuYjmuGZhNlRTeIyvxeQTnjVJsiRkutHCSw" client_id = _register(client)["client_id"] c = postj(client, "/api/v1/login", username=client_id, password=pwd) - tok = ooniapi.auth.decode_jwt(c["token"], audience="probe_token") - assert tok["registration_time"] is not None + with app.app_context(): + tok = ooniapi.auth.decode_jwt(c["token"], audience="probe_token") + assert tok["registration_time"] is not None url = "/api/v1/test-list/psiphon-config" # broken token @@ -289,14 +294,15 @@ def test_psiphon(mock_load_json, client): @patch("ooniapi.probe_services._load_json") -def test_tor_targets(mock_load_json, client): +def test_tor_targets(mock_load_json, client, app): # register and login pwd = "HLdywVhzVCNqLvHCfmnMhIXqGmUFMTuYjmuGZhNlRTeIyvxeQTnjVJsiRkutHCSw" client_id = _register(client)["client_id"] c = postj(client, "/api/v1/login", username=client_id, password=pwd) - tok = ooniapi.auth.decode_jwt(c["token"], audience="probe_token") - assert tok["registration_time"] is not None + with app.app_context(): + tok = ooniapi.auth.decode_jwt(c["token"], audience="probe_token") + assert tok["registration_time"] is not None url = "/api/v1/test-list/tor-targets" # broken token diff --git a/api/tests/unit/test_probe_services.py b/api/tests/unit/test_probe_services.py index 96d1f4756..e3c9df01c 100644 --- a/api/tests/unit/test_probe_services.py +++ b/api/tests/unit/test_probe_services.py @@ -13,7 +13,6 @@ def test_web_test_helpers(mock): "https://1.th.ooni.org", "https://2.th.ooni.org", "https://3.th.ooni.org", - "https://4.th.ooni.org", ] ) r2 = round_robin_web_test_helpers()