* add endpoint to fetch managed user from client id * update typings * minor tweaks * custom hook to fetch managed users from client id * add translations for platform onboarding * add isPlatformOrg boolean to figure out which is platform and which is not * set isPlatform hook based on data obtained from org * add limitWidth prop to control component width * add props to shell to make sidebar display different tabs based on if the shell isPlattform or not * platform related pages * fix merge conflicts * fix merge conflicts * platform oauth client form and card * remove everything related to platform from organization * update oauth client card and form * fixup * fix imports and remove logs * fixup * update redirect url * split oauth client form into separate update and create forms * separate forms for create and edit oauth clients * fixup * fixup * dynamic routes for oauth client edit page * fixup fixup * fix to not show error when redirect uri is empty * refactor create handler for org * cleaup comments * add custom hook to check user billing * export managed user type * refactor platform index page * refactor edit and create pages * dashboard component containing oauth client list and managed user * common oauth client form used for create and edit form * platform pricing helper * platform pricing component * fix typing and data response for billing * use custom hook to check team billing info * fix type checks * upgrade conditional rendering for upgrade to org banner * add isLoading prop to check button loading state * pass in button handler * add custom hook to subscribe to stripe and typings * update typings * fix incorrect endpoint * pass in team id as prop * fix type check * update stripe success and cancel redirect url * add and pass redirect url param to custom hook * custom hooks for platform * cleanup * update imports * fix merge conflicts * fixup * fixup fixup * fixup * merge conflicts fixup * merge conlficts battle :( * minor fixes * skip admin checks for a platform client * fix typo * append slug with _platform for a platform user * PR feedback * dashboard refactor * bring back org form to its orginal state * add platform folder to ee * update typings * use new create platform form * fixup * fix typo and update plans * simplifying rendering * remove managed users endpoint since it already exists * url for endpoint * rename tabs * pr feedback * managed users endpoint * update endpoint * remove form --------- Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: exception <erik@erosemberg.com> Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com>
162 lines
4.2 KiB
TypeScript
162 lines
4.2 KiB
TypeScript
import { getOrgUsernameFromEmail } from "@calcom/features/auth/signup/utils/getOrgUsernameFromEmail";
|
|
import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
|
|
import logger from "@calcom/lib/logger";
|
|
import { safeStringify } from "@calcom/lib/safeStringify";
|
|
import { prisma } from "@calcom/prisma";
|
|
import { MembershipRole } from "@calcom/prisma/enums";
|
|
|
|
import { createAProfileForAnExistingUser } from "../../createAProfileForAnExistingUser";
|
|
import { UserRepository } from "./user";
|
|
|
|
const orgSelect = {
|
|
id: true,
|
|
name: true,
|
|
slug: true,
|
|
logoUrl: true,
|
|
};
|
|
export class OrganizationRepository {
|
|
static async createWithExistingUserAsOwner({
|
|
orgData,
|
|
owner,
|
|
}: {
|
|
orgData: {
|
|
name: string;
|
|
slug: string;
|
|
isOrganizationConfigured: boolean;
|
|
isOrganizationAdminReviewed: boolean;
|
|
autoAcceptEmail: string;
|
|
seats: number | null;
|
|
pricePerSeat: number | null;
|
|
isPlatform: boolean;
|
|
};
|
|
owner: {
|
|
id: number;
|
|
email: string;
|
|
nonOrgUsername: string;
|
|
};
|
|
}) {
|
|
logger.debug("createWithExistingUserAsOwner", safeStringify({ orgData, owner }));
|
|
const organization = await this.create(orgData);
|
|
const ownerProfile = await createAProfileForAnExistingUser({
|
|
user: {
|
|
id: owner.id,
|
|
email: owner.email,
|
|
currentUsername: owner.nonOrgUsername,
|
|
},
|
|
organizationId: organization.id,
|
|
});
|
|
|
|
await prisma.membership.create({
|
|
data: {
|
|
userId: owner.id,
|
|
role: MembershipRole.OWNER,
|
|
accepted: true,
|
|
teamId: organization.id,
|
|
},
|
|
});
|
|
return { organization, ownerProfile };
|
|
}
|
|
|
|
static async createWithNonExistentOwner({
|
|
orgData,
|
|
owner,
|
|
}: {
|
|
orgData: {
|
|
name: string;
|
|
slug: string;
|
|
isOrganizationConfigured: boolean;
|
|
isOrganizationAdminReviewed: boolean;
|
|
autoAcceptEmail: string;
|
|
seats: number | null;
|
|
pricePerSeat: number | null;
|
|
isPlatform: boolean;
|
|
};
|
|
owner: {
|
|
email: string;
|
|
};
|
|
}) {
|
|
logger.debug("createWithNonExistentOwner", safeStringify({ orgData, owner }));
|
|
const organization = await this.create(orgData);
|
|
const ownerUsernameInOrg = getOrgUsernameFromEmail(owner.email, orgData.autoAcceptEmail);
|
|
const ownerInDb = await UserRepository.create({
|
|
email: owner.email,
|
|
username: ownerUsernameInOrg,
|
|
organizationId: organization.id,
|
|
});
|
|
|
|
await prisma.membership.create({
|
|
data: {
|
|
userId: ownerInDb.id,
|
|
role: MembershipRole.OWNER,
|
|
accepted: true,
|
|
teamId: organization.id,
|
|
},
|
|
});
|
|
|
|
return {
|
|
orgOwner: ownerInDb,
|
|
organization,
|
|
ownerProfile: {
|
|
username: ownerUsernameInOrg,
|
|
},
|
|
};
|
|
}
|
|
|
|
static async create(orgData: {
|
|
name: string;
|
|
slug: string;
|
|
isOrganizationConfigured: boolean;
|
|
isOrganizationAdminReviewed: boolean;
|
|
autoAcceptEmail: string;
|
|
seats: number | null;
|
|
pricePerSeat: number | null;
|
|
isPlatform: boolean;
|
|
}) {
|
|
return await prisma.team.create({
|
|
data: {
|
|
name: orgData.name,
|
|
isOrganization: true,
|
|
...(!IS_TEAM_BILLING_ENABLED ? { slug: orgData.slug } : {}),
|
|
organizationSettings: {
|
|
create: {
|
|
isAdminReviewed: orgData.isOrganizationAdminReviewed,
|
|
isOrganizationVerified: true,
|
|
isOrganizationConfigured: orgData.isOrganizationConfigured,
|
|
orgAutoAcceptEmail: orgData.autoAcceptEmail,
|
|
},
|
|
},
|
|
metadata: {
|
|
...(IS_TEAM_BILLING_ENABLED ? { requestedSlug: orgData.slug } : {}),
|
|
orgSeats: orgData.seats,
|
|
orgPricePerSeat: orgData.pricePerSeat,
|
|
isPlatform: orgData.isPlatform,
|
|
},
|
|
isPlatform: orgData.isPlatform,
|
|
},
|
|
});
|
|
}
|
|
|
|
static async findById({ id }: { id: number }) {
|
|
return prisma.team.findUnique({
|
|
where: {
|
|
id,
|
|
isOrganization: true,
|
|
},
|
|
select: orgSelect,
|
|
});
|
|
}
|
|
|
|
static async findByIdIncludeOrganizationSettings({ id }: { id: number }) {
|
|
return prisma.team.findUnique({
|
|
where: {
|
|
id,
|
|
isOrganization: true,
|
|
},
|
|
select: {
|
|
...orgSelect,
|
|
organizationSettings: true,
|
|
},
|
|
});
|
|
}
|
|
}
|