From e76cc998d4f93437c9ae29d71be1de6f8186ddaf Mon Sep 17 00:00:00 2001 From: albertlast Date: Tue, 16 May 2023 20:37:33 +0200 Subject: [PATCH] GitHub oAuth2 login --- .env.example | 2 ++ src/hooks.server.ts | 7 +++++++ src/lib/config.server.ts | 2 ++ src/lib/i18n/en/index.ts | 1 + src/lib/i18n/i18n-types.ts | 8 ++++++++ src/routes/+page.svelte | 15 +++++++++++++++ tests/oauth.test.ts | 8 +++++++- 7 files changed, 42 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index b8fb4ac..dcff51f 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,8 @@ AUTH_SECRET=generate-long-random-string-for-this YOUTUBE_API_KEY=insert-your-api-key-here GOOGLE_CLIENT_ID=insert-your-client-id-here GOOGLE_CLIENT_SECRET=insert-your-client-secret-here +GITHUB_CLIENT_ID=insert-your-client-id-here +GITHUB_CLIENT_SECRET=insert-your-client-secret-here REDIS_PORT=6379 REDIS_URL=redis://localhost:${REDIS_PORT} DB_HOST=localhost diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 2ac6912..62eaaa9 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -4,6 +4,7 @@ import { initAcceptLanguageHeaderDetector } from 'typesafe-i18n/detectors'; import { detectLocale } from '$lib/i18n/i18n-util.js'; import { SvelteKitAuth } from '@auth/sveltekit'; import Google from '@auth/core/providers/google'; +import GitHub from '@auth/core/providers/github'; import PrismaAdapter from '$lib/prisma/client'; import { config } from '$/lib/config.server'; import prismaClient from '$/lib/db.server'; @@ -29,6 +30,12 @@ const handleAuth = (async (...args) => { clientId: config.GOOGLE_CLIENT_ID, clientSecret: config.GOOGLE_CLIENT_SECRET, }), + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + GitHub({ + clientId: config.GITHUB_CLIENT_ID, + clientSecret: config.GITHUB_CLIENT_SECRET, + }), ], callbacks: { async session({ session, user }) { diff --git a/src/lib/config.server.ts b/src/lib/config.server.ts index 08e4fa3..2ae39c7 100644 --- a/src/lib/config.server.ts +++ b/src/lib/config.server.ts @@ -7,6 +7,8 @@ export const ServerConfigSchema = z.object({ AUTH_SECRET: z.string().trim().min(32), GOOGLE_CLIENT_ID: z.string().trim().min(1), GOOGLE_CLIENT_SECRET: z.string().trim().min(1), + GITHUB_CLIENT_ID: z.string().trim().min(1), + GITHUB_CLIENT_SECRET: z.string().trim().min(1), DB_HOST: z.string().trim().min(1), DB_USER: z.string().trim().min(1), DB_PASSWORD: z.string().trim().min(1), diff --git a/src/lib/i18n/en/index.ts b/src/lib/i18n/en/index.ts index 791dafe..2f7df3e 100644 --- a/src/lib/i18n/en/index.ts +++ b/src/lib/i18n/en/index.ts @@ -12,6 +12,7 @@ const en: BaseTranslation = { update: 'Update', logOut: 'Logout', loginYouTube: 'Login with YouTube', + loginGitHub: 'Login with GitHub', }, labels: { title: 'Title', diff --git a/src/lib/i18n/i18n-types.ts b/src/lib/i18n/i18n-types.ts index 81f3eee..03395f4 100644 --- a/src/lib/i18n/i18n-types.ts +++ b/src/lib/i18n/i18n-types.ts @@ -40,6 +40,10 @@ type RootTranslation = { * L​o​g​i​n​ ​w​i​t​h​ ​Y​o​u​T​u​b​e */ loginYouTube: string + /** + * L​o​g​i​n​ ​w​i​t​h​ ​G​i​t​H​u​b + */ + loginGitHub: string } labels: { /** @@ -178,6 +182,10 @@ export type TranslationFunctions = { * Login with YouTube */ loginYouTube: () => LocalizedString + /** + * Login with GitHub + */ + loginGitHub: () => LocalizedString } labels: { /** diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 1631b94..820e849 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -44,6 +44,7 @@ signIn('google'); }} disabled={loading} + data-testid="google-btn" class="btn variant-filled-primary cursor-pointer"> {#if loading} {$LL.messages.pleaseWait()} @@ -51,5 +52,19 @@ {$LL.buttons.loginYouTube()} {/if} + {/if} diff --git a/tests/oauth.test.ts b/tests/oauth.test.ts index b01036a..dd810b9 100644 --- a/tests/oauth.test.ts +++ b/tests/oauth.test.ts @@ -2,7 +2,13 @@ import { expect, test } from '@playwright/test'; test('login button redirects to google', async ({ page }) => { await page.goto('/'); - await page.getByRole('button').click(); + await page.getByTestId('google-btn').click(); await page.waitForURL('**/accounts.google.com/**'); expect(page.url()).toContain('https://accounts.google.com/'); }); +test('login button redirects to github', async ({ page }) => { + await page.goto('/'); + await page.getByTestId('github-btn').click(); + await page.waitForURL('**/github.com/**'); + expect(page.url()).toContain('https://github.com/login'); +});