mirror of
https://forgejo.merr.is/annika/isl-vue3.git
synced 2025-12-11 10:56:31 -05:00
Syncing Lots Of Auth Tweaks
This commit is contained in:
parent
baf8e0f954
commit
a1aa171bb1
11 changed files with 227 additions and 28 deletions
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
|
@ -14,6 +14,7 @@
|
|||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@zitadel/vue": "^1.0.0",
|
||||
"axios": "^1.6.5",
|
||||
"axios-retry": "^4.0.0",
|
||||
"pinia": "^2.1.7",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"apiBaseUrl": "http://localhost:3000"
|
||||
"apiBaseURL": "http://localhost:3000"
|
||||
}
|
||||
44
src/main.ts
44
src/main.ts
|
|
@ -13,6 +13,8 @@ import { createVuetify } from 'vuetify'
|
|||
import * as components from 'vuetify/components'
|
||||
import * as directives from 'vuetify/directives'
|
||||
import axios from 'axios'
|
||||
import zitadelAuth from '@/services/zitadelAuth'
|
||||
import { apiBaseURL } from './types/ConfigSymbols'
|
||||
|
||||
const vuetify = createVuetify({
|
||||
components,
|
||||
|
|
@ -25,20 +27,32 @@ const vuetify = createVuetify({
|
|||
}
|
||||
})
|
||||
|
||||
const app = createApp(App)
|
||||
const pinia = createPinia()
|
||||
app.use(pinia)
|
||||
app.use(router)
|
||||
app.use(vuetify)
|
||||
// Stuff to get OIDC auth working through Zitadel
|
||||
declare module 'vue' {
|
||||
interface ComponentCustomProperties {
|
||||
$zitadel: typeof zitadelAuth
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch my config
|
||||
axios
|
||||
.get('/config.json?noCache=' + Date.now())
|
||||
.then((resp) => {
|
||||
app.config.globalProperties.$apiBaseUrl = resp.data.apiBaseUrl
|
||||
zitadelAuth.oidcAuth.startup().then(() => {
|
||||
const app = createApp(App)
|
||||
const pinia = createPinia()
|
||||
|
||||
app.mount('#app')
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
app.use(router)
|
||||
app.use(vuetify)
|
||||
app.use(pinia)
|
||||
|
||||
app.config.globalProperties.$zitadel = zitadelAuth
|
||||
|
||||
// Fetch my config
|
||||
axios
|
||||
.get('/config.json?noCache=' + Date.now())
|
||||
.then((resp) => {
|
||||
app.provide(apiBaseURL, resp.data.apiBaseURL)
|
||||
|
||||
app.mount('#app')
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import zitadelAuth from '@/services/zitadelAuth'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
const router = createRouter({
|
||||
|
|
@ -9,26 +10,46 @@ const router = createRouter({
|
|||
component: () => import('@/views/HomeView.vue')
|
||||
},
|
||||
{
|
||||
path: "/blessing-power",
|
||||
name: "blessing-power",
|
||||
path: '/blessing-power',
|
||||
name: 'blessing-power',
|
||||
component: () => import('@/views/BlessingPowerView.vue')
|
||||
},
|
||||
{
|
||||
path: "/fellow-power",
|
||||
name: "fellow-power",
|
||||
path: '/fellow-power',
|
||||
name: 'fellow-power',
|
||||
component: () => import('@/views/FellowPowerView.vue')
|
||||
},
|
||||
{
|
||||
path: "/intimacy-power",
|
||||
name: "intimacy-power",
|
||||
path: '/intimacy-power',
|
||||
name: 'intimacy-power',
|
||||
component: () => import('@/views/IntimacyPowerView.vue')
|
||||
},
|
||||
{
|
||||
path: "/test",
|
||||
name: "test",
|
||||
path: '/test',
|
||||
name: 'test',
|
||||
component: () => import('@/views/Test.vue')
|
||||
},
|
||||
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
meta: {
|
||||
authName: zitadelAuth.oidcAuth.authName
|
||||
},
|
||||
component: () => import('@/views/Login.vue')
|
||||
},
|
||||
{
|
||||
path: '/admin',
|
||||
name: 'admin',
|
||||
meta: {
|
||||
authName: zitadelAuth.oidcAuth.authName
|
||||
},
|
||||
component: () =>
|
||||
zitadelAuth.hasRole('admin') ? import('@/views/Admin.vue') : import('@/views/NoAccess.vue')
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
zitadelAuth.oidcAuth.useRouter(router)
|
||||
|
||||
export default router
|
||||
|
|
|
|||
46
src/services/zitadelAuth.ts
Normal file
46
src/services/zitadelAuth.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import {createZITADELAuth} from "@zitadel/vue";
|
||||
import {User} from "oidc-client";
|
||||
|
||||
const zitadelAuth = createZITADELAuth({
|
||||
project_resource_id: '252968011466539011',
|
||||
client_id: "252968365600079875@isl",
|
||||
issuer: "http://localhost:8080/",
|
||||
})
|
||||
|
||||
// handle events
|
||||
zitadelAuth.oidcAuth.events.addAccessTokenExpiring(function() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('access token expiring')
|
||||
})
|
||||
|
||||
zitadelAuth.oidcAuth.events.addAccessTokenExpired(function() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('access token expired')
|
||||
})
|
||||
|
||||
zitadelAuth.oidcAuth.events.addSilentRenewError(function(err: Error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('silent renew error', err)
|
||||
})
|
||||
|
||||
zitadelAuth.oidcAuth.events.addUserLoaded(function(user: User) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('user loaded', user)
|
||||
})
|
||||
|
||||
zitadelAuth.oidcAuth.events.addUserUnloaded(function() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('user unloaded')
|
||||
})
|
||||
|
||||
zitadelAuth.oidcAuth.events.addUserSignedOut(function() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('user signed out')
|
||||
})
|
||||
|
||||
zitadelAuth.oidcAuth.events.addUserSessionChanged(function() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('user session changed')
|
||||
})
|
||||
|
||||
export default zitadelAuth
|
||||
|
|
@ -4,6 +4,8 @@ import { defineStore } from 'pinia'
|
|||
import { computed, ref, toRaw } from 'vue'
|
||||
import axiosRetry from 'axios-retry'
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import { apiBaseURL as apiBaseURLKey } from '@/types/ConfigSymbols'
|
||||
import { inject } from 'vue'
|
||||
|
||||
const BLESSING = 1
|
||||
const INTIMACY = 2
|
||||
|
|
@ -26,7 +28,9 @@ export const usePowerItems = defineStore('powerItems', () => {
|
|||
const fellowPowerItems = ref(new Map<string, PowerItem>())
|
||||
const intimacyPowerItems = ref(new Map<string, PowerItem>())
|
||||
const isLoadComplete = ref(false)
|
||||
const apiBaseUrl = getCurrentInstance()?.appContext.config.globalProperties.$apiBaseUrl
|
||||
const auth = getCurrentInstance()?.appContext.config.globalProperties.$zitadel
|
||||
auth?.oidcAuth.mgr.getUser().then(res => console.log(res?.id_token))
|
||||
console.log(auth?.oidcAuth.accessToken)
|
||||
|
||||
axiosRetry(axios, {
|
||||
retries: 3,
|
||||
|
|
@ -34,8 +38,9 @@ export const usePowerItems = defineStore('powerItems', () => {
|
|||
})
|
||||
|
||||
async function fetchPowerItems() {
|
||||
const apiBaseURL = inject(apiBaseURLKey)
|
||||
axios
|
||||
.get(apiBaseUrl + '/powerItem/byType/' + BLESSING + '/asMap', noCacheConfig)
|
||||
.get(apiBaseURL + '/powerItems/byType/' + BLESSING + '/asMap', noCacheConfig)
|
||||
.then((resp) => {
|
||||
const plainMap = new Map<string, PowerItem>(
|
||||
Object.entries(JSON.parse(localStorage.getItem(BLESSING_POWER_ITEM_STORAGE) || '{}'))
|
||||
|
|
@ -51,7 +56,7 @@ export const usePowerItems = defineStore('powerItems', () => {
|
|||
console.log(err)
|
||||
})
|
||||
axios
|
||||
.get(apiBaseUrl + '/powerItem/byType/' + FELLOW + '/asMap', noCacheConfig)
|
||||
.get(apiBaseURL + '/powerItems/byType/' + FELLOW + '/asMap', noCacheConfig)
|
||||
.then((resp) => {
|
||||
const plainMap = new Map<string, PowerItem>(
|
||||
Object.entries(JSON.parse(localStorage.getItem(FELLOW_POWER_ITEM_STORAGE) || '{}'))
|
||||
|
|
@ -67,7 +72,7 @@ export const usePowerItems = defineStore('powerItems', () => {
|
|||
console.log(err)
|
||||
})
|
||||
axios
|
||||
.get(apiBaseUrl + '/powerItem/byType/' + INTIMACY + '/asMap', noCacheConfig)
|
||||
.get(apiBaseURL + '/powerItems/byType/' + INTIMACY + '/asMap', noCacheConfig)
|
||||
.then((resp) => {
|
||||
const plainMap = new Map<string, PowerItem>(
|
||||
Object.entries(JSON.parse(localStorage.getItem(INTIMACY_POWER_ITEM_STORAGE) || '{}'))
|
||||
|
|
|
|||
7
src/types/ConfigSymbols.ts
Normal file
7
src/types/ConfigSymbols.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import type { InjectionKey } from "vue";
|
||||
|
||||
const apiBaseURL = Symbol() as InjectionKey<string>
|
||||
|
||||
export {
|
||||
apiBaseURL
|
||||
}
|
||||
22
src/views/Admin.vue
Normal file
22
src/views/Admin.vue
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<div class="admin">
|
||||
<div>
|
||||
<h1>
|
||||
This is an administrator page.
|
||||
</h1>
|
||||
<h2>
|
||||
You can see it because you have the role "admin" in your ZITADEL project.
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@media (min-width: 1024px) {
|
||||
.admin {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
61
src/views/Login.vue
Normal file
61
src/views/Login.vue
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<div class="userinfo">
|
||||
<div>
|
||||
<h1>This is a login-protected page</h1>
|
||||
<h2>
|
||||
The following profile data is extended by information from ZITADELs userinfo endpoint.
|
||||
</h2>
|
||||
<p>
|
||||
<ul class="claims">
|
||||
<li v-for="c in claims" :key="c.key">
|
||||
<strong>{{ c.key }}</strong
|
||||
>: {{ c.value }}
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
<button @click="signout">Sign Out</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@media (min-width: 1024px) {
|
||||
.userinfo {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script lang="ts">
|
||||
import { getCurrentInstance } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
computed: {
|
||||
user() {
|
||||
return this.$zitadel.oidcAuth.userProfile
|
||||
},
|
||||
claims() {
|
||||
if (this.user) {
|
||||
return Object.keys(this.user).map((key) => ({
|
||||
key,
|
||||
value: this.user[key]
|
||||
}))
|
||||
}
|
||||
return []
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
const zitadel = ref(getCurrentInstance()?.appContext.config.globalProperties.$zitadel!)
|
||||
const user = ref(zitadel.value.oidcAuth.userProfile)
|
||||
const signout = function() {
|
||||
if (user.value) {
|
||||
zitadel.value.oidcAuth.signOut()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
22
src/views/NoAccess.vue
Normal file
22
src/views/NoAccess.vue
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<div class="admin">
|
||||
<div>
|
||||
<h1>
|
||||
Access denied
|
||||
</h1>
|
||||
<h2>
|
||||
You don't have the role "admin" in your ZITADEL project.
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@media (min-width: 1024px) {
|
||||
.admin {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue