refactor: replace hand-rolled OIDC with @logto/react SDK
The hand-rolled OIDC flow (manual PKCE, token exchange, URL construction) was fragile and accumulated multiple bugs. Replaced with the official @logto/react SDK which handles PKCE, token exchange, storage, and refresh automatically. - Add @logto/react SDK dependency - Add LogtoProvider with runtime config in main.tsx - Add TokenSync component bridging SDK tokens to API client - Add useAuth hook replacing Zustand auth store - Simplify LoginPage to signIn(), CallbackPage to useHandleSignInCallback() - Delete pkce.ts and auth-store.ts (replaced by SDK) - Fix react-router-dom → react-router imports in page files - All 17 React Query hooks unchanged (token provider pattern) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { useNavigate, useParams, Link } from 'react-router-dom';
|
||||
import { useNavigate, useParams, Link } from 'react-router';
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
useToast,
|
||||
} from '@cameleer/design-system';
|
||||
import type { Column, LogEntry as DSLogEntry } from '@cameleer/design-system';
|
||||
import { useAuthStore } from '../auth/auth-store';
|
||||
import { useAuth } from '../auth/useAuth';
|
||||
import {
|
||||
useApp,
|
||||
useDeployment,
|
||||
@@ -118,7 +118,7 @@ export function AppDetailPage() {
|
||||
const { envId = '', appId = '' } = useParams<{ envId: string; appId: string }>();
|
||||
const navigate = useNavigate();
|
||||
const { toast } = useToast();
|
||||
const tenantId = useAuthStore((s) => s.tenantId);
|
||||
const { tenantId } = useAuth();
|
||||
const { canManageApps, canDeploy } = usePermissions();
|
||||
|
||||
// Active tab
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useCallback, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
KpiStrip,
|
||||
Spinner,
|
||||
} from '@cameleer/design-system';
|
||||
import { useAuthStore } from '../auth/auth-store';
|
||||
import { useAuth } from '../auth/useAuth';
|
||||
import { useTenant, useEnvironments, useApps } from '../api/hooks';
|
||||
import { RequirePermission } from '../components/RequirePermission';
|
||||
import type { EnvironmentResponse, AppResponse } from '../types/api';
|
||||
@@ -41,7 +41,7 @@ function tierColor(tier: string): 'primary' | 'success' | 'warning' | 'error' {
|
||||
|
||||
export function DashboardPage() {
|
||||
const navigate = useNavigate();
|
||||
const tenantId = useAuthStore((s) => s.tenantId);
|
||||
const { tenantId } = useAuth();
|
||||
|
||||
const { data: tenant, isLoading: tenantLoading } = useTenant(tenantId ?? '');
|
||||
const { data: environments, isLoading: envsLoading } = useEnvironments(tenantId ?? '');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { useNavigate, useParams } from 'react-router';
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
useToast,
|
||||
} from '@cameleer/design-system';
|
||||
import type { Column } from '@cameleer/design-system';
|
||||
import { useAuthStore } from '../auth/auth-store';
|
||||
import { useAuth } from '../auth/useAuth';
|
||||
import {
|
||||
useEnvironments,
|
||||
useUpdateEnvironment,
|
||||
@@ -77,7 +77,7 @@ export function EnvironmentDetailPage() {
|
||||
const navigate = useNavigate();
|
||||
const { envId } = useParams<{ envId: string }>();
|
||||
const { toast } = useToast();
|
||||
const tenantId = useAuthStore((s) => s.tenantId);
|
||||
const { tenantId } = useAuth();
|
||||
|
||||
const { data: environments, isLoading: envsLoading } = useEnvironments(tenantId ?? '');
|
||||
const environment = environments?.find((e) => e.id === envId);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
useToast,
|
||||
} from '@cameleer/design-system';
|
||||
import type { Column } from '@cameleer/design-system';
|
||||
import { useAuthStore } from '../auth/auth-store';
|
||||
import { useAuth } from '../auth/useAuth';
|
||||
import { useEnvironments, useCreateEnvironment } from '../api/hooks';
|
||||
import { RequirePermission } from '../components/RequirePermission';
|
||||
import type { EnvironmentResponse } from '../types/api';
|
||||
@@ -67,7 +67,7 @@ const columns: Column<TableRow>[] = [
|
||||
export function EnvironmentsPage() {
|
||||
const navigate = useNavigate();
|
||||
const { toast } = useToast();
|
||||
const tenantId = useAuthStore((s) => s.tenantId);
|
||||
const { tenantId } = useAuth();
|
||||
|
||||
const { data: environments, isLoading } = useEnvironments(tenantId ?? '');
|
||||
const createMutation = useCreateEnvironment(tenantId ?? '');
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
EmptyState,
|
||||
Spinner,
|
||||
} from '@cameleer/design-system';
|
||||
import { useAuthStore } from '../auth/auth-store';
|
||||
import { useAuth } from '../auth/useAuth';
|
||||
import { useLicense } from '../api/hooks';
|
||||
|
||||
const FEATURE_LABELS: Record<string, string> = {
|
||||
@@ -39,7 +39,7 @@ function daysRemaining(expiresAt: string): number {
|
||||
}
|
||||
|
||||
export function LicensePage() {
|
||||
const tenantId = useAuthStore((s) => s.tenantId);
|
||||
const { tenantId } = useAuth();
|
||||
const { data: license, isLoading, isError } = useLicense(tenantId ?? '');
|
||||
const [tokenExpanded, setTokenExpanded] = useState(false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user