diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..8ee4be900f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,129 @@ +**/*.untracked +**/*.untracked.* + + + +**/.vercel + +# Misc +**/.DS_Store +**/.eslintcache +**/.env.local +**/.env.*.local + +**/npm-debug.log* +**/yarn-debug.log* +**/yarn-error.log* +**/firebase-debug.log +**/ui-debug.log +**/.pnpm-debug.log +**/.husky +**/tmp + +**/vitest.config.ts.timestamp-* +**/tsup.config.bundled_* + +# Dependencies +**/node_modules + +# Build dirs +**/.next +**/build +**/dist + +# Generated files +**/.docusaurus +**/.cache-loader +**/**.tsbuildinfo + +**/.xata* + +# VS +/.vs/slnx.sqlite-journal +/.vs/slnx.sqlite +/.vs +.vscode/generated* + +# Jetbrains +.idea + +# GitHub Actions runner +/actions-runner +/_work + +# DB +**/dev.db* +packages/adapter-prisma/prisma/dev.db +packages/adapter-prisma/prisma/migrations +**/db.sqlite +packages/adapter-supabase/supabase/.branches +packages/adapter-drizzle/.drizzle + +# Tests +**/coverage +**/dynamodblocal-bin +**/firestore-debug.log +**/test.schema.gql +**/test-results +**/playwright-report +**/blob-report +**/playwright/.cache + + +# Turborepo +**/.turbo + +# docusaurus +docs/.docusaurus +docs/manifest.mjs + +# Core +packages/core/src/providers/oauth-types.ts +packages/core/lib +packages/core/providers +docs/docs/reference/core + +# Next.js +docs/docs/reference/nextjs +next-env.d.ts + +# SvelteKit +packages/frameworks-sveltekit/index.* +packages/frameworks-sveltekit/client.* +packages/frameworks-sveltekit/.svelte-kit +packages/frameworks-sveltekit/package +packages/frameworks-sveltekit/vite.config.js.timestamp-* +packages/frameworks-sveltekit/vite.config.ts.timestamp-* +docs/docs/reference/sveltekit + +# SolidStart +docs/docs/reference/solidstart + + +# Express +docs/docs/reference/express + + +# Adapters +docs/docs/reference/adapter + +## Drizzle migration folder +**/.drizzle + +# Sentry Config File +**/.sentryclirc + +# python +**/__pycache__/ +**/.venv/ + +# env +**/.env.* +**/.env + +# ignore +apps/e2e +apps/oauth-mock-server +examples +.vscode +.changeset \ No newline at end of file diff --git a/.gitignore b/.gitignore index cb9d46371b..caacb44db7 100644 --- a/.gitignore +++ b/.gitignore @@ -116,3 +116,5 @@ docs/docs/reference/adapter # python __pycache__/ .venv/ + +docker/**/.env \ No newline at end of file diff --git a/apps/backend/next.config.mjs b/apps/backend/next.config.mjs index fc6d4d5b06..7c052b6a9c 100644 --- a/apps/backend/next.config.mjs +++ b/apps/backend/next.config.mjs @@ -14,8 +14,8 @@ const withConfiguredSentryConfig = (nextConfig) => // Suppresses source map uploading logs during build silent: true, - org: process.env.SENTRY_ORG, - project: process.env.SENTRY_PROJECT, + org: process.env.NEXT_PUBLIC_SENTRY_ORG, + project: process.env.NEXT_PUBLIC_SENTRY_PROJECT, }, { // For all available options, see: @@ -49,6 +49,7 @@ const withConfiguredSentryConfig = (nextConfig) => /** @type {import('next').NextConfig} */ const nextConfig = { + output: "standalone", // we're open-source, so we can provide source maps productionBrowserSourceMaps: true, poweredByHeader: false, diff --git a/apps/dashboard/next.config.mjs b/apps/dashboard/next.config.mjs index 50a163d33d..4df1f8765c 100644 --- a/apps/dashboard/next.config.mjs +++ b/apps/dashboard/next.config.mjs @@ -28,8 +28,8 @@ const withConfiguredSentryConfig = (nextConfig) => // Suppresses source map uploading logs during build silent: true, - org: "stackframe-pw", - project: "stack-server", + org: process.env.NEXT_PUBLIC_SENTRY_ORG, + project: process.env.NEXT_PUBLIC_SENTRY_PROJECT, }, { // For all available options, see: @@ -63,6 +63,7 @@ const withConfiguredSentryConfig = (nextConfig) => /** @type {import('next').NextConfig} */ const nextConfig = { + output: "standalone", pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"], // we're open-source, so we can provide source maps diff --git a/apps/dashboard/sentry.client.config.ts b/apps/dashboard/sentry.client.config.ts index af6c93ba4b..b15e67e625 100644 --- a/apps/dashboard/sentry.client.config.ts +++ b/apps/dashboard/sentry.client.config.ts @@ -6,7 +6,7 @@ import * as Sentry from "@sentry/nextjs"; import { nicify } from "@stackframe/stack-shared/dist/utils/strings"; Sentry.init({ - dsn: "https://6e618f142965a385267f1030793e0400@o4507084192022528.ingest.us.sentry.io/4507084192219136", + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, // Adjust this value in production, or use tracesSampler for greater control tracesSampleRate: 1, diff --git a/apps/dashboard/sentry.edge.config.ts b/apps/dashboard/sentry.edge.config.ts index 73363a547b..d38fa6ef2d 100644 --- a/apps/dashboard/sentry.edge.config.ts +++ b/apps/dashboard/sentry.edge.config.ts @@ -7,7 +7,7 @@ import * as Sentry from "@sentry/nextjs"; import { nicify } from "@stackframe/stack-shared/dist/utils/strings"; Sentry.init({ - dsn: "https://6e618f142965a385267f1030793e0400@o4507084192022528.ingest.us.sentry.io/4507084192219136", + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, // Adjust this value in production, or use tracesSampler for greater control tracesSampleRate: 1, diff --git a/apps/dashboard/sentry.server.config.ts b/apps/dashboard/sentry.server.config.ts index a2cf430bb7..e0963f12fa 100644 --- a/apps/dashboard/sentry.server.config.ts +++ b/apps/dashboard/sentry.server.config.ts @@ -6,7 +6,7 @@ import * as Sentry from "@sentry/nextjs"; import { nicify } from "@stackframe/stack-shared/dist/utils/strings"; Sentry.init({ - dsn: "https://6e618f142965a385267f1030793e0400@o4507084192022528.ingest.us.sentry.io/4507084192219136", + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, // Adjust this value in production, or use tracesSampler for greater control tracesSampleRate: 1, diff --git a/docker/.env.development b/docker/.env.development new file mode 100644 index 0000000000..f60867371f --- /dev/null +++ b/docker/.env.development @@ -0,0 +1,83 @@ +############ +# Secret +############ + +# stack +STACK_SERVER_SECRET=u8WXA6g18tS2pGy8LKECYel5wlZAqgIo9Gxq67W1PF4 +NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=pck_ky1m54r6yk4sf11fqhq5jatgkgqdxnxgwd60w5q40tmb0 +STACK_SECRET_SERVER_KEY=this-secret-server-key-is-for-local-development-only +STACK_SUPER_SECRET_ADMIN_KEY=this-secret-admin-key-is-for-local-development-only + +# db +POSTGRES_STACKFRAME_PASSWORD=this-db-password-is-for-local-development-only + +# svix +POSTGRES_SVIX_PASSWORD=this-svix-password-is-for-local-development-only +SVIX_JWT_SECRET=x6HeHo0IZGmTigbwq4AiCWb--wtTb9PxLiE8Kuj8RxU +STACK_SVIX_API_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2NTUxNDA2MzksImV4cCI6MTk3MDUwMDYzOSwibmJmIjoxNjU1MTQwNjM5LCJpc3MiOiJzdml4LXNlcnZlciIsInN1YiI6Im9yZ18yM3JiOFlkR3FNVDBxSXpwZ0d3ZFhmSGlyTXUifQ.VCP8uc2wqIQfMZfalNykRd1xNVyKKKEZFGnatwvwO7M + +############ +# Config +############ + +POSTGRES_DELAY_MS=0 +# This is needed for local development to allow self-signed certificates +NODE_TLS_REJECT_UNAUTHORIZED=0 + +############ +# Stack Dashboard +############ + +NEXT_PUBLIC_STACK_URL=https://api.stack-auth.internal +NEXT_PUBLIC_STACK_PROJECT_ID=internal +NEXT_PUBLIC_STACK_SVIX_SERVER_URL=https://svix-api.stack-auth.internal +STACK_ACCESS_TOKEN_EXPIRATION_TIME= +NEXT_PUBLIC_STACK_HEAD_TAGS=[{ "tagName": "script", "attributes": {}, "innerHTML": "// insert head tags here" }] + +############ +# Sentry +############ + +NEXT_PUBLIC_SENTRY_DSN= +NEXT_PUBLIC_SENTRY_ORG= +NEXT_PUBLIC_SENTRY_PROJECT= +SENTRY_AUTH_TOKEN= + +############ +# Auth +############ + +# OAuth mock provider settings +STACK_OAUTH_MOCK_URL= + +# OAuth shared keys +# Can be set to MOCK to use mock OAuth providers +STACK_GITHUB_CLIENT_ID= +STACK_GITHUB_CLIENT_SECRET= +STACK_GOOGLE_CLIENT_ID= +STACK_GOOGLE_CLIENT_SECRET= +STACK_MICROSOFT_CLIENT_ID= +STACK_MICROSOFT_CLIENT_SECRET= +STACK_SPOTIFY_CLIENT_ID= +STACK_SPOTIFY_CLIENT_SECRET= + +# Email +# For local development, you can spin up a local SMTP server like inbucket +STACK_EMAIL_HOST= +STACK_EMAIL_PORT= +STACK_EMAIL_SECURE= +STACK_EMAIL_USERNAME= +STACK_EMAIL_PASSWORD= +STACK_EMAIL_SENDER= + +# Misc, optional +STACK_ACCESS_TOKEN_EXPIRATION_TIME= +STACK_SETUP_ADMIN_GITHUB_ID= +OTEL_EXPORTER_OTLP_ENDPOINT= + +############ +# Database - You can change these to any PostgreSQL database that has logical replication enabled. +############ + +STACK_DATABASE_CONNECTION_STRING=postgres://postgres:${POSTGRES_STACKFRAME_PASSWORD}@127.0.0.1:8111/stackframe +STACK_DIRECT_DATABASE_CONNECTION_STRING=postgres://postgres:${POSTGRES_STACKFRAME_PASSWORD}@127.0.0.1:8111/stackframe \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000000..408c243fce --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,111 @@ +FROM node:20-alpine AS base + +FROM base AS deps +RUN apk add --no-cache libc6-compat +RUN npm install -g pnpm +WORKDIR /app +COPY package.json pnpm-lock.yaml* ./ +COPY pnpm-workspace.yaml ./ +COPY packages/stack-sc/package.json ./packages/stack-sc/ +COPY packages/stack-ui/package.json ./packages/stack-ui/ +COPY packages/stack-emails/package.json ./packages/stack-emails/ +COPY packages/stack/package.json ./packages/stack/ +COPY packages/init-stack/package.json ./packages/init-stack/ +COPY packages/stack-shared/package.json ./packages/stack-shared/ +COPY apps/backend/package.json ./apps/backend/ +COPY apps/dashboard/package.json ./apps/dashboard/ +RUN pnpm install --frozen-lockfile + +FROM base AS dep +RUN npm install -g pnpm +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY --from=deps /app/packages/stack-sc/node_modules ./packages/stack-sc/node_modules +COPY --from=deps /app/packages/stack-ui/node_modules ./packages/stack-ui/node_modules +COPY --from=deps /app/packages/stack-emails/node_modules ./packages/stack-emails/node_modules +COPY --from=deps /app/packages/stack/node_modules ./packages/stack/node_modules +COPY --from=deps /app/packages/init-stack/node_modules ./packages/init-stack/node_modules +COPY --from=deps /app/packages/stack-shared/node_modules ./packages/stack-shared/node_modules +COPY --from=deps /app/apps/backend/node_modules ./apps/backend/node_modules +COPY --from=deps /app/apps/dashboard/node_modules ./apps/dashboard/node_modules + +COPY timestamp.txt ./timestamp.txt + +COPY package.json pnpm-lock.yaml* ./ +COPY pnpm-workspace.yaml ./ +COPY turbo.json ./ +COPY LICENSE ./ + +COPY packages ./packages +COPY apps ./apps +COPY docs ./docs +COPY eslint-configs ./eslint-configs + +RUN pnpm install --frozen-lockfile + +ARG NEXT_PUBLIC_SENTRY_DSN +ARG NEXT_PUBLIC_SENTRY_ORG +ARG NEXT_PUBLIC_SENTRY_PROJECT +ARG SENTRY_AUTH_TOKEN + +ENV NEXT_PUBLIC_SENTRY_DSN=${NEXT_PUBLIC_SENTRY_DSN} +ENV NEXT_PUBLIC_SENTRY_ORG=${NEXT_PUBLIC_SENTRY_ORG} +ENV NEXT_PUBLIC_SENTRY_PROJECT=${NEXT_PUBLIC_SENTRY_PROJECT} +ENV SENTRY_AUTH_TOKEN=${SENTRY_AUTH_TOKEN} + +FROM dep AS builder-backend + +ARG STACK_SERVER_SECRET + +ENV STACK_SERVER_SECRET=${STACK_SERVER_SECRET} + +RUN pnpm run build:backend + +FROM dep AS builder-dashboard + +ARG NEXT_PUBLIC_STACK_URL +ARG NEXT_PUBLIC_STACK_PROJECT_ID +ARG NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY +ARG STACK_SECRET_SERVER_KEY +ARG NEXT_PUBLIC_STACK_SVIX_SERVER_URL +ARG NEXT_PUBLIC_STACK_HEAD_TAGS + +ENV NEXT_PUBLIC_STACK_URL=${NEXT_PUBLIC_STACK_URL} +ENV NEXT_PUBLIC_STACK_PROJECT_ID=${NEXT_PUBLIC_STACK_PROJECT_ID} +ENV NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=${NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY} +ENV STACK_SECRET_SERVER_KEY=${STACK_SECRET_SERVER_KEY} +ENV NEXT_PUBLIC_STACK_SVIX_SERVER_URL=${NEXT_PUBLIC_STACK_SVIX_SERVER_URL} +ENV NEXT_PUBLIC_STACK_HEAD_TAGS=${NEXT_PUBLIC_STACK_HEAD_TAGS} + +RUN pnpm run build:dashboard + +FROM base AS backend + +WORKDIR /app + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +USER nextjs + +COPY --from=builder-backend /app/apps/backend/.next/standalone ./ +COPY --from=builder-backend /app/apps/backend/.next/static ./apps/backend/.next/static +COPY apps/backend/LICENSE ./ + +CMD PORT=8102 node ./apps/backend/server.js + +FROM base AS dashboard + +WORKDIR /app + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +USER nextjs + +COPY --from=builder-dashboard /app/apps/dashboard/.next/standalone ./ +COPY --from=builder-dashboard /app/apps/dashboard/.next/static ./apps/dashboard/.next/static +COPY --from=builder-dashboard /app/apps/dashboard/public ./apps/dashboard/public +COPY apps/dashboard/LICENSE ./apps/ + +CMD PORT=8101 node ./apps/dashboard/server.js \ No newline at end of file diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000000..fffe4e91fb --- /dev/null +++ b/docker/README.md @@ -0,0 +1,95 @@ +### Stack Auth Setup Guide + +This guide provides step-by-step instructions to set up the `stack-auth` environment using Docker. Follow each step carefully to ensure proper configuration and smooth execution. + +--- + +### 1. **Create `.env` File** + - Copy the development environment file: + ```sh + cp .env.development .env + ``` + - **Note**: After copying, open the new `.env` file and adjust environment variables as needed. + +--- + +### 2. **Build Docker Images** + - Build Docker images. If you change any `NEXT_JS_*` environment variables in `.env`, rebuild the images for those changes to take effect: + ```sh + docker compose -f docker-compose.builder.yaml build + ``` + +--- + +### 3. **Setup Service** + - **Download Config Files**: + - Fetch the latest config files and organize them into the required directories: + ```sh + wget https://github.com/ShaunDyson-leetcode/stack/archive/refs/heads/dev.zip -O repo.zip + unzip repo.zip "stack-dev/docker/*" -d stack-auth + mv stack-auth/stack-dev/docker stack-auth/ + rm -rf stack-auth/stack-dev repo.zip + ``` + +--- + +### 4. **Network and DNS Setup** + - **DNS Entries**: + - Add the following entries to your system’s `/etc/hosts` file (or DNS management system): + - `stack-auth.internal` + - `svix-api.stack-auth.internal` + - `api.stack-auth.internal` + - **Port Exposure**: + - Ensure the following ports are accessible: + - **443**: Main service + - **8111**: Optional (database) + - **Firewall**: If you are on a network with firewall restrictions, ensure these ports are open. + - **Self-Signed SSL Certificates**: + - Place SSL files in the `volumes/nginx/certs` directory. + - If you need to create self-signed certificates, use: + ```sh + openssl genrsa -out stack-auth.key 2048 + openssl req -new -key stack-auth.key -out stack-auth.csr + openssl x509 -req -days 365 -in stack-auth.csr -signkey stack-auth.key -out stack-auth.crt + ``` + - **Note**: This is optional for development but recommended for production. Uncomment `DEPTH_ZERO_SELF_SIGNED_CERT` in `.env` if using self-signed certificates. + +--- + +### 5. **Start Services** + - Start Docker services in detached mode: + ```sh + docker compose up -d + ``` + - **Verification**: Run `docker ps` to confirm that all services started successfully. + - **Troubleshooting**: Common errors at this step may include port conflicts or permission issues. Check Docker logs if services fail to start. + + - **Access Services**: + - Open the following URLs in your browser: + - `https://svix-api.stack-auth.internal` + - `https://api.stack-auth.internal` + - `https://stack-auth.internal` + - **Browser Compatibility**: Certain browsers may show a warning for self-signed certificates; proceed past these warnings to access the sites. + +--- + +### 6. **User Signup** + - Access `https://stack-auth.internal` to complete the signup process. + - **Note**: Ignore any whitelist warnings on your first login; these warnings will not affect your signup process. + +--- + +### 7. **Set Domains and Handlers** + - Access the Admin project (refer to the project documentation if unsure how to access this). + - Update settings as follows: + - **Disable**: `localhost` domain for security. + - **Add**: `https://stack-auth.internal` to the allowed domains. + - **Set User Verification**: Set the user to "verified" for OTP. + +--- + +## **Development** + +```sh +pnpm prisma migrate diff --from-empty --to-schema-datamodel ../../apps/backend/prisma/schema.prisma --script > ../stack-auth-services/volumes/db/stack-auth-init.sql +``` \ No newline at end of file diff --git a/docker/docker-compose.builder.yaml b/docker/docker-compose.builder.yaml new file mode 100644 index 0000000000..4819818535 --- /dev/null +++ b/docker/docker-compose.builder.yaml @@ -0,0 +1,31 @@ +# docker-compose.yml +services: + stack-auth-dashboard: + image: stack-auth/dashboard + build: + context: ../ + target: dashboard + dockerfile: ./docker/Dockerfile + args: # Pass all necessary variables for build + NEXT_PUBLIC_STACK_URL: ${NEXT_PUBLIC_STACK_URL} + NEXT_PUBLIC_STACK_PROJECT_ID: ${NEXT_PUBLIC_STACK_PROJECT_ID} + NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY: ${NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY} + STACK_SECRET_SERVER_KEY: ${STACK_SECRET_SERVER_KEY} + NEXT_PUBLIC_STACK_SVIX_SERVER_URL: ${NEXT_PUBLIC_STACK_SVIX_SERVER_URL} + NEXT_PUBLIC_STACK_HEAD_TAGS: ${NEXT_PUBLIC_STACK_HEAD_TAGS} + NEXT_PUBLIC_SENTRY_DSN: ${NEXT_PUBLIC_SENTRY_DSN} + NEXT_PUBLIC_SENTRY_ORG: ${NEXT_PUBLIC_SENTRY_ORG} + NEXT_PUBLIC_SENTRY_PROJECT: ${NEXT_PUBLIC_SENTRY_PROJECT} + SENTRY_AUTH_TOKEN: ${SENTRY_AUTH_TOKEN} + stack-auth-backend: + image: stack-auth/backend + build: + context: ../ + target: backend + dockerfile: ./docker/Dockerfile + args: # Pass all necessary variables for build + NEXT_PUBLIC_SENTRY_DSN: ${NEXT_PUBLIC_SENTRY_DSN} + NEXT_PUBLIC_SENTRY_ORG: ${NEXT_PUBLIC_SENTRY_ORG} + NEXT_PUBLIC_SENTRY_PROJECT: ${NEXT_PUBLIC_SENTRY_PROJECT} + SENTRY_AUTH_TOKEN: ${SENTRY_AUTH_TOKEN} + STACK_SERVER_SECRET: ${STACK_SERVER_SECRET} \ No newline at end of file diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml new file mode 100644 index 0000000000..64edfa634a --- /dev/null +++ b/docker/docker-compose.yaml @@ -0,0 +1,162 @@ +services: + # ================= Stack Auth ================= + + stack-auth-backend: + container_name: stack-auth.backend + image: stack-auth/backend + networks: + - stack-auth-network + environment: + STACK_BASE_URL: http://stack-auth-backend:8102 + STACK_SVIX_SERVER_URL: http://svix-server:8071 + STACK_DATABASE_CONNECTION_STRING: postgres://postgres:${POSTGRES_STACKFRAME_PASSWORD}@db:5432/stackframe + STACK_DIRECT_DATABASE_CONNECTION_STRING: postgres://postgres:${POSTGRES_STACKFRAME_PASSWORD}@db:5432/stackframe + STACK_SERVER_SECRET: ${STACK_SERVER_SECRET} + STACK_SVIX_API_KEY: ${STACK_SVIX_API_KEY} + STACK_OAUTH_MOCK_URL: ${STACK_OAUTH_MOCK_URL} + STACK_GITHUB_CLIENT_ID: ${STACK_GITHUB_CLIENT_ID} + STACK_GITHUB_CLIENT_SECRET: ${STACK_GITHUB_CLIENT_SECRET} + STACK_GOOGLE_CLIENT_ID: ${STACK_GOOGLE_CLIENT_ID} + STACK_GOOGLE_CLIENT_SECRET: ${STACK_GOOGLE_CLIENT_SECRET} + STACK_MICROSOFT_CLIENT_ID: ${STACK_MICROSOFT_CLIENT_ID} + STACK_MICROSOFT_CLIENT_SECRET: ${STACK_MICROSOFT_CLIENT_SECRET} + STACK_SPOTIFY_CLIENT_ID: ${STACK_SPOTIFY_CLIENT_ID} + STACK_SPOTIFY_CLIENT_SECRET: ${STACK_SPOTIFY_CLIENT_SECRET} + STACK_EMAIL_HOST: ${STACK_EMAIL_HOST} + STACK_EMAIL_PORT: ${STACK_EMAIL_PORT} + STACK_EMAIL_SECURE: ${STACK_EMAIL_SECURE} + STACK_EMAIL_USERNAME: ${STACK_EMAIL_USERNAME} + STACK_EMAIL_PASSWORD: ${STACK_EMAIL_PASSWORD} + STACK_EMAIL_SENDER: ${STACK_EMAIL_SENDER} + STACK_ACCESS_TOKEN_EXPIRATION_TIME: ${STACK_ACCESS_TOKEN_EXPIRATION_TIME} + STACK_SETUP_ADMIN_GITHUB_ID: ${STACK_SETUP_ADMIN_GITHUB_ID} + OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT} + NEXT_PUBLIC_SENTRY_DSN: ${NEXT_PUBLIC_SENTRY_DSN} + NEXT_PUBLIC_SENTRY_ORG: ${NEXT_PUBLIC_SENTRY_ORG} + NEXT_PUBLIC_SENTRY_PROJECT: ${NEXT_PUBLIC_SENTRY_PROJECT} + SENTRY_AUTH_TOKEN: ${SENTRY_AUTH_TOKEN} + ports: + - 8102:8102 + depends_on: + - db + - svix-server + + stack-auth-dashboard: + container_name: stack-auth.dashboard + image: stack-auth/dashboard + networks: + - stack-auth-network + environment: + NEXT_PUBLIC_STACK_URL: ${NEXT_PUBLIC_STACK_URL} + NEXT_PUBLIC_STACK_PROJECT_ID: ${NEXT_PUBLIC_STACK_PROJECT_ID} + NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY: ${NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY} + STACK_SECRET_SERVER_KEY: ${STACK_SECRET_SERVER_KEY} + NEXT_PUBLIC_STACK_SVIX_SERVER_URL: ${NEXT_PUBLIC_STACK_SVIX_SERVER_URL} + STACK_ACCESS_TOKEN_EXPIRATION_TIME: ${STACK_ACCESS_TOKEN_EXPIRATION_TIME} + NEXT_PUBLIC_STACK_HEAD_TAGS: ${NEXT_PUBLIC_STACK_HEAD_TAGS} + NODE_TLS_REJECT_UNAUTHORIZED: ${NODE_TLS_REJECT_UNAUTHORIZED} + depends_on: + - stack-auth-backend + + nginx: + image: nginx + container_name: nginx + networks: + stack-auth-network: + aliases: + - stack-auth.internal + - api.stack-auth.internal + - svix-api.stack-auth.internal + ports: + - 443:443 + volumes: + - ./volumes/nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./volumes/nginx/certs:/etc/nginx/ssl:ro + depends_on: + - stack-auth-dashboard + + # ================= PostgreSQL ================= + + db: + container_name: stack-auth.db + image: postgres:latest + networks: + - stack-auth-network + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${POSTGRES_STACKFRAME_PASSWORD} + POSTGRES_DB: stackframe + POSTGRES_DELAY_MS: ${POSTGRES_DELAY_MS:-0} + NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY: ${NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY} + STACK_SECRET_SERVER_KEY: ${STACK_SECRET_SERVER_KEY} + STACK_SUPER_SECRET_ADMIN_KEY: ${STACK_SUPER_SECRET_ADMIN_KEY} + ports: + - 8111:5432 + volumes: + - ./volumes/db/stack-auth-init.sql:/docker-entrypoint-initdb.d/99-stack-auth-init.sql:Z + - postgres-data:/var/lib/postgresql/data + entrypoint: ["sh", "-c", " + if [ $POSTGRES_DELAY_MS -gt 0 ]; then + apt-get update && apt-get install -y iproute2 && \ + tc qdisc add dev eth0 root netem delay ${POSTGRES_DELAY_MS}ms; + fi; + exec docker-entrypoint.sh postgres"] + cap_add: + - NET_ADMIN + + # ================= svix ================= + + svix-db: + container_name: stack-auth.svix.db + image: postgres:latest + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${POSTGRES_SVIX_PASSWORD} + POSTGRES_DB: svix + networks: + - stack-auth-network + volumes: + - svix-postgres-data:/var/lib/postgresql/data + + svix-redis: + container_name: stack-auth.redis.db + image: docker.io/redis:7-alpine + command: --save 60 500 --appendonly yes --appendfsync everysec + networks: + - stack-auth-network + volumes: + - svix-redis-data:/data + + svix-server: + container_name: stack-auth.svix + image: svix/svix-server + environment: + WAIT_FOR: 'true' + SVIX_REDIS_DSN: redis://svix-redis:6379 + SVIX_DB_DSN: postgres://postgres:${POSTGRES_SVIX_PASSWORD}@svix-db:5432/svix + SVIX_CACHE_TYPE: memory + SVIX_JWT_SECRET: ${SVIX_JWT_SECRET} + SVIX_LOG_LEVEL: trace + SVIX_QUEUE_TYPE: redis + networks: + - stack-auth-network + ports: + - 8113:8071 + depends_on: + - svix-redis + - svix-db + +# ================= volumes ================= + +volumes: + postgres-data: + name: stack_auth_postgres_data + svix-redis-data: + name: stack_auth_svix_redis_data + svix-postgres-data: + name: stack_auth_svix_postgres_data + +networks: + stack-auth-network: + driver: bridge + name: stack_auth_network diff --git a/docker/volumes/db/stack-auth-init.sql b/docker/volumes/db/stack-auth-init.sql new file mode 100644 index 0000000000..40170dd540 --- /dev/null +++ b/docker/volumes/db/stack-auth-init.sql @@ -0,0 +1,841 @@ +-- CreateEnum +CREATE TYPE "BooleanTrue" AS ENUM ('TRUE'); + +-- CreateEnum +CREATE TYPE "PermissionScope" AS ENUM ('GLOBAL', 'TEAM'); + +-- CreateEnum +CREATE TYPE "TeamSystemPermission" AS ENUM ('UPDATE_TEAM', 'DELETE_TEAM', 'READ_MEMBERS', 'REMOVE_MEMBERS', 'INVITE_MEMBERS'); + +-- CreateEnum +CREATE TYPE "ContactChannelType" AS ENUM ('EMAIL'); + +-- CreateEnum +CREATE TYPE "ProxiedOAuthProviderType" AS ENUM ('GITHUB', 'GOOGLE', 'MICROSOFT', 'SPOTIFY'); + +-- CreateEnum +CREATE TYPE "StandardOAuthProviderType" AS ENUM ('GITHUB', 'FACEBOOK', 'GOOGLE', 'MICROSOFT', 'SPOTIFY', 'DISCORD', 'GITLAB', 'BITBUCKET', 'LINKEDIN', 'APPLE', 'X'); + +-- CreateEnum +CREATE TYPE "VerificationCodeType" AS ENUM ('ONE_TIME_PASSWORD', 'PASSWORD_RESET', 'CONTACT_CHANNEL_VERIFICATION', 'TEAM_INVITATION', 'MFA_ATTEMPT', 'PASSKEY_REGISTRATION_CHALLENGE', 'PASSKEY_AUTHENTICATION_CHALLENGE'); + +-- CreateEnum +CREATE TYPE "EmailTemplateType" AS ENUM ('EMAIL_VERIFICATION', 'PASSWORD_RESET', 'MAGIC_LINK', 'TEAM_INVITATION'); + +-- CreateTable +CREATE TABLE "Project" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "displayName" TEXT NOT NULL, + "description" TEXT DEFAULT '', + "configId" UUID NOT NULL, + "isProductionMode" BOOLEAN NOT NULL, + + CONSTRAINT "Project_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ProjectConfig" ( + "id" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "allowLocalhost" BOOLEAN NOT NULL, + "signUpEnabled" BOOLEAN NOT NULL DEFAULT true, + "createTeamOnSignUp" BOOLEAN NOT NULL, + "clientTeamCreationEnabled" BOOLEAN NOT NULL, + "clientUserDeletionEnabled" BOOLEAN NOT NULL DEFAULT false, + "legacyGlobalJwtSigning" BOOLEAN NOT NULL DEFAULT false, + "teamCreateDefaultSystemPermissions" "TeamSystemPermission"[], + "teamMemberDefaultSystemPermissions" "TeamSystemPermission"[], + + CONSTRAINT "ProjectConfig_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ProjectDomain" ( + "projectConfigId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "domain" TEXT NOT NULL, + "handlerPath" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "ProjectConfigOverride" ( + "projectId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "ProjectConfigOverride_pkey" PRIMARY KEY ("projectId") +); + +-- CreateTable +CREATE TABLE "Team" ( + "projectId" TEXT NOT NULL, + "teamId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "displayName" TEXT NOT NULL, + "profileImageUrl" TEXT, + "clientMetadata" JSONB, + "clientReadOnlyMetadata" JSONB, + "serverMetadata" JSONB, + + CONSTRAINT "Team_pkey" PRIMARY KEY ("projectId","teamId") +); + +-- CreateTable +CREATE TABLE "TeamMember" ( + "projectId" TEXT NOT NULL, + "projectUserId" UUID NOT NULL, + "teamId" UUID NOT NULL, + "displayName" TEXT, + "profileImageUrl" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "isSelected" "BooleanTrue", + + CONSTRAINT "TeamMember_pkey" PRIMARY KEY ("projectId","projectUserId","teamId") +); + +-- CreateTable +CREATE TABLE "TeamMemberDirectPermission" ( + "id" UUID NOT NULL, + "projectId" TEXT NOT NULL, + "projectUserId" UUID NOT NULL, + "teamId" UUID NOT NULL, + "permissionDbId" UUID, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "systemPermission" "TeamSystemPermission", + + CONSTRAINT "TeamMemberDirectPermission_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Permission" ( + "queryableId" TEXT NOT NULL, + "dbId" UUID NOT NULL, + "projectConfigId" UUID, + "projectId" TEXT, + "teamId" UUID, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "description" TEXT, + "scope" "PermissionScope" NOT NULL, + "isDefaultTeamCreatorPermission" BOOLEAN NOT NULL DEFAULT false, + "isDefaultTeamMemberPermission" BOOLEAN NOT NULL DEFAULT false, + + CONSTRAINT "Permission_pkey" PRIMARY KEY ("dbId") +); + +-- CreateTable +CREATE TABLE "PermissionEdge" ( + "edgeId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "parentPermissionDbId" UUID, + "parentTeamSystemPermission" "TeamSystemPermission", + "childPermissionDbId" UUID NOT NULL, + + CONSTRAINT "PermissionEdge_pkey" PRIMARY KEY ("edgeId") +); + +-- CreateTable +CREATE TABLE "ProjectUser" ( + "projectId" TEXT NOT NULL, + "projectUserId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "profileImageUrl" TEXT, + "displayName" TEXT, + "serverMetadata" JSONB, + "clientReadOnlyMetadata" JSONB, + "clientMetadata" JSONB, + "requiresTotpMfa" BOOLEAN NOT NULL DEFAULT false, + "totpSecret" BYTEA, + + CONSTRAINT "ProjectUser_pkey" PRIMARY KEY ("projectId","projectUserId") +); + +-- CreateTable +CREATE TABLE "ProjectUserOAuthAccount" ( + "projectId" TEXT NOT NULL, + "projectUserId" UUID NOT NULL, + "projectConfigId" UUID NOT NULL, + "oauthProviderConfigId" TEXT NOT NULL, + "providerAccountId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "email" TEXT, + + CONSTRAINT "ProjectUserOAuthAccount_pkey" PRIMARY KEY ("projectId","oauthProviderConfigId","providerAccountId") +); + +-- CreateTable +CREATE TABLE "ContactChannel" ( + "projectId" TEXT NOT NULL, + "projectUserId" UUID NOT NULL, + "id" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "type" "ContactChannelType" NOT NULL, + "isPrimary" "BooleanTrue", + "usedForAuth" "BooleanTrue", + "isVerified" BOOLEAN NOT NULL, + "value" TEXT NOT NULL, + + CONSTRAINT "ContactChannel_pkey" PRIMARY KEY ("projectId","projectUserId","id") +); + +-- CreateTable +CREATE TABLE "ConnectedAccountConfig" ( + "projectConfigId" UUID NOT NULL, + "id" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "enabled" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "ConnectedAccountConfig_pkey" PRIMARY KEY ("projectConfigId","id") +); + +-- CreateTable +CREATE TABLE "ConnectedAccount" ( + "projectId" TEXT NOT NULL, + "id" UUID NOT NULL, + "projectConfigId" UUID NOT NULL, + "connectedAccountConfigId" UUID NOT NULL, + "projectUserId" UUID NOT NULL, + "oauthProviderConfigId" TEXT NOT NULL, + "providerAccountId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "ConnectedAccount_pkey" PRIMARY KEY ("projectId","id") +); + +-- CreateTable +CREATE TABLE "AuthMethodConfig" ( + "projectConfigId" UUID NOT NULL, + "id" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "enabled" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "AuthMethodConfig_pkey" PRIMARY KEY ("projectConfigId","id") +); + +-- CreateTable +CREATE TABLE "OtpAuthMethodConfig" ( + "projectConfigId" UUID NOT NULL, + "authMethodConfigId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "contactChannelType" "ContactChannelType" NOT NULL, + + CONSTRAINT "OtpAuthMethodConfig_pkey" PRIMARY KEY ("projectConfigId","authMethodConfigId") +); + +-- CreateTable +CREATE TABLE "PasswordAuthMethodConfig" ( + "projectConfigId" UUID NOT NULL, + "authMethodConfigId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "PasswordAuthMethodConfig_pkey" PRIMARY KEY ("projectConfigId","authMethodConfigId") +); + +-- CreateTable +CREATE TABLE "PasskeyAuthMethodConfig" ( + "projectConfigId" UUID NOT NULL, + "authMethodConfigId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "PasskeyAuthMethodConfig_pkey" PRIMARY KEY ("projectConfigId","authMethodConfigId") +); + +-- CreateTable +CREATE TABLE "OAuthProviderConfig" ( + "projectConfigId" UUID NOT NULL, + "id" TEXT NOT NULL, + "authMethodConfigId" UUID, + "connectedAccountConfigId" UUID, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "OAuthProviderConfig_pkey" PRIMARY KEY ("projectConfigId","id") +); + +-- CreateTable +CREATE TABLE "ProxiedOAuthProviderConfig" ( + "projectConfigId" UUID NOT NULL, + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "type" "ProxiedOAuthProviderType" NOT NULL, + + CONSTRAINT "ProxiedOAuthProviderConfig_pkey" PRIMARY KEY ("projectConfigId","id") +); + +-- CreateTable +CREATE TABLE "StandardOAuthProviderConfig" ( + "projectConfigId" UUID NOT NULL, + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "type" "StandardOAuthProviderType" NOT NULL, + "clientId" TEXT NOT NULL, + "clientSecret" TEXT NOT NULL, + "facebookConfigId" TEXT, + "microsoftTenantId" TEXT, + + CONSTRAINT "StandardOAuthProviderConfig_pkey" PRIMARY KEY ("projectConfigId","id") +); + +-- CreateTable +CREATE TABLE "AuthMethod" ( + "projectId" TEXT NOT NULL, + "id" UUID NOT NULL, + "projectUserId" UUID NOT NULL, + "authMethodConfigId" UUID NOT NULL, + "projectConfigId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "AuthMethod_pkey" PRIMARY KEY ("projectId","id") +); + +-- CreateTable +CREATE TABLE "OtpAuthMethod" ( + "projectId" TEXT NOT NULL, + "authMethodId" UUID NOT NULL, + "projectUserId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "OtpAuthMethod_pkey" PRIMARY KEY ("projectId","authMethodId") +); + +-- CreateTable +CREATE TABLE "PasswordAuthMethod" ( + "projectId" TEXT NOT NULL, + "authMethodId" UUID NOT NULL, + "projectUserId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "passwordHash" TEXT NOT NULL, + + CONSTRAINT "PasswordAuthMethod_pkey" PRIMARY KEY ("projectId","authMethodId") +); + +-- CreateTable +CREATE TABLE "PasskeyAuthMethod" ( + "projectId" TEXT NOT NULL, + "authMethodId" UUID NOT NULL, + "projectUserId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "credentialId" TEXT NOT NULL, + "publicKey" TEXT NOT NULL, + "userHandle" TEXT NOT NULL, + "transports" TEXT[], + "credentialDeviceType" TEXT NOT NULL, + "counter" INTEGER NOT NULL, + + CONSTRAINT "PasskeyAuthMethod_pkey" PRIMARY KEY ("projectId","authMethodId") +); + +-- CreateTable +CREATE TABLE "OAuthAuthMethod" ( + "projectId" TEXT NOT NULL, + "projectConfigId" UUID NOT NULL, + "authMethodId" UUID NOT NULL, + "oauthProviderConfigId" TEXT NOT NULL, + "providerAccountId" TEXT NOT NULL, + "projectUserId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "OAuthAuthMethod_pkey" PRIMARY KEY ("projectId","authMethodId") +); + +-- CreateTable +CREATE TABLE "OAuthToken" ( + "id" UUID NOT NULL, + "projectId" TEXT NOT NULL, + "oAuthProviderConfigId" TEXT NOT NULL, + "providerAccountId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "refreshToken" TEXT NOT NULL, + "scopes" TEXT[], + + CONSTRAINT "OAuthToken_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "OAuthAccessToken" ( + "id" UUID NOT NULL, + "projectId" TEXT NOT NULL, + "oAuthProviderConfigId" TEXT NOT NULL, + "providerAccountId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "accessToken" TEXT NOT NULL, + "scopes" TEXT[], + "expiresAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "OAuthAccessToken_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "OAuthOuterInfo" ( + "id" UUID NOT NULL, + "info" JSONB NOT NULL, + "innerState" TEXT NOT NULL, + "expiresAt" TIMESTAMP(3) NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "OAuthOuterInfo_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ProjectUserRefreshToken" ( + "projectId" TEXT NOT NULL, + "projectUserId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "refreshToken" TEXT NOT NULL, + "expiresAt" TIMESTAMP(3), + + CONSTRAINT "ProjectUserRefreshToken_pkey" PRIMARY KEY ("projectId","refreshToken") +); + +-- CreateTable +CREATE TABLE "ProjectUserAuthorizationCode" ( + "projectId" TEXT NOT NULL, + "projectUserId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "authorizationCode" TEXT NOT NULL, + "redirectUri" TEXT NOT NULL, + "expiresAt" TIMESTAMP(3) NOT NULL, + "codeChallenge" TEXT NOT NULL, + "codeChallengeMethod" TEXT NOT NULL, + "newUser" BOOLEAN NOT NULL, + "afterCallbackRedirectUrl" TEXT, + + CONSTRAINT "ProjectUserAuthorizationCode_pkey" PRIMARY KEY ("projectId","authorizationCode") +); + +-- CreateTable +CREATE TABLE "VerificationCode" ( + "projectId" TEXT NOT NULL, + "id" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "type" "VerificationCodeType" NOT NULL, + "code" TEXT NOT NULL, + "expiresAt" TIMESTAMP(3) NOT NULL, + "usedAt" TIMESTAMP(3), + "redirectUrl" TEXT, + "method" JSONB NOT NULL DEFAULT 'null', + "data" JSONB NOT NULL, + "attemptCount" INTEGER NOT NULL DEFAULT 0, + + CONSTRAINT "VerificationCode_pkey" PRIMARY KEY ("projectId","id") +); + +-- CreateTable +CREATE TABLE "ApiKeySet" ( + "projectId" TEXT NOT NULL, + "id" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "description" TEXT NOT NULL, + "expiresAt" TIMESTAMP(3) NOT NULL, + "manuallyRevokedAt" TIMESTAMP(3), + "publishableClientKey" TEXT, + "secretServerKey" TEXT, + "superSecretAdminKey" TEXT, + + CONSTRAINT "ApiKeySet_pkey" PRIMARY KEY ("projectId","id") +); + +-- CreateTable +CREATE TABLE "EmailServiceConfig" ( + "projectConfigId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "EmailServiceConfig_pkey" PRIMARY KEY ("projectConfigId") +); + +-- CreateTable +CREATE TABLE "EmailTemplate" ( + "projectConfigId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "content" JSONB NOT NULL, + "type" "EmailTemplateType" NOT NULL, + "subject" TEXT NOT NULL, + + CONSTRAINT "EmailTemplate_pkey" PRIMARY KEY ("projectConfigId","type") +); + +-- CreateTable +CREATE TABLE "ProxiedEmailServiceConfig" ( + "projectConfigId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "ProxiedEmailServiceConfig_pkey" PRIMARY KEY ("projectConfigId") +); + +-- CreateTable +CREATE TABLE "StandardEmailServiceConfig" ( + "projectConfigId" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "senderName" TEXT NOT NULL, + "senderEmail" TEXT NOT NULL, + "host" TEXT NOT NULL, + "port" INTEGER NOT NULL, + "username" TEXT NOT NULL, + "password" TEXT NOT NULL, + + CONSTRAINT "StandardEmailServiceConfig_pkey" PRIMARY KEY ("projectConfigId") +); + +-- CreateTable +CREATE TABLE "Event" ( + "id" UUID NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "isWide" BOOLEAN NOT NULL, + "eventStartedAt" TIMESTAMP(3) NOT NULL, + "eventEndedAt" TIMESTAMP(3) NOT NULL, + "systemEventTypeIds" TEXT[], + "data" JSONB NOT NULL, + + CONSTRAINT "Event_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "ProjectDomain_projectConfigId_domain_key" ON "ProjectDomain"("projectConfigId", "domain"); + +-- CreateIndex +CREATE UNIQUE INDEX "TeamMember_projectId_projectUserId_isSelected_key" ON "TeamMember"("projectId", "projectUserId", "isSelected"); + +-- CreateIndex +CREATE UNIQUE INDEX "TeamMemberDirectPermission_projectId_projectUserId_teamId_p_key" ON "TeamMemberDirectPermission"("projectId", "projectUserId", "teamId", "permissionDbId"); + +-- CreateIndex +CREATE UNIQUE INDEX "TeamMemberDirectPermission_projectId_projectUserId_teamId_s_key" ON "TeamMemberDirectPermission"("projectId", "projectUserId", "teamId", "systemPermission"); + +-- CreateIndex +CREATE UNIQUE INDEX "Permission_projectConfigId_queryableId_key" ON "Permission"("projectConfigId", "queryableId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Permission_projectId_teamId_queryableId_key" ON "Permission"("projectId", "teamId", "queryableId"); + +-- CreateIndex +CREATE INDEX "ProjectUser_displayName_asc" ON "ProjectUser"("projectId", "displayName" ASC); + +-- CreateIndex +CREATE INDEX "ProjectUser_displayName_desc" ON "ProjectUser"("projectId", "displayName" DESC); + +-- CreateIndex +CREATE INDEX "ProjectUser_createdAt_asc" ON "ProjectUser"("projectId", "createdAt" ASC); + +-- CreateIndex +CREATE INDEX "ProjectUser_createdAt_desc" ON "ProjectUser"("projectId", "createdAt" DESC); + +-- CreateIndex +CREATE UNIQUE INDEX "ContactChannel_projectId_projectUserId_type_isPrimary_key" ON "ContactChannel"("projectId", "projectUserId", "type", "isPrimary"); + +-- CreateIndex +CREATE UNIQUE INDEX "ContactChannel_projectId_projectUserId_type_value_key" ON "ContactChannel"("projectId", "projectUserId", "type", "value"); + +-- CreateIndex +CREATE UNIQUE INDEX "ContactChannel_projectId_type_value_usedForAuth_key" ON "ContactChannel"("projectId", "type", "value", "usedForAuth"); + +-- CreateIndex +CREATE UNIQUE INDEX "ConnectedAccount_projectId_oauthProviderConfigId_providerAc_key" ON "ConnectedAccount"("projectId", "oauthProviderConfigId", "providerAccountId"); + +-- CreateIndex +CREATE UNIQUE INDEX "OAuthProviderConfig_projectConfigId_authMethodConfigId_key" ON "OAuthProviderConfig"("projectConfigId", "authMethodConfigId"); + +-- CreateIndex +CREATE UNIQUE INDEX "OAuthProviderConfig_projectConfigId_connectedAccountConfigI_key" ON "OAuthProviderConfig"("projectConfigId", "connectedAccountConfigId"); + +-- CreateIndex +CREATE UNIQUE INDEX "ProxiedOAuthProviderConfig_projectConfigId_type_key" ON "ProxiedOAuthProviderConfig"("projectConfigId", "type"); + +-- CreateIndex +CREATE UNIQUE INDEX "OtpAuthMethod_projectId_projectUserId_key" ON "OtpAuthMethod"("projectId", "projectUserId"); + +-- CreateIndex +CREATE UNIQUE INDEX "PasswordAuthMethod_projectId_projectUserId_key" ON "PasswordAuthMethod"("projectId", "projectUserId"); + +-- CreateIndex +CREATE UNIQUE INDEX "PasskeyAuthMethod_projectId_projectUserId_key" ON "PasskeyAuthMethod"("projectId", "projectUserId"); + +-- CreateIndex +CREATE UNIQUE INDEX "OAuthAuthMethod_projectId_oauthProviderConfigId_providerAcc_key" ON "OAuthAuthMethod"("projectId", "oauthProviderConfigId", "providerAccountId"); + +-- CreateIndex +CREATE UNIQUE INDEX "OAuthOuterInfo_innerState_key" ON "OAuthOuterInfo"("innerState"); + +-- CreateIndex +CREATE UNIQUE INDEX "ProjectUserRefreshToken_refreshToken_key" ON "ProjectUserRefreshToken"("refreshToken"); + +-- CreateIndex +CREATE UNIQUE INDEX "ProjectUserAuthorizationCode_authorizationCode_key" ON "ProjectUserAuthorizationCode"("authorizationCode"); + +-- CreateIndex +CREATE UNIQUE INDEX "VerificationCode_projectId_code_key" ON "VerificationCode"("projectId", "code"); + +-- CreateIndex +CREATE UNIQUE INDEX "ApiKeySet_publishableClientKey_key" ON "ApiKeySet"("publishableClientKey"); + +-- CreateIndex +CREATE UNIQUE INDEX "ApiKeySet_secretServerKey_key" ON "ApiKeySet"("secretServerKey"); + +-- CreateIndex +CREATE UNIQUE INDEX "ApiKeySet_superSecretAdminKey_key" ON "ApiKeySet"("superSecretAdminKey"); + +-- CreateIndex +CREATE INDEX "Event_data_idx" ON "Event" USING GIN ("data" jsonb_path_ops); + +-- AddForeignKey +ALTER TABLE "Project" ADD CONSTRAINT "Project_configId_fkey" FOREIGN KEY ("configId") REFERENCES "ProjectConfig"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProjectDomain" ADD CONSTRAINT "ProjectDomain_projectConfigId_fkey" FOREIGN KEY ("projectConfigId") REFERENCES "ProjectConfig"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProjectConfigOverride" ADD CONSTRAINT "ProjectConfigOverride_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Team" ADD CONSTRAINT "Team_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TeamMember" ADD CONSTRAINT "TeamMember_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TeamMember" ADD CONSTRAINT "TeamMember_projectId_teamId_fkey" FOREIGN KEY ("projectId", "teamId") REFERENCES "Team"("projectId", "teamId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TeamMemberDirectPermission" ADD CONSTRAINT "TeamMemberDirectPermission_projectId_projectUserId_teamId_fkey" FOREIGN KEY ("projectId", "projectUserId", "teamId") REFERENCES "TeamMember"("projectId", "projectUserId", "teamId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "TeamMemberDirectPermission" ADD CONSTRAINT "TeamMemberDirectPermission_permissionDbId_fkey" FOREIGN KEY ("permissionDbId") REFERENCES "Permission"("dbId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Permission" ADD CONSTRAINT "Permission_projectConfigId_fkey" FOREIGN KEY ("projectConfigId") REFERENCES "ProjectConfig"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Permission" ADD CONSTRAINT "Permission_projectId_teamId_fkey" FOREIGN KEY ("projectId", "teamId") REFERENCES "Team"("projectId", "teamId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PermissionEdge" ADD CONSTRAINT "PermissionEdge_parentPermissionDbId_fkey" FOREIGN KEY ("parentPermissionDbId") REFERENCES "Permission"("dbId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PermissionEdge" ADD CONSTRAINT "PermissionEdge_childPermissionDbId_fkey" FOREIGN KEY ("childPermissionDbId") REFERENCES "Permission"("dbId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProjectUser" ADD CONSTRAINT "ProjectUser_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProjectUserOAuthAccount" ADD CONSTRAINT "ProjectUserOAuthAccount_projectConfigId_oauthProviderConfi_fkey" FOREIGN KEY ("projectConfigId", "oauthProviderConfigId") REFERENCES "OAuthProviderConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProjectUserOAuthAccount" ADD CONSTRAINT "ProjectUserOAuthAccount_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ContactChannel" ADD CONSTRAINT "ContactChannel_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ContactChannel" ADD CONSTRAINT "ContactChannel_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ConnectedAccountConfig" ADD CONSTRAINT "ConnectedAccountConfig_projectConfigId_fkey" FOREIGN KEY ("projectConfigId") REFERENCES "ProjectConfig"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ConnectedAccount" ADD CONSTRAINT "ConnectedAccount_projectId_oauthProviderConfigId_providerA_fkey" FOREIGN KEY ("projectId", "oauthProviderConfigId", "providerAccountId") REFERENCES "ProjectUserOAuthAccount"("projectId", "oauthProviderConfigId", "providerAccountId") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ConnectedAccount" ADD CONSTRAINT "ConnectedAccount_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ConnectedAccount" ADD CONSTRAINT "ConnectedAccount_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ConnectedAccount" ADD CONSTRAINT "ConnectedAccount_projectConfigId_connectedAccountConfigId_fkey" FOREIGN KEY ("projectConfigId", "connectedAccountConfigId") REFERENCES "ConnectedAccountConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ConnectedAccount" ADD CONSTRAINT "ConnectedAccount_projectConfigId_oauthProviderConfigId_fkey" FOREIGN KEY ("projectConfigId", "oauthProviderConfigId") REFERENCES "OAuthProviderConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AuthMethodConfig" ADD CONSTRAINT "AuthMethodConfig_projectConfigId_fkey" FOREIGN KEY ("projectConfigId") REFERENCES "ProjectConfig"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OtpAuthMethodConfig" ADD CONSTRAINT "OtpAuthMethodConfig_projectConfigId_authMethodConfigId_fkey" FOREIGN KEY ("projectConfigId", "authMethodConfigId") REFERENCES "AuthMethodConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PasswordAuthMethodConfig" ADD CONSTRAINT "PasswordAuthMethodConfig_projectConfigId_authMethodConfigI_fkey" FOREIGN KEY ("projectConfigId", "authMethodConfigId") REFERENCES "AuthMethodConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PasskeyAuthMethodConfig" ADD CONSTRAINT "PasskeyAuthMethodConfig_projectConfigId_authMethodConfigId_fkey" FOREIGN KEY ("projectConfigId", "authMethodConfigId") REFERENCES "AuthMethodConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OAuthProviderConfig" ADD CONSTRAINT "OAuthProviderConfig_projectConfigId_authMethodConfigId_fkey" FOREIGN KEY ("projectConfigId", "authMethodConfigId") REFERENCES "AuthMethodConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OAuthProviderConfig" ADD CONSTRAINT "OAuthProviderConfig_projectConfigId_connectedAccountConfig_fkey" FOREIGN KEY ("projectConfigId", "connectedAccountConfigId") REFERENCES "ConnectedAccountConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OAuthProviderConfig" ADD CONSTRAINT "OAuthProviderConfig_projectConfigId_fkey" FOREIGN KEY ("projectConfigId") REFERENCES "ProjectConfig"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProxiedOAuthProviderConfig" ADD CONSTRAINT "ProxiedOAuthProviderConfig_projectConfigId_id_fkey" FOREIGN KEY ("projectConfigId", "id") REFERENCES "OAuthProviderConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "StandardOAuthProviderConfig" ADD CONSTRAINT "StandardOAuthProviderConfig_projectConfigId_id_fkey" FOREIGN KEY ("projectConfigId", "id") REFERENCES "OAuthProviderConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AuthMethod" ADD CONSTRAINT "AuthMethod_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AuthMethod" ADD CONSTRAINT "AuthMethod_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AuthMethod" ADD CONSTRAINT "AuthMethod_projectConfigId_authMethodConfigId_fkey" FOREIGN KEY ("projectConfigId", "authMethodConfigId") REFERENCES "AuthMethodConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OtpAuthMethod" ADD CONSTRAINT "OtpAuthMethod_projectId_authMethodId_fkey" FOREIGN KEY ("projectId", "authMethodId") REFERENCES "AuthMethod"("projectId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OtpAuthMethod" ADD CONSTRAINT "OtpAuthMethod_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PasswordAuthMethod" ADD CONSTRAINT "PasswordAuthMethod_projectId_authMethodId_fkey" FOREIGN KEY ("projectId", "authMethodId") REFERENCES "AuthMethod"("projectId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PasswordAuthMethod" ADD CONSTRAINT "PasswordAuthMethod_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PasskeyAuthMethod" ADD CONSTRAINT "PasskeyAuthMethod_projectId_authMethodId_fkey" FOREIGN KEY ("projectId", "authMethodId") REFERENCES "AuthMethod"("projectId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PasskeyAuthMethod" ADD CONSTRAINT "PasskeyAuthMethod_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OAuthAuthMethod" ADD CONSTRAINT "OAuthAuthMethod_projectId_authMethodId_fkey" FOREIGN KEY ("projectId", "authMethodId") REFERENCES "AuthMethod"("projectId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OAuthAuthMethod" ADD CONSTRAINT "OAuthAuthMethod_projectId_oauthProviderConfigId_providerAc_fkey" FOREIGN KEY ("projectId", "oauthProviderConfigId", "providerAccountId") REFERENCES "ProjectUserOAuthAccount"("projectId", "oauthProviderConfigId", "providerAccountId") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OAuthAuthMethod" ADD CONSTRAINT "OAuthAuthMethod_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OAuthAuthMethod" ADD CONSTRAINT "OAuthAuthMethod_projectConfigId_oauthProviderConfigId_fkey" FOREIGN KEY ("projectConfigId", "oauthProviderConfigId") REFERENCES "OAuthProviderConfig"("projectConfigId", "id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OAuthToken" ADD CONSTRAINT "OAuthToken_projectId_oAuthProviderConfigId_providerAccount_fkey" FOREIGN KEY ("projectId", "oAuthProviderConfigId", "providerAccountId") REFERENCES "ProjectUserOAuthAccount"("projectId", "oauthProviderConfigId", "providerAccountId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OAuthAccessToken" ADD CONSTRAINT "OAuthAccessToken_projectId_oAuthProviderConfigId_providerA_fkey" FOREIGN KEY ("projectId", "oAuthProviderConfigId", "providerAccountId") REFERENCES "ProjectUserOAuthAccount"("projectId", "oauthProviderConfigId", "providerAccountId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProjectUserRefreshToken" ADD CONSTRAINT "ProjectUserRefreshToken_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProjectUserAuthorizationCode" ADD CONSTRAINT "ProjectUserAuthorizationCode_projectId_projectUserId_fkey" FOREIGN KEY ("projectId", "projectUserId") REFERENCES "ProjectUser"("projectId", "projectUserId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ApiKeySet" ADD CONSTRAINT "ApiKeySet_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EmailServiceConfig" ADD CONSTRAINT "EmailServiceConfig_projectConfigId_fkey" FOREIGN KEY ("projectConfigId") REFERENCES "ProjectConfig"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EmailTemplate" ADD CONSTRAINT "EmailTemplate_projectConfigId_fkey" FOREIGN KEY ("projectConfigId") REFERENCES "EmailServiceConfig"("projectConfigId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProxiedEmailServiceConfig" ADD CONSTRAINT "ProxiedEmailServiceConfig_projectConfigId_fkey" FOREIGN KEY ("projectConfigId") REFERENCES "EmailServiceConfig"("projectConfigId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "StandardEmailServiceConfig" ADD CONSTRAINT "StandardEmailServiceConfig_projectConfigId_fkey" FOREIGN KEY ("projectConfigId") REFERENCES "EmailServiceConfig"("projectConfigId") ON DELETE CASCADE ON UPDATE CASCADE; + +\set publishableClientKey `echo "'$NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY'"` +\set secretServerKey `echo "'$STACK_SECRET_SERVER_KEY'"` +\set superSecretAdminKey `echo "'$STACK_SUPER_SECRET_ADMIN_KEY'"` + +-- Insert data into ProjectConfig +INSERT INTO public."ProjectConfig" (id, "createdAt", "updatedAt", "allowLocalhost", "signUpEnabled", "createTeamOnSignUp", "clientTeamCreationEnabled", "clientUserDeletionEnabled", "legacyGlobalJwtSigning", "teamCreateDefaultSystemPermissions", "teamMemberDefaultSystemPermissions") +VALUES +('a36222cf-028b-4287-9606-89c49790cb18', NOW(), NOW(), 't', 't', 'f', 't', 'f', 'f', NULL, NULL); + +-- Insert data into Project +INSERT INTO public."Project" (id, "createdAt", "updatedAt", "displayName", description, "configId", "isProductionMode") +VALUES +('internal', NOW(), NOW(), 'Stack Dashboard', 'Stack Dashboard Stack''s admin dashboard', 'a36222cf-028b-4287-9606-89c49790cb18', 'f'); + +-- Insert data into ApiKeySet +INSERT INTO public."ApiKeySet" ("projectId", id, "createdAt", "updatedAt", description, "expiresAt", "manuallyRevokedAt", "publishableClientKey", "secretServerKey", "superSecretAdminKey") +VALUES +('internal', 'cbd08984-6100-40ea-86c0-bf1c5b6bd638', NOW(), NOW(), 'Internal API key set', '2099-12-31 23:59:59', NULL, :publishableClientKey, :secretServerKey, :superSecretAdminKey); + +-- Insert data into AuthMethodConfig +INSERT INTO public."AuthMethodConfig" ("projectConfigId", id, "createdAt", "updatedAt", enabled) +VALUES +('a36222cf-028b-4287-9606-89c49790cb18', '6478b9ae-01ed-4362-b6f5-8df59ae53432', NOW(), NOW(), 't'), +('a36222cf-028b-4287-9606-89c49790cb18', '22bba3fa-1c7c-4645-8dbd-9b51a2fbdbaa', NOW(), NOW(), 't'), +('a36222cf-028b-4287-9606-89c49790cb18', '1271bcb2-a785-4746-a871-81f841e2c8e4', NOW(), NOW(), 't'), +('a36222cf-028b-4287-9606-89c49790cb18', '1e22b7a4-5047-4165-a987-3e0f1a0c738f', NOW(), NOW(), 't'), +('a36222cf-028b-4287-9606-89c49790cb18', 'c3047a5f-9198-4da6-b988-627bfc86e579', NOW(), NOW(), 't'), +('a36222cf-028b-4287-9606-89c49790cb18', '416192c9-8663-4e72-8928-252041548430', NOW(), NOW(), 't'); + +-- Insert data into EmailServiceConfig +INSERT INTO public."EmailServiceConfig" ("projectConfigId", "createdAt", "updatedAt") +VALUES +('a36222cf-028b-4287-9606-89c49790cb18', NOW(), NOW()); + +-- Insert data into OAuthProviderConfig +INSERT INTO public."OAuthProviderConfig" ("projectConfigId", id, "authMethodConfigId", "connectedAccountConfigId", "createdAt", "updatedAt") +VALUES +('a36222cf-028b-4287-9606-89c49790cb18', 'microsoft', '1271bcb2-a785-4746-a871-81f841e2c8e4', NULL, NOW(), NOW()), +('a36222cf-028b-4287-9606-89c49790cb18', 'google', '1e22b7a4-5047-4165-a987-3e0f1a0c738f', NULL, NOW(), NOW()), +('a36222cf-028b-4287-9606-89c49790cb18', 'spotify', 'c3047a5f-9198-4da6-b988-627bfc86e579', NULL, NOW(), NOW()), +('a36222cf-028b-4287-9606-89c49790cb18', 'github', '416192c9-8663-4e72-8928-252041548430', NULL, NOW(), NOW()); + + +-- Insert data into ProxiedEmailServiceConfig +INSERT INTO public."ProxiedEmailServiceConfig" ("projectConfigId", "createdAt", "updatedAt") +VALUES +('a36222cf-028b-4287-9606-89c49790cb18', NOW(), NOW()); + +-- Insert data into ProxiedOAuthProviderConfig +INSERT INTO public."ProxiedOAuthProviderConfig" ("projectConfigId", id, "createdAt", "updatedAt", type) +VALUES +('a36222cf-028b-4287-9606-89c49790cb18', 'github', NOW(), NOW(), 'GITHUB'), +('a36222cf-028b-4287-9606-89c49790cb18', 'spotify', NOW(), NOW(), 'SPOTIFY'), +('a36222cf-028b-4287-9606-89c49790cb18', 'google', NOW(), NOW(), 'GOOGLE'), +('a36222cf-028b-4287-9606-89c49790cb18', 'microsoft', NOW(), NOW(), 'MICROSOFT'); + +-- Insert data into OtpAuthMethodConfig +INSERT INTO public."OtpAuthMethodConfig" ("projectConfigId", "authMethodConfigId", "createdAt", "updatedAt", "contactChannelType") +VALUES +('a36222cf-028b-4287-9606-89c49790cb18', '6478b9ae-01ed-4362-b6f5-8df59ae53432', NOW(), NOW(), 'EMAIL'); + +-- Insert data into PasswordAuthMethodConfig +INSERT INTO public."PasswordAuthMethodConfig" ("projectConfigId", "authMethodConfigId", "createdAt", "updatedAt") +VALUES +('a36222cf-028b-4287-9606-89c49790cb18', '22bba3fa-1c7c-4645-8dbd-9b51a2fbdbaa', NOW(), NOW()); \ No newline at end of file diff --git a/docker/volumes/nginx/certs/.gitignore b/docker/volumes/nginx/certs/.gitignore new file mode 100644 index 0000000000..b8987f0ba0 --- /dev/null +++ b/docker/volumes/nginx/certs/.gitignore @@ -0,0 +1,2 @@ +*.crt +*.key \ No newline at end of file diff --git a/docker/volumes/nginx/nginx.conf b/docker/volumes/nginx/nginx.conf new file mode 100644 index 0000000000..f5c34b2c23 --- /dev/null +++ b/docker/volumes/nginx/nginx.conf @@ -0,0 +1,60 @@ +events {} + +http { + upstream dashboard { + server stack-auth-dashboard:8101; + } + upstream backend { + server stack-auth-backend:8102; + } + upstream svix-server0 { + server svix-server:8071; + } + + server { + listen 443 ssl; + server_name stack-auth.internal; + ssl_certificate /etc/nginx/ssl/stack-auth.crt; + ssl_certificate_key /etc/nginx/ssl/stack-auth.key; + location / { + proxy_pass http://dashboard; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_ssl_verify off; + } + } + + + server { + listen 443 ssl; + server_name api.stack-auth.internal; + ssl_certificate /etc/nginx/ssl/stack-auth.crt; + ssl_certificate_key /etc/nginx/ssl/stack-auth.key; + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_ssl_verify off; + } + } + + server { + listen 443 ssl; + server_name svix-api.stack-auth.internal; + ssl_certificate /etc/nginx/ssl/stack-auth.crt; + ssl_certificate_key /etc/nginx/ssl/stack-auth.key; + location / { + proxy_pass http://svix-server0; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_ssl_verify off; + } + } + +} \ No newline at end of file diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index fa56e0cce5..890963b9be 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,3 @@ packages: - packages/* - - apps/* - - examples/* - - docs + - apps/* \ No newline at end of file diff --git a/timestamp.txt b/timestamp.txt new file mode 100644 index 0000000000..f2bc2dc305 --- /dev/null +++ b/timestamp.txt @@ -0,0 +1 @@ +Fri Nov 1 04:21:45 UTC 2024