Newer
Older
import axios from 'axios'
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { components as steeringTypes } from '../steering-types'
import { components as tankTypes } from '../tank-types'
import { createUnpaginatedAPIStore, createSteeringURL, createTankURL } from '@/api'
import { getUser, oidcManager } from '@/oidc'
const log = globalThis.console
export type CurrentUser = {
name: string
email: string
oidcAccessToken: string
tankSessionToken: string
}
export type SteeringUser = steeringTypes['schemas']['User']
export const useUserStore = createUnpaginatedAPIStore<SteeringUser>(
createSteeringURL.prefix('users'),
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
{
getRequestDefaults() {
const authStore = useAuthStore()
return authStore.currentUser
? { headers: { Authorization: `Bearer ${authStore.currentUser.oidcAccessToken}` } }
: {}
},
},
)
async function createTankSession(
accessToken: string,
): Promise<tankTypes['schemas']['auth.NewSessionResponse']> {
const res = await fetch(`${import.meta.env.VUE_APP_TANK}/auth/session`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
backend: 'oidc',
arguments: {
access_token: accessToken,
token_type: 'Bearer',
},
}),
})
if (res.ok) {
return await res.json()
} else {
throw new Error('Could not initialize Tank session.')
}
}
export const useAuthStore = defineStore('auth', () => {
const currentUser = ref<CurrentUser>()
const _steeringUser = ref<steeringTypes['schemas']['User']>()
const steeringUser = computed(() => (currentUser.value ? _steeringUser.value : undefined))
const isSuperuser = computed(() => steeringUser.value?.is_superuser === true)
async function loadUser() {
const oidcUser = await getUser()
const userStore = useUserStore()
const users = await userStore.list({
headers: { Authorization: `Bearer ${oidcUser.access_token}` },
})
const user = users.find((user: SteeringUser) => user.username === oidcUser.profile?.username)
// now that we have a valid token, we can create a session with tank
let tankSessionToken: string
try {
tankSessionToken = (await createTankSession(oidcUser.access_token))?.token ?? ''
log.debug('Tank session token:', tankSessionToken)
} catch (e) {
log.error('Could not create tank session.', e)
return
}
if (!tankSessionToken) {
log.error('Tank session creation was successful, but no token has been assigned.')
return
}
_steeringUser.value = user
currentUser.value = {
name: oidcUser.profile.nickname ?? '',
email: oidcUser.profile.email ?? '',
oidcAccessToken: oidcUser.access_token,
tankSessionToken,
}
}
async function init() {
log.debug('Initializing oidc client')
oidcManager.events.addUserSignedOut(async () => {
log.debug('User has signed out. Resetting auth store.')
currentUser.value = undefined
})
oidcManager.events.addAccessTokenExpiring(async () => {
log.debug('User token expiration imminent. Starting silent access token renewal.')
try {
const user = await oidcManager.signinSilent()
if (currentUser.value) {
log.debug('Successfully renewed user access token.')
currentUser.value.oidcAccessToken = user.access_token
}
} catch (e) {
log.error('Silent OIDC access token renewal has failed.', e)
}
})
oidcManager.events.addAccessTokenExpired(() => {
log.debug('OIDC token has expired. Logging out...')
currentUser.value = undefined
})
try {
await loadUser()
} catch (e) {
log.debug('Could not load user data.')
currentUser.value = undefined
_steeringUser.value = undefined
}
}
return { currentUser, steeringUser, isSuperuser, init }
})
axios.interceptors.request.use((config) => {
const url = config?.url
const authStore = useAuthStore()
if (!url || !authStore.currentUser) return config
if (url.startsWith(createSteeringURL())) {
config.headers.set('Authorization', `Bearer ${authStore.currentUser.oidcAccessToken}`)
}
if (url.startsWith(createTankURL())) {
config.headers.set('Authorization', `Bearer ${authStore.currentUser.tankSessionToken}`)
}
return config
})