mirror of
https://github.com/Noooste/garage-ui.git
synced 2026-08-29 16:37:10 +00:00
feat: implement admin and OIDC authentication methods; add login and user info endpoints
Signed-off-by: Noste <83548733+Noooste@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import type { AuthConfig, AuthUser, AuthState } from '@/types/auth';
|
||||
import { authApi } from '@/lib/api';
|
||||
|
||||
interface AuthStore extends AuthState {
|
||||
config: AuthConfig | null;
|
||||
|
||||
// Actions
|
||||
setUser: (user: AuthUser | null) => void;
|
||||
setConfig: (config: AuthConfig) => void;
|
||||
setLoading: (loading: boolean) => void;
|
||||
setError: (error: string | null) => void;
|
||||
setAuthenticated: (authenticated: boolean) => void;
|
||||
|
||||
// Async actions
|
||||
initialize: () => Promise<void>;
|
||||
loginAdmin: (username: string, password: string) => Promise<void>;
|
||||
loginOIDC: () => void;
|
||||
logout: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const useAuthStore = create<AuthStore>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
user: null,
|
||||
config: null,
|
||||
isAuthenticated: false,
|
||||
isLoading: true,
|
||||
error: null,
|
||||
|
||||
setUser: (user) => set({ user, isAuthenticated: !!user }),
|
||||
setConfig: (config) => set({ config }),
|
||||
setLoading: (isLoading) => set({ isLoading }),
|
||||
setError: (error) => set({ error }),
|
||||
setAuthenticated: (isAuthenticated) => set({ isAuthenticated }),
|
||||
|
||||
initialize: async () => {
|
||||
try {
|
||||
set({ isLoading: true, error: null });
|
||||
|
||||
// Fetch auth configuration
|
||||
const configResponse = await authApi.getConfig();
|
||||
const config = configResponse.data as AuthConfig;
|
||||
set({ config });
|
||||
|
||||
// If no auth is enabled, mark as authenticated immediately
|
||||
if (!config.admin.enabled && !config.oidc.enabled) {
|
||||
set({
|
||||
isAuthenticated: true,
|
||||
isLoading: false,
|
||||
user: { username: 'guest' }
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get current user (check if already authenticated)
|
||||
try {
|
||||
const userResponse = await authApi.me();
|
||||
const user = userResponse.data.user;
|
||||
set({
|
||||
user,
|
||||
isAuthenticated: true,
|
||||
isLoading: false
|
||||
});
|
||||
} catch (error) {
|
||||
// Not authenticated - this is okay
|
||||
set({
|
||||
user: null,
|
||||
isAuthenticated: false,
|
||||
isLoading: false
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize auth:', error);
|
||||
set({
|
||||
error: 'Failed to initialize authentication',
|
||||
isLoading: false,
|
||||
isAuthenticated: false
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
loginAdmin: async (username, password) => {
|
||||
try {
|
||||
set({ isLoading: true, error: null });
|
||||
|
||||
const response = await authApi.loginAdmin(username, password);
|
||||
const { token, user } = response.data;
|
||||
|
||||
// Store token in localStorage
|
||||
localStorage.setItem('auth-token', token);
|
||||
|
||||
// Update state
|
||||
set({
|
||||
user,
|
||||
isAuthenticated: true,
|
||||
isLoading: false,
|
||||
error: null
|
||||
});
|
||||
} catch (error: any) {
|
||||
const errorMessage = error.response?.data?.error?.message || 'Login failed';
|
||||
set({
|
||||
error: errorMessage,
|
||||
isLoading: false,
|
||||
isAuthenticated: false,
|
||||
user: null
|
||||
});
|
||||
throw error; // Re-throw for form handling
|
||||
}
|
||||
},
|
||||
|
||||
loginOIDC: () => {
|
||||
// Redirect to OIDC login endpoint
|
||||
window.location.href = '/auth/oidc/login';
|
||||
},
|
||||
|
||||
logout: async () => {
|
||||
const { config } = get();
|
||||
|
||||
try {
|
||||
// Call logout endpoint for OIDC mode
|
||||
if (config?.oidc.enabled) {
|
||||
await authApi.logoutOIDC();
|
||||
} else if (config?.admin.enabled) {
|
||||
await authApi.logoutAdmin();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Logout API call failed:', error);
|
||||
}
|
||||
|
||||
// Clear local storage
|
||||
localStorage.removeItem('auth-token');
|
||||
|
||||
// Clear state
|
||||
set({
|
||||
user: null,
|
||||
isAuthenticated: false,
|
||||
error: null
|
||||
});
|
||||
|
||||
// Redirect to login page
|
||||
window.location.href = '/login';
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: 'auth-storage',
|
||||
partialize: (state) => ({
|
||||
user: state.user,
|
||||
// Don't persist config, isLoading, or error
|
||||
}),
|
||||
}
|
||||
)
|
||||
);
|
||||
Reference in New Issue
Block a user