diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index c57d889a..f951c642 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -22,6 +22,7 @@ env: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} CERTIFICATE_ARN: ${{ secrets.CERTIFICATE_ARN }} DATABASE_URL: ${{ secrets.PROD_DB_URL }} + MIGRATION_DB_URL: ${{ secrets.MIGRATION_DB_URL }} jobs: deploy: @@ -42,4 +43,4 @@ jobs: run: pnpm install --frozen-lockfile - name: Deploy ZotMeet to production - run: pnpm migrate && pnpm sst deploy --stage prod + run: STAGE=prod pnpm migrate && pnpm sst deploy --stage prod diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml index 095fbdc9..461ccb90 100644 --- a/.github/workflows/deploy-staging.yml +++ b/.github/workflows/deploy-staging.yml @@ -25,6 +25,7 @@ env: CERTIFICATE_ARN: ${{ secrets.CERTIFICATE_ARN }} DATABASE_URL: ${{ secrets.DEV_DB_URL }} PR_NUM: ${{ github.event.pull_request.number }} + MIGRATION_DB_URL: ${{ secrets.MIGRATION_DB_URL }} jobs: deploy: diff --git a/package.json b/package.json index 6a083f8f..f6d21243 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "clsx": "^2.1.0", "dotenv": "^16.4.5", "dotenv-cli": "^7.4.1", - "drizzle-orm": "0.29.4", + "drizzle-orm": "0.29.5", "lucia": "^3.1.1", "pg": "^8.11.3", "postgres": "3.4.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d07a7d11..c637ddab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,8 +24,8 @@ dependencies: specifier: ^7.4.1 version: 7.4.1 drizzle-orm: - specifier: 0.29.4 - version: 0.29.4(@aws-sdk/client-rds-data@3.533.0)(@types/pg@8.11.2)(kysely@0.25.0)(pg@8.11.3)(postgres@3.4.3)(react@18.2.0) + specifier: 0.29.5 + version: 0.29.5(@aws-sdk/client-rds-data@3.533.0)(@types/pg@8.11.2)(kysely@0.25.0)(pg@8.11.3)(postgres@3.4.3)(react@18.2.0) lucia: specifier: ^3.1.1 version: 3.1.1 @@ -5784,8 +5784,8 @@ packages: - supports-color dev: true - /drizzle-orm@0.29.4(@aws-sdk/client-rds-data@3.533.0)(@types/pg@8.11.2)(kysely@0.25.0)(pg@8.11.3)(postgres@3.4.3)(react@18.2.0): - resolution: {integrity: sha512-ZnSM8TAxFhzH7p1s3+w3pRE/eKaOeNkH9SKitm717pubDVVcV2I0BCDBPGKV+pe02+wMfw37ntlTcCyo2rA3IA==} + /drizzle-orm@0.29.5(@aws-sdk/client-rds-data@3.533.0)(@types/pg@8.11.2)(kysely@0.25.0)(pg@8.11.3)(postgres@3.4.3)(react@18.2.0): + resolution: {integrity: sha512-jS3+uyzTz4P0Y2CICx8FmRQ1eplURPaIMWDn/yq6k4ShRFj9V7vlJk67lSf2kyYPzQ60GkkNGXcJcwrxZ6QCRw==} peerDependencies: '@aws-sdk/client-rds-data': '>=3' '@cloudflare/workers-types': '>=3' diff --git a/src/lib/db/migrate.ts b/src/lib/db/migrate.ts index 7077417e..e19df51d 100644 --- a/src/lib/db/migrate.ts +++ b/src/lib/db/migrate.ts @@ -3,14 +3,20 @@ import { drizzle } from "drizzle-orm/postgres-js"; import { migrate } from "drizzle-orm/postgres-js/migrator"; import postgres from "postgres"; -const DATABASE_URL = process.env["DATABASE_URL"]; -if (!DATABASE_URL) { +const MIGRATION_DB_URL = process.env["MIGRATION_DB_URL"]; +if (!MIGRATION_DB_URL) { throw new Error( - "DATABASE_URL not found. Please ensure you have the DATABASE_URL variable defined inside of your environment configuration.", + "MIGRATION_DB_URL not found. Please ensure you have the MIGRATION_DB_URL variable defined inside of your environment configuration.", ); } -const migrationClient = postgres(DATABASE_URL, { max: 1, ssl: "prefer" }); +const migrationClient = postgres( + `${MIGRATION_DB_URL}${process.env["STAGE"] === "prod" ? "" : "?search_path=dev"}`, + { max: 1, ssl: "prefer" }, +); const db = drizzle(migrationClient); -await migrate(db, { migrationsFolder: "src/lib/db/migrations" }); +await migrate(db, { + migrationsFolder: "src/lib/db/migrations", + migrationsTable: process.env["STAGE"] === "prod" ? "public_migrations" : "dev_migrations", +}); await migrationClient.end(); diff --git a/src/lib/db/sql/access_control.sql b/src/lib/db/sql/access_control.sql new file mode 100644 index 00000000..dfe34930 --- /dev/null +++ b/src/lib/db/sql/access_control.sql @@ -0,0 +1,38 @@ +-- This file is used to control access to the database. +-- You probably do not need to modify this. + +CREATE ROLE zotmeet_migrations LOGIN; +CREATE ROLE zotmeet_prod LOGIN; +CREATE ROLE zotmeet_staging LOGIN; + +GRANT ALL ON DATABASE zotmeet TO zotmeet_migrations; +GRANT ALL ON DATABASE zotmeet TO zotmeet_prod; +GRANT ALL ON DATABASE zotmeet TO zotmeet_staging; + +GRANT ALL ON SCHEMA drizzle TO zotmeet_migrations; +GRANT ALL ON SCHEMA public TO zotmeet_migrations; +GRANT ALL ON SCHEMA dev TO zotmeet_migrations; +GRANT ALL ON SCHEMA public TO zotmeet_prod; +GRANT ALL ON SCHEMA dev TO zotmeet_staging; + +GRANT ALL ON ALL TABLES IN SCHEMA public TO zotmeet_migrations; +GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO zotmeet_migrations; +GRANT ALL ON ALL ROUTINES IN SCHEMA public TO zotmeet_migrations; +GRANT ALL ON ALL TABLES IN SCHEMA dev TO zotmeet_migrations; +GRANT ALL ON ALL SEQUENCES IN SCHEMA dev TO zotmeet_migrations; +GRANT ALL ON ALL ROUTINES IN SCHEMA dev TO zotmeet_migrations; +GRANT ALL ON ALL TABLES IN SCHEMA public TO zotmeet_prod; +GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO zotmeet_prod; +GRANT ALL ON ALL ROUTINES IN SCHEMA public TO zotmeet_prod; +GRANT ALL ON ALL TABLES IN SCHEMA dev TO zotmeet_staging; +GRANT ALL ON ALL SEQUENCES IN SCHEMA dev TO zotmeet_staging; +GRANT ALL ON ALL ROUTINES IN SCHEMA dev TO zotmeet_staging; + +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO zotmeet_prod; +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO zotmeet_prod; +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON ROUTINES TO zotmeet_prod; +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TYPES TO zotmeet_prod; +ALTER DEFAULT PRIVILEGES IN SCHEMA dev GRANT ALL ON TABLES TO zotmeet_staging; +ALTER DEFAULT PRIVILEGES IN SCHEMA dev GRANT ALL ON SEQUENCES TO zotmeet_staging; +ALTER DEFAULT PRIVILEGES IN SCHEMA dev GRANT ALL ON ROUTINES TO zotmeet_staging; +ALTER DEFAULT PRIVILEGES IN SCHEMA dev GRANT ALL ON TYPES TO zotmeet_staging;