186 lines
5.9 KiB
JavaScript
186 lines
5.9 KiB
JavaScript
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
|
|
}
|
|
}
|