(input: Record<string, unknown>)
| 1990 | |
| 1991 | // Shared handler for get_account and get_organization_details |
| 1992 | const getAccountHandler = async (input: Record<string, unknown>) => { |
| 1993 | |
| 1994 | const pool = getPool(); |
| 1995 | const query = input.query as string; |
| 1996 | // Escape LIKE wildcards in the user-supplied query so a literal `%` or `_` |
| 1997 | // doesn't fan out to every org or signup. Equality comparison ($2) doesn't |
| 1998 | // need it; prefix and substring comparisons do. |
| 1999 | const escapedQuery = query.replace(/[\\%_]/g, '\\$&'); |
| 2000 | const searchPattern = `%${escapedQuery}%`; |
| 2001 | |
| 2002 | try { |
| 2003 | // Find organizations by name or domain - get up to 5 matches |
| 2004 | const result = await pool.query( |
| 2005 | `SELECT o.*, |
| 2006 | p.name as parent_name |
| 2007 | FROM organizations o |
| 2008 | LEFT JOIN brands db_parent ON o.email_domain = db_parent.domain |
| 2009 | LEFT JOIN organizations p ON db_parent.house_domain = p.email_domain |
| 2010 | WHERE o.is_personal = false |
| 2011 | AND (LOWER(o.name) LIKE LOWER($1) ESCAPE '\\' OR LOWER(o.email_domain) LIKE LOWER($1) ESCAPE '\\') |
| 2012 | ORDER BY |
| 2013 | CASE WHEN LOWER(o.name) = LOWER($2) THEN 0 |
| 2014 | WHEN LOWER(o.name) LIKE LOWER($3) ESCAPE '\\' THEN 1 |
| 2015 | ELSE 2 END, |
| 2016 | o.updated_at DESC |
| 2017 | LIMIT 5`, |
| 2018 | [searchPattern, query, `${escapedQuery}%`] |
| 2019 | ); |
| 2020 | |
| 2021 | if (result.rows.length === 0) { |
| 2022 | // Fall back to the users table — inbound website signups don't create |
| 2023 | // an org row (the user self-serves during onboarding), so the only |
| 2024 | // record of "someone from this company signed up" lives in `users`. |
| 2025 | // Domain anchor: pattern is `%@<query>%` so "diageo" matches @diageo.com |
| 2026 | // and @diageo.co.uk but NOT @nondiageo.com — query must immediately |
| 2027 | // follow `@`. `escapedQuery` (declared above) neutralizes LIKE |
| 2028 | // wildcards so a literal `%` doesn't fan out to every signup. |
| 2029 | const usersResult = await pool.query( |
| 2030 | `SELECT u.workos_user_id, u.email, u.first_name, u.last_name, |
| 2031 | u.created_at, u.primary_organization_id, o.name AS primary_org_name |
| 2032 | FROM users u |
| 2033 | LEFT JOIN organizations o ON o.workos_organization_id = u.primary_organization_id |
| 2034 | WHERE LOWER(u.email) LIKE LOWER($1) ESCAPE '\\' |
| 2035 | ORDER BY u.created_at DESC |
| 2036 | LIMIT 10`, |
| 2037 | [`%@${escapedQuery}%`] |
| 2038 | ); |
| 2039 | |
| 2040 | if (usersResult.rows.length === 0) { |
| 2041 | return `No organization found matching "${query}". Try searching by company name or domain.`; |
| 2042 | } |
| 2043 | |
| 2044 | const orphans = usersResult.rows.filter(u => !u.primary_organization_id); |
| 2045 | const linked = usersResult.rows.filter(u => u.primary_organization_id); |
| 2046 | |
| 2047 | let response = `No organization found matching "${query}", but ${usersResult.rows.length} user${usersResult.rows.length === 1 ? '' : 's'} signed up with a matching email domain.\n\n`; |
| 2048 | |
| 2049 | if (orphans.length > 0) { |
nothing calls this directly
no test coverage detected