forked from wangziqi/gongxue-base
fix: reject legacy SMS auth providers in production
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { randomBytes } from 'node:crypto';
|
||||
import type pg from 'pg';
|
||||
import { HttpError, type RequestContext } from '../../core/http.js';
|
||||
import { config as appConfig } from '../../core/config.js';
|
||||
import { intParam, optionalString, readJsonBody, requiredString, stringParam } from '../../core/request.js';
|
||||
import { query, queryOne, transaction } from '../../core/db.js';
|
||||
import {
|
||||
@@ -390,6 +391,14 @@ function defaultAuthSecretScope(provider: string): SecretScope {
|
||||
return 'oauth';
|
||||
}
|
||||
|
||||
function assertProductionAuthProviderAllowed(provider: string, status: string) {
|
||||
if (!appConfig.isProduction || !['active', 'testing'].includes(status)) return;
|
||||
const normalized = provider.toLowerCase().replace(/[_\s]/g, '-');
|
||||
if (normalized === 'aliyun' || normalized === 'aliyun-sms' || normalized === 'tencent' || normalized === 'tencent-sms') {
|
||||
throw new HttpError(400, 'Production SMS auth providers must use aliyun-pnvs', 'PRODUCTION_SMS_PROVIDER_MUST_BE_PNVS');
|
||||
}
|
||||
}
|
||||
|
||||
function parseSecretScope(value: unknown, fallback: SecretScope): SecretScope {
|
||||
const candidate = (nullableString(value) || fallback) as SecretScope;
|
||||
if (!SECRET_SCOPES.has(candidate)) {
|
||||
@@ -1400,6 +1409,8 @@ export async function upsertAuthProviderRoute(ctx: RequestContext) {
|
||||
const fallbackScope = defaultAuthSecretScope(provider);
|
||||
const secretPayload = parseSecretPayload(body, fallbackScope, provider, provider);
|
||||
const configPublic = objectValue(body.configPublic);
|
||||
const status = optionalStatus(body.status, AUTH_STATUSES, 'disabled');
|
||||
assertProductionAuthProviderAllowed(provider, status);
|
||||
|
||||
const item = await transaction(async client => {
|
||||
const secret = secretPayload ? await upsertTenantSecret(client, auth, secretPayload) : null;
|
||||
@@ -1420,7 +1431,7 @@ export async function upsertAuthProviderRoute(ctx: RequestContext) {
|
||||
[
|
||||
auth.tenantId,
|
||||
provider,
|
||||
optionalStatus(body.status, AUTH_STATUSES, 'disabled'),
|
||||
status,
|
||||
optionalString(body, 'displayName') || null,
|
||||
publicJsonValue(configPublic),
|
||||
],
|
||||
|
||||
@@ -26,6 +26,7 @@ assert.match(routeSource, /export async function bindPhoneRoute[\s\S]*activeSmsP
|
||||
assert.match(routeSource, /purpose !== 'bind_phone'/, 'phone binding should require bind_phone purpose');
|
||||
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(tenantAdminRouteSource, /assertProductionAuthProviderAllowed[\s\S]*PRODUCTION_SMS_PROVIDER_MUST_BE_PNVS/, 'tenant admin should reject active legacy SMS auth providers in production');
|
||||
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');
|
||||
|
||||
Reference in New Issue
Block a user