feat: route registration through 太极 AI PAD API

Registration now goes through the Agnet auth proxy (/api/heicode-auth/*)
instead of the local Manager API. Email verification is always required
(太极 mandates it). After successful registration, tokens are used
directly to establish the Manager session without a redundant login call.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 17:24:39 +08:00
co-authored by Claude Opus 4.6
parent 853e3b4ca9
commit e6e80c6a18
2 changed files with 72 additions and 14 deletions
+56 -10
View File
@@ -101,6 +101,19 @@ async function establishManagerSessionFromAgnet(): Promise<{
return { managerUserId: body.data?.id }
}
export async function loginWithAgnetTokens(
accessToken: string,
refreshToken?: string
): Promise<{ managerUserId?: number }> {
writeTokens(accessToken, refreshToken)
try {
return await establishManagerSessionFromAgnet()
} catch (err) {
clearHeicodeTokens()
throw err
}
}
async function callHeicodeAuth<T>(
path: string,
init: RequestInit = {},
@@ -317,23 +330,56 @@ export async function wechatLoginByCode(code: string): Promise<ApiResponse> {
// Registration
// ----------------------------------------------------------------------------
// User registration
export async function register(payload: RegisterPayload): Promise<ApiResponse> {
const res = await api.post(`/api/user/register`, payload, {
params: { turnstile: payload.turnstile ?? '' },
// User registration via Agnet (太极 AI PAD)
export async function register(payload: RegisterPayload): Promise<ApiResponse & {
data?: {
token?: string
refreshToken?: string
user?: { id?: string; name?: string; email?: string; role?: string; channelId?: string }
}
}> {
const res = await callHeicodeAuth<{
success: boolean
message?: string
detail?: string
data?: {
token?: string
refreshToken?: string
user?: { id?: string; name?: string; email?: string; role?: string; channelId?: string }
}
}>('/api/auth/register', {
method: 'POST',
body: JSON.stringify({
username: payload.username,
email: payload.email,
password: payload.password,
verification_code: payload.verification_code,
full_name: payload.username,
}),
})
return res.data
return {
success: Boolean(res?.success),
message: res?.message || res?.detail || '',
data: res?.data,
}
}
// Send email verification code
// Send email verification code via Agnet (太极 AI PAD)
export async function sendEmailVerification(
email: string,
turnstile?: string
_turnstile?: string
): Promise<ApiResponse> {
const res = await api.get('/api/verification', {
params: { email, turnstile },
const res = await callHeicodeAuth<{
success: boolean
message?: string
detail?: string
}>(`/api/auth/register/send-code?email=${encodeURIComponent(email)}`, {
method: 'POST',
})
return res.data
return {
success: Boolean(res?.success),
message: res?.message || res?.detail || '',
}
}
// Bind email to OAuth account
@@ -28,7 +28,7 @@ import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { PasswordInput } from '@/components/password-input'
import { Turnstile } from '@/components/turnstile'
import { register, wechatLoginByCode } from '@/features/auth/api'
import { register, loginWithAgnetTokens, wechatLoginByCode } from '@/features/auth/api'
import { LegalConsent } from '@/features/auth/components/legal-consent'
import { OAuthProviders } from '@/features/auth/components/oauth-providers'
import { registerFormSchema } from '@/features/auth/constants'
@@ -80,7 +80,7 @@ export function SignUpForm({
})
const emailValue = form.watch('email')
const emailVerificationRequired = !!status?.email_verification
const emailVerificationRequired = true
const hasUserAgreement = Boolean(status?.user_agreement_enabled)
const hasPrivacyPolicy = Boolean(status?.privacy_policy_enabled)
const requiresLegalConsent = hasUserAgreement || hasPrivacyPolicy
@@ -142,9 +142,21 @@ export function SignUpForm({
})
if (res?.success) {
toast.success(t('Account created! Please sign in'))
toast.success(t('Account created!'))
if (res.data?.token) {
const sessionRes = await loginWithAgnetTokens(
res.data.token,
res.data.refreshToken
)
await handleLoginSuccess(
sessionRes.managerUserId
? { id: sessionRes.managerUserId }
: null
)
} else {
redirectToLogin()
}
}
} catch (_error) {
// Errors are handled by global interceptor
} finally {