Move allauth + auth UI to legacy/

allauth/ (44 files) is a django-allauth React UI — a separate concern
from the Mizan protocol. Moved to legacy/ pending extraction into a
standalone mizan-django-allauth package.

Also moved to legacy/:
- client/AuthContext.tsx — generic auth state from /me endpoint
- client/RouterContext.tsx — framework-agnostic router adapter
- client/routing.tsx — UserRoute/StaffRoute/AnonymousRoute guards
- client/nextjs.tsx — Next.js router adapter for auth

These are auth UI infrastructure, not Mizan protocol. The Mizan core
only needs JWT for auth header selection (jwt/ stays — MizanProvider
depends on useJWT() to decide between Bearer and session auth).

Cleaned up re-exports in client/react.ts and vitest aliases.

33 React tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 03:41:22 -04:00
parent 24ff0ae66d
commit 27c30d7e50
50 changed files with 0 additions and 8 deletions

142
legacy/AuthContext.tsx Normal file
View File

@@ -0,0 +1,142 @@
'use client'
import {
createContext,
useContext,
useState,
useCallback,
useMemo,
type ReactNode,
} from 'react'
import { createDjangoCSRClient, Auth } from './index'
import type { BaseUser, AuthDetails, AuthRoutes } from './types'
/**
* Auth state provided by AuthContext.
*/
export interface AuthState<TUser extends BaseUser = BaseUser> {
/** Current user (null if not authenticated) */
user: TUser | null
/** Whether auth state is loading */
isLoading: boolean
/** Refresh user from server */
refresh: () => Promise<TUser | null>
}
const Context = createContext<AuthState | null>(null)
/**
* Default routes configuration.
*/
export const defaultRoutes: AuthRoutes = {
login: '/auth/login',
authenticated: '/dashboard',
}
const RoutesContext = createContext<AuthRoutes>(defaultRoutes)
export interface AuthContextProps<TUser extends BaseUser = BaseUser> {
children: ReactNode
/** Initial user from SSR hydration (null if not authenticated) */
user?: TUser | null
/** API endpoint to fetch user data (default: '/api/auth/me/') */
userEndpoint?: string
/** Route configuration for guards */
routes?: Partial<AuthRoutes>
}
/**
* Base auth context for Django-React apps.
*
* Provides user state from a simple /me endpoint.
* For allauth integration, use AllauthContext instead.
*/
// Create client once at module level (session auth, no dynamic config needed)
const client = createDjangoCSRClient(Auth.SESSION)
export function AuthContext<TUser extends BaseUser = BaseUser>({
children,
user: initialUser = null,
userEndpoint = '/api/auth/me/',
routes,
}: AuthContextProps<TUser>) {
const [user, setUser] = useState<TUser | null>(initialUser)
const [isLoading, setIsLoading] = useState(false)
const refresh = useCallback(async (): Promise<TUser | null> => {
setIsLoading(true)
try {
const resp = await client.request('GET', userEndpoint)
if (resp.ok) {
const userData = await resp.json()
setUser(userData)
return userData
} else if (resp.status === 401 || resp.status === 403) {
setUser(null)
return null
}
throw new Error(`Failed to fetch user: ${resp.status}`)
} catch (e) {
console.error('[AuthContext] Failed to fetch user:', e)
return null
} finally {
setIsLoading(false)
}
}, [userEndpoint])
const authState = useMemo<AuthState<TUser>>(() => ({
user,
isLoading,
refresh,
}), [user, isLoading, refresh])
const routesValue = useMemo(() => ({
...defaultRoutes,
...routes,
}), [routes])
return (
<RoutesContext value={routesValue}>
<Context value={authState}>
{children}
</Context>
</RoutesContext>
)
}
/**
* Hook to access auth state.
* Throws if used outside AuthContext.
*/
export function useAuthState<TUser extends BaseUser = BaseUser>(): AuthState<TUser> {
const ctx = useContext(Context)
if (!ctx) throw new Error('useAuthState must be used within AuthContext')
return ctx as AuthState<TUser>
}
/**
* Hook to access current user.
* Returns null if not authenticated.
*/
export function useUser<TUser extends BaseUser = BaseUser>(): TUser | null {
return useAuthState<TUser>().user
}
/**
* Hook to access auth details (isAuthenticated, isStaff, etc.)
*/
export function useAuth(): AuthDetails {
const user = useUser()
return {
isAuthenticated: user !== null,
isStaff: user?.is_staff ?? false,
isSuperuser: user?.is_superuser ?? false,
}
}
/**
* Hook to access route configuration.
*/
export function useAuthRoutes(): AuthRoutes {
return useContext(RoutesContext)
}