Files
calendar/packages/trpc/server/routers/viewer/teams/resendInvitation.handler.ts
Benny JooGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
96bec9f7b9 refactor: Move repositories from @calcom/lib to @calcom/features domain folders (#27570)
* refactor: move repositories from lib to features domain folders

- Move HolidayRepository to features/holidays/repositories
- Move PrismaTrackingRepository to features/bookings/repositories
- Move PrismaBookingPaymentRepository to features/bookings/repositories
- Move PrismaRoutingFormResponseRepository to features/routing-forms/repositories
- Move PrismaAssignmentReasonRepository to features/assignment-reason/repositories
- Move VerificationTokenRepository to features/auth/repositories
- Move WorkspacePlatformRepository to features/workspace-platform/repositories
- Move DTO files to their respective feature domains
- Merge lib DestinationCalendarRepository into features version
- Merge lib SelectedCalendarRepository into features version
- Update all import paths across the codebase

This follows the vertical slice architecture pattern by organizing
repositories by domain rather than by technical layer.

Co-Authored-By: [email protected] <[email protected]>

* fix: update VerificationTokenService import path to new location

Co-Authored-By: [email protected] <[email protected]>

* fix: update test file imports to use new repository locations

Co-Authored-By: [email protected] <[email protected]>

* mv

* fix structure

* fix

* refactor: merge unit tests for SelectedCalendarRepository into single file

Co-Authored-By: [email protected] <[email protected]>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-02-09 08:41:04 -03:00

85 lines
3.1 KiB
TypeScript

import { sendTeamInviteEmail } from "@calcom/emails/organization-email-service";
import { OnboardingPathService } from "@calcom/features/onboarding/lib/onboarding-path.service";
import { UserRepository } from "@calcom/features/users/repositories/UserRepository";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { getTranslation } from "@calcom/lib/server/i18n";
import { VerificationTokenRepository } from "@calcom/app-store/stripepayment/lib/repositories/VerificationTokenRepository";
import { prisma } from "@calcom/prisma";
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { ensureAtleastAdminPermissions, getTeamOrThrow } from "./inviteMember/utils";
import type { TResendInvitationInputSchema } from "./resendInvitation.schema";
type InviteMemberOptions = {
ctx: {
user: NonNullable<TrpcSessionUser>;
};
input: TResendInvitationInputSchema;
};
export const resendInvitationHandler = async ({ ctx, input }: InviteMemberOptions) => {
const team = await getTeamOrThrow(input.teamId);
await ensureAtleastAdminPermissions({
userId: ctx.user.id,
teamId:
ctx.user.organization.id && ctx.user.organization.isOrgAdmin ? ctx.user.organization.id : input.teamId,
isOrg: input.isOrg,
});
let verificationToken:
| Awaited<ReturnType<typeof VerificationTokenRepository.updateTeamInviteTokenExpirationDate>>
| undefined;
try {
verificationToken = await VerificationTokenRepository.updateTeamInviteTokenExpirationDate({
email: input.email,
teamId: input.teamId,
expiresInDays: 7,
});
} catch (error) {
console.error("[resendInvitationHandler] Error updating verification token: ", error);
}
const inviteTeamOptions = {
joinLink: `${WEBAPP_URL}/auth/login?callbackUrl=/settings/teams`,
isCalcomMember: true,
isAutoJoin: false,
};
if (verificationToken) {
try {
const user = await new UserRepository(prisma).findByEmail({ email: input.email });
if (user?.completedOnboarding) {
inviteTeamOptions.joinLink = `${WEBAPP_URL}/teams?token=${verificationToken.token}&autoAccept=true`;
} else {
const gettingStartedPath = await OnboardingPathService.getGettingStartedPathWhenInvited();
inviteTeamOptions.joinLink = `${WEBAPP_URL}/signup?token=${verificationToken.token}&callbackUrl=${gettingStartedPath}`;
inviteTeamOptions.isCalcomMember = false;
}
} catch (error) {
console.error("[resendInvitationHandler] Error fetching user: ", error);
}
}
const translation = await getTranslation(input.language ?? "en", "common");
await sendTeamInviteEmail({
language: translation,
from: ctx.user.name || `${team.name}'s admin`,
to: input.email,
teamName: team.name,
...inviteTeamOptions,
isOrg: input.isOrg,
parentTeamName: team?.parent?.name,
// We don't know at his moment if this user was an existing user or a new user as it is a resend. So, we assume it's a new user and we can avoid sending the prevLink and newLink.
isExistingUserMovedToOrg: false,
prevLink: null,
newLink: null,
});
return input;
};
export default resendInvitationHandler;