()
| 66 | * Returns a router for API routes (/api/organizations/*) |
| 67 | */ |
| 68 | export function createOrganizationsRouter(): Router { |
| 69 | const router = Router(); |
| 70 | |
| 71 | // ========================================================================= |
| 72 | // ORGANIZATION SEARCH & DISCOVERY |
| 73 | // ========================================================================= |
| 74 | |
| 75 | // GET /api/organizations/search - Search for organizations by name |
| 76 | // Used in the "find your company" feature during onboarding |
| 77 | router.get('/search', requireAuth, async (req, res) => { |
| 78 | try { |
| 79 | const user = req.user!; |
| 80 | const query = (req.query.q as string) || ''; |
| 81 | |
| 82 | if (!query || query.trim().length < 2) { |
| 83 | return res.json({ organizations: [], user_domain: getCompanyDomain(user.email) }); |
| 84 | } |
| 85 | |
| 86 | const joinRequestDb = new JoinRequestDatabase(); |
| 87 | |
| 88 | // Get user's current org memberships to exclude |
| 89 | const userMemberships = await workos!.userManagement.listOrganizationMemberships({ |
| 90 | userId: user.id, |
| 91 | }); |
| 92 | const userOrgIds = userMemberships.data.map(m => m.organizationId); |
| 93 | |
| 94 | // Get user's pending join requests |
| 95 | const pendingRequests = await joinRequestDb.getUserPendingRequests(user.id); |
| 96 | const pendingOrgIds = new Set(pendingRequests.map(r => r.workos_organization_id)); |
| 97 | |
| 98 | // Search organizations |
| 99 | const results = await orgDb.searchOrganizations({ |
| 100 | query: query.trim(), |
| 101 | excludeOrgIds: userOrgIds, |
| 102 | limit: 10, |
| 103 | }); |
| 104 | |
| 105 | // Get admin contact info for each org (masked) |
| 106 | const orgsWithAdmins = await Promise.all( |
| 107 | results.map(async (org) => { |
| 108 | let adminContact: string | null = null; |
| 109 | try { |
| 110 | const memberships = await workos!.userManagement.listOrganizationMemberships({ |
| 111 | organizationId: org.workos_organization_id, |
| 112 | }); |
| 113 | |
| 114 | // Find an admin or owner |
| 115 | const adminMembership = memberships.data.find(m => { |
| 116 | const role = m.role?.slug || 'member'; |
| 117 | return role === 'admin' || role === 'owner'; |
| 118 | }); |
| 119 | |
| 120 | if (adminMembership) { |
| 121 | const adminUser = await workos!.userManagement.getUser(adminMembership.userId); |
| 122 | // Mask the email: "j***@company.com" |
| 123 | const email = adminUser.email; |
| 124 | const [local, domain] = email.split('@'); |
| 125 | adminContact = `${local[0]}***@${domain}`; |
no test coverage detected