Compare commits

..

11 Commits

Author SHA1 Message Date
e530f23103 chore: Update Dependencies 2024-03-10 15:12:34 +01:00
9dd25fa545 fix: missing template 2024-02-17 15:36:37 +01:00
cfcb55dc33 chore(deps): Update dependencies & switched to pnpm 2024-02-17 15:36:22 +01:00
54fefdd927 chore(deps): Update dependencies 2024-02-17 14:07:28 +01:00
fe525afd9f fix: Remove Console Log 2023-11-11 17:43:00 +01:00
e5bbecb689 fix: Set Auth Layout to not leak App 2023-11-11 16:42:29 +01:00
2f4583f423 chore(Layout): Refactored default Layout 2023-11-11 16:33:30 +01:00
ee69746ac7 feat(Error): Added Error Page 2023-11-11 16:33:02 +01:00
db084a579f fix: Typo from Testing 2023-11-11 16:32:41 +01:00
02a6bb6025 feat(Roles): Added Role Functionality 2023-11-11 16:32:21 +01:00
d9955a64d4 fix: Lint Errors 2023-11-11 16:31:29 +01:00
24 changed files with 9105 additions and 57 deletions

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
node-linker=hoisted

BIN
bun.lockb

Binary file not shown.

View File

@@ -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
View 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,
}
}

View File

@@ -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
View 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>

View File

@@ -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
View File

@@ -0,0 +1,5 @@
<template>
<div>
<slot />
</div>
</template>

View File

@@ -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
View 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,
})
}
})

View File

@@ -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 })
}
})

View File

@@ -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 })
}
})

View File

@@ -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('/')
}
}) })

View File

@@ -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')
}
})

View File

@@ -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'],

View File

@@ -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"
} }
} }

View File

@@ -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()

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
definePageMeta({ middleware: ['auth'], layout: 'app' }) definePageMeta({ middleware: ['auth'] })
</script> </script>
<template> <template>

View File

@@ -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()

View File

@@ -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>

View File

@@ -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()

View File

@@ -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()
}) })

View File

@@ -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

File diff suppressed because it is too large Load Diff