feat(frontend): Use betterAuth implementation from nuxthub-better-auth project
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
<component
|
<component
|
||||||
:is="getResolvedComponent(formElement)"
|
:is="getResolvedComponent(formElement)"
|
||||||
:form-options="formElement.options"
|
:form-options="formElement.options"
|
||||||
|
:disabled="props.disabled"
|
||||||
@update:form-options="updateFormOptions($event, index)"
|
@update:form-options="updateFormOptions($event, index)"
|
||||||
/>
|
/>
|
||||||
</UFormField>
|
</UFormField>
|
||||||
@@ -17,6 +18,7 @@ import { resolveComponent } from 'vue'
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: FormElementDto[]
|
modelValue: FormElementDto[]
|
||||||
|
disabled?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -60,13 +60,13 @@ const colors = [
|
|||||||
]
|
]
|
||||||
const neutrals = ['slate', 'gray', 'zinc', 'neutral', 'stone']
|
const neutrals = ['slate', 'gray', 'zinc', 'neutral', 'stone']
|
||||||
|
|
||||||
const { data: session } = await useSession(useFetch)
|
const { user: betterAuthUser, signOut } = await useAuth()
|
||||||
|
|
||||||
const user = ref({
|
const user = ref({
|
||||||
name: session?.value?.user?.name,
|
name: betterAuthUser.value?.name,
|
||||||
avatar: {
|
avatar: {
|
||||||
src: '/_nuxt/public/favicon.ico',
|
src: '/_nuxt/public/favicon.ico',
|
||||||
alt: session?.value?.user?.name
|
alt: betterAuthUser.value?.name
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -115,7 +115,6 @@ const items = computed<DropdownMenuItem[][]>(() => [
|
|||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
onSelect: (e) => {
|
onSelect: (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
appConfig.ui.colors.primary = color
|
appConfig.ui.colors.primary = color
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@@ -136,7 +135,6 @@ const items = computed<DropdownMenuItem[][]>(() => [
|
|||||||
checked: appConfig.ui.colors.neutral === color,
|
checked: appConfig.ui.colors.neutral === color,
|
||||||
onSelect: (e) => {
|
onSelect: (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
appConfig.ui.colors.neutral = color
|
appConfig.ui.colors.neutral = color
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@@ -154,7 +152,6 @@ const items = computed<DropdownMenuItem[][]>(() => [
|
|||||||
checked: colorMode.value === 'light',
|
checked: colorMode.value === 'light',
|
||||||
onSelect(e: Event) {
|
onSelect(e: Event) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
colorMode.preference = 'light'
|
colorMode.preference = 'light'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -182,7 +179,6 @@ const items = computed<DropdownMenuItem[][]>(() => [
|
|||||||
async onSelect(e: Event) {
|
async onSelect(e: Event) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
signOut()
|
signOut()
|
||||||
await navigateTo('/login')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
84
legalconsenthub/composables/useAuth.ts
Normal file
84
legalconsenthub/composables/useAuth.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
// Copied from https://github.com/atinux/nuxthub-better-auth
|
||||||
|
|
||||||
|
import { defu } from 'defu'
|
||||||
|
import { createAuthClient } from 'better-auth/client'
|
||||||
|
import type { InferSessionFromClient, InferUserFromClient, ClientOptions } from 'better-auth/client'
|
||||||
|
import { organizationClient } from 'better-auth/client/plugins'
|
||||||
|
import type { RouteLocationRaw } from 'vue-router'
|
||||||
|
|
||||||
|
interface RuntimeAuthConfig {
|
||||||
|
redirectUserTo: RouteLocationRaw | string
|
||||||
|
redirectGuestTo: RouteLocationRaw | string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAuth() {
|
||||||
|
const url = useRequestURL()
|
||||||
|
const headers = import.meta.server ? useRequestHeaders() : undefined
|
||||||
|
|
||||||
|
const client = createAuthClient({
|
||||||
|
baseURL: url.origin,
|
||||||
|
fetchOptions: {
|
||||||
|
headers
|
||||||
|
},
|
||||||
|
plugins: [organizationClient()]
|
||||||
|
})
|
||||||
|
|
||||||
|
const options = defu(useRuntimeConfig().public.auth as Partial<RuntimeAuthConfig>, {
|
||||||
|
redirectUserTo: '/',
|
||||||
|
redirectGuestTo: '/login'
|
||||||
|
})
|
||||||
|
const session = useState<InferSessionFromClient<ClientOptions> | null>('auth:session', () => null)
|
||||||
|
const user = useState<InferUserFromClient<ClientOptions> | null>('auth:user', () => null)
|
||||||
|
const sessionFetching = import.meta.server ? ref(false) : useState('auth:sessionFetching', () => false)
|
||||||
|
|
||||||
|
const fetchSession = async () => {
|
||||||
|
if (sessionFetching.value) {
|
||||||
|
console.log('already fetching session')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sessionFetching.value = true
|
||||||
|
const { data } = await client.getSession({
|
||||||
|
fetchOptions: {
|
||||||
|
headers
|
||||||
|
}
|
||||||
|
})
|
||||||
|
session.value = data?.session || null
|
||||||
|
user.value = data?.user || null
|
||||||
|
sessionFetching.value = false
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
if (import.meta.client) {
|
||||||
|
client.$store.listen('$sessionSignal', async (signal) => {
|
||||||
|
if (!signal) return
|
||||||
|
await fetchSession()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function signOut({ redirectTo }: { redirectTo?: RouteLocationRaw } = {}) {
|
||||||
|
const res = await client.signOut()
|
||||||
|
if (res.error) {
|
||||||
|
console.error('Error signing out:', res.error)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
session.value = null
|
||||||
|
user.value = null
|
||||||
|
if (redirectTo) {
|
||||||
|
await navigateTo(redirectTo)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
session,
|
||||||
|
user,
|
||||||
|
loggedIn: computed(() => !!session.value),
|
||||||
|
signIn: client.signIn,
|
||||||
|
signUp: client.signUp,
|
||||||
|
signOut,
|
||||||
|
organization: client.organization,
|
||||||
|
options,
|
||||||
|
fetchSession,
|
||||||
|
client
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ const selectedOrgId = ref<string | undefined>(undefined)
|
|||||||
|
|
||||||
export function useBetterAuth() {
|
export function useBetterAuth() {
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
const { organization } = useAuth()
|
||||||
|
|
||||||
async function createOrganization(name: string, slug: string, logo?: string) {
|
async function createOrganization(name: string, slug: string, logo?: string) {
|
||||||
await organization.create(
|
await organization.create(
|
||||||
@@ -25,7 +26,7 @@ export function useBetterAuth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function deleteOrganization() {
|
async function deleteOrganization() {
|
||||||
await authClient.organization.delete(
|
await organization.delete(
|
||||||
{ organizationId: activeOrganization.value?.id ?? '' },
|
{ organizationId: activeOrganization.value?.id ?? '' },
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
@@ -41,7 +42,7 @@ export function useBetterAuth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getInvitation(invitationId: string): Promise<CustomInvitation> {
|
async function getInvitation(invitationId: string): Promise<CustomInvitation> {
|
||||||
return authClient.organization.getInvitation({
|
return organization.getInvitation({
|
||||||
query: { id: invitationId },
|
query: { id: invitationId },
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
throw: true,
|
throw: true,
|
||||||
@@ -56,7 +57,7 @@ export function useBetterAuth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function inviteMember(email: string, role: 'member' | 'admin') {
|
async function inviteMember(email: string, role: 'member' | 'admin') {
|
||||||
await authClient.organization.inviteMember({
|
await organization.inviteMember({
|
||||||
email,
|
email,
|
||||||
role,
|
role,
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
@@ -77,7 +78,7 @@ export function useBetterAuth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function acceptInvitation(invitationId: string) {
|
async function acceptInvitation(invitationId: string) {
|
||||||
await authClient.organization.acceptInvitation({
|
await organization.acceptInvitation({
|
||||||
invitationId,
|
invitationId,
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
throw: true,
|
throw: true,
|
||||||
@@ -93,7 +94,7 @@ export function useBetterAuth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function rejectInvitation(invitationId: string) {
|
async function rejectInvitation(invitationId: string) {
|
||||||
await authClient.organization.rejectInvitation({
|
await organization.rejectInvitation({
|
||||||
invitationId,
|
invitationId,
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
throw: true,
|
throw: true,
|
||||||
|
|||||||
63
legalconsenthub/middleware/auth.global.ts
Normal file
63
legalconsenthub/middleware/auth.global.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// Copied from https://github.com/atinux/nuxthub-better-auth
|
||||||
|
|
||||||
|
import { defu } from 'defu'
|
||||||
|
|
||||||
|
type MiddlewareOptions =
|
||||||
|
| false
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* Only apply auth middleware to guest or user
|
||||||
|
*/
|
||||||
|
only?: 'guest' | 'user'
|
||||||
|
/**
|
||||||
|
* Redirect authenticated user to this route
|
||||||
|
*/
|
||||||
|
redirectUserTo?: string
|
||||||
|
/**
|
||||||
|
* Redirect guest to this route
|
||||||
|
*/
|
||||||
|
redirectGuestTo?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '#app' {
|
||||||
|
interface PageMeta {
|
||||||
|
auth?: MiddlewareOptions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'vue-router' {
|
||||||
|
interface RouteMeta {
|
||||||
|
auth?: MiddlewareOptions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineNuxtRouteMiddleware(async (to) => {
|
||||||
|
// If auth is disabled, skip middleware
|
||||||
|
if (to.meta?.auth === false) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { loggedIn, options, fetchSession } = useAuth()
|
||||||
|
const { only, redirectUserTo, redirectGuestTo } = defu(to.meta?.auth, options)
|
||||||
|
|
||||||
|
// If guest mode, redirect if authenticated
|
||||||
|
if (only === 'guest' && loggedIn.value) {
|
||||||
|
// Avoid infinite redirect
|
||||||
|
if (to.path === redirectUserTo) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return navigateTo(redirectUserTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If client-side, fetch session between each navigation
|
||||||
|
if (import.meta.client) {
|
||||||
|
await fetchSession()
|
||||||
|
}
|
||||||
|
// If not authenticated, redirect to home
|
||||||
|
if (!loggedIn.value) {
|
||||||
|
// Avoid infinite redirect
|
||||||
|
if (to.path === redirectGuestTo) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return navigateTo(redirectGuestTo)
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
export default defineNuxtRouteMiddleware(async (_to, _from) => {
|
|
||||||
const { data: session } = await useSession(useFetch)
|
|
||||||
|
|
||||||
if (!session.value) {
|
|
||||||
return navigateTo('/login')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -6,7 +6,11 @@ export default defineNuxtConfig({
|
|||||||
public: {
|
public: {
|
||||||
clientProxyBasePath: 'NOT_SET',
|
clientProxyBasePath: 'NOT_SET',
|
||||||
serverApiBaseUrl: 'NOT_SET',
|
serverApiBaseUrl: 'NOT_SET',
|
||||||
serverApiBasePath: 'NOT_SET'
|
serverApiBasePath: 'NOT_SET',
|
||||||
|
auth: {
|
||||||
|
redirectUserTo: '/',
|
||||||
|
redirectGuestTo: '/login'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: [
|
components: [
|
||||||
|
|||||||
@@ -69,16 +69,16 @@
|
|||||||
<p class="text-xs text-gray-500">{{ member.role }}</p>
|
<p class="text-xs text-gray-500">{{ member.role }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="session && canRemove({ role: 'owner' }, member)">
|
<div v-if="user && canRemove({ role: 'owner' }, member)">
|
||||||
<UButton size="xs" color="error" @click="organization.removeMember({ memberIdOrEmail: member.id })">
|
<UButton size="xs" color="error" @click="organization.removeMember({ memberIdOrEmail: member.id })">
|
||||||
{{ member.user.id === session.id ? 'Leave' : 'Remove' }}
|
{{ member.user.id === user.id ? 'Leave' : 'Remove' }}
|
||||||
</UButton>
|
</UButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!activeOrganization?.id" class="flex items-center gap-2">
|
<div v-if="!activeOrganization?.id" class="flex items-center gap-2">
|
||||||
<UAvatar :src="session?.image ?? undefined" />
|
<UAvatar :src="user?.image ?? undefined" />
|
||||||
<div>
|
<div>
|
||||||
<p class="text-sm">{{ session?.name }}</p>
|
<p class="text-sm">{{ user?.name }}</p>
|
||||||
<p class="text-xs text-gray-500">Owner</p>
|
<p class="text-xs text-gray-500">Owner</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -141,7 +141,8 @@ import { useClipboard } from '@vueuse/core'
|
|||||||
const { copy, copied } = useClipboard()
|
const { copy, copied } = useClipboard()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
const organizations = computed(() => useListOrganizations().value.data || [])
|
const { organization, client } = useAuth()
|
||||||
|
const organizations = computed(() => client.useListOrganizations.value?.data || [])
|
||||||
const { deleteOrganization: betterAuthDeleteOrganization, activeOrganization, selectedOrgId } = useBetterAuth()
|
const { deleteOrganization: betterAuthDeleteOrganization, activeOrganization, selectedOrgId } = useBetterAuth()
|
||||||
|
|
||||||
const selectItems = computed(() => organizations.value.map((org) => ({ label: org.name, value: org.id })))
|
const selectItems = computed(() => organizations.value.map((org) => ({ label: org.name, value: org.id })))
|
||||||
@@ -151,8 +152,7 @@ watch(selectedOrgId, async (newId) => {
|
|||||||
activeOrganization.value = data
|
activeOrganization.value = data
|
||||||
})
|
})
|
||||||
|
|
||||||
const { data: sessionData } = useSession().value
|
const { user } = await useAuth()
|
||||||
const session = computed(() => sessionData?.user)
|
|
||||||
|
|
||||||
const isRevoking = ref<string[]>([])
|
const isRevoking = ref<string[]>([])
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,8 @@
|
|||||||
<div class="flex flex-col gap-4 sm:gap-6 lg:gap-12 w-full lg:max-w-4xl mx-auto">
|
<div class="flex flex-col gap-4 sm:gap-6 lg:gap-12 w-full lg:max-w-4xl mx-auto">
|
||||||
<UPageCard variant="subtle">
|
<UPageCard variant="subtle">
|
||||||
<UForm class="space-y-4" :state="{}" @submit="onSubmit">
|
<UForm class="space-y-4" :state="{}" @submit="onSubmit">
|
||||||
<FormEngine v-if="applicationForm" v-model="applicationForm.formElements" />
|
<FormEngine v-if="applicationForm" v-model="applicationForm.formElements" :disabled="isReadOnly" />
|
||||||
<UButton type="submit">Submit</UButton>
|
<UButton type="submit" :disabled="isReadOnly">Submit</UButton>
|
||||||
</UForm>
|
</UForm>
|
||||||
</UPageCard>
|
</UPageCard>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,8 +33,10 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ApplicationFormDto } from '~/.api-client'
|
import type { ApplicationFormDto } from '~/.api-client'
|
||||||
|
|
||||||
const { getApplicationFormById, updateApplicationForm } = useApplicationForm()
|
const { getApplicationFormById, updateApplicationForm } = useApplicationForm()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const { user } = useAuth()
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
[
|
[
|
||||||
@@ -59,6 +61,10 @@ const applicationForm = computed({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const isReadOnly = computed(() => {
|
||||||
|
return applicationForm.value?.createdBy !== user.value?.name
|
||||||
|
})
|
||||||
|
|
||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
if (data?.value) {
|
if (data?.value) {
|
||||||
await updateApplicationForm(data.value.id, data.value)
|
await updateApplicationForm(data.value.id, data.value)
|
||||||
|
|||||||
@@ -39,14 +39,10 @@ import { ComplianceStatus, type PagedApplicationFormDto } from '~/.api-client'
|
|||||||
import { useApplicationFormValidator } from '~/composables/useApplicationFormValidator'
|
import { useApplicationFormValidator } from '~/composables/useApplicationFormValidator'
|
||||||
import type { FormElementId } from '~/types/FormElement'
|
import type { FormElementId } from '~/types/FormElement'
|
||||||
|
|
||||||
definePageMeta({
|
|
||||||
middleware: ['auth']
|
|
||||||
})
|
|
||||||
|
|
||||||
const { getAllApplicationFormTemplates } = useApplicationFormTemplate()
|
const { getAllApplicationFormTemplates } = useApplicationFormTemplate()
|
||||||
const { createApplicationForm } = useApplicationForm()
|
const { createApplicationForm } = useApplicationForm()
|
||||||
const { validateFormElements, getHighestComplianceStatus } = useApplicationFormValidator()
|
const { validateFormElements, getHighestComplianceStatus } = useApplicationFormValidator()
|
||||||
const { data: session } = await useSession(useFetch)
|
const { user } = await useAuth()
|
||||||
|
|
||||||
const { data } = await useAsyncData<PagedApplicationFormDto>(async () => {
|
const { data } = await useAsyncData<PagedApplicationFormDto>(async () => {
|
||||||
return await getAllApplicationFormTemplates()
|
return await getAllApplicationFormTemplates()
|
||||||
@@ -96,8 +92,8 @@ const ampelStatusEmoji = computed(() => {
|
|||||||
|
|
||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
if (applicationFormTemplate.value) {
|
if (applicationFormTemplate.value) {
|
||||||
applicationFormTemplate.value.createdBy = session.value?.user?.name ?? 'Unknown'
|
applicationFormTemplate.value.createdBy = user.value?.name ?? 'Unknown'
|
||||||
applicationFormTemplate.value.lastModifiedBy = session.value?.user?.name ?? 'Unknown'
|
applicationFormTemplate.value.lastModifiedBy = user.value?.name ?? 'Unknown'
|
||||||
|
|
||||||
await createApplicationForm(applicationFormTemplate.value)
|
await createApplicationForm(applicationFormTemplate.value)
|
||||||
await navigateTo('/')
|
await navigateTo('/')
|
||||||
|
|||||||
@@ -56,10 +56,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ApplicationFormDto, PagedApplicationFormDto } from '~/.api-client'
|
import type { ApplicationFormDto, PagedApplicationFormDto } from '~/.api-client'
|
||||||
|
|
||||||
definePageMeta({
|
|
||||||
middleware: ['auth']
|
|
||||||
})
|
|
||||||
|
|
||||||
const { getAllApplicationForms, deleteApplicationFormById } = useApplicationForm()
|
const { getAllApplicationForms, deleteApplicationFormById } = useApplicationForm()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ definePageMeta({ layout: 'auth' })
|
|||||||
useSeoMeta({ title: 'Login' })
|
useSeoMeta({ title: 'Login' })
|
||||||
|
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
const { signIn } = useAuth()
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
{
|
{
|
||||||
@@ -81,7 +82,7 @@ function onSubmit(payload: FormSubmitEvent<Schema>) {
|
|||||||
alert('Bitte alle Felder ausfüllen')
|
alert('Bitte alle Felder ausfüllen')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
authClient.signIn.email(
|
signIn.email(
|
||||||
{
|
{
|
||||||
email: payload.data.email,
|
email: payload.data.email,
|
||||||
password: payload.data.password
|
password: payload.data.password
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ definePageMeta({ layout: 'auth' })
|
|||||||
useSeoMeta({ title: 'Sign up' })
|
useSeoMeta({ title: 'Sign up' })
|
||||||
|
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
const { signUp } = useAuth()
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
{
|
{
|
||||||
|
|||||||
12
legalconsenthub/plugins/auth.client.ts
Normal file
12
legalconsenthub/plugins/auth.client.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// Copied from https://github.com/atinux/nuxthub-better-auth
|
||||||
|
|
||||||
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
||||||
|
if (!nuxtApp.payload.serverRendered) {
|
||||||
|
await useAuth().fetchSession()
|
||||||
|
} else if (Boolean(nuxtApp.payload.prerenderedAt) || Boolean(nuxtApp.payload.isCached)) {
|
||||||
|
// To avoid hydration mismatch
|
||||||
|
nuxtApp.hook('app:mounted', async () => {
|
||||||
|
await useAuth().fetchSession()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
13
legalconsenthub/plugins/auth.server.ts
Normal file
13
legalconsenthub/plugins/auth.server.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// Copied from https://github.com/atinux/nuxthub-better-auth
|
||||||
|
|
||||||
|
export default defineNuxtPlugin({
|
||||||
|
name: 'better-auth-fetch-plugin',
|
||||||
|
enforce: 'pre',
|
||||||
|
async setup(nuxtApp) {
|
||||||
|
// Flag if request is cached
|
||||||
|
nuxtApp.payload.isCached = Boolean(useRequestEvent()?.context.cache)
|
||||||
|
if (nuxtApp.payload.serverRendered && !nuxtApp.payload.prerenderedAt && !nuxtApp.payload.isCached) {
|
||||||
|
await useAuth().fetchSession()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { createAuthClient } from 'better-auth/vue'
|
|
||||||
import { organizationClient } from 'better-auth/client/plugins'
|
|
||||||
|
|
||||||
export const authClient = createAuthClient({
|
|
||||||
baseURL: 'http://localhost:3001',
|
|
||||||
plugins: [organizationClient()]
|
|
||||||
})
|
|
||||||
|
|
||||||
export const {
|
|
||||||
signIn,
|
|
||||||
signOut,
|
|
||||||
signUp,
|
|
||||||
useSession,
|
|
||||||
forgetPassword,
|
|
||||||
resetPassword,
|
|
||||||
organization,
|
|
||||||
useListOrganizations
|
|
||||||
} = authClient
|
|
||||||
@@ -1,10 +1,3 @@
|
|||||||
import type { auth } from '../server/utils/auth'
|
|
||||||
import type { authClient } from './auth-client'
|
|
||||||
|
|
||||||
export type Session = typeof auth.$Infer.Session
|
|
||||||
export type ActiveOrganization = typeof authClient.$Infer.ActiveOrganization
|
|
||||||
export type Invitation = typeof authClient.$Infer.Invitation
|
|
||||||
|
|
||||||
// Types can be found here: https://github.com/better-auth/better-auth/blob/3f574ec70bb15c155a78673d42c5e25f7376ced3/packages/better-auth/src/plugins/organization/routes/crud-invites.ts#L531
|
// Types can be found here: https://github.com/better-auth/better-auth/blob/3f574ec70bb15c155a78673d42c5e25f7376ced3/packages/better-auth/src/plugins/organization/routes/crud-invites.ts#L531
|
||||||
export type CustomInvitation = {
|
export type CustomInvitation = {
|
||||||
organizationName: string
|
organizationName: string
|
||||||
|
|||||||
Reference in New Issue
Block a user