feat(15-03): rewrite login page and auth hooks for OIDC

- Login page redirects to Logto instead of showing credential form
- AuthState uses string id (Logto sub claim) instead of number
- Remove useLogin, useSetup, useChangePassword hooks
- useLogout redirects to /logout (server-side OIDC logout)
- Remove ChangePasswordSection from settings page
- Update UserMenu to use new useLogout API
- Settings page shows API keys section when authenticated
This commit is contained in:
2026-04-04 20:52:58 +02:00
parent f7c9f3dc94
commit 79b27b6bcc
4 changed files with 37 additions and 186 deletions

View File

@@ -1,9 +1,9 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { apiDelete, apiGet, apiPost, apiPut } from "../lib/api";
import { apiDelete, apiGet, apiPost } from "../lib/api";
interface AuthState {
user: { id: number } | null;
setupRequired: boolean;
user: { id: string; email?: string } | null;
authenticated: boolean;
}
export function useAuth() {
@@ -14,43 +14,11 @@ export function useAuth() {
});
}
export function useLogin() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: { username: string; password: string }) =>
apiPost<{ username: string }>("/api/auth/login", data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["auth"] });
},
});
}
export function useLogout() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: () => apiPost<{ success: boolean }>("/api/auth/logout", {}),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["auth"] });
},
});
}
export function useSetup() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: { username: string; password: string }) =>
apiPost<{ username: string }>("/api/auth/setup", data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["auth"] });
},
});
}
export function useChangePassword() {
return useMutation({
mutationFn: (data: { currentPassword: string; newPassword: string }) =>
apiPut<{ success: boolean }>("/api/auth/password", data),
});
const logout = () => {
window.location.href = "/logout";
};
return { logout };
}
interface ApiKeyListItem {