mirror of
				https://github.com/bartvdbraak/omnidash.git
				synced 2025-10-31 00:19:12 +00:00 
			
		
		
		
	Merge pull request #226 from bartvdbraak/safari-support
Refactor OAuth2Form component
This commit is contained in:
		
						commit
						f90f4f42ef
					
				
					 5 changed files with 53 additions and 82 deletions
				
			
		|  | @ -1,3 +1,3 @@ | ||||||
| export { default as LoginForm } from './login-form.svelte'; | export { default as LoginForm } from './login-form.svelte'; | ||||||
| export { default as RegisterForm } from './register-form.svelte'; | export { default as RegisterForm } from './register-form.svelte'; | ||||||
| export { default as SSOForm } from './sso-form.svelte'; | export { default as Oauth2Form } from './oauth2-form.svelte'; | ||||||
|  |  | ||||||
|  | @ -14,7 +14,6 @@ | ||||||
| 	import SuperDebug from 'sveltekit-superforms'; | 	import SuperDebug from 'sveltekit-superforms'; | ||||||
| 	import { zodClient } from 'sveltekit-superforms/adapters'; | 	import { zodClient } from 'sveltekit-superforms/adapters'; | ||||||
| 	import { browser, dev } from '$app/environment'; | 	import { browser, dev } from '$app/environment'; | ||||||
| 	// import { PUBLIC_DEBUG_FORMS } from '$env/static/public'; |  | ||||||
| 	import { toast } from 'svelte-sonner'; | 	import { toast } from 'svelte-sonner'; | ||||||
| 	import { Icons } from '$lib/components/site'; | 	import { Icons } from '$lib/components/site'; | ||||||
| 	import { cn } from '$lib/utils'; | 	import { cn } from '$lib/utils'; | ||||||
|  | @ -31,12 +30,22 @@ | ||||||
| 		}, | 		}, | ||||||
| 		onUpdated: ({ form: f }) => { | 		onUpdated: ({ form: f }) => { | ||||||
| 			isLoading = false; | 			isLoading = false; | ||||||
| 			if (f.valid) { | 			if (!f.valid) { | ||||||
| 				toast.success('Succesfully logged in.'); |  | ||||||
| 			} else { |  | ||||||
| 				toast.error('Please fix the errors.'); | 				toast.error('Please fix the errors.'); | ||||||
| 			} | 			} | ||||||
|  | 		}, | ||||||
|  | 		onError: (e) => { | ||||||
|  | 			toast.error(e.result.error.message); | ||||||
|  | 		}, | ||||||
|  | 		onResult: (e) => { | ||||||
|  | 			if (e.result.status === 303) { | ||||||
|  | 				toast.success('Logged in successfully.'); | ||||||
|  | 			} else { | ||||||
|  | 				console.log(e) | ||||||
|  | 				toast.error('Invalid credentials.'); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	const { form: formData, enhance } = form; | 	const { form: formData, enhance } = form; | ||||||
|  |  | ||||||
|  | @ -1,49 +1,14 @@ | ||||||
| <script lang="ts" context="module"> |  | ||||||
| 	import { z } from 'zod'; |  | ||||||
| 	export const ssoFormSchema = z.object({ |  | ||||||
| 		token: z.string() |  | ||||||
| 	}); |  | ||||||
| 	export type SsoFormSchema = typeof ssoFormSchema; |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| 	import * as Form from '$lib/components/ui/form'; |  | ||||||
| 	import { Input } from '$lib/components/ui/input'; |  | ||||||
| 	import { type SuperValidated, type Infer, superForm } from 'sveltekit-superforms'; |  | ||||||
| 	import SuperDebug from 'sveltekit-superforms'; |  | ||||||
| 	import { zodClient } from 'sveltekit-superforms/adapters'; |  | ||||||
| 	import { browser, dev } from '$app/environment'; |  | ||||||
| 	import { toast } from 'svelte-sonner'; |  | ||||||
| 	import { Icons } from '$lib/components/site'; | 	import { Icons } from '$lib/components/site'; | ||||||
| 	import PocketBase from 'pocketbase'; | 	import PocketBase from 'pocketbase'; | ||||||
| 	import { PUBLIC_CLIENT_PB } from '$env/static/public'; | 	import { PUBLIC_CLIENT_PB } from '$env/static/public'; | ||||||
|  | 	import { enhance } from '$app/forms'; | ||||||
| 	import { Button } from '$lib/components/ui/button'; | 	import { Button } from '$lib/components/ui/button'; | ||||||
| 	import { Separator } from '$lib/components/ui/separator'; | 	import { Separator } from '$lib/components/ui/separator'; | ||||||
| 	import * as DropdownMenu from '$lib/components/ui/dropdown-menu'; | 	import * as DropdownMenu from '$lib/components/ui/dropdown-menu'; | ||||||
| 	import { ChevronDown } from 'radix-icons-svelte'; | 	import { ChevronDown } from 'radix-icons-svelte'; | ||||||
| 	import { debugForms } from '$lib/config/site'; |  | ||||||
| 
 |  | ||||||
| 	export let data: SuperValidated<Infer<SsoFormSchema>>; |  | ||||||
| 	let isLoading = false; |  | ||||||
| 
 |  | ||||||
| 	const form = superForm(data, { |  | ||||||
| 		validators: zodClient(ssoFormSchema), |  | ||||||
| 		onSubmit: () => { |  | ||||||
| 			isLoading = true; |  | ||||||
| 			toast.loading('Logging in...'); |  | ||||||
| 		}, |  | ||||||
| 		onUpdated: ({ form: f }) => { |  | ||||||
| 			isLoading = false; |  | ||||||
| 			if (f.valid) { |  | ||||||
| 				toast.success('Succesfully logged in.'); |  | ||||||
| 			} else { |  | ||||||
| 				toast.error('Please fix the errors.'); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
| 
 |  | ||||||
| 	const { form: formData, enhance } = form; |  | ||||||
| 
 | 
 | ||||||
|  | 	export let isLoading = false; | ||||||
| 	/* eslint-disable  @typescript-eslint/no-explicit-any */ | 	/* eslint-disable  @typescript-eslint/no-explicit-any */ | ||||||
| 	export let providers: { name: string; icon?: any; displayName: string }[]; | 	export let providers: { name: string; icon?: any; displayName: string }[]; | ||||||
| 	let currentProvider = providers[0]; | 	let currentProvider = providers[0]; | ||||||
|  | @ -52,7 +17,13 @@ | ||||||
| 	let oauth2Form: HTMLFormElement; | 	let oauth2Form: HTMLFormElement; | ||||||
| 	async function loginWithOauth2(provider: string) { | 	async function loginWithOauth2(provider: string) { | ||||||
| 		try { | 		try { | ||||||
| 			await pb.collection('users').authWithOAuth2({ provider }); | 			let w = window.open(); | ||||||
|  | 			await pb.collection('users').authWithOAuth2({ | ||||||
|  | 				provider: provider, | ||||||
|  | 				urlCallback: (url) => { | ||||||
|  | 					if (w) w.location.href = url; | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
| 			const input = document.createElement('input'); | 			const input = document.createElement('input'); | ||||||
| 			input.type = 'hidden'; | 			input.type = 'hidden'; | ||||||
| 			input.name = 'token'; | 			input.name = 'token'; | ||||||
|  | @ -65,14 +36,26 @@ | ||||||
| 	} | 	} | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <form method="POST" action="?/sso" class="grid gap-2" use:enhance> | <form | ||||||
| 	<Form.Field {form} name="token" class="grid gap-2"> | 	method="POST" | ||||||
| 		<Form.Control let:attrs> | 	action="?/oauth2" | ||||||
| 			<Input {...attrs} bind:value={$formData.token} class="hidden" /> | 	bind:this={oauth2Form} | ||||||
| 		</Form.Control> | 	use:enhance={() => { | ||||||
| 		<Form.FieldErrors /> | 		isLoading = true; | ||||||
| 	</Form.Field> | 		return async ({ update }) => { | ||||||
| 
 | 			isLoading = false; | ||||||
|  | 			update(); | ||||||
|  | 		}; | ||||||
|  | 	}} | ||||||
|  | > | ||||||
|  | 	<div class="relative"> | ||||||
|  | 		<div class="absolute inset-0 flex items-center"> | ||||||
|  | 			<span class="w-full border-t" /> | ||||||
|  | 		</div> | ||||||
|  | 		<div class="relative flex justify-center text-xs uppercase"> | ||||||
|  | 			<span class="bg-background px-2 py-4 text-muted-foreground"> Or continue with </span> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
| 	<div | 	<div | ||||||
| 		class="flex items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" | 		class="flex items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" | ||||||
| 	> | 	> | ||||||
|  | @ -137,9 +120,3 @@ | ||||||
| 		{/if} | 		{/if} | ||||||
| 	</div> | 	</div> | ||||||
| </form> | </form> | ||||||
| 
 |  | ||||||
| {#if dev && debugForms && browser} |  | ||||||
| 	<div class="pt-4"> |  | ||||||
| 		<SuperDebug data={$formData} /> |  | ||||||
| 	</div> |  | ||||||
| {/if} |  | ||||||
|  | @ -3,14 +3,12 @@ import { superValidate } from 'sveltekit-superforms'; | ||||||
| import { zod } from 'sveltekit-superforms/adapters'; | import { zod } from 'sveltekit-superforms/adapters'; | ||||||
| import { loginFormSchema } from './(components)/login-form.svelte'; | import { loginFormSchema } from './(components)/login-form.svelte'; | ||||||
| import { registerFormSchema } from './(components)/register-form.svelte'; | import { registerFormSchema } from './(components)/register-form.svelte'; | ||||||
| import { ssoFormSchema } from './(components)/sso-form.svelte'; |  | ||||||
| import { fail, type Actions, redirect } from '@sveltejs/kit'; | import { fail, type Actions, redirect } from '@sveltejs/kit'; | ||||||
| 
 | 
 | ||||||
| export const load: PageServerLoad = async () => { | export const load: PageServerLoad = async () => { | ||||||
| 	return { | 	return { | ||||||
| 		loginForm: await superValidate(zod(loginFormSchema)), | 		loginForm: await superValidate(zod(loginFormSchema)), | ||||||
| 		registerForm: await superValidate(zod(registerFormSchema)), | 		registerForm: await superValidate(zod(registerFormSchema)) | ||||||
| 		ssoForm: await superValidate(zod(ssoFormSchema)) |  | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -54,26 +52,13 @@ export const actions: Actions = { | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	sso: async ({ request, cookies }) => { | 	oauth2: async ({ request, cookies }) => { | ||||||
| 		const form = await superValidate(request, zod(ssoFormSchema)); | 		const form = await request.formData(); | ||||||
| 		if (!form.valid) { | 		const token = form.get('token'); | ||||||
| 			return fail(400, { | 		if (!token || typeof token !== 'string') { | ||||||
| 				form | 			throw redirect(303, '/auth'); | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 		const token = form.data.token; |  | ||||||
| 		try { |  | ||||||
| 			if (!token || typeof token !== 'string') { |  | ||||||
| 				throw redirect(303, '/auth'); |  | ||||||
| 			} |  | ||||||
| 			cookies.set('pb_auth', JSON.stringify({ token: token }), { path: '/' }); |  | ||||||
| 			return { |  | ||||||
| 				form |  | ||||||
| 			}; |  | ||||||
| 		} catch (err) { |  | ||||||
| 			return fail(500, { |  | ||||||
| 				form |  | ||||||
| 			}); |  | ||||||
| 		} | 		} | ||||||
|  | 		cookies.set('pb_auth', JSON.stringify({ token: token }), { path: '/' }); | ||||||
|  | 		throw redirect(303, '/'); | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| 	import { Icons } from '$lib/components/site/index.js'; | 	import { Icons } from '$lib/components/site/index.js'; | ||||||
| 	import * as Tabs from '$lib/components/ui/tabs'; | 	import * as Tabs from '$lib/components/ui/tabs'; | ||||||
| 	import type { PageData } from './$types.js'; | 	import type { PageData } from './$types.js'; | ||||||
| 	import { LoginForm, RegisterForm, SSOForm } from './(components)'; | 	import { LoginForm, RegisterForm, Oauth2Form } from './(components)'; | ||||||
| 
 | 
 | ||||||
| 	export let data: PageData; | 	export let data: PageData; | ||||||
| 
 | 
 | ||||||
|  | @ -37,7 +37,7 @@ | ||||||
| 			Forgot password? <a class="text-primary underline" href="/reset-password">Reset password.</a> | 			Forgot password? <a class="text-primary underline" href="/reset-password">Reset password.</a> | ||||||
| 		</p> | 		</p> | ||||||
| 		{#if providers.length} | 		{#if providers.length} | ||||||
| 			<SSOForm data={data.ssoForm} providers={providersWithIcons} /> | 			<Oauth2Form providers={providersWithIcons} /> | ||||||
| 		{/if} | 		{/if} | ||||||
| 	</Tabs.Root> | 	</Tabs.Root> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue