@plutocms/supabase 0.0.1-alpha.16 → 0.0.1-alpha.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -4
- package/app/composables/auth.ts +27 -4
- package/app/middleware/auth.ts +6 -10
- package/app/pages/admin/(auth)/signup.vue +1 -1
- package/app/pages/admin/(auth)/update-password.vue +14 -0
- package/app/pages/admin.vue +2 -4
- package/eslint.config.mjs +1 -0
- package/package.json +1 -1
- package/server/api/auth/reset-password.post.ts +0 -36
- /package/server/api/{signup.post.ts → auth/signup.post.ts} +0 -0
package/README.md
CHANGED
|
@@ -35,9 +35,7 @@ bun add @nuxtjs/supabase supabase
|
|
|
35
35
|
```ts
|
|
36
36
|
// nuxt.config.ts
|
|
37
37
|
export default defineNuxtConfig({
|
|
38
|
-
extends: [
|
|
39
|
-
['github:plutocms/supabase', { install: true }],
|
|
40
|
-
],
|
|
38
|
+
extends: [['github:plutocms/supabase', { install: true }]],
|
|
41
39
|
})
|
|
42
40
|
```
|
|
43
41
|
|
|
@@ -55,7 +53,7 @@ The layer includes API routes for interacting with Supabase services, such as au
|
|
|
55
53
|
|
|
56
54
|
- GET `/api/settings`
|
|
57
55
|
- POST `/api/settings/update`
|
|
58
|
-
- POST `/api/signup`
|
|
56
|
+
- POST `/api/auth/signup`
|
|
59
57
|
|
|
60
58
|
### Types
|
|
61
59
|
|
package/app/composables/auth.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
RouteLocationNormalizedGeneric,
|
|
3
|
+
RouteLocationRaw,
|
|
4
|
+
} from 'vue-router'
|
|
2
5
|
|
|
3
6
|
interface PlutoSupabaseAuthOptions {
|
|
4
7
|
route?: RouteLocationNormalizedGeneric
|
|
@@ -16,6 +19,15 @@ export async function useAuth(authOptions?: PlutoSupabaseAuthOptions) {
|
|
|
16
19
|
const isLoggedIn = computed<boolean>(() => !!supabaseSession.value)
|
|
17
20
|
const isSubmitting = ref<boolean>(false)
|
|
18
21
|
|
|
22
|
+
const allowedUnauthenticatedPaths: RouteLocationRaw[] = [
|
|
23
|
+
'/admin/login',
|
|
24
|
+
'/admin/signup',
|
|
25
|
+
'/admin/confirm',
|
|
26
|
+
'/admin/setup',
|
|
27
|
+
'/admin/forgot-password',
|
|
28
|
+
'/admin/update-password',
|
|
29
|
+
]
|
|
30
|
+
|
|
19
31
|
interface LoginForm {
|
|
20
32
|
email: string
|
|
21
33
|
password: string
|
|
@@ -108,11 +120,21 @@ export async function useAuth(authOptions?: PlutoSupabaseAuthOptions) {
|
|
|
108
120
|
isSubmitting.value = true
|
|
109
121
|
|
|
110
122
|
try {
|
|
111
|
-
await
|
|
112
|
-
|
|
113
|
-
body: { email },
|
|
123
|
+
const { error } = await supabase.auth.resetPasswordForEmail(email, {
|
|
124
|
+
redirectTo: `${window.location.origin}/admin/update-password`,
|
|
114
125
|
})
|
|
115
126
|
|
|
127
|
+
if (error) {
|
|
128
|
+
toast.add({
|
|
129
|
+
title: 'Could not send reset email',
|
|
130
|
+
description: error.message,
|
|
131
|
+
icon: 'lucide:circle-x',
|
|
132
|
+
color: 'error',
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
return { success: false }
|
|
136
|
+
}
|
|
137
|
+
|
|
116
138
|
return { success: true }
|
|
117
139
|
} catch (error) {
|
|
118
140
|
toast.add({
|
|
@@ -176,5 +198,6 @@ export async function useAuth(authOptions?: PlutoSupabaseAuthOptions) {
|
|
|
176
198
|
logout,
|
|
177
199
|
requestPasswordReset,
|
|
178
200
|
updatePassword,
|
|
201
|
+
allowedUnauthenticatedPaths,
|
|
179
202
|
}
|
|
180
203
|
}
|
package/app/middleware/auth.ts
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
import type { RouteLocationNormalizedGeneric } from 'vue-router'
|
|
2
2
|
|
|
3
3
|
export default defineNuxtRouteMiddleware(async (to, from) => {
|
|
4
|
-
const { isLoggedIn, logout } = await useAuth({
|
|
4
|
+
const { isLoggedIn, logout, allowedUnauthenticatedPaths } = await useAuth({
|
|
5
5
|
route: to as RouteLocationNormalizedGeneric,
|
|
6
6
|
})
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
'/admin/
|
|
12
|
-
|
|
13
|
-
'/admin/forgot-password',
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
if (isLoggedIn.value && allowedUnauthenticatedPaths.includes(to.path)) {
|
|
8
|
+
if (
|
|
9
|
+
isLoggedIn.value &&
|
|
10
|
+
allowedUnauthenticatedPaths.includes(to.path) &&
|
|
11
|
+
to.path !== '/admin/update-password'
|
|
12
|
+
) {
|
|
17
13
|
return navigateTo(
|
|
18
14
|
to.query.redirect
|
|
19
15
|
? decodeURIComponent(to.query.redirect as string)
|
|
@@ -7,6 +7,18 @@ useHead({
|
|
|
7
7
|
title: 'Update Password',
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
+
const route = useRoute()
|
|
11
|
+
const supabase = useSupabaseClient()
|
|
12
|
+
|
|
13
|
+
// Exchange the PKCE code for a session when arriving from a password reset email
|
|
14
|
+
onMounted(async () => {
|
|
15
|
+
const code = route.query.code as string | undefined
|
|
16
|
+
|
|
17
|
+
if (code) {
|
|
18
|
+
await supabase.auth.exchangeCodeForSession(code)
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
|
|
10
22
|
const { isSubmitting, updatePassword } = await useAuth()
|
|
11
23
|
|
|
12
24
|
const form = ref({
|
|
@@ -29,6 +41,8 @@ async function submitForm() {
|
|
|
29
41
|
|
|
30
42
|
if (result.success) {
|
|
31
43
|
isPasswordUpdated.value = true
|
|
44
|
+
|
|
45
|
+
await supabase.auth.signOut()
|
|
32
46
|
}
|
|
33
47
|
}
|
|
34
48
|
</script>
|
package/app/pages/admin.vue
CHANGED
|
@@ -5,7 +5,7 @@ definePageMeta({
|
|
|
5
5
|
})
|
|
6
6
|
|
|
7
7
|
const route = useRoute()
|
|
8
|
-
const { isLoggedIn, logout } = await useAuth()
|
|
8
|
+
const { isLoggedIn, logout, allowedUnauthenticatedPaths } = await useAuth()
|
|
9
9
|
const toast = useToast()
|
|
10
10
|
|
|
11
11
|
const visibility = useDocumentVisibility()
|
|
@@ -15,9 +15,7 @@ watch(visibility, async (current, previous) => {
|
|
|
15
15
|
if (
|
|
16
16
|
!isLoggedIn.value &&
|
|
17
17
|
!route.path.startsWith('/admin/setup') &&
|
|
18
|
-
route.path
|
|
19
|
-
route.path !== '/admin/login' &&
|
|
20
|
-
route.path !== '/admin/signup'
|
|
18
|
+
!allowedUnauthenticatedPaths.includes(route.path)
|
|
21
19
|
) {
|
|
22
20
|
await logout({ redirectTo: route.path })
|
|
23
21
|
|
package/eslint.config.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { serverSupabaseClient } from '#supabase/server'
|
|
2
|
-
|
|
3
|
-
interface Payload {
|
|
4
|
-
email: string
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export default defineEventHandler(async (event) => {
|
|
8
|
-
const client = await serverSupabaseClient<Database>(event)
|
|
9
|
-
const body = await readBody<Payload>(event)
|
|
10
|
-
|
|
11
|
-
if (!body.email) {
|
|
12
|
-
return {
|
|
13
|
-
success: false,
|
|
14
|
-
message: 'Email is required.',
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const { origin } = getRequestURL(event)
|
|
19
|
-
|
|
20
|
-
const { error } = await client.auth.resetPasswordForEmail(body.email, {
|
|
21
|
-
redirectTo: `${origin}/admin/update-password`,
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
if (error) {
|
|
25
|
-
return {
|
|
26
|
-
success: false,
|
|
27
|
-
message: error.message,
|
|
28
|
-
error,
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
success: true,
|
|
34
|
-
message: 'Password reset email sent.',
|
|
35
|
-
}
|
|
36
|
-
})
|
|
File without changes
|