Combines shared, blog, market, cart, events, federation, and account into a single repository. Eliminates submodule sync, sibling model copying at build time, and per-app CI orchestration. Changes: - Remove per-app .git, .gitmodules, .gitea, submodule shared/ dirs - Remove stale sibling model copies from each app - Update all 6 Dockerfiles for monorepo build context (root = .) - Add build directives to docker-compose.yml - Add single .gitea/workflows/ci.yml with change detection - Add .dockerignore for monorepo build context - Create __init__.py for federation and account (cross-app imports)
47 lines
1017 B
Python
47 lines
1017 B
Python
import os
|
|
import time
|
|
import jwt # PyJWT
|
|
from typing import Tuple
|
|
|
|
|
|
def _split_key(raw_key: str) -> Tuple[str, bytes]:
|
|
"""
|
|
raw_key is the 'id:secret' from Ghost.
|
|
Returns (id, secret_bytes)
|
|
"""
|
|
key_id, key_secret_hex = raw_key.split(':', 1)
|
|
secret_bytes = bytes.fromhex(key_secret_hex)
|
|
return key_id, secret_bytes
|
|
|
|
|
|
def make_ghost_admin_jwt() -> str:
|
|
"""
|
|
Generate a short-lived JWT suitable for Authorization: Ghost <token>
|
|
"""
|
|
raw_key = os.environ["GHOST_ADMIN_API_KEY"]
|
|
key_id, secret_bytes = _split_key(raw_key)
|
|
|
|
now = int(time.time())
|
|
|
|
payload = {
|
|
"iat": now,
|
|
"exp": now + 5 * 60, # now + 5 minutes
|
|
"aud": "/admin/",
|
|
}
|
|
|
|
headers = {
|
|
"alg": "HS256",
|
|
"kid": key_id,
|
|
"typ": "JWT",
|
|
}
|
|
|
|
token = jwt.encode(
|
|
payload,
|
|
secret_bytes,
|
|
algorithm="HS256",
|
|
headers=headers,
|
|
)
|
|
|
|
# PyJWT returns str in recent versions; Ghost expects bare token string
|
|
return token
|