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:
87
legacy/allauth/components/settings/ConnectionsSection.tsx
Normal file
87
legacy/allauth/components/settings/ConnectionsSection.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useConfig } from '../../contexts/AuthContext'
|
||||
import { useAllauthAPI } from '../../contexts/APIContext'
|
||||
import { SettingsSection, SettingsItem, SettingsList, Button } from './SettingsComponents'
|
||||
|
||||
interface Connection {
|
||||
uid: string
|
||||
provider: { id: string; name: string }
|
||||
display: string
|
||||
}
|
||||
|
||||
interface ConnectionsSectionProps {
|
||||
/** URL to redirect back to after OAuth connect */
|
||||
redirectUrl?: string
|
||||
}
|
||||
|
||||
export function ConnectionsSection({ redirectUrl = '/account' }: ConnectionsSectionProps) {
|
||||
const api = useAllauthAPI()
|
||||
const config = useConfig()
|
||||
const [connections, setConnections] = useState<Connection[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
const availableProviders = config?.data?.socialaccount?.providers || []
|
||||
|
||||
const fetchConnections = async () => {
|
||||
const res = await api.oauth.list()
|
||||
if (res.status === 200 && res.data) {
|
||||
setConnections(res.data)
|
||||
}
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
useEffect(() => { fetchConnections() }, [])
|
||||
|
||||
const handleConnect = (providerId: string) => {
|
||||
api.oauth.provider(providerId).connect.withRedirect(redirectUrl)
|
||||
}
|
||||
|
||||
const handleDisconnect = async (providerId: string, uid: string) => {
|
||||
if (!confirm('Disconnect this account?')) return
|
||||
await api.oauth.provider(providerId).removeFrom(uid)
|
||||
fetchConnections()
|
||||
}
|
||||
|
||||
// Don't render if no providers configured or still loading
|
||||
if (loading) return null
|
||||
|
||||
const connectedProviderIds = connections.map(c => c.provider.id)
|
||||
const unconnectedProviders = availableProviders.filter(
|
||||
(p: { id: string }) => !connectedProviderIds.includes(p.id)
|
||||
)
|
||||
|
||||
// Hide section entirely if no social providers
|
||||
if (connections.length === 0 && availableProviders.length === 0) return null
|
||||
|
||||
return (
|
||||
<SettingsSection title="Connected Accounts">
|
||||
<SettingsList>
|
||||
{connections.map(conn => (
|
||||
<SettingsItem
|
||||
key={conn.uid}
|
||||
label={conn.provider.name}
|
||||
meta={conn.display}
|
||||
actions={
|
||||
<Button variant="danger" onClick={() => handleDisconnect(conn.provider.id, conn.uid)}>
|
||||
Disconnect
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
{unconnectedProviders.map((provider: { id: string; name: string }) => (
|
||||
<SettingsItem
|
||||
key={provider.id}
|
||||
label={provider.name}
|
||||
actions={
|
||||
<Button onClick={() => handleConnect(provider.id)}>
|
||||
Connect
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</SettingsList>
|
||||
</SettingsSection>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user