diff --git a/frontend/.env.example b/frontend/.env.example
index 7aa65a1..e8a373f 100644
--- a/frontend/.env.example
+++ b/frontend/.env.example
@@ -24,3 +24,7 @@ PRIVATE_FLYIO_IPV6=
# Resend config (if you have a Resend hosting provider)
PRIVATE_RESEND_API_KEY=
+
+# Google OAuth
+PRIVATE_GOOGLE_CLIENT_ID=
+PRIVATE_GOOGLE_CLIENT_SECRET=
\ No newline at end of file
diff --git a/frontend/bun.lockb b/frontend/bun.lockb
index d4a3e76..d9aea3b 100755
Binary files a/frontend/bun.lockb and b/frontend/bun.lockb differ
diff --git a/frontend/drizzle/0016_steady_darkstar.sql b/frontend/drizzle/0016_steady_darkstar.sql
new file mode 100644
index 0000000..c10b4cc
--- /dev/null
+++ b/frontend/drizzle/0016_steady_darkstar.sql
@@ -0,0 +1,2 @@
+ALTER TABLE "user" ALTER COLUMN "password" DROP NOT NULL;--> statement-breakpoint
+ALTER TABLE "user" ADD COLUMN "google_id" varchar(255);
\ No newline at end of file
diff --git a/frontend/drizzle/meta/0016_snapshot.json b/frontend/drizzle/meta/0016_snapshot.json
new file mode 100644
index 0000000..f72f870
--- /dev/null
+++ b/frontend/drizzle/meta/0016_snapshot.json
@@ -0,0 +1,419 @@
+{
+ "id": "9ba9c83e-b94c-42c5-84c9-010050810026",
+ "prevId": "ac377af2-68ea-4c36-a69c-4cc57a04a523",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.email_verification_token": {
+ "name": "email_verification_token",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(255)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.project": {
+ "name": "project",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "qr_background": {
+ "name": "qr_background",
+ "type": "varchar(7)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'#ffffff'"
+ },
+ "qr_foreground": {
+ "name": "qr_foreground",
+ "type": "varchar(7)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'#000000'"
+ },
+ "domain_status": {
+ "name": "domain_status",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'verified'"
+ },
+ "enable_custom_domain": {
+ "name": "enable_custom_domain",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "custom_ip": {
+ "name": "custom_ip",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "custom_domain_id": {
+ "name": "custom_domain_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "custom_domain": {
+ "name": "custom_domain",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.session": {
+ "name": "session",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(255)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.setting": {
+ "name": "setting",
+ "schema": "",
+ "columns": {
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "qr_background": {
+ "name": "qr_background",
+ "type": "varchar(7)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "qr_foreground": {
+ "name": "qr_foreground",
+ "type": "varchar(7)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.shortener": {
+ "name": "shortener",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "link": {
+ "name": "link",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ios": {
+ "name": "ios",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "ios_link": {
+ "name": "ios_link",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "android": {
+ "name": "android",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "android_link": {
+ "name": "android_link",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "code": {
+ "name": "code",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "active": {
+ "name": "active",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "project_id": {
+ "name": "project_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "shortener_code_unique": {
+ "name": "shortener_code_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "code"
+ ]
+ }
+ }
+ },
+ "public.user": {
+ "name": "user",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "gen_random_uuid()"
+ },
+ "email_verified": {
+ "name": "email_verified",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "google_id": {
+ "name": "google_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "username": {
+ "name": "username",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "password": {
+ "name": "password",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "user_email_unique": {
+ "name": "user_email_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "email"
+ ]
+ }
+ }
+ },
+ "public.visitor": {
+ "name": "visitor",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "shortener_id": {
+ "name": "shortener_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "country_code": {
+ "name": "country_code",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "country": {
+ "name": "country",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "city": {
+ "name": "city",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "device_type": {
+ "name": "device_type",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "device_vendor": {
+ "name": "device_vendor",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "os": {
+ "name": "os",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "browser": {
+ "name": "browser",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/frontend/drizzle/meta/_journal.json b/frontend/drizzle/meta/_journal.json
index e0f9ba1..a853288 100644
--- a/frontend/drizzle/meta/_journal.json
+++ b/frontend/drizzle/meta/_journal.json
@@ -113,6 +113,13 @@
"when": 1723360689804,
"tag": "0015_tidy_electro",
"breakpoints": true
+ },
+ {
+ "idx": 16,
+ "version": "7",
+ "when": 1724250058955,
+ "tag": "0016_steady_darkstar",
+ "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/frontend/package.json b/frontend/package.json
index 09e79ea..89aeda9 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,68 +1,69 @@
{
- "name": "link-shortener-svelte",
- "version": "0.0.1",
- "private": true,
- "scripts": {
- "dev": "vite dev",
- "build": "vite build",
- "preview": "vite preview",
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
- "lint": "prettier --plugin-search-dir . --check .",
- "format": "prettier --write .",
- "migrate": "bun ./src/lib/db/migrate.ts",
- "db:push": "drizzle-kit push",
- "db:generate": "drizzle-kit generate",
- "db:migrate": "drizzle-kit migrate"
- },
- "devDependencies": {
- "@sveltejs/adapter-node": "^2.0.0",
- "@sveltejs/kit": "^2.5.5",
- "@sveltejs/vite-plugin-svelte": "^3.0.2",
- "@types/pg": "^8.11.6",
- "autoprefixer": "^10.4.14",
- "bun-types": "^1.0.11",
- "drizzle-kit": "^0.23.1",
- "lucia": "^3.1.1",
- "postcss": "^8.4.24",
- "postcss-load-config": "^4.0.1",
- "prettier": "^3.1.0",
- "prettier-plugin-svelte": "^3.1.0",
- "prettier-plugin-tailwindcss": "^0.5.7",
- "svelte": "^4.2.17",
- "svelte-adapter-bun": "^0.5.1",
- "svelte-check": "^3.4.3",
- "tailwindcss": "^3.3.2",
- "tslib": "^2.4.1",
- "typescript": "^5.0.0",
- "vite": "^5.2.8"
- },
- "type": "module",
- "dependencies": {
- "@lucia-auth/adapter-drizzle": "^1.0.7",
- "@prgm/sveltekit-progress-bar": "^2.0.0",
- "@types/he": "^1.2.3",
- "apexcharts": "^3.44.0",
- "bits-ui": "^0.21.13",
- "clsx": "^2.0.0",
- "cmdk-sv": "^0.0.13",
- "drizzle-orm": "^0.32.1",
- "formsnap": "^1.0.0",
- "he": "^1.2.0",
- "lucide-svelte": "^0.418.0",
- "mode-watcher": "^0.1.2",
- "nanoid": "^5.0.3",
- "node-html-parser": "^6.1.12",
- "oslo": "^1.2.0",
- "pg": "^8.11.5",
- "postgres": "^3.4.3",
- "qr-code-styling": "^1.6.0-rc.1",
- "resend": "^3.4.0",
- "svelte-sonner": "^0.3.10",
- "sveltekit-superforms": "^2.12.2",
- "tailwind-merge": "^2.0.0",
- "tailwind-variants": "^0.1.18",
- "vaul-svelte": "^0.3.1",
- "zod": "^3.22.4"
- }
+ "name": "link-shortener-svelte",
+ "version": "0.0.1",
+ "private": true,
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "vite preview",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "lint": "prettier --plugin-search-dir . --check .",
+ "format": "prettier --write .",
+ "migrate": "bun ./src/lib/db/migrate.ts",
+ "db:push": "drizzle-kit push",
+ "db:generate": "drizzle-kit generate",
+ "db:migrate": "drizzle-kit migrate"
+ },
+ "devDependencies": {
+ "@sveltejs/adapter-node": "^2.0.0",
+ "@sveltejs/kit": "^2.5.5",
+ "@sveltejs/vite-plugin-svelte": "^3.0.2",
+ "@types/pg": "^8.11.6",
+ "autoprefixer": "^10.4.14",
+ "bun-types": "^1.0.11",
+ "drizzle-kit": "^0.23.1",
+ "lucia": "^3.1.1",
+ "postcss": "^8.4.24",
+ "postcss-load-config": "^4.0.1",
+ "prettier": "^3.1.0",
+ "prettier-plugin-svelte": "^3.1.0",
+ "prettier-plugin-tailwindcss": "^0.5.7",
+ "svelte": "^4.2.17",
+ "svelte-adapter-bun": "^0.5.1",
+ "svelte-check": "^3.4.3",
+ "tailwindcss": "^3.3.2",
+ "tslib": "^2.4.1",
+ "typescript": "^5.0.0",
+ "vite": "^5.2.8"
+ },
+ "type": "module",
+ "dependencies": {
+ "@lucia-auth/adapter-drizzle": "^1.0.7",
+ "@prgm/sveltekit-progress-bar": "^2.0.0",
+ "@types/he": "^1.2.3",
+ "apexcharts": "^3.44.0",
+ "arctic": "^1.9.2",
+ "bits-ui": "^0.21.13",
+ "clsx": "^2.0.0",
+ "cmdk-sv": "^0.0.13",
+ "drizzle-orm": "^0.32.1",
+ "formsnap": "^1.0.0",
+ "he": "^1.2.0",
+ "lucide-svelte": "^0.418.0",
+ "mode-watcher": "^0.1.2",
+ "nanoid": "^5.0.3",
+ "node-html-parser": "^6.1.12",
+ "oslo": "^1.2.0",
+ "pg": "^8.11.5",
+ "postgres": "^3.4.3",
+ "qr-code-styling": "^1.6.0-rc.1",
+ "resend": "^3.4.0",
+ "svelte-sonner": "^0.3.10",
+ "sveltekit-superforms": "^2.12.2",
+ "tailwind-merge": "^2.0.0",
+ "tailwind-variants": "^0.1.18",
+ "vaul-svelte": "^0.3.1",
+ "zod": "^3.22.4"
+ }
}
diff --git a/frontend/src/lib/components/icons/google.svelte b/frontend/src/lib/components/icons/google.svelte
new file mode 100644
index 0000000..580ae4b
--- /dev/null
+++ b/frontend/src/lib/components/icons/google.svelte
@@ -0,0 +1,11 @@
+
+
+
diff --git a/frontend/src/lib/db/schema.ts b/frontend/src/lib/db/schema.ts
index 6ea307b..880209c 100644
--- a/frontend/src/lib/db/schema.ts
+++ b/frontend/src/lib/db/schema.ts
@@ -14,8 +14,9 @@ export const user = pgTable('user', {
uuid: uuid('uuid').defaultRandom(),
email_verified: boolean('email_verified').notNull().default(false),
email: varchar('email', { length: 255 }).notNull().unique(),
+ googleId: varchar('google_id', { length: 255 }),
username: varchar('username', { length: 255 }),
- password: varchar('password', { length: 255 }).notNull(),
+ password: varchar('password', { length: 255 }),
createdAt: timestamp('created_at', { mode: 'string' })
.defaultNow()
.notNull(),
diff --git a/frontend/src/lib/server/auth.ts b/frontend/src/lib/server/auth.ts
index ebf30d5..0994823 100644
--- a/frontend/src/lib/server/auth.ts
+++ b/frontend/src/lib/server/auth.ts
@@ -3,6 +3,8 @@ import { db } from '$lib/db'
import { session, user } from '$lib/db/schema'
import { type User } from '$lib/db/types'
import { Lucia } from 'lucia'
+import { Google } from 'arctic'
+import { env } from '$env/dynamic/private'
declare module 'lucia' {
interface Register {
@@ -23,3 +25,10 @@ export const lucia = new Lucia(adapter, {
}
},
})
+
+export const google = new Google(
+ env.PRIVATE_GOOGLE_CLIENT_ID,
+ env.PRIVATE_GOOGLE_CLIENT_SECRET,
+ (env.APP_ENV === 'prod' ? env.ORIGIN : 'http://localhost:5173') +
+ '/login/google/callback',
+)
diff --git a/frontend/src/routes/(auth)/login/(components)/form.svelte b/frontend/src/routes/(auth)/login/(components)/form.svelte
index 37235fa..b60adc4 100644
--- a/frontend/src/routes/(auth)/login/(components)/form.svelte
+++ b/frontend/src/routes/(auth)/login/(components)/form.svelte
@@ -56,6 +56,6 @@
{#if $submitting}
+
Enter your email below to login to your account
+
Don't Have An Account? Signup{' '} + class="hover:text-primary underline underline-offset-4"> Here
diff --git a/frontend/src/routes/(auth)/login/google/+server.ts b/frontend/src/routes/(auth)/login/google/+server.ts new file mode 100644 index 0000000..2b33d55 --- /dev/null +++ b/frontend/src/routes/(auth)/login/google/+server.ts @@ -0,0 +1,36 @@ +import { google } from '$lib/server/auth' +import { generateState, generateCodeVerifier } from 'arctic' +import { serializeCookie } from 'oslo/cookie' +import { env } from '$env/dynamic/private' +import { redirect } from '@sveltejs/kit' + +export const GET = async (event) => { + const state = generateState() + const codeVerifier = generateCodeVerifier() + + const url = await google.createAuthorizationURL( + state, + codeVerifier, + { + scopes: ['email', 'profile'], + }, + ) + + event.cookies.set('google_oauth_state', state, { + httpOnly: true, + secure: env.APP_ENV === 'prod', + maxAge: 60 * 10, // 10 minutes + path: '/', + sameSite: 'lax', + }) + + event.cookies.set('google_oauth_code_verifier', codeVerifier, { + httpOnly: true, + secure: env.APP_ENV === 'prod', + maxAge: 60 * 10, // 10 minutes + path: '/', + sameSite: 'lax', + }) + + return redirect(302, url.toString()) +} diff --git a/frontend/src/routes/(auth)/login/google/callback/+server.ts b/frontend/src/routes/(auth)/login/google/callback/+server.ts new file mode 100644 index 0000000..85ff945 --- /dev/null +++ b/frontend/src/routes/(auth)/login/google/callback/+server.ts @@ -0,0 +1,127 @@ +import { OAuth2RequestError } from 'arctic' +import { google, lucia } from '$lib/server/auth' +import { db } from '$lib/db' +import { user } from '$lib/db/schema' +import { eq } from 'drizzle-orm' + +interface GoogleUser { + sub: string // Unique identifier for the user + name: string // Full name of the user + email: string // Email address of the user +} + +export async function GET(event) { + const code = event.url.searchParams.get('code') + const state = event.url.searchParams.get('state') + const codeVerifier = event.cookies.get('google_oauth_code_verifier') + const storedState = event.cookies.get('google_oauth_state') ?? null + + if ( + !code || + !state || + !storedState || + !codeVerifier || + state !== storedState + ) { + return new Response(null, { + status: 400, + }) + } + + try { + const tokens = await google.validateAuthorizationCode( + code, + codeVerifier, + ) + const googleUserResponse = await fetch( + 'https://www.googleapis.com/oauth2/v3/userinfo', + { + headers: { + Authorization: `Bearer ${tokens.accessToken}`, + }, + }, + ) + const googleUser: GoogleUser = await googleUserResponse.json() + + const existingGoogleUser = await db.query.user.findFirst({ + where: (user, { eq }) => eq(user.googleId, googleUser.sub), + }) + + if (existingGoogleUser) { + const session = await lucia.createSession( + existingGoogleUser.id, + {}, + ) + const sessionCookie = lucia.createSessionCookie(session.id) + event.cookies.set(sessionCookie.name, sessionCookie.value, { + path: '.', + ...sessionCookie.attributes, + }) + + return new Response(null, { + status: 302, + headers: { + Location: '/dashboard', + }, + }) + } + + const existingUser = await db.query.user.findFirst({ + where: (user, { eq }) => eq(user.email, googleUser.email), + }) + + if (existingUser) { + const updateUser = await db + .update(user) + .set({ + email_verified: true, + password: null, + username: googleUser.name, + }) + .where(eq(user.id, existingUser.id)) + .returning() + + const newUser = updateUser[0] + + const session = await lucia.createSession(newUser.id, {}) + const sessionCookie = lucia.createSessionCookie(session.id) + event.cookies.set(sessionCookie.name, sessionCookie.value, { + path: '.', + ...sessionCookie.attributes, + }) + } else { + const insertUser = await db + .insert(user) + .values({ + email: googleUser.email, // Using email as username + email_verified: true, + googleId: googleUser.sub, + username: googleUser.name, // Name field may not always be present, handle accordingly + }) + .returning() + + const newUser = insertUser[0] + + const session = await lucia.createSession(newUser.id, {}) + const sessionCookie = lucia.createSessionCookie(session.id) + event.cookies.set(sessionCookie.name, sessionCookie.value, { + path: '.', + ...sessionCookie.attributes, + }) + } + + return new Response(null, { + status: 302, + headers: { + Location: '/dashboard', + }, + }) + } catch (e) { + return new Response(null, { + status: 302, + headers: { + Location: '/login', + }, + }) + } +} diff --git a/frontend/src/routes/(auth)/signup/+page.server.ts b/frontend/src/routes/(auth)/signup/+page.server.ts index 62181ad..4179452 100644 --- a/frontend/src/routes/(auth)/signup/+page.server.ts +++ b/frontend/src/routes/(auth)/signup/+page.server.ts @@ -37,6 +37,13 @@ export const actions: Actions = { const user = users[0] if (user) { + if (user.googleId) { + return setError( + form, + 'email', + 'This email is detected on Google login, please login via Google', + ) + } return setError(form, 'email', 'Email Already Exist') }