163 lines
5.0 KiB
JavaScript
163 lines
5.0 KiB
JavaScript
"use strict";
|
|
|
|
const assert = require("assert");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
const toDataModuleUrl = (source) =>
|
|
`data:text/javascript;base64,${Buffer.from(source).toString("base64")}`;
|
|
|
|
const run = async () => {
|
|
const source = fs.readFileSync(
|
|
path.join(__dirname, "../utils/auth-verification.js"),
|
|
"utf8",
|
|
);
|
|
const {
|
|
AUTH_VERIFICATION_OPERATION,
|
|
isAuthPhone,
|
|
assertSmsCode,
|
|
normalizeCaptchaRequirement,
|
|
createTacRenderContext,
|
|
normalizeTacSuccess,
|
|
isSmsDeliveryOutcomeUnknown,
|
|
} = await import(toDataModuleUrl(source));
|
|
|
|
assert.deepStrictEqual(
|
|
{ ...AUTH_VERIFICATION_OPERATION },
|
|
{
|
|
PASSWORD_LOGIN: "password-login",
|
|
SMS_LOGIN: "sms-login",
|
|
REGISTER: "register",
|
|
FORGOT_PASSWORD: "forgot-password",
|
|
},
|
|
"认证动作必须由受保护 OpenAPI 的唯一枚举拥有",
|
|
);
|
|
|
|
assert.strictEqual(isAuthPhone("13800138000"), true);
|
|
for (const invalid of ["", "12800138000", "1380013800", "138001380000", 13800138000, null]) {
|
|
assert.strictEqual(isAuthPhone(invalid), false, `非法认证手机号被放行:${invalid}`);
|
|
}
|
|
|
|
assert.strictEqual(assertSmsCode("1234"), "1234");
|
|
for (const invalid of ["", "123", "12345", "12a4", 1234, null]) {
|
|
assert.throws(() => assertSmsCode(invalid), /4 位短信验证码/);
|
|
}
|
|
|
|
const requirement = normalizeCaptchaRequirement(
|
|
{
|
|
required: true,
|
|
providerCode: "TIANAI",
|
|
captchaType: "SLIDER",
|
|
sceneCode: "APP_REGISTER",
|
|
ttlSeconds: 300,
|
|
},
|
|
);
|
|
assert.deepStrictEqual(requirement, {
|
|
required: true,
|
|
providerCode: "TIANAI",
|
|
captchaType: "SLIDER",
|
|
sceneCode: "APP_REGISTER",
|
|
ttlSeconds: 300,
|
|
});
|
|
assert.deepStrictEqual(
|
|
normalizeCaptchaRequirement({ ...requirement, required: false }),
|
|
{ required: false, sceneCode: "APP_REGISTER" },
|
|
"策略关闭时必须保留服务端绑定场景并跳过 TAC 渲染",
|
|
);
|
|
assert.throws(
|
|
() => normalizeCaptchaRequirement({ ...requirement, providerCode: "OTHER" }),
|
|
/TIANAI/,
|
|
);
|
|
assert.throws(
|
|
() => normalizeCaptchaRequirement({ ...requirement, captchaType: "math" }),
|
|
/验证码类型/,
|
|
);
|
|
|
|
const context = createTacRenderContext({
|
|
requestId: "register-1",
|
|
baseUrl: "https://backend-api.ddxcjp.cn/",
|
|
clientId: "client-1",
|
|
tenantId: "000000",
|
|
operationCode: AUTH_VERIFICATION_OPERATION.REGISTER,
|
|
subject: "13800138000",
|
|
requirement,
|
|
});
|
|
assert.deepStrictEqual(context, {
|
|
requestId: "register-1",
|
|
baseUrl: "https://backend-api.ddxcjp.cn",
|
|
challengeUrl: "https://backend-api.ddxcjp.cn/genealogy/app/auth/verification/register/challenge",
|
|
verifyUrl: "https://backend-api.ddxcjp.cn/genealogy/app/auth/verification/register/verify",
|
|
clientId: "client-1",
|
|
tenantId: "000000",
|
|
operationCode: AUTH_VERIFICATION_OPERATION.REGISTER,
|
|
subject: "13800138000",
|
|
providerCode: "TIANAI",
|
|
captchaType: "SLIDER",
|
|
});
|
|
assert.throws(
|
|
() => createTacRenderContext({ ...context, baseUrl: "http://backend-api.ddxcjp.cn", requirement }),
|
|
/HTTPS/,
|
|
);
|
|
assert.throws(
|
|
() => createTacRenderContext({ ...context, subject: "1380013800", requirement }),
|
|
/手机号/,
|
|
);
|
|
assert.throws(
|
|
() => createTacRenderContext({ ...context, operationCode: "APP_REGISTER", requirement }),
|
|
/认证动作/,
|
|
);
|
|
assert.throws(
|
|
() => createTacRenderContext({ ...context, requirement: { ...requirement, required: false } }),
|
|
/无需行为验证/,
|
|
);
|
|
|
|
assert.deepStrictEqual(
|
|
normalizeTacSuccess(
|
|
{ requestId: "register-1", validToken: "ticket-1", expireSeconds: 300 },
|
|
"register-1",
|
|
),
|
|
{ requestId: "register-1", validToken: "ticket-1", expireSeconds: 300 },
|
|
);
|
|
assert.throws(
|
|
() => normalizeTacSuccess({ requestId: "stale", validToken: "ticket-1" }, "register-1"),
|
|
/已过期|不匹配/,
|
|
);
|
|
assert.throws(
|
|
() => normalizeTacSuccess({ requestId: "register-1", validToken: "" }, "register-1"),
|
|
/票据/,
|
|
);
|
|
|
|
for (const error of [
|
|
{ code: "REQUEST_TIMEOUT" },
|
|
{ code: "NETWORK_ERROR" },
|
|
{ code: "RESPONSE_INVALID" },
|
|
{ code: "REQUEST_CANCELLED" },
|
|
{ code: "HTTP_ERROR", httpStatus: 201 },
|
|
{ code: "HTTP_ERROR", httpStatus: 204 },
|
|
{ code: "HTTP_ERROR", httpStatus: 302 },
|
|
{ code: "HTTP_ERROR", httpStatus: 408 },
|
|
{ code: "HTTP_ERROR", httpStatus: 500 },
|
|
{ code: "BUSINESS_ERROR", businessCode: 408 },
|
|
{ code: "BUSINESS_ERROR", businessCode: 500 },
|
|
]) {
|
|
assert.strictEqual(isSmsDeliveryOutcomeUnknown(error), true);
|
|
}
|
|
for (const error of [
|
|
null,
|
|
{ code: "HTTP_ERROR", httpStatus: 400 },
|
|
{ code: "HTTP_ERROR", httpStatus: 401 },
|
|
{ code: "HTTP_ERROR", httpStatus: 422 },
|
|
{ code: "HTTP_ERROR", httpStatus: 429 },
|
|
{ code: "BUSINESS_ERROR", businessCode: 429 },
|
|
]) {
|
|
assert.strictEqual(isSmsDeliveryOutcomeUnknown(error), false);
|
|
}
|
|
|
|
process.stdout.write("AUTH-VERIFICATION-RUNTIME-SMOKE PASS\n");
|
|
};
|
|
|
|
run().catch((error) => {
|
|
process.stderr.write(`${error.stack || error.message}\n`);
|
|
process.exit(1);
|
|
});
|