diff --git a/scripts/dev-api.js b/scripts/dev-api.js index 4020083..f59f6e1 100644 --- a/scripts/dev-api.js +++ b/scripts/dev-api.js @@ -6313,6 +6313,7 @@ export function buildHermesChannelConfigValues(config = {}, envValues = {}) { putHermesString(form, extra, 'app_token') form.appToken = hermesEnvValue(envValues, 'SLACK_APP_TOKEN') || form.appToken || '' putHermesString(form, extra, 'signing_secret') + form.signingSecret = hermesEnvValue(envValues, 'SLACK_SIGNING_SECRET') || form.signingSecret || '' putHermesString(form, extra, 'webhook_path') } else if (platform === 'feishu') { for (const key of ['app_id', 'app_secret', 'domain', 'connection_mode', 'webhook_path', 'reaction_notifications']) { @@ -6772,6 +6773,7 @@ export function buildHermesChannelEnvUpdates(platform, form = {}) { } else if (platform === 'slack') { updates.SLACK_BOT_TOKEN = String(form.botToken || '').trim() updates.SLACK_APP_TOKEN = String(form.appToken || '').trim() + updates.SLACK_SIGNING_SECRET = String(form.signingSecret || '').trim() updates.SLACK_ALLOWED_USERS = csvEnvValue(form.allowFrom) if (Object.hasOwn(form, 'requireMention')) updates.SLACK_REQUIRE_MENTION = boolEnvValue(form.requireMention) } else if (platform === 'feishu') { diff --git a/src-tauri/src/commands/hermes.rs b/src-tauri/src/commands/hermes.rs index 8d5da33..5d0b783 100644 --- a/src-tauri/src/commands/hermes.rs +++ b/src-tauri/src/commands/hermes.rs @@ -3402,6 +3402,13 @@ fn build_hermes_channel_config_values( .unwrap_or_default(); form.insert("appToken".to_string(), Value::String(app_token)); insert_json_string_if_present(&mut form, &extra, "signing_secret", "signingSecret"); + let signing_secret = hermes_env_value(env_values, "SLACK_SIGNING_SECRET") + .or_else(|| json_form_string(&form, "signingSecret")) + .unwrap_or_default(); + form.insert( + "signingSecret".to_string(), + Value::String(signing_secret), + ); insert_json_string_if_present(&mut form, &extra, "webhook_path", "webhookPath"); } "feishu" => { @@ -11182,6 +11189,10 @@ fn build_hermes_channel_env_updates(platform: &str, form: &Value) -> Vec<(String "SLACK_APP_TOKEN", form_string(form, "appToken").unwrap_or_default(), ); + push( + "SLACK_SIGNING_SECRET", + form_string(form, "signingSecret").unwrap_or_default(), + ); push("SLACK_ALLOWED_USERS", csv_env_value(form, "allowFrom")); if let Some(value) = form_bool(form, "requireMention") { push("SLACK_REQUIRE_MENTION", bool_env_value(value)); @@ -11431,6 +11442,7 @@ fn write_hermes_channel_env(platform: &str, form: &Value) -> Result<(), String> "slack" => vec![ "SLACK_BOT_TOKEN", "SLACK_APP_TOKEN", + "SLACK_SIGNING_SECRET", "SLACK_ALLOWED_USERS", "SLACK_REQUIRE_MENTION", ], @@ -24515,6 +24527,21 @@ platforms: config["platforms"]["slack"]["extra"]["unknown_option"].as_str(), Some("keep-me") ); + + let env = build_hermes_channel_env_updates( + "slack", + &json!({ + "enabled": true, + "botToken": "xoxb-new", + "appToken": "xapp-new", + "signingSecret": "new-signing-secret", + "webhookPath": "/slack/events", + }), + ); + assert!(env.contains(&( + "SLACK_SIGNING_SECRET".to_string(), + "new-signing-secret".to_string() + ))); } #[test] diff --git a/tests/hermes-channel-config.test.js b/tests/hermes-channel-config.test.js index 7ff5419..7b18dda 100644 --- a/tests/hermes-channel-config.test.js +++ b/tests/hermes-channel-config.test.js @@ -358,6 +358,38 @@ test('Hermes 渠道保存会从 YAML 清理旧凭证,避免覆盖 .env 运行 assert.equal(next.platforms.slack.extra.signing_secret, undefined) assert.equal(next.platforms.slack.extra.webhook_path, '/slack/events') assert.equal(next.platforms.slack.extra.unknown_option, 'keep-me') + + const env = buildHermesChannelEnvUpdates('slack', { + enabled: true, + botToken: 'xoxb-new', + appToken: 'xapp-new', + signingSecret: 'new-signing-secret', + webhookPath: '/slack/events', + }) + assert.equal(env.SLACK_BOT_TOKEN, 'xoxb-new') + assert.equal(env.SLACK_APP_TOKEN, 'xapp-new') + assert.equal(env.SLACK_SIGNING_SECRET, 'new-signing-secret') +}) + +test('Hermes Slack 读取会从 .env 回填 signing secret', () => { + const values = buildHermesChannelConfigValues({ + platforms: { + slack: { + enabled: true, + extra: { + webhook_path: '/slack/events', + }, + }, + }, + }, { + SLACK_SIGNING_SECRET: 'env-signing-secret', + SLACK_BOT_TOKEN: 'xoxb-env', + SLACK_APP_TOKEN: 'xapp-env', + }) + + assert.equal(values.slack.signingSecret, 'env-signing-secret') + assert.equal(values.slack.botToken, 'xoxb-env') + assert.equal(values.slack.appToken, 'xapp-env') }) test('Hermes 钉钉保存会使用运行时实际读取的字段', () => {