* Try to auto-map a Slack user to a web user by email * Maps them if the email matches and neither account is already mapped
(slackUserId: string, email: string)
| 247 | * Maps them if the email matches and neither account is already mapped |
| 248 | */ |
| 249 | async function tryAutoMapByEmail(slackUserId: string, email: string): Promise<void> { |
| 250 | try { |
| 251 | const pool = getPool(); |
| 252 | |
| 253 | // Look up the web user by email |
| 254 | const result = await pool.query<{ workos_user_id: string }>( |
| 255 | `SELECT workos_user_id FROM organization_memberships WHERE LOWER(email) = LOWER($1) LIMIT 1`, |
| 256 | [email] |
| 257 | ); |
| 258 | |
| 259 | if (result.rows.length === 0) { |
| 260 | logger.debug({ email }, 'No web account found for Slack user email'); |
| 261 | return; |
| 262 | } |
| 263 | |
| 264 | const workosUserId = result.rows[0].workos_user_id; |
| 265 | |
| 266 | // Check if this WorkOS user is already mapped to a different Slack user |
| 267 | const existingWorkosMapping = await slackDb.getByWorkosUserId(workosUserId); |
| 268 | if (existingWorkosMapping) { |
| 269 | logger.debug( |
| 270 | { email, workosUserId, existingSlackUserId: existingWorkosMapping.slack_user_id }, |
| 271 | 'Web user already mapped to different Slack account' |
| 272 | ); |
| 273 | return; |
| 274 | } |
| 275 | |
| 276 | // Check if this Slack user is already mapped (race condition guard) |
| 277 | const existingSlackMapping = await slackDb.getBySlackUserId(slackUserId); |
| 278 | if (existingSlackMapping?.workos_user_id) { |
| 279 | logger.debug( |
| 280 | { slackUserId, existingWorkosUserId: existingSlackMapping.workos_user_id }, |
| 281 | 'Slack user already mapped to a web account' |
| 282 | ); |
| 283 | return; |
| 284 | } |
| 285 | |
| 286 | // Map the user |
| 287 | await slackDb.mapUser({ |
| 288 | slack_user_id: slackUserId, |
| 289 | workos_user_id: workosUserId, |
| 290 | mapping_source: 'email_auto', |
| 291 | }); |
| 292 | |
| 293 | logger.info({ slackUserId, workosUserId, email }, 'Auto-mapped Slack user to web account by email'); |
| 294 | |
| 295 | // Apply any pending marketing opt-in preference captured via Slack DM |
| 296 | // Only apply if the user hasn't already made an explicit choice on the web |
| 297 | if (existingSlackMapping?.pending_marketing_opt_in != null) { |
| 298 | try { |
| 299 | const { EmailPreferencesDatabase } = await import('../db/email-preferences-db.js'); |
| 300 | const emailPrefsDb = new EmailPreferencesDatabase(); |
| 301 | const wasSet = await emailPrefsDb.setMarketingOptInIfNotSet({ |
| 302 | workos_user_id: workosUserId, |
| 303 | email, |
| 304 | optIn: existingSlackMapping.pending_marketing_opt_in, |
| 305 | }); |
| 306 | // Clear the pending flag now that it's been processed |
no test coverage detected