diff --git a/README.md b/README.md index ce33dbc..e543594 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ Customizable authentication UI component with custom themes and extensible style - [Options](#options) - [Supported Views](#supported-views) - [Anonymous Sign-ins](#anonymous-sign-ins) + - [Events and Callbacks](#events-and-callbacks) - [Customization](#customization) - [Predefined themes](#predefined-themes) - [Switch theme variations](#switch-theme-variations) @@ -247,7 +248,42 @@ const { data, error } = await supabase.auth.signInAnonymously() [Enable manual linking](https://supabase.com/dashboard/project/_/settings/auth) in supabase Currently works for magic link and social login. -If you use password login, you need user to update password after he +If you use password login, you need user to update password after he sign in. + +### Events and Callbacks + +Control the authentication flow with the `beforeSubmit` callback and `on-submit` event. + +- `beforeSubmit`: A function that runs before form submission. Return `false` to abort. +- `on-submit`: An event emitted with the user's email after submission. + +```html + + + +``` ## Customization diff --git a/packages/auth/Auth.vue b/packages/auth/Auth.vue index ba89fab..72a245d 100644 --- a/packages/auth/Auth.vue +++ b/packages/auth/Auth.vue @@ -28,6 +28,8 @@ :showLinks="showLinks" :i18n="i18n" :additionalData="additionalData" + :before-submit="props.beforeSubmit" + @on-submit="handleSubmit" /> @@ -47,6 +51,8 @@ :redirectTo="redirectTo" :showLinks="showLinks" :i18n="i18n" + :before-submit="props.beforeSubmit" + @on-submit="handleSubmit" /> (), { anonymouslyCredentials: undefined }) -const emit = defineEmits(['update:view']) +const emit = defineEmits(['update:view', 'on-submit']) const authView = ref(props.view) const setAuthView = (newView: AuthViewType) => { @@ -109,6 +115,10 @@ const setAuthView = (newView: AuthViewType) => { authView.value = newView } +const handleSubmit = (e: Event) => { + emit('on-submit', e) +} + provide(AuthViewKey, { authView, setAuthView diff --git a/packages/auth/EmailAuth.vue b/packages/auth/EmailAuth.vue index 3880edf..43843d0 100644 --- a/packages/auth/EmailAuth.vue +++ b/packages/auth/EmailAuth.vue @@ -116,7 +116,6 @@ import { } from '../types' import { Anchor, - Button, BrandButton, Container, Input, @@ -135,10 +134,13 @@ export interface EmailAuthProps { showLinks?: boolean i18n?: AuthI18nVariables additionalData?: { [key: string]: any } + beforeSubmit?: (email: string) => Promise | boolean | void } const props = withDefaults(defineProps(), {}) +const emit = defineEmits(['on-submit']) + const email = ref('') const password = ref('') const error = ref('') @@ -151,12 +153,20 @@ const labels = computed( () => props.i18n?.[authView.value] as AuthI18nVariables['sign_in' | 'sign_up'] ) const handleSubmit = async (e: Event) => { + if (props.beforeSubmit) { + const canSubmit = await props.beforeSubmit(email.value) + if (canSubmit === false) { + return + } + } + // console.log(props) error.value = '' message.value = '' isLoading.value = true switch (authView.value) { case 'sign_in': + emit('on-submit', email.value) const { // data: { user: signInUser, session: signInSession }, error: signInError @@ -176,6 +186,7 @@ const handleSubmit = async (e: Event) => { if (props.additionalData) { options.data = props.additionalData } + emit('on-submit', email.value) const { data: { user: signUpUser, session: signUpSession }, error: signUpError diff --git a/packages/auth/ForgottenPassword.vue b/packages/auth/ForgottenPassword.vue index 10ddbe3..87bda7e 100644 --- a/packages/auth/ForgottenPassword.vue +++ b/packages/auth/ForgottenPassword.vue @@ -82,9 +82,11 @@ export interface ForgottenPasswordProps { redirectTo?: RedirectTo showLinks?: boolean i18n?: AuthI18nVariables + beforeSubmit?: (email: string) => Promise | boolean | void } const props = withDefaults(defineProps(), {}) +const emit = defineEmits(['on-submit']) const email = ref('') const error = ref('') @@ -98,6 +100,13 @@ const labels = computed( ) const handleSubmit = async (e: Event) => { + if (props.beforeSubmit) { + const canSubmit = await props.beforeSubmit(email.value) + if (canSubmit === false) { + return + } + } + emit('on-submit', email.value) // console.log(props) error.value = '' message.value = '' diff --git a/packages/auth/MagicLink.vue b/packages/auth/MagicLink.vue index f401f9e..8a932c8 100644 --- a/packages/auth/MagicLink.vue +++ b/packages/auth/MagicLink.vue @@ -83,8 +83,15 @@ export interface MagicLinkProps { redirectTo?: RedirectTo showLinks?: boolean i18n?: AuthI18nVariables + /** + * A function that will be called before the magic link is sent. + * If the function returns `false`, the submission will be aborted. + */ + beforeSubmit?: (email: string) => Promise | boolean | void } +const emit = defineEmits(['on-submit']) + const props = withDefaults(defineProps(), {}) const { supabaseUser } = useSupabaseUser(props.supabaseClient) @@ -101,12 +108,20 @@ const labels = computed( ) const handleSubmit = async (e: Event) => { + if (props.beforeSubmit) { + const canSubmit = await props.beforeSubmit(email.value) + if (canSubmit === false) { + return + } + } + // console.log(props) error.value = '' message.value = '' isLoading.value = true const isAnonymous = supabaseUser.value?.is_anonymous let signInError: Error | null = null + emit('on-submit', email.value) if (isAnonymous) { const { error: err } = await props.supabaseClient.auth.updateUser( { diff --git a/packages/types.ts b/packages/types.ts index e91b755..576bf65 100644 --- a/packages/types.ts +++ b/packages/types.ts @@ -77,6 +77,11 @@ export interface AuthProps extends BaseAuth { variables?: AuthI18nVariables } anonymouslyCredentials?: SignInAnonymouslyCredentials + /** + * A function that will be called before the authentication is submitted. + * If the function returns `false`, the submission will be aborted. + */ + beforeSubmit?: (email: string) => Promise | boolean | void } export type AuthProvider = diff --git a/src/App.vue b/src/App.vue index 4f2f528..ec8f3d4 100644 --- a/src/App.vue +++ b/src/App.vue @@ -52,6 +52,8 @@ variables: I18nVariables }" :redirect-to="redirectTo" + :before-submit="handleEmailSubmit" + @on-submit="handleSubmit" show-links /> @@ -320,6 +322,18 @@ const handleSignOut = () => { supabaseUser.value = null } +const handleEmailSubmit = async (email: string) => { + if (email.endsWith('@suspicious.com')) { + alert('This email provider is not allowed.') + return false + } + return true +} + +const handleSubmit = (event: Event) => { + console.log(event) +} + watch( () => supabaseUser.value, (newUser) => {