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 = {
* Login with YouTube
*/
loginYouTube: string
+ /**
+ * Login with GitHub
+ */
+ 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');
+});