feat(frontend): expose isAdmin on current user and add config feature check

This commit is contained in:
kolaente 2026-04-20 18:58:01 +02:00 committed by kolaente
parent c9b3d4775c
commit 23c82bd5fa
5 changed files with 52 additions and 1 deletions

View File

@ -23,4 +23,5 @@ export interface IUser extends IAbstract {
isLocalUser: boolean
deletionScheduledAt: string | Date | null
isAdmin?: boolean
}

View File

@ -81,6 +81,7 @@ export default class UserModel extends AbstractModel<IUser> implements IUser {
isLocalUser: boolean
deletionScheduledAt: null
isAdmin?: boolean
constructor(data: Partial<IUser> = {}) {
super()

View File

@ -0,0 +1,40 @@
import {describe, it, expect, beforeEach} from 'vitest'
import {setActivePinia, createPinia} from 'pinia'
import {computed} from 'vue'
import {useConfigStore} from './config'
describe('config store', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
describe('isProFeatureEnabled', () => {
it('returns true when the feature is in the enabledProFeatures list', () => {
const store = useConfigStore()
store.enabledProFeatures = ['admin_panel']
expect(store.isProFeatureEnabled('admin_panel')).toBe(true)
})
it('returns false for features not present in the list', () => {
const store = useConfigStore()
store.enabledProFeatures = ['admin_panel']
expect(store.isProFeatureEnabled('time_tracking')).toBe(false)
})
it('returns false when the list is empty (free mode)', () => {
const store = useConfigStore()
store.enabledProFeatures = []
expect(store.isProFeatureEnabled('admin_panel')).toBe(false)
})
it('reacts to store updates when wrapped in computed', () => {
const store = useConfigStore()
store.enabledProFeatures = []
const enabled = computed(() => store.isProFeatureEnabled('admin_panel'))
expect(enabled.value).toBe(false)
store.enabledProFeatures = ['admin_panel']
expect(enabled.value).toBe(true)
})
})
})

View File

@ -44,6 +44,7 @@ export interface ConfigState {
},
},
publicTeamsEnabled: boolean,
enabledProFeatures: string[],
}
export const useConfigStore = defineStore('config', () => {
@ -83,6 +84,7 @@ export const useConfigStore = defineStore('config', () => {
},
},
publicTeamsEnabled: false,
enabledProFeatures: [],
})
const migratorsEnabled = computed(() => state.availableMigrators?.length > 0)
@ -100,6 +102,10 @@ export const useConfigStore = defineStore('config', () => {
Object.assign(state, config)
}
function isProFeatureEnabled(name: string): boolean {
return state.enabledProFeatures?.includes(name) ?? false
}
async function update(): Promise<boolean> {
const HTTP = HTTPFactory()
const {data: config} = await HTTP.get('info')
@ -108,7 +114,7 @@ export const useConfigStore = defineStore('config', () => {
throw new InvalidApiUrlProvidedError()
}
setConfig(objectToCamelCase(config))
setConfig(objectToCamelCase(config) as ConfigState)
return !!config
}
@ -118,6 +124,7 @@ export const useConfigStore = defineStore('config', () => {
migratorsEnabled,
apiBase,
setConfig,
isProFeatureEnabled,
update,
}

View File

@ -38,6 +38,7 @@ type UserWithSettings struct {
DeletionScheduledAt time.Time `json:"deletion_scheduled_at"`
IsLocalUser bool `json:"is_local_user"`
AuthProvider string `json:"auth_provider"`
IsAdmin bool `json:"is_admin"`
}
// UserShow gets all information about the current user
@ -83,6 +84,7 @@ func UserShow(c *echo.Context) error {
},
DeletionScheduledAt: u.DeletionScheduledAt,
IsLocalUser: u.Issuer == user.IssuerLocal,
IsAdmin: u.IsAdmin,
}
us.AuthProvider, err = getAuthProviderName(u)