Skip to content

feat(dev): support running locally without full auth/S3 config#10

Merged
dosaki merged 1 commit into
mainfrom
chore/local-dev-setup
Jun 12, 2026
Merged

feat(dev): support running locally without full auth/S3 config#10
dosaki merged 1 commit into
mainfrom
chore/local-dev-setup

Conversation

@dosaki

@dosaki dosaki commented Jun 12, 2026

Copy link
Copy Markdown
Member

Summary

Makes the app boot gracefully when optional integrations aren't configured, and documents the full local-dev setup.

  • OIDC optional (app/__init__.py): skip Keycloak client registration when OIDC_ISSUER_URL is unset and log a warning, so flask db … / other CLI commands run without auth configured. Auth routes fail only if someone actually tries to log in.
  • S3 optional (app/storage.py): public_url() returns "" when S3_PUBLIC_BASE_URL is unset, so pages render with a broken <img> rather than 500ing the whole page.
  • Compose (docker-compose.yml): comment out the local Keycloak service + volume (local dev points at the remote realm); keep Postgres + MinIO.
  • .env.example: add OIDC and S3/MinIO dev defaults.
  • README: document the OIDC/S3 env vars and MinIO bootstrap, and switch the schema step from flask db init/migrate to flask db upgrade against the committed migrations.

Notes

These changes pre-existed in the working tree at the start of the session (not part of the branding PR #9) and are grouped here as one cohesive local-dev concern.

🤖 Generated with Claude Code

Make the app boot gracefully when optional integrations are absent,
and document the full local setup:

- OIDC: skip Keycloak client registration when OIDC_ISSUER_URL is
  unset and log a warning, so `flask db ...` and other CLI commands
  work without auth configured (auth routes fail only on actual login).
- storage: public_url() returns "" when S3_PUBLIC_BASE_URL is unset,
  so pages render with broken <img> tags instead of 500ing.
- compose: comment out the local Keycloak service/volume (local dev
  points at the remote realm); keep Postgres + MinIO.
- .env.example: add OIDC and S3/MinIO dev defaults.
- README: document the OIDC/S3 env vars, MinIO bootstrap, and switch
  the schema step from `flask db init/migrate` to `flask db upgrade`
  against the committed migrations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 12, 2026 10:00
@dosaki dosaki merged commit 674be72 into main Jun 12, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the local-development experience by making optional external integrations (OIDC/Keycloak and S3/MinIO) non-fatal at app startup, and updates developer documentation to match the intended “boots with minimal config” workflow.

Changes:

  • Make OIDC initialization optional by skipping Keycloak client registration when OIDC_ISSUER_URL is unset.
  • Make S3 image URL resolution optional by not crashing when S3_PUBLIC_BASE_URL is unset.
  • Update local-dev docs and compose configuration (MinIO bootstrap + guidance; Keycloak service commented out).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
README.md Documents local-dev env vars, backing services, and using flask db upgrade against committed migrations.
docker-compose.yml Keeps Postgres + MinIO + bucket bootstrap; comments out local Keycloak service/volume.
app/storage.py Avoids raising on missing public S3 base URL when rendering image URLs.
app/__init__.py Avoids failing app creation when OIDC issuer is not configured.
.env.example Adds example OIDC and S3/MinIO environment variables for local development.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/storage.py
Comment on lines +95 to +100
base = current_app.config["S3_PUBLIC_BASE_URL"]
if not base:
# No public bucket configured — e.g. local dev without the S3/MinIO
# env vars set. Return "" so templates render a broken <img> rather
# than 500ing the whole page on a missing optional config.
return ""
Comment thread .env.example
Comment on lines +6 to +10
# auth
OIDC_ISSUER_URL=https://login.keyholding.com/realms/keyholding
OIDC_CLIENT_ID=tkc-library
OIDC_CLIENT_SECRET=dev-secret

Comment thread README.md
| `AWS_ACCESS_KEY_ID` | `minioadmin` | MinIO/S3 access key (needed for uploads) |
| `AWS_SECRET_ACCESS_KEY` | `minioadmin` | MinIO/S3 secret key (needed for uploads) |

> If `OIDC_ISSUER_URL` or `S3_PUBLIC_BASE_URL` are unset, the app still boots (handy for running `flask db …` commands): auth routes are disabled and book images render broken, rather than crashing the page.
Comment thread app/__init__.py
Comment on lines +51 to +75
issuer_url = app.config["OIDC_ISSUER_URL"]
if issuer_url:
oauth.register(
name="keycloak",
server_metadata_url=f"{issuer_url.rstrip('/')}/.well-known/openid-configuration",
client_id=app.config["OIDC_CLIENT_ID"],
client_secret=app.config["OIDC_CLIENT_SECRET"],
# PKCE is required by the Keycloak client config (S256). Authlib
# doesn't auto-enable it from server metadata; opting in here makes
# the SDK generate the code_verifier and send code_challenge /
# code_challenge_method on the authorize redirect.
client_kwargs={
"scope": "openid email profile",
"code_challenge_method": "S256",
},
)
else:
# No OIDC config — e.g. running `flask db ...` or other CLI commands
# locally without auth set up. Skip client registration so the app
# factory doesn't crash; the /auth/* routes resolve `oauth.keycloak`
# lazily and will fail only if someone actually tries to log in.
app.logger.warning(
"OIDC_ISSUER_URL is unset — Keycloak auth disabled; /auth/* routes "
"will be unavailable until it is configured."
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants