( input: SendInvitationEmailInput )
| 183 | } |
| 184 | |
| 185 | export async function sendInvitationEmail( |
| 186 | input: SendInvitationEmailInput |
| 187 | ): Promise<SendInvitationEmailResult> { |
| 188 | const inviteUrl = `${getBaseUrl()}/invite/${input.invitationId}?token=${input.token}` |
| 189 | |
| 190 | if (input.kind === 'workspace') { |
| 191 | if (input.grants.length === 0) { |
| 192 | return { success: false, error: 'Workspace invitation is missing a workspace grant' } |
| 193 | } |
| 194 | |
| 195 | const grantWorkspaceIds = input.grants.map((grant) => grant.workspaceId) |
| 196 | const workspaceRows = await db |
| 197 | .select({ id: workspace.id, name: workspace.name }) |
| 198 | .from(workspace) |
| 199 | .where(inArray(workspace.id, grantWorkspaceIds)) |
| 200 | const workspaceNames = grantWorkspaceIds.map( |
| 201 | (id) => workspaceRows.find((row) => row.id === id)?.name || 'a workspace' |
| 202 | ) |
| 203 | |
| 204 | const emailHtml = await renderWorkspaceInvitationEmail( |
| 205 | input.inviterName, |
| 206 | workspaceNames, |
| 207 | inviteUrl |
| 208 | ) |
| 209 | |
| 210 | const brandName = getBrandConfig().name |
| 211 | const subject = |
| 212 | workspaceNames.length === 1 |
| 213 | ? `You've been invited to join "${workspaceNames[0]}" on ${brandName}` |
| 214 | : `You've been invited to join ${workspaceNames.length} workspaces on ${brandName}` |
| 215 | |
| 216 | const result = await sendEmail({ |
| 217 | to: input.email, |
| 218 | subject, |
| 219 | html: emailHtml, |
| 220 | from: getFromEmailAddress(), |
| 221 | emailType: 'transactional', |
| 222 | }) |
| 223 | if (!result.success) { |
| 224 | return { success: false, error: result.message } |
| 225 | } |
| 226 | return { success: true } |
| 227 | } |
| 228 | |
| 229 | if (!input.organizationId) { |
| 230 | return { success: false, error: 'Organization invitation missing organization id' } |
| 231 | } |
| 232 | |
| 233 | const [orgRow] = await db |
| 234 | .select({ name: organization.name }) |
| 235 | .from(organization) |
| 236 | .where(eq(organization.id, input.organizationId)) |
| 237 | .limit(1) |
| 238 | const organizationName = orgRow?.name || 'organization' |
| 239 | |
| 240 | if (input.grants.length > 0) { |
| 241 | const workspaceIds = input.grants.map((grant) => grant.workspaceId) |
| 242 | const workspaceRows = await db |
no test coverage detected