import { assertSmsCode } from '@/utils/auth/verification.js' import { runtimeConfig } from '@/utils/runtime-config.js' import { assertAuthVerificationOperation, assertPasswordHash, assertWechatAuthorizationCode, normalizeOptionalReferralCode, normalizeOptionalValidToken, saveLogin } from './auth-contract.js' import { normalizeOptionalText } from './request-normalizers.js' import { normalizePhoneChangePayload } from './profile-contract.js' import { createRequestError, requestAuth, requestAuthVoid, requestStrict } from './request-client.js' export const authApi = { async getCaptchaRequirement({ operationCode, subject }, requestOptions = {}) { return requestAuth({ url: `/genealogy/app/auth/verification/${encodeURIComponent(assertAuthVerificationOperation(operationCode))}/require`, method: 'GET', data: { tenantId: runtimeConfig.tenantId, subject } }, requestOptions) }, async sendSmsCode({ operationCode, phone, validToken }, requestOptions = {}) { const normalizedValidToken = normalizeOptionalValidToken(validToken) return requestAuthVoid({ url: `/genealogy/app/auth/sms/${encodeURIComponent(assertAuthVerificationOperation(operationCode))}/code`, method: 'POST', data: { tenantId: runtimeConfig.tenantId, grantType: 'sms', phone, ...(normalizedValidToken ? { validToken: normalizedValidToken } : {}) } }, requestOptions) }, async loginWithPassword({ phone, passwordHash, validToken }, requestOptions = {}) { const normalizedValidToken = normalizeOptionalValidToken(validToken) const loginSession = await requestAuth({ url: '/genealogy/app/auth/login', method: 'POST', data: { tenantId: runtimeConfig.tenantId, grantType: 'password', phone, password: assertPasswordHash(passwordHash), ...(normalizedValidToken ? { validToken: normalizedValidToken } : {}) } }, requestOptions) return saveLogin(loginSession) }, async loginWithSms({ phone, smsCode }, requestOptions = {}) { const loginSession = await requestAuth({ url: '/genealogy/app/auth/login/sms', method: 'POST', data: { tenantId: runtimeConfig.tenantId, grantType: 'sms', phone, smsCode: assertSmsCode(smsCode) } }, requestOptions) return saveLogin(loginSession) }, async loginWithWechat({ code }, requestOptions = {}) { const loginResult = await requestAuth({ url: '/genealogy/app/auth/login/wechat', method: 'POST', data: { code: assertWechatAuthorizationCode(code) } }, requestOptions) if (loginResult?.status === 'ACCOUNT_BINDING_REQUIRED') { throw createRequestError( '该微信尚未绑定账号,请先用手机号登录,再到“账号与安全”绑定微信', 'ACCOUNT_BINDING_REQUIRED' ) } if (loginResult?.status !== 'AUTHENTICATED' || !loginResult.login) { throw createRequestError('微信登录响应无效', 'AUTH_RESPONSE_INVALID') } return saveLogin(loginResult.login) }, async bindWechat({ code }, requestOptions = {}) { await requestStrict({ url: '/genealogy/app/auth/wechat/bind', method: 'POST', data: { code: assertWechatAuthorizationCode(code) } }, { requireData: false, requestController: requestOptions.requestController ?? null }) return null }, async registerWithPassword({ phone, passwordHash, smsCode, nickName, referralCode }, requestOptions = {}) { const normalizedNickName = normalizeOptionalText(nickName, '昵称') const normalizedReferralCode = normalizeOptionalReferralCode(referralCode) const loginSession = await requestAuth({ url: '/genealogy/app/auth/register', method: 'POST', data: { tenantId: runtimeConfig.tenantId, grantType: 'password', phone, password: assertPasswordHash(passwordHash), smsCode: assertSmsCode(smsCode), ...(normalizedNickName ? { nickName: normalizedNickName } : {}), ...(normalizedReferralCode ? { referralCode: normalizedReferralCode } : {}) } }, requestOptions) return saveLogin(loginSession) }, async resetPassword({ phone, passwordHash, smsCode }, requestOptions = {}) { return requestAuthVoid({ url: '/genealogy/app/auth/password/reset', method: 'PUT', data: { tenantId: runtimeConfig.tenantId, grantType: 'password', phone, newPassword: assertPasswordHash(passwordHash), smsCode: assertSmsCode(smsCode) } }, requestOptions) }, async changePassword({ oldPasswordHash, newPasswordHash }, requestOptions = {}) { await requestStrict({ url: '/genealogy/app/auth/password', method: 'PUT', data: { oldPassword: assertPasswordHash(oldPasswordHash), newPassword: assertPasswordHash(newPasswordHash) } }, { requireData: false, requestController: requestOptions.requestController ?? null }) return null }, async deactivateAccount({ smsCode }, requestOptions = {}) { await requestStrict({ url: '/genealogy/app/auth/account/deactivate', method: 'POST', data: { smsCode: assertSmsCode(smsCode) } }, { requireData: false, requestController: requestOptions.requestController ?? null }) return null }, async logout(requestOptions = {}) { await requestStrict({ url: '/genealogy/app/auth/logout', method: 'DELETE' }, { requireData: false, requestController: requestOptions.requestController ?? null }) return null }, async changePhone(payload, requestOptions = {}) { await requestStrict({ url: '/genealogy/app/auth/phone', method: 'PUT', data: normalizePhoneChangePayload(payload) }, { requireData: false, requestController: requestOptions.requestController ?? null }) return null } }