Add new vue-based frontend

This commit is contained in:
2025-07-05 16:00:29 +02:00
parent c7ecc3f365
commit 3ef659be61
73 changed files with 14431 additions and 0 deletions

View File

@ -0,0 +1,78 @@
import { defineStore } from 'pinia'
import { client } from '@/client/client.gen'
import { SshecretAdmin } from '@/client'
import type { Token } from '@/client'
export function setAuthToken(token: string | null) {
client.setConfig({
headers: token ? { Authorization: `Bearer ${token}` } : {}
})
}
export const useAuthTokenStore = defineStore('authtoken', {
state: () => ({
accessToken: '' as string,
refreshToken: '' as string,
isLoggedIn: false,
}),
actions: {
async login(username: string, password: string): Promise<boolean> {
try {
const response = await SshecretAdmin.loginForAccessTokenApiV1TokenPost({ body: { username, password } })
const tokenData: Token = response.data
const accessToken = tokenData.access_token
const refreshToken = tokenData.refresh_token
this.accessToken = accessToken
this.refreshToken = refreshToken
this.isLoggedIn = true
localStorage.setItem('accessToken', accessToken)
localStorage.setItem('refreshToken', refreshToken)
setAuthToken(this.accessToken)
return true
}
catch (err) {
console.log(err)
return false
}
},
async refresh(): Promise<boolean> {
try {
console.log("Refreshing token")
const response = await SshecretAdmin.refreshTokenApiV1RefreshPost({ body: { grant_type: "refresh_token", refresh_token: this.refreshToken } })
const tokenData: Token = response.data
const accessToken = tokenData.access_token
const refreshToken = tokenData.refresh_token
this.accessToken = accessToken
this.refreshToken = refreshToken
localStorage.setItem('accessToken', accessToken)
localStorage.setItem('refreshToken', refreshToken)
setAuthToken(this.accessToken)
return true
}
catch (err) {
console.log(err)
return false
}
},
loadFromStorage() {
// Load token from user storage.
const accessToken = localStorage.getItem('accessToken')
const refreshToken = localStorage.getItem('refreshToken')
if (accessToken && refreshToken) {
this.accessToken = accessToken
this.refreshToken = refreshToken
this.isLoggedIn = true
setAuthToken(accessToken)
}
},
logout() {
this.accessToken = ''
this.refreshToken = ''
this.isLoggedIn = false
localStorage.removeItem('accessToken')
localStorage.removeItem('refreshToken')
}
}
})

View File

@ -0,0 +1,138 @@
import { defineStore } from 'pinia'
import { SshecretObjectType } from '@/api/types'
import type { SshecretObject } from '@/api/types'
import { SshecretAdmin } from '@/client'
import type { ClientQueryResult, Client, SecretView } from '@/client'
export const useTreeState = defineStore('treeState', {
state: () => ({
selected: null as SshecretObject | null,
parent: null as SshecretObject | null,
clients: null as ClientQueryResult | null,
}),
actions: {
selectClient(id: string) {
this.selected = { objectType: SshecretObjectType.Client, id: id }
},
selectSecret(name: string, parent?: string) {
this.selected = { objectType: SshecretObjectType.ClientSecret, id: name }
if (parent) {
this.parent = { objectType: SshecretObjectType.Client, id: parent }
}
},
unselect() {
this.selected = null
},
async loadClients(offset: number = 0, limit: number = 100): Promise<number> {
const response = await SshecretAdmin.queryClientsApiV1QueryClientsGet({
query: {
offset,
limit,
}
})
if (response.data) {
this.clients = response.data
return response.data.total_results
}
this.clients = null
return 0
},
async queryClients(query: string, offset: number = 0, limit: number = 100): Promise<number> {
// Query or search. Result is the number of hits.
const response = await SshecretAdmin.queryClientsApiV1QueryClientsGet({
query: {
offset,
limit,
name__like: `%${query}%`,
order_by: "name",
order_reverse: false,
}
})
if (response.data) {
this.clients = response.data
return response.data.total_results
}
this.clients = null
return 0
},
async getClient(id: string | null = null): Promise<Client> {
if (!id && this.selected?.objectType === SshecretObjectType.Client) {
id = this.selected.id
} else if (!id) {
throw "No client selected"
}
if (!this.clients) {
await this.loadClients()
}
if (this.clients) {
const existing = this.clients.clients.find(c => c.id === id)
if (existing) {
return existing
}
}
const response = await SshecretAdmin.getClientApiV1ClientsIdGet({ path: { id: id } })
if (response.data) {
return response.data
}
throw "Client not found"
},
async getSecret(name: string): Promise<SecretView> {
const response = await SshecretAdmin.getSecretApiV1SecretsNameGet({ path: { name: name } })
if (response.data) {
return response.data
}
throw "Secret not found"
},
async getSelected(): Promise<Client | SecretView | null> {
if (!this.selected) {
return null
}
if (this.selected.objectType === SshecretObjectType.Client) {
return await this.getClient(this.selected.id)
} else if (this.selected.objectType === SshecretObjectType.ClientSecret) {
return await this.getSecret(this.selected.id)
}
else {
throw "Invalid object"
}
},
async refreshClient(id: string): Promise<boolean> {
// Refresh a client
if (this.clients) {
const clientIndex = this.clients.clients.findIndex(c => c.id === id)
if (clientIndex >= 0) {
console.log("found client at index: ", clientIndex, this.clients.clients[clientIndex])
const response = await SshecretAdmin.getClientApiV1ClientsIdGet({ path: { id: id } })
if (response.data) {
const newClient = response.data
this.clients.clients = this.clients.clients.map(c => c.id === id ? newClient : c)
return true
}
}
}
return false
}
},
getters: {
clientSelected() {
if (!this.selected) {
return false
}
if (this.selected.objectType === SshecretObjectType.Client) {
return true
}
return false
},
secretSelected() {
if (!this.selected) {
return false
}
if (this.selected.objectType === SshecretObjectType.ClientSecret) {
return true
}
return false
}
}
})