(params: AddMemberParams)
| 707 | * - Usage limit sync |
| 708 | */ |
| 709 | export async function addUserToOrganization(params: AddMemberParams): Promise<AddMemberResult> { |
| 710 | const { |
| 711 | userId, |
| 712 | organizationId, |
| 713 | role, |
| 714 | skipBillingLogic = false, |
| 715 | skipSeatValidation = false, |
| 716 | acceptingInvitationId, |
| 717 | } = params |
| 718 | |
| 719 | const billingActions: AddMemberResult['billingActions'] = { |
| 720 | proUsageSnapshotted: false, |
| 721 | proCancelledAtPeriodEnd: false, |
| 722 | } |
| 723 | |
| 724 | try { |
| 725 | if (!skipSeatValidation) { |
| 726 | const validation = await validateMembershipAddition(userId, organizationId, { |
| 727 | acceptingInvitationId, |
| 728 | }) |
| 729 | if (!validation.canAdd) { |
| 730 | return { |
| 731 | success: false, |
| 732 | error: validation.reason, |
| 733 | failureCode: validation.failureCode, |
| 734 | billingActions, |
| 735 | } |
| 736 | } |
| 737 | } else { |
| 738 | const existingMemberships = await db |
| 739 | .select({ organizationId: member.organizationId }) |
| 740 | .from(member) |
| 741 | .where(eq(member.userId, userId)) |
| 742 | |
| 743 | if (existingMemberships.length > 0) { |
| 744 | const isAlreadyMemberOfThisOrg = existingMemberships.some( |
| 745 | (m) => m.organizationId === organizationId |
| 746 | ) |
| 747 | |
| 748 | if (isAlreadyMemberOfThisOrg) { |
| 749 | return { |
| 750 | success: false, |
| 751 | error: 'User is already a member of this organization', |
| 752 | failureCode: 'already-member', |
| 753 | billingActions, |
| 754 | } |
| 755 | } |
| 756 | |
| 757 | return { |
| 758 | success: false, |
| 759 | error: |
| 760 | 'User is already a member of another organization. Users can only belong to one organization at a time.', |
| 761 | failureCode: 'already-in-other-organization', |
| 762 | billingActions, |
| 763 | } |
| 764 | } |
| 765 | } |
| 766 |
no test coverage detected