From 84e30eead0746d259d3c05c2fa50c7525586cd9b Mon Sep 17 00:00:00 2001 From: Zai Shi Date: Wed, 11 Sep 2024 02:25:18 +0200 Subject: [PATCH] Remove shared Facebook (#238) * removed facebook shared * updated test * added migration file * facebook enabled var * fixed migration file * fixed connected account migration file --- apps/backend/.env | 2 - apps/backend/.env.development | 2 - .../migration.sql | 2 +- .../migration.sql | 46 +++++++++++++++++++ apps/backend/prisma/schema.prisma | 1 - apps/backend/prisma/seed.ts | 4 +- apps/dashboard/.env | 2 - .../new-project/page-client.tsx | 4 +- apps/e2e/tests/backend/backend-helpers.ts | 4 +- .../api/v1/auth/oauth/authorize.test.ts | 12 ++--- .../api/v1/auth/oauth/callback.test.ts | 2 +- .../endpoints/api/v1/auth/oauth/token.test.ts | 6 +-- .../api/v1/internal/projects.test.ts | 16 +++---- .../backend/endpoints/api/v1/projects.test.ts | 26 +++++------ packages/stack-shared/src/utils/oauth.tsx | 6 +-- 15 files changed, 87 insertions(+), 48 deletions(-) create mode 100644 apps/backend/prisma/migrations/20240910211533_remove_shared_facebook/migration.sql diff --git a/apps/backend/.env b/apps/backend/.env index e5746c461..747eaf762 100644 --- a/apps/backend/.env +++ b/apps/backend/.env @@ -11,8 +11,6 @@ STACK_GITHUB_CLIENT_ID=# client STACK_GITHUB_CLIENT_SECRET=# client secret STACK_GOOGLE_CLIENT_ID=# client id STACK_GOOGLE_CLIENT_SECRET=# client secret -STACK_FACEBOOK_CLIENT_ID=# client id -STACK_FACEBOOK_CLIENT_SECRET=# client secret STACK_MICROSOFT_CLIENT_ID=# client id STACK_MICROSOFT_CLIENT_SECRET=# client secret STACK_SPOTIFY_CLIENT_ID=# client id diff --git a/apps/backend/.env.development b/apps/backend/.env.development index d14c2f147..93b809ff7 100644 --- a/apps/backend/.env.development +++ b/apps/backend/.env.development @@ -7,8 +7,6 @@ STACK_GITHUB_CLIENT_ID=MOCK STACK_GITHUB_CLIENT_SECRET=MOCK STACK_GOOGLE_CLIENT_ID=MOCK STACK_GOOGLE_CLIENT_SECRET=MOCK -STACK_FACEBOOK_CLIENT_ID=MOCK -STACK_FACEBOOK_CLIENT_SECRET=MOCK STACK_MICROSOFT_CLIENT_ID=MOCK STACK_MICROSOFT_CLIENT_SECRET=MOCK STACK_SPOTIFY_CLIENT_ID=MOCK diff --git a/apps/backend/prisma/migrations/20240901224341_connected_account/migration.sql b/apps/backend/prisma/migrations/20240901224341_connected_account/migration.sql index 6f5b7ac51..069afe7ea 100644 --- a/apps/backend/prisma/migrations/20240901224341_connected_account/migration.sql +++ b/apps/backend/prisma/migrations/20240901224341_connected_account/migration.sql @@ -224,7 +224,7 @@ INSERT INTO "OtpAuthMethodConfig" ("projectConfigId", "authMethodConfigId", "cre SELECT "id", gen_random_uuid(), "createdAt", "updatedAt", 'EMAIL' FROM "ProjectConfig"; INSERT INTO "AuthMethodConfig" ("projectConfigId", "id", "createdAt", "updatedAt", "enabled") - SELECT "projectConfigId", "authMethodConfigId", "OtpAuthMethodConfig"."createdAt", "OtpAuthMethodConfig"."updatedAt", ("ProjectConfig"."credentialEnabled" = true) + SELECT "projectConfigId", "authMethodConfigId", "OtpAuthMethodConfig"."createdAt", "OtpAuthMethodConfig"."updatedAt", ("ProjectConfig"."magicLinkEnabled" = true) FROM "OtpAuthMethodConfig" LEFT JOIN "ProjectConfig" ON "OtpAuthMethodConfig"."projectConfigId" = "ProjectConfig"."id"; diff --git a/apps/backend/prisma/migrations/20240910211533_remove_shared_facebook/migration.sql b/apps/backend/prisma/migrations/20240910211533_remove_shared_facebook/migration.sql new file mode 100644 index 000000000..04d2902ed --- /dev/null +++ b/apps/backend/prisma/migrations/20240910211533_remove_shared_facebook/migration.sql @@ -0,0 +1,46 @@ +/* + Warnings: + + - The values [FACEBOOK] on the enum `ProxiedOAuthProviderType` will be removed. If these variants are still used in the database, this will fail. +*/ + +-- Update shared facebook project to be a standard oauth provider + +-- First, disable all the auth method configs that are shared facebook +UPDATE "AuthMethodConfig" +SET "enabled" = false +WHERE "id" IN ( + SELECT "authMethodConfigId" + FROM "OAuthProviderConfig" + WHERE "id" IN ( + SELECT "id" + FROM "ProxiedOAuthProviderConfig" + WHERE "type" = 'FACEBOOK' + ) +); + +-- Second, create StandardOAuthProviderConfig entries for Facebook providers +INSERT INTO "StandardOAuthProviderConfig" ("projectConfigId", "id", "type", "clientId", "clientSecret", "createdAt", "updatedAt") +SELECT + p."projectConfigId", + p."id", + 'FACEBOOK', + 'client id', + 'client secret', + NOW(), + NOW() +FROM "ProxiedOAuthProviderConfig" p +WHERE p."type" = 'FACEBOOK'; + +-- Then, delete the corresponding ProxiedOAuthProviderConfig entries +DELETE FROM "ProxiedOAuthProviderConfig" +WHERE "type" = 'FACEBOOK'; + +-- AlterEnum +BEGIN; +CREATE TYPE "ProxiedOAuthProviderType_new" AS ENUM ('GITHUB', 'GOOGLE', 'MICROSOFT', 'SPOTIFY'); +ALTER TABLE "ProxiedOAuthProviderConfig" ALTER COLUMN "type" TYPE "ProxiedOAuthProviderType_new" USING ("type"::text::"ProxiedOAuthProviderType_new"); +ALTER TYPE "ProxiedOAuthProviderType" RENAME TO "ProxiedOAuthProviderType_old"; +ALTER TYPE "ProxiedOAuthProviderType_new" RENAME TO "ProxiedOAuthProviderType"; +DROP TYPE "ProxiedOAuthProviderType_old"; +COMMIT; \ No newline at end of file diff --git a/apps/backend/prisma/schema.prisma b/apps/backend/prisma/schema.prisma index d1434fc7b..a96af6f84 100644 --- a/apps/backend/prisma/schema.prisma +++ b/apps/backend/prisma/schema.prisma @@ -444,7 +444,6 @@ model ProxiedOAuthProviderConfig { enum ProxiedOAuthProviderType { GITHUB - FACEBOOK GOOGLE MICROSOFT SPOTIFY diff --git a/apps/backend/prisma/seed.ts b/apps/backend/prisma/seed.ts index 2e0eab67f..86ea5689e 100644 --- a/apps/backend/prisma/seed.ts +++ b/apps/backend/prisma/seed.ts @@ -38,7 +38,7 @@ async function seed() { create: { allowLocalhost: true, oauthProviderConfigs: { - create: (['github', 'facebook', 'google', 'microsoft'] as const).map((id) => ({ + create: (['github', 'spotify', 'google', 'microsoft'] as const).map((id) => ({ id, proxiedOAuthConfig: { create: { @@ -86,7 +86,7 @@ async function seed() { } } }, - ...(['github', 'facebook', 'google', 'microsoft'] as const).map((id) => ({ + ...(['github', 'spotify', 'google', 'microsoft'] as const).map((id) => ({ oauthProviderConfig: { connect: { projectConfigId_id: { diff --git a/apps/dashboard/.env b/apps/dashboard/.env index 4240773fb..e970cef3b 100644 --- a/apps/dashboard/.env +++ b/apps/dashboard/.env @@ -12,8 +12,6 @@ STACK_GITHUB_CLIENT_ID=# client STACK_GITHUB_CLIENT_SECRET=# client secret STACK_GOOGLE_CLIENT_ID=# client id STACK_GOOGLE_CLIENT_SECRET=# client secret -STACK_FACEBOOK_CLIENT_ID=# client id -STACK_FACEBOOK_CLIENT_SECRET=# client secret STACK_MICROSOFT_CLIENT_ID=# client id STACK_MICROSOFT_CLIENT_SECRET=# client secret STACK_SPOTIFY_CLIENT_ID=# client id diff --git a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client.tsx index 67d36c2f4..1ce2acaab 100644 --- a/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/(outside-dashboard)/new-project/page-client.tsx @@ -37,7 +37,7 @@ export default function PageClient () { signUpEnabled: true, credentialEnabled: form.watch("signInMethods").includes("credential"), magicLinkEnabled: form.watch("signInMethods").includes("magicLink"), - oauthProviders: form.watch('signInMethods').filter((method) => ["google", "github", "microsoft", "facebook"].includes(method)).map(provider => ({ id: provider, type: 'shared' })), + oauthProviders: form.watch('signInMethods').filter((method) => ["google", "github", "microsoft", "spotify"].includes(method)).map(provider => ({ id: provider, type: 'shared' })), } }; @@ -88,7 +88,7 @@ export default function PageClient () { { value: "google", label: "Google" }, { value: "github", label: "GitHub" }, { value: "microsoft", label: "Microsoft" }, - { value: "facebook", label: "Facebook" }, + { value: "spotify", label: "Spotify" }, ]} /> diff --git a/apps/e2e/tests/backend/backend-helpers.ts b/apps/e2e/tests/backend/backend-helpers.ts index e9d06b86f..83f699c1a 100644 --- a/apps/e2e/tests/backend/backend-helpers.ts +++ b/apps/e2e/tests/backend/backend-helpers.ts @@ -403,7 +403,7 @@ export namespace Auth { } export async function authorize(options?: { redirectUrl?: string, errorRedirectUrl?: string }) { - const response = await niceBackendFetch("/api/v1/auth/oauth/authorize/facebook", { + const response = await niceBackendFetch("/api/v1/auth/oauth/authorize/spotify", { redirect: "manual", query: { ...await Auth.OAuth.getAuthorizeQuery(), @@ -495,7 +495,7 @@ export namespace Auth { }); const innerCallbackUrl = new URL(redirectResponse3.headers.get("location") ?? throwErr("missing redirect location", { redirectResponse3 })); expect(innerCallbackUrl.origin).toBe("http://localhost:8102"); - expect(innerCallbackUrl.pathname).toBe("/api/v1/auth/oauth/callback/facebook"); + expect(innerCallbackUrl.pathname).toBe("/api/v1/auth/oauth/callback/spotify"); return { ...options, innerCallbackUrl, diff --git a/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/authorize.test.ts b/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/authorize.test.ts index ef9773905..c8682c175 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/authorize.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/authorize.test.ts @@ -11,11 +11,11 @@ it("should redirect the user to the OAuth provider with the right arguments", as it("should be able to fetch the inner callback URL by following the OAuth provider redirects", async ({ expect }) => { const { innerCallbackUrl } = await Auth.OAuth.getInnerCallbackUrl(); expect(innerCallbackUrl.origin).toBe("http://localhost:8102"); - expect(innerCallbackUrl.pathname).toBe("/api/v1/auth/oauth/callback/facebook"); + expect(innerCallbackUrl.pathname).toBe("/api/v1/auth/oauth/callback/spotify"); }); it("should fail if an invalid client_id is provided", async ({ expect }) => { - const response = await niceBackendFetch("/api/v1/auth/oauth/authorize/facebook", { + const response = await niceBackendFetch("/api/v1/auth/oauth/authorize/spotify", { redirect: "manual", query: { ...await Auth.OAuth.getAuthorizeQuery(), @@ -39,7 +39,7 @@ it("should fail if an invalid client_id is provided", async ({ expect }) => { }); it("should fail if an invalid client_secret is provided", async ({ expect }) => { - const response = await niceBackendFetch("/api/v1/auth/oauth/authorize/facebook", { + const response = await niceBackendFetch("/api/v1/auth/oauth/authorize/spotify", { redirect: "manual", query: { ...await Auth.OAuth.getAuthorizeQuery(), @@ -63,7 +63,7 @@ it("should fail if an invalid client_secret is provided", async ({ expect }) => }); it("should fail if an invalid redirect URL is provided", async ({ expect }) => { - const response = await niceBackendFetch("/api/v1/auth/oauth/authorize/facebook", { + const response = await niceBackendFetch("/api/v1/auth/oauth/authorize/spotify", { redirect: "manual", query: { ...await Auth.OAuth.getAuthorizeQuery(), @@ -75,8 +75,8 @@ it("should fail if an invalid redirect URL is provided", async ({ expect }) => { "status": 400, "body": { "code": "SCHEMA_ERROR", - "details": { "message": "Request validation failed on GET /api/v1/auth/oauth/authorize/facebook:\\n - Invalid URL" }, - "error": "Request validation failed on GET /api/v1/auth/oauth/authorize/facebook:\\n - Invalid URL", + "details": { "message": "Request validation failed on GET /api/v1/auth/oauth/authorize/spotify:\\n - Invalid URL" }, + "error": "Request validation failed on GET /api/v1/auth/oauth/authorize/spotify:\\n - Invalid URL", }, "headers": Headers { "x-stack-known-error": "SCHEMA_ERROR", diff --git a/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/callback.test.ts b/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/callback.test.ts index 1da33fde5..5e4c6e172 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/callback.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/callback.test.ts @@ -42,7 +42,7 @@ it("should fail when inner callback has invalid provider ID", async ({ expect }) }); it("should fail when account is new and sign ups are disabled", async ({ expect }) => { - await Project.createAndSwitch({ config: { sign_up_enabled: false, oauth_providers: [ { id: "facebook", type: "shared", enabled: true } ] } }); + await Project.createAndSwitch({ config: { sign_up_enabled: false, oauth_providers: [ { id: "spotify", type: "shared", enabled: true } ] } }); await ApiKey.createAndSetProjectKeys(); const getInnerCallbackUrlResponse = await Auth.OAuth.getInnerCallbackUrl(); const cookie = updateCookiesFromResponse("", getInnerCallbackUrlResponse.authorizeResponse); diff --git a/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/token.test.ts b/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/token.test.ts index 6d09bd585..f50db2a26 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/token.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/auth/oauth/token.test.ts @@ -37,9 +37,9 @@ describe("with grant_type === 'authorization_code'", async () => { "auth_methods": [ { "provider": { - "id": "facebook", + "id": "spotify", "provider_user_id": "@stack-generated.example.com", - "type": "facebook", + "type": "spotify", }, "type": "oauth", }, @@ -55,7 +55,7 @@ describe("with grant_type === 'authorization_code'", async () => { { "account_id": "@stack-generated.example.com", "email": "@stack-generated.example.com", - "id": "facebook", + "id": "spotify", }, ], "primary_email": "@stack-generated.example.com", diff --git a/apps/e2e/tests/backend/endpoints/api/v1/internal/projects.test.ts b/apps/e2e/tests/backend/endpoints/api/v1/internal/projects.test.ts index 6045201fb..1f4088e7b 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/internal/projects.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/internal/projects.test.ts @@ -146,7 +146,7 @@ it("creates a new project with different configurations", async ({ expect }) => enabled: true, }, { - id: "facebook", + id: "spotify", type: "standard", enabled: false, client_id: "client_id", @@ -170,18 +170,18 @@ it("creates a new project with different configurations", async ({ expect }) => "id": "", "magic_link_enabled": false, "oauth_providers": [ - { - "client_id": "client_id", - "client_secret": "client_secret", - "enabled": false, - "id": "facebook", - "type": "standard", - }, { "enabled": true, "id": "google", "type": "shared", }, + { + "client_id": "client_id", + "client_secret": "client_secret", + "enabled": false, + "id": "spotify", + "type": "standard", + }, ], "sign_up_enabled": true, "team_creator_default_permissions": [{ "id": "admin" }], diff --git a/apps/e2e/tests/backend/endpoints/api/v1/projects.test.ts b/apps/e2e/tests/backend/endpoints/api/v1/projects.test.ts index 9fee6b974..59acd8b93 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/projects.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/projects.test.ts @@ -34,10 +34,10 @@ it("gets current project (internal)", async ({ expect }) => { "client_team_creation_enabled": true, "credential_enabled": true, "enabled_oauth_providers": [ - { "id": "facebook" }, { "id": "github" }, { "id": "google" }, { "id": "microsoft" }, + { "id": "spotify" }, ], "magic_link_enabled": true, "sign_up_enabled": true, @@ -690,7 +690,7 @@ it("updates the project oauth configuration", async ({ expect }) => { const { updateProjectResponse: response4 } = await Project.updateCurrent(adminAccessToken, { config: { oauth_providers: [{ - id: "facebook", + id: "spotify", type: "shared", enabled: true, }] @@ -709,7 +709,7 @@ it("updates the project oauth configuration", async ({ expect }) => { config: { oauth_providers: [ { - id: "facebook", + id: "spotify", type: "shared", enabled: true, }, @@ -733,20 +733,20 @@ it("updates the project oauth configuration", async ({ expect }) => { "domains": [], "email_config": { "type": "shared" }, "enabled_oauth_providers": [ - { "id": "facebook" }, { "id": "google" }, + { "id": "spotify" }, ], "id": "", "magic_link_enabled": false, "oauth_providers": [ { "enabled": true, - "id": "facebook", + "id": "google", "type": "shared", }, { "enabled": true, - "id": "google", + "id": "spotify", "type": "shared", }, ], @@ -770,7 +770,7 @@ it("updates the project oauth configuration", async ({ expect }) => { config: { oauth_providers: [ { - id: "facebook", + id: "spotify", type: "shared", enabled: true, }, @@ -793,18 +793,18 @@ it("updates the project oauth configuration", async ({ expect }) => { "credential_enabled": true, "domains": [], "email_config": { "type": "shared" }, - "enabled_oauth_providers": [{ "id": "facebook" }], + "enabled_oauth_providers": [{ "id": "spotify" }], "id": "", "magic_link_enabled": false, "oauth_providers": [ { - "enabled": true, - "id": "facebook", + "enabled": false, + "id": "google", "type": "shared", }, { - "enabled": false, - "id": "google", + "enabled": true, + "id": "spotify", "type": "shared", }, ], @@ -890,7 +890,7 @@ it("deletes a project with users, teams, and permissions", async ({ expect }) => enabled: true, }, { - id: "facebook", + id: "spotify", type: "standard", enabled: true, client_id: "client_id", diff --git a/packages/stack-shared/src/utils/oauth.tsx b/packages/stack-shared/src/utils/oauth.tsx index 077d72a2b..94f0325e2 100644 --- a/packages/stack-shared/src/utils/oauth.tsx +++ b/packages/stack-shared/src/utils/oauth.tsx @@ -1,7 +1,7 @@ -export const standardProviders = ["google", "github", "facebook", "microsoft", "spotify", "discord", "gitlab", "bitbucket"] as const; +export const standardProviders = ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket"] as const; // No more shared providers should be added except for special cases -export const sharedProviders = ["google", "github", "facebook", "microsoft", "spotify"] as const; -export const allProviders = ["google", "github", "facebook", "microsoft", "spotify", "discord", "gitlab", "bitbucket"] as const; +export const sharedProviders = ["google", "github", "microsoft", "spotify"] as const; +export const allProviders = ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket"] as const; export type ProviderType = typeof allProviders[number]; export type StandardProviderType = typeof standardProviders[number];