forked from wangziqi/gongxue-base
feat: add platform dunning notifications
This commit is contained in:
@@ -333,6 +333,12 @@ function validateEnv() {
|
||||
pass('env.worker_platform_audit_notification_insecure_localhost', 'Platform audit notification worker insecure localhost webhook mode is disabled');
|
||||
}
|
||||
|
||||
if (envBool('WORKER_PLATFORM_DUNNING_NOTIFICATION_ALLOW_INSECURE_LOCALHOST', false)) {
|
||||
block('env.worker_platform_dunning_notification_insecure_localhost', 'WORKER_PLATFORM_DUNNING_NOTIFICATION_ALLOW_INSECURE_LOCALHOST must be false in production');
|
||||
} else {
|
||||
pass('env.worker_platform_dunning_notification_insecure_localhost', 'Platform dunning notification worker insecure localhost webhook mode is disabled');
|
||||
}
|
||||
|
||||
const requiredPositiveNumbers = [
|
||||
'WORKER_CRM_BATCH_SIZE',
|
||||
'WORKER_COMMERCE_BATCH_SIZE',
|
||||
@@ -470,6 +476,51 @@ async function validateDatabase() {
|
||||
pass('db.platform_audit_notification_secrets', 'Signed platform audit notification channels have private secret rows');
|
||||
}
|
||||
|
||||
const unsafePlatformDunningNotificationRows = await pool.query(`
|
||||
select id, channel_code, provider, webhook_url
|
||||
from public.platform_dunning_notification_channels
|
||||
where enabled = true
|
||||
and (
|
||||
webhook_url !~* '^https://'
|
||||
or webhook_url ~* '^https?://(localhost|127\\.0\\.0\\.1|\\[?::1\\]?)'
|
||||
)
|
||||
`);
|
||||
if (unsafePlatformDunningNotificationRows.rowCount > 0) {
|
||||
block('db.platform_dunning_notification_webhooks', 'Enabled platform dunning notification webhooks must use production HTTPS URLs', {
|
||||
count: unsafePlatformDunningNotificationRows.rowCount,
|
||||
samples: unsafePlatformDunningNotificationRows.rows.slice(0, 5).map(row => ({
|
||||
id: row.id,
|
||||
channelCode: row.channel_code,
|
||||
provider: row.provider,
|
||||
})),
|
||||
});
|
||||
} else {
|
||||
pass('db.platform_dunning_notification_webhooks', 'Enabled platform dunning notification webhooks use production HTTPS URLs');
|
||||
}
|
||||
|
||||
const missingPlatformDunningNotificationSecretRows = await pool.query(`
|
||||
select c.id, c.channel_code, c.provider, c.secret_ref
|
||||
from public.platform_dunning_notification_channels c
|
||||
left join app_private.platform_secrets s
|
||||
on s.secret_scope = split_part(c.secret_ref, ':', 2)
|
||||
and s.secret_key = split_part(c.secret_ref, ':', 3)
|
||||
where c.enabled = true
|
||||
and c.provider in ('dingtalk', 'feishu')
|
||||
and (c.secret_ref is null or c.secret_ref !~ '^app_private\\.platform_secrets:' or s.id is null)
|
||||
`);
|
||||
if (missingPlatformDunningNotificationSecretRows.rowCount > 0) {
|
||||
block('db.platform_dunning_notification_secrets', 'Signed platform dunning notification channels require app_private.platform_secrets rows', {
|
||||
count: missingPlatformDunningNotificationSecretRows.rowCount,
|
||||
samples: missingPlatformDunningNotificationSecretRows.rows.slice(0, 5).map(row => ({
|
||||
id: row.id,
|
||||
channelCode: row.channel_code,
|
||||
provider: row.provider,
|
||||
})),
|
||||
});
|
||||
} else {
|
||||
pass('db.platform_dunning_notification_secrets', 'Signed platform dunning notification channels have private secret rows');
|
||||
}
|
||||
|
||||
const unverifiedDomainRows = await pool.query(`
|
||||
select count(*)::int as count
|
||||
from public.tenant_domains
|
||||
|
||||
Reference in New Issue
Block a user