fix: default tenant PNVS secrets to sms scope

This commit is contained in:
Codex
2026-07-03 22:54:36 +08:00
parent 9f4fd6530a
commit cd0f465689
3 changed files with 39 additions and 1 deletions

View File

@@ -379,6 +379,17 @@ function secretRef(scope: SecretScope, secretKey: string) {
return `app_private.tenant_secrets:${scope}:${secretKey}`;
}
function defaultAuthSecretScope(provider: string): SecretScope {
const normalized = provider.toLowerCase().replace(/[_\s]/g, '-');
if (
normalized.includes('sms') ||
normalized === 'aliyun' ||
normalized === 'aliyun-pnvs' ||
normalized === 'tencent'
) return 'sms';
return 'oauth';
}
function parseSecretScope(value: unknown, fallback: SecretScope): SecretScope {
const candidate = (nullableString(value) || fallback) as SecretScope;
if (!SECRET_SCOPES.has(candidate)) {
@@ -1386,7 +1397,7 @@ export async function upsertAuthProviderRoute(ctx: RequestContext) {
requireTenantPermission(auth, 'tenant:auth:write');
const body = await readJsonBody(ctx);
const provider = requiredString(body, 'provider');
const fallbackScope = provider.toLowerCase().includes('sms') ? 'sms' : 'oauth';
const fallbackScope = defaultAuthSecretScope(provider);
const secretPayload = parseSecretPayload(body, fallbackScope, provider, provider);
const configPublic = objectValue(body.configPublic);

View File

@@ -4,6 +4,7 @@ import path from 'node:path';
const providerSource = fs.readFileSync(path.join(process.cwd(), 'apps/api/src/features/auth/providers.ts'), 'utf8');
const routeSource = fs.readFileSync(path.join(process.cwd(), 'apps/api/src/features/auth/routes.ts'), 'utf8');
const tenantAdminRouteSource = fs.readFileSync(path.join(process.cwd(), 'apps/api/src/features/tenant-admin/routes.ts'), 'utf8');
const deployEnvExample = fs.readFileSync(path.join(process.cwd(), 'scripts/deploy/env/api.env.example'), 'utf8');
const providerDoc = fs.readFileSync(path.join(process.cwd(), 'docs/refactor/auth-payment-provider-plan.md'), 'utf8');
const launchChecklist = fs.readFileSync(path.join(process.cwd(), 'docs/refactor/web-launch-acceptance-checklist.md'), 'utf8');
@@ -19,6 +20,7 @@ assert.match(routeSource, /aliyun-pnvs/, 'auth routes should recognize aliyun-pn
assert.match(routeSource, /verification.*provider/s, 'auth routes should store provider verification mode');
assert.match(routeSource, /provider\.verify/, 'auth routes should delegate PNVS verification to provider');
assert.match(tenantProviderConfigSource, /normalized === 'aliyun-pnvs'[\s\S]*return 'sms'/, 'PNVS secrets should default to sms scope');
assert.match(tenantAdminRouteSource, /normalized === 'aliyun-pnvs'[\s\S]*return 'sms'/, 'tenant admin PNVS secrets should default to sms scope');
assert.match(deployEnvExample, /AUTH_SMS_PROVIDER=aliyun-pnvs/, 'deploy env example should prefer aliyun-pnvs');
assert.match(readinessSource, /aliyunPnvs/, 'production readiness should validate aliyun-pnvs public config');
assert.match(providerDoc, /SendSmsVerifyCode/, 'provider doc should document PNVS send action');

View File

@@ -7996,6 +7996,31 @@ async function testTenantAdminOps() {
assert.equal(authProvider.item?.secret?.hasSecretValue, true, 'auth provider should report masked secret status');
assert.ok(!JSON.stringify(authProvider).includes('wechat-app-secret-smoke'), 'auth provider response must not include secret plaintext');
const pnvsAuthProvider = await request('/api/tenant-admin/auth-providers', {
userId: TENANT_ADMIN_USER_ID,
method: 'PUT',
body: {
provider: 'aliyun-pnvs',
displayName: '阿里云短信认证',
status: 'testing',
configPublic: {
signName: '短信签名',
templateCode: 'SMS_123456789',
endpoint: 'https://dypnsapi.aliyuncs.com',
},
secret: {
secretJson: {
accessKeyId: 'pnvs-access-key-id',
accessKeySecret: 'pnvs-access-key-secret',
},
},
},
});
assert.equal(pnvsAuthProvider.item?.provider, 'aliyun-pnvs', 'tenant admin should upsert PNVS auth provider');
assert.equal(pnvsAuthProvider.item?.configPublic?.secretRef, 'app_private.tenant_secrets:sms:aliyun-pnvs', 'PNVS auth provider should default secrets to sms scope');
assert.equal(pnvsAuthProvider.item?.secret?.hasSecretJson, true, 'PNVS auth provider should report masked JSON secret status');
assert.ok(!JSON.stringify(pnvsAuthProvider).includes('pnvs-access-key-secret'), 'PNVS auth provider response must not include secret plaintext');
const miniappLogin = await request('/api/auth/oauth/wechat-miniapp', {
userId: false,
method: 'POST',