Compare commits
11 Commits
5892921a7c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e530f23103 | |||
| 9dd25fa545 | |||
| cfcb55dc33 | |||
| 54fefdd927 | |||
| fe525afd9f | |||
| e5bbecb689 | |||
| 2f4583f423 | |||
| ee69746ac7 | |||
| db084a579f | |||
| 02a6bb6025 | |||
| d9955a64d4 |
@@ -5,10 +5,15 @@ export interface User {
|
|||||||
email_verified_at: string | null
|
email_verified_at: string | null
|
||||||
password?: string
|
password?: string
|
||||||
remember_token?: string | null
|
remember_token?: string | null
|
||||||
|
roles: Role[]
|
||||||
created_at: string | null
|
created_at: string | null
|
||||||
updated_at: string | null
|
updated_at: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Role {
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface LoginCredentials {
|
export interface LoginCredentials {
|
||||||
email: string
|
email: string
|
||||||
password: string
|
password: string
|
||||||
@@ -50,7 +55,9 @@ export function useAuth<T = User>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function login(credentials: LoginCredentials) {
|
async function login(credentials: LoginCredentials) {
|
||||||
if (isLoggedIn.value) { return }
|
if (isLoggedIn.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
await $larafetch('/login', { method: 'post', body: credentials })
|
await $larafetch('/login', { method: 'post', body: credentials })
|
||||||
await refresh()
|
await refresh()
|
||||||
@@ -71,7 +78,9 @@ export function useAuth<T = User>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function logout() {
|
async function logout() {
|
||||||
if (!isLoggedIn.value) { return }
|
if (!isLoggedIn.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
await $larafetch('/logout', { method: 'post' })
|
await $larafetch('/logout', { method: 'post' })
|
||||||
user.value = null
|
user.value = null
|
||||||
@@ -114,8 +123,12 @@ export async function fetchCurrentUser<T = User>() {
|
|||||||
return await $larafetch<T>('/api/user')
|
return await $larafetch<T>('/api/user')
|
||||||
}
|
}
|
||||||
catch (error: any) {
|
catch (error: any) {
|
||||||
if ([401, 419].includes(error?.response?.status)) { return null }
|
if ([401, 419].includes(error?.response?.status)) {
|
||||||
if (error?.response?.status === undefined) { return null }
|
return null
|
||||||
|
}
|
||||||
|
if (error?.response?.status === undefined) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
composables/useRoles.ts
Normal file
11
composables/useRoles.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export function useRoles() {
|
||||||
|
const user = useUser()
|
||||||
|
|
||||||
|
function hasRole(roleName: string) {
|
||||||
|
return user.value?.roles?.some(role => role.name === roleName) ?? false
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
hasRole,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,7 +44,9 @@ export function useSubmit<T>(
|
|||||||
validationErrors.value = []
|
validationErrors.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.response?.status !== 422) { throw e }
|
if (e.response?.status !== 422) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
inProgress.value = false
|
inProgress.value = false
|
||||||
|
|||||||
13
error.vue
Normal file
13
error.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { NuxtError } from '#app'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
error: NuxtError
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NuxtLayout name="auth">
|
||||||
|
<UPageError :error="error" />
|
||||||
|
</NuxtLayout>
|
||||||
|
</template>
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<Header />
|
|
||||||
<UPage>
|
|
||||||
<template #left>
|
|
||||||
<UAside class="lg:static">
|
|
||||||
<Navigation />
|
|
||||||
</UAside>
|
|
||||||
</template>
|
|
||||||
<UPageBody>
|
|
||||||
<UContainer>
|
|
||||||
<slot />
|
|
||||||
</UContainer>
|
|
||||||
</UPageBody>
|
|
||||||
</UPage>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
5
layouts/auth.vue
Normal file
5
layouts/auth.vue
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,5 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<slot />
|
<Header />
|
||||||
|
<UPage>
|
||||||
|
<template #left>
|
||||||
|
<UAside class="lg:static">
|
||||||
|
<Navigation />
|
||||||
|
</UAside>
|
||||||
|
</template>
|
||||||
|
<UPageBody>
|
||||||
|
<UContainer>
|
||||||
|
<slot />
|
||||||
|
</UContainer>
|
||||||
|
</UPageBody>
|
||||||
|
</UPage>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
11
middleware/admin.ts
Normal file
11
middleware/admin.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export default defineNuxtRouteMiddleware(async () => {
|
||||||
|
const { hasRole } = useRoles()
|
||||||
|
const requiredRole = 'super-admin' // Define the role required for this route
|
||||||
|
|
||||||
|
if (!hasRole(requiredRole)) {
|
||||||
|
return abortNavigation({
|
||||||
|
message: 'You are not authorized to access this page',
|
||||||
|
statusCode: 403,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
export default defineNuxtRouteMiddleware(async () => {
|
export default defineNuxtRouteMiddleware(async () => {
|
||||||
const user = useUser();
|
const user = useUser()
|
||||||
if (!user.value) return navigateTo("/login", { replace: true });
|
if (!user.value) {
|
||||||
});
|
return navigateTo('/login', { replace: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
export default defineNuxtRouteMiddleware(async () => {
|
export default defineNuxtRouteMiddleware(async () => {
|
||||||
const user = useUser();
|
const user = useUser()
|
||||||
if (user.value) return navigateTo("/", { replace: true });
|
if (user.value) {
|
||||||
});
|
return navigateTo('/', { replace: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
export default defineNuxtRouteMiddleware(() => {
|
export default defineNuxtRouteMiddleware(() => {
|
||||||
const user = useUser()
|
const user = useUser()
|
||||||
|
|
||||||
if (!user.value) { return navigateTo('/login') }
|
if (!user.value) {
|
||||||
|
return navigateTo('/login')
|
||||||
|
}
|
||||||
|
|
||||||
if (user.value.email_verified_at) { return navigateTo('/') }
|
if (user.value.email_verified_at) {
|
||||||
|
return navigateTo('/')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
export default defineNuxtRouteMiddleware(() => {
|
export default defineNuxtRouteMiddleware(() => {
|
||||||
const user = useUser();
|
const user = useUser()
|
||||||
|
|
||||||
if (!user.value) return navigateTo("/login");
|
if (!user.value) {
|
||||||
|
return navigateTo('/login')
|
||||||
// @ts-ignore
|
}
|
||||||
if (!(user.value.email_verified_at || user.value.is_verified))
|
|
||||||
return navigateTo("/verify-email");
|
if (!(user.value.email_verified_at)) {
|
||||||
});
|
return navigateTo('/verify-email')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
// https://nuxt.com/docs/api/configuration/nbun uxt-config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
extends: ['@nuxt/ui-pro'],
|
extends: ['@nuxt/ui-pro'],
|
||||||
modules: ['@nuxt/ui'],
|
modules: ['@nuxt/ui'],
|
||||||
|
|||||||
16
package.json
16
package.json
@@ -12,17 +12,17 @@
|
|||||||
"postinstall": "nuxt prepare"
|
"postinstall": "nuxt prepare"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "^1.1.0",
|
"@antfu/eslint-config": "^2.8.0",
|
||||||
"@iconify-json/heroicons": "^1.1.13",
|
"@iconify-json/heroicons": "^1.1.20",
|
||||||
"@nuxt/devtools": "latest",
|
"@nuxt/devtools": "latest",
|
||||||
"@nuxt/ui-pro": "^0.4.2",
|
"@nuxt/ui-pro": "^1.0.2",
|
||||||
"eslint": "^8.53.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-tailwindcss": "^3.13.0",
|
"eslint-plugin-tailwindcss": "^3.14.2",
|
||||||
"laravel-echo": "^1.15.3",
|
"laravel-echo": "^1.15.3",
|
||||||
"nuxt": "^3.8.1",
|
"nuxt": "^3.10.3",
|
||||||
"pusher-js": "^8.3.0",
|
"pusher-js": "^8.3.0",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.3.3",
|
||||||
"vue": "^3.3.8",
|
"vue": "^3.4.19",
|
||||||
"vue-router": "^4.2.5"
|
"vue-router": "^4.2.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePageMeta({ middleware: ['guest'] })
|
definePageMeta({ middleware: ['guest'], layout: 'auth' })
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { forgotPassword } = useAuth()
|
const { forgotPassword } = useAuth()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePageMeta({ middleware: ['auth'], layout: 'app' })
|
definePageMeta({ middleware: ['auth'] })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePageMeta({ middleware: ['guest'] })
|
definePageMeta({ middleware: ['guest'], layout: 'auth' })
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePageMeta({ middleware: ['auth'] })
|
definePageMeta({ middleware: ['guest'], layout: 'auth' })
|
||||||
const { logout } = useAuth()
|
const { logout } = useAuth()
|
||||||
logout()
|
logout()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePageMeta({ middleware: ['guest'] })
|
definePageMeta({ middleware: ['guest'], layout: 'auth' })
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ export default defineNuxtPlugin(async () => {
|
|||||||
const user = useUser()
|
const user = useUser()
|
||||||
|
|
||||||
// Skip if already initialized on server
|
// Skip if already initialized on server
|
||||||
if (user.value !== undefined) { return }
|
if (user.value !== undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
user.value = await fetchCurrentUser()
|
user.value = await fetchCurrentUser()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import { FetchError } from 'ofetch'
|
|||||||
|
|
||||||
export default defineNuxtPlugin(async (nuxtApp) => {
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
||||||
nuxtApp.hook('vue:error', (error) => {
|
nuxtApp.hook('vue:error', (error) => {
|
||||||
if (!(error instanceof FetchError)) { throw error }
|
if (!(error instanceof FetchError)) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
const status = error.response?.status ?? -1
|
const status = error.response?.status ?? -1
|
||||||
|
|
||||||
|
|||||||
8980
pnpm-lock.yaml
generated
Normal file
8980
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user