Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.coverage
.DS_STORE
.env
.env.tests
.idea/
.mypy_cache/
.tox/
Expand Down
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,15 @@ start: .env
test: .env $(INSTALL_STAMP)
COVERAGE_REPORT=1 bin/test.sh

.env.tests: .env setup $(INSTALL_STAMP)
cp tests/integration/basket.env .env.tests
poetry run ctms/bin/client_credentials.py -e [email protected] integration-test --save-file creds.json
echo "CTMS_CLIENT_ID=$(jq -r .client_id creds.json)" >> .env.tests
echo "CTMS_CLIENT_SECRET=$(jq -r .client_secret creds.json)" >> .env.tests
rm creds.json

.PHONY: integration-test
integration-test: .env setup $(INSTALL_STAMP)
integration-test: .env.tests
echo "Starting containers..."
${DOCKER_COMPOSE} --profile integration-test up --force-recreate --wait basket
echo "Start test suite..."
Expand Down
3 changes: 0 additions & 3 deletions bin/integration-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,5 @@ export TZ=UTC
# Create newsletters in basket
cat tests/integration/basket-db-init.sql | $DOCKER_COMPOSE exec -T mysql mariadb -u root -h mysql basket

# Create token in CTMS (will only work with specific CTMS_SECRET, see .sql source)
cat tests/integration/ctms-db-init.sql | $DOCKER_COMPOSE exec -T postgres psql --user postgres -d postgres

# We don't capture tests output to trace retries of failing assertions.
$POETRY_RUN pytest --capture=no tests/integration/
32 changes: 24 additions & 8 deletions ctms/bin/client_credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"""Generate OAuth2 client credentials."""

import argparse
import json
import re
from secrets import token_urlsafe

Expand Down Expand Up @@ -86,6 +87,18 @@ def print_new_credentials(
)


def save_json(output, client_id, client_secret):
with open(output, "w") as f:
json.dump(
{
"client_id": client_id,
"client_secret": client_secret,
},
f,
)
print(f"Credentials saved to {output!r}.")


def main(db, settings, test_args=None): # noqa: PLR0912
"""
Process the command line and create or update client credentials
Expand All @@ -99,6 +112,9 @@ def main(db, settings, test_args=None): # noqa: PLR0912
parser = argparse.ArgumentParser(description="Create or update client credentials.")
parser.add_argument("name", help="short name of the client")
parser.add_argument("-e", "--email", help="contact email for the client")
parser.add_argument(
"--save-file", help="output credentials into file in JSON format"
)
parser.add_argument(
"--enable", action="store_true", help="enable a disabled client"
)
Expand All @@ -115,6 +131,7 @@ def main(db, settings, test_args=None): # noqa: PLR0912
enable = args.enable
disable = args.disable
rotate = args.rotate_secret
save_file = args.save_file

if not re.match(r"^[-_.a-zA-Z0-9]*$", name):
print(
Expand All @@ -126,10 +143,8 @@ def main(db, settings, test_args=None): # noqa: PLR0912
print("Can only pick one of --enable and --disable")
return 1

if name.startswith("id_"):
client_id = name
else:
client_id = f"id_{name}"
client_id = name if name.startswith("id_") else f"id_{name}"

existing = get_api_client_by_id(db, client_id)
if existing:
if disable and existing.enabled:
Expand All @@ -139,10 +154,7 @@ def main(db, settings, test_args=None): # noqa: PLR0912
else:
enabled = None

if rotate:
new_secret = create_secret()
else:
new_secret = None
new_secret = create_secret() if rotate else None

if new_secret is None and enabled is None and email in (None, existing.email):
print(f"Nothing to change for existing credentials for {name}.")
Expand All @@ -158,6 +170,8 @@ def main(db, settings, test_args=None): # noqa: PLR0912
sample_email=email,
enabled=enabled,
)
if save_file:
save_json(save_file, existing.client_id, new_secret)
else:
print(f"Credentials for {name} are updated.")
else:
Expand All @@ -171,6 +185,8 @@ def main(db, settings, test_args=None): # noqa: PLR0912
print_new_credentials(
client_id, client_secret, settings, sample_email=email, enabled=enabled
)
if save_file:
save_json(save_file, client_id, client_secret)
return 0


Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ services:
profiles: [integration-test]
image: mozmeao/basket:2024-10-21
env_file:
- ./tests/integration/basket.env
- .env.tests
command:
./bin/run-dev.sh
ports:
Expand All @@ -68,7 +68,7 @@ services:
profiles: [integration-test]
image: mozmeao/basket:2024-10-21
env_file:
- ./tests/integration/basket.env
- .env.tests
command:
./bin/run-worker.sh
depends_on:
Expand Down
3 changes: 0 additions & 3 deletions tests/integration/basket.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ REDIS_URL=redis://redis:6379

CTMS_ENABLED=True
CTMS_URL=http://web:8000
CTMS_CLIENT_ID=id_integration-test
# See `ctms-db-init.sql`
CTMS_CLIENT_SECRET=bogus_MzOWu8UMz5N6M4--2iX9jgJ05JX5MziH6KeH8dI6hrw # pragma: allowlist secret
DEBUG=True
ALLOWED_HOSTS=*
SECRET_KEY=sssssssshhhhhhhhhh # pragma: allowlist secret
Expand Down
20 changes: 0 additions & 20 deletions tests/integration/ctms-db-init.sql

This file was deleted.

9 changes: 4 additions & 5 deletions tests/integration/test_basket_waitlist_subscription.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import logging
import os
from pathlib import Path
from uuid import uuid4

import backoff
Expand All @@ -9,17 +9,16 @@

from tests.conftest import FuzzyAssert

TEST_FOLDER = os.path.dirname(os.path.realpath(__file__))
ROOT_FOLDER = Path(__file__).parent.parent


class Settings(BaseSettings):
basket_server_url: str = "http://127.0.0.1:9000"
ctms_server_url: str = "http://127.0.0.1:8000"
# We initialize CTMS api client id/secret in `ctms-db-init.sql`
ctms_client_id: str = "id_integration-test"
ctms_client_id: str
ctms_client_secret: str
model_config = SettingsConfigDict(
env_file=os.path.join(TEST_FOLDER, "basket.env"), extra="ignore"
env_file=str(ROOT_FOLDER / ".env.tests"), extra="ignore"
)


Expand Down
Loading