feat/Update_Controllers_to_Allow_for_Premium_Membership
This commit is contained in:
+56
-2
@@ -52,6 +52,7 @@ AUTH_ADMIN_EMAIL=you@example.com
|
||||
AUTH_ADMIN_PASSWORD=replace_with_strong_password
|
||||
AUTH_REQUIRE_EMAIL_VERIFICATION=true
|
||||
APP_PUBLIC_BASE_URL=https://your-domain.example
|
||||
WEB_PROXY_SUBNET=172.31.250.0/29
|
||||
STRIPE_SECRET_KEY=sk_live_...
|
||||
STRIPE_PRICE_PREMIUM=price_...
|
||||
STRIPE_WEBHOOK_SECRET=whsec_...
|
||||
@@ -89,10 +90,23 @@ If this app is going to be a real production service on Ubuntu:
|
||||
- MariaDB is still a reasonable option if preferred
|
||||
|
||||
## Deployment flow
|
||||
|
||||
Production automation always selects `docker-compose.yml` explicitly. Local development must add
|
||||
`docker-compose.dev.yml`; never add that file to a production command. The base configuration has no
|
||||
host bindings for frontend, backend, ai-service, or bundled Ollama.
|
||||
|
||||
The external Traefik configuration is operator-owned and is not stored here. Before deployment it
|
||||
must route only the exact host from `APP_PUBLIC_BASE_URL` to frontend port 80 on
|
||||
`jobtracker_shared`, terminate TLS, replace `X-Forwarded-For` and `X-Forwarded-Proto=https`, and
|
||||
expose no direct application or Ollama host ports.
|
||||
|
||||
Nginx independently rejects non-canonical Hosts except `/health`, forwards Traefik's sanitized
|
||||
single-hop values, and reaches the backend only over `WEB_PROXY_SUBNET`. The backend fails startup
|
||||
if forwarded-header trust is enabled without a valid known CIDR.
|
||||
1. push to `main`
|
||||
2. Gitea Actions runs tests
|
||||
3. if green, workflow uploads repo to server
|
||||
4. `deploy/deploy.sh` links `/opt/job-tracker/shared/.env` into the repo checkout, then runs `docker compose build && docker compose up -d`
|
||||
4. `deploy/deploy.sh` links `/opt/job-tracker/shared/.env` into the repo checkout, then explicitly runs `docker compose -f docker-compose.yml build` and `up -d`
|
||||
5. if `OLLAMA_MODEL` is set, the deploy script waits for Ollama, pulls the configured model if missing, then restarts `ai-service` so hybrid CV classification can use it
|
||||
6. workflow checks service status after deployment
|
||||
|
||||
@@ -141,7 +155,47 @@ or replaced. A missing variable aborts the deploy while the running stack is sti
|
||||
| `JOBTRACKER_CONNECTION_STRING` | When provider is `mariadb`/`mysql` | Without it there is no way to dump the database |
|
||||
| `AI_SERVICE_TOKEN` | Always | `docker-compose.yml` declares it with `:?`; missing it kills the stack *after* the images are built |
|
||||
| `AUTH_JWT_KEY` | Always | Compose sets `Auth__Require=true`, and the backend throws at startup on a blank key — after the containers have been replaced |
|
||||
| `APP_PUBLIC_BASE_URL` | Optional | If unset the post-deploy public smoke check is skipped, and the script says so rather than skipping silently |
|
||||
| `APP_PUBLIC_BASE_URL` | Always | Canonical HTTPS origin for links, OAuth callbacks, billing redirects, secure cookies, Host validation, and the public smoke check |
|
||||
| `AUTH_MICROSOFT_TENANT` | When `AUTH_MICROSOFT_CLIENT_ID` is set | Exact Microsoft application sign-in account mode; distinct from the Graph mailbox tenant |
|
||||
| `WEB_PROXY_SUBNET` | Always | Dedicated nginx-to-backend CIDR trusted for exactly one forwarded hop; must not overlap another Docker network |
|
||||
|
||||
### Microsoft sign-in migration gate
|
||||
|
||||
Before enabling `AUTH_MICROSOFT_CLIENT_ID` with the canonical identity release, take the normal
|
||||
backup and record counts only. Do not print subjects or email addresses:
|
||||
|
||||
```sql
|
||||
SELECT COUNT(*) AS legacy_links
|
||||
FROM AspNetUsers
|
||||
WHERE MicrosoftSubject IS NOT NULL OR MicrosoftEmail IS NOT NULL;
|
||||
|
||||
SELECT COUNT(*) AS legacy_without_alternate_credential
|
||||
FROM AspNetUsers
|
||||
WHERE (MicrosoftSubject IS NOT NULL OR MicrosoftEmail IS NOT NULL)
|
||||
AND PasswordHash IS NULL
|
||||
AND GoogleSubject IS NULL;
|
||||
|
||||
SELECT COUNT(*) AS duplicate_legacy_subject_groups
|
||||
FROM (
|
||||
SELECT MicrosoftSubject
|
||||
FROM AspNetUsers
|
||||
WHERE MicrosoftSubject IS NOT NULL
|
||||
GROUP BY MicrosoftSubject HAVING COUNT(*) > 1
|
||||
) duplicate_subjects;
|
||||
|
||||
SELECT COUNT(*) AS duplicate_legacy_email_groups
|
||||
FROM (
|
||||
SELECT MicrosoftEmail
|
||||
FROM AspNetUsers
|
||||
WHERE MicrosoftEmail IS NOT NULL
|
||||
GROUP BY MicrosoftEmail HAVING COUNT(*) > 1
|
||||
) duplicate_emails;
|
||||
```
|
||||
|
||||
Apply `20260802212509_AddCanonicalMicrosoftIdentity` before deploying code that queries the two new
|
||||
columns. The migration does not backfill legacy rows and adds a unique nullable composite index.
|
||||
Keep Microsoft sign-in disabled if the inventory or migration fails. Roll back the application
|
||||
binary while leaving the additive columns in place; never roll back to email auto-linking.
|
||||
|
||||
`DATABASE_PROVIDER` deliberately has **no default**. An unset value used to mean "sqlite"; it now
|
||||
means "stop and tell me".
|
||||
|
||||
Reference in New Issue
Block a user