Merge branch 'main' into integromat-app

This commit is contained in:
Carina Wollendorfer 2023-07-03 09:26:02 -04:00 committed by GitHub
commit f5911d8995
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 122 additions and 138 deletions

View File

@ -2,7 +2,7 @@ import { useRouter } from "next/router";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { subdomainSuffix } from "@calcom/features/ee/organizations/lib/orgDomains";
import { getOrgFullDomain } from "@calcom/features/ee/organizations/lib/orgDomains";
import { IS_SELF_HOSTED } from "@calcom/lib/constants";
import type { TRPCClientErrorLike } from "@calcom/trpc/client";
import type { RouterOutputs } from "@calcom/trpc/react";
@ -24,9 +24,9 @@ interface UsernameAvailabilityFieldProps {
function useUserNamePrefix(organization: RouterOutputs["viewer"]["me"]["organization"]): string {
return organization
? organization.slug
? `${organization.slug}.${subdomainSuffix()}/`
? getOrgFullDomain(organization.slug, { protocol: false })
: organization.metadata && organization.metadata.requestedSlug
? `${organization.metadata.requestedSlug}.${subdomainSuffix()}/`
? getOrgFullDomain(organization.metadata.requestedSlug, { protocol: false })
: process.env.NEXT_PUBLIC_WEBSITE_URL.replace("https://", "").replace("http://", "")
: process.env.NEXT_PUBLIC_WEBSITE_URL.replace("https://", "").replace("http://", "");
}

View File

@ -8,7 +8,6 @@ import { useEffect, useState, memo } from "react";
import { z } from "zod";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { subdomainSuffix } from "@calcom/features/ee/organizations/lib/orgDomains";
import useIntercom from "@calcom/features/ee/support/lib/intercom/useIntercom";
import { EventTypeDescriptionLazy as EventTypeDescription } from "@calcom/features/eventtypes/components";
import CreateEventTypeDialog from "@calcom/features/eventtypes/components/CreateEventTypeDialog";
@ -371,9 +370,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<ul ref={parent} className="divide-subtle !static w-full divide-y" data-testid="event-types">
{types.map((type, index) => {
const embedLink = `${group.profile.slug}/${type.slug}`;
const calLink = `${
orgBranding ? `${new URL(CAL_URL).protocol}//${orgBranding.slug}.${subdomainSuffix()}` : CAL_URL
}/${embedLink}`;
const calLink = `${orgBranding?.fullDomain ?? CAL_URL}/${embedLink}`;
const isManagedEventType = type.schedulingType === SchedulingType.MANAGED;
const isChildrenManagedEventType =
type.metadata?.managedEventConfig !== undefined && type.schedulingType !== SchedulingType.MANAGED;
@ -698,10 +695,10 @@ const EventTypeListHeading = ({
profile,
membershipCount,
teamId,
orgSlug,
}: EventTypeListHeadingProps): JSX.Element => {
const { t } = useLocale();
const router = useRouter();
const orgBranding = useOrgBrandingValues();
const publishTeamMutation = trpc.viewer.teams.publish.useMutation({
onSuccess(data) {
@ -739,9 +736,9 @@ const EventTypeListHeading = ({
)}
{profile?.slug && (
<Link href={`${CAL_URL}/${profile.slug}`} className="text-subtle block text-xs">
{orgSlug
? `${orgSlug}.${subdomainSuffix()}/${profile.slug}`
: `${CAL_URL?.replace("https://", "")}/${profile.slug}`}
{orgBranding
? `${orgBranding.fullDomain.replace("https://", "").replace("http://", "")}${profile.slug}`
: `${CAL_URL?.replace("https://", "").replace("http://", "")}/${profile.slug}`}
</Link>
)}
</div>

View File

@ -93,16 +93,18 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) {
}
async function getUserPageProps(context: GetServerSidePropsContext) {
const { user: username, type: slug } = paramsSchema.parse(context.params);
const { user: uname, type: slug } = paramsSchema.parse(context.params);
const { rescheduleUid } = context.query;
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req.headers.host ?? "");
/** TODO: We should standarize this */
const username = uname.toLowerCase().replace(/( |%20)/g, "+");
const { ssrInit } = await import("@server/lib/ssr");
const ssr = await ssrInit(context);
const user = await prisma.user.findFirst({
where: {
/** TODO: We should standarize this */
username: username.toLowerCase().replace(/( |%20)/g, "+"),
username,
organization: isValidOrgDomain
? {
slug: currentOrgDomain,

View File

@ -8,12 +8,14 @@ import { z } from "zod";
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
import { checkPremiumUsername } from "@calcom/features/ee/common/lib/checkPremiumUsername";
import { getOrgFullDomain } from "@calcom/features/ee/organizations/lib/orgDomains";
import { isSAMLLoginEnabled } from "@calcom/features/ee/sso/lib/saml";
import { useFlagMap } from "@calcom/features/flags/context/provider";
import { getFeatureFlagMap } from "@calcom/features/flags/server/utils";
import { IS_SELF_HOSTED, WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import type { inferSSRProps } from "@calcom/types/inferSSRProps";
import { Alert, Button, EmailField, HeadSeo, PasswordField, TextField } from "@calcom/ui";
@ -30,7 +32,9 @@ type FormValues = {
token?: string;
};
export default function Signup({ prepopulateFormValues, token }: inferSSRProps<typeof getServerSideProps>) {
type SignupProps = inferSSRProps<typeof getServerSideProps>;
export default function Signup({ prepopulateFormValues, token, orgSlug }: SignupProps) {
const { t, i18n } = useLocale();
const router = useRouter();
const flags = useFlagMap();
@ -116,7 +120,11 @@ export default function Signup({ prepopulateFormValues, token }: inferSSRProps<t
{errors.apiError && <Alert severity="error" message={errors.apiError?.message} />}
<div className="space-y-4">
<TextField
addOnLeading={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/`}
addOnLeading={
orgSlug
? getOrgFullDomain(orgSlug, { protocol: false })
: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/`
}
{...register("username")}
required
/>
@ -233,6 +241,22 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
let username = guessUsernameFromEmail(verificationToken.identifier);
const orgInfo = await prisma.user.findFirst({
where: {
email: verificationToken?.identifier,
},
select: {
organization: {
select: {
slug: true,
metadata: true,
},
},
},
});
const userOrgMetadata = teamMetadataSchema.parse(orgInfo?.organization?.metadata ?? {});
if (!IS_SELF_HOSTED) {
// Im not sure we actually hit this because of next redirects signup to website repo - but just in case this is pretty cool :)
const { available, suggestion } = await checkPremiumUsername(username);
@ -248,6 +272,7 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
email: verificationToken.identifier,
username,
},
orgSlug: (orgInfo?.organization?.slug || userOrgMetadata?.requestedSlug) ?? null,
},
};
};

View File

@ -65,6 +65,7 @@ export const AboutOrganizationForm = () => {
fallback={<Plus className="text-subtle h-6 w-6" />}
asChild
className="items-center"
imageSrc={image}
size="lg"
/>
<div className="ms-4">

View File

@ -12,7 +12,9 @@ export type OrganizationBranding =
| ({
logo?: string | null | undefined;
name?: string;
slug?: string;
slug: string;
fullDomain: string;
domainSuffix: string;
} & z.infer<typeof teamMetadataSchema>)
| null
| undefined;

View File

@ -4,7 +4,7 @@ import { ALLOWED_HOSTNAMES, RESERVED_SUBDOMAINS, WEBAPP_URL } from "@calcom/lib/
* return the org slug
* @param hostname
*/
export function getOrgDomain(hostname: string) {
export function getOrgSlug(hostname: string) {
// Find which hostname is being currently used
const currentHostname = ALLOWED_HOSTNAMES.find((ahn) => {
const url = new URL(WEBAPP_URL);
@ -20,7 +20,7 @@ export function getOrgDomain(hostname: string) {
}
export function orgDomainConfig(hostname: string) {
const currentOrgDomain = getOrgDomain(hostname);
const currentOrgDomain = getOrgSlug(hostname);
return {
currentOrgDomain,
isValidOrgDomain: currentOrgDomain !== null && !RESERVED_SUBDOMAINS.includes(currentOrgDomain),
@ -31,3 +31,7 @@ export function subdomainSuffix() {
const urlSplit = WEBAPP_URL.replace("https://", "")?.replace("http://", "").split(".");
return urlSplit.length === 3 ? urlSplit.slice(1).join(".") : urlSplit.join(".");
}
export function getOrgFullDomain(slug: string, options: { protocol: boolean } = { protocol: true }) {
return `${options.protocol ? `${new URL(WEBAPP_URL).protocol}//` : ""}${slug}.${subdomainSuffix()}/`;
}

View File

@ -1,7 +1,6 @@
import { useRouter } from "next/router";
import { Controller, useForm } from "react-hook-form";
import { APP_NAME } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { MembershipRole } from "@calcom/prisma/enums";
import { trpc } from "@calcom/trpc/react";
@ -14,7 +13,6 @@ import {
SkeletonButton,
SkeletonContainer,
SkeletonText,
Switch,
} from "@calcom/ui";
import ThemeLabel from "../../../../settings/ThemeLabel";
@ -170,59 +168,6 @@ const OrgAppearanceView = () => {
)}
/>
</div>
<hr className="border-subtle my-8" />
<div className="flex flex-col gap-8">
<div className="relative flex items-start">
<div className="flex-grow text-sm">
<label htmlFor="hide-branding" className="text-default font-medium">
{t("disable_cal_branding", { appName: APP_NAME })}
</label>
<p className="text-subtle">
{t("team_disable_cal_branding_description", { appName: APP_NAME })}
</p>
</div>
<div className="flex-none">
<Controller
control={form.control}
defaultValue={currentOrg?.hideBranding ?? false}
name="hideBranding"
render={({ field }) => (
<Switch
defaultChecked={field.value}
onCheckedChange={(isChecked) => {
form.setValue("hideBranding", isChecked);
}}
/>
)}
/>
</div>
</div>
<div className="relative flex items-start">
<div className="flex-grow text-sm">
<label htmlFor="hide-branding" className="text-default font-medium">
{t("hide_book_a_team_member")}
</label>
<p className="text-subtle">{t("hide_book_a_team_member_description")}</p>
</div>
<div className="flex-none">
<Controller
control={form.control}
defaultValue={currentOrg?.hideBookATeamMember ?? false}
name="hideBookATeamMember"
render={({ field }) => (
<Switch
defaultChecked={field.value}
onCheckedChange={(isChecked) => {
form.setValue("hideBookATeamMember", isChecked);
}}
/>
)}
/>
</div>
</div>
</div>
<Button color="primary" className="mt-8" type="submit" loading={mutation.isLoading}>
{t("update")}
</Button>

View File

@ -1,7 +1,6 @@
import { zodResolver } from "@hookform/resolvers/zod";
import type { Prisma } from "@prisma/client";
import { LinkIcon, Trash2 } from "lucide-react";
import { useSession } from "next-auth/react";
import { useRouter } from "next/router";
import { useState, useLayoutEffect } from "react";
import { Controller, useForm } from "react-hook-form";
@ -34,8 +33,6 @@ import {
import { getLayout } from "../../../../settings/layouts/SettingsLayout";
const regex = new RegExp("^[a-zA-Z0-9-]*$");
const orgProfileFormSchema = z.object({
name: z.string(),
logo: z.string(),
@ -46,7 +43,6 @@ const OrgProfileView = () => {
const { t } = useLocale();
const router = useRouter();
const utils = trpc.useContext();
const session = useSession();
const [firstRender, setFirstRender] = useState(true);
const orgBranding = useOrgBrandingValues();
@ -54,6 +50,10 @@ const OrgProfileView = () => {
document.body.focus();
}, []);
const form = useForm({
resolver: zodResolver(orgProfileFormSchema),
});
const mutation = trpc.viewer.organizations.update.useMutation({
onError: (err) => {
showToast(err.message, "error");
@ -64,10 +64,6 @@ const OrgProfileView = () => {
},
});
const form = useForm({
resolver: zodResolver(orgProfileFormSchema),
});
const { data: currentOrganisation, isLoading } = trpc.viewer.organizations.listCurrent.useQuery(undefined, {
onError: () => {
router.push("/settings");
@ -90,10 +86,6 @@ const OrgProfileView = () => {
(currentOrganisation.user.role === MembershipRole.OWNER ||
currentOrganisation.user.role === MembershipRole.ADMIN);
const permalink = `${new URL(process.env.NEXT_PUBLIC_WEBSITE_URL || "").protocol}//${
orgBranding?.slug
}.${subdomainSuffix()}`;
const isBioEmpty =
!currentOrganisation ||
!currentOrganisation.bio ||
@ -107,6 +99,8 @@ const OrgProfileView = () => {
},
});
if (!orgBranding) return null;
function deleteTeam() {
if (currentOrganisation?.id) deleteTeamMutation.mutate({ teamId: currentOrganisation.id });
}
@ -222,7 +216,7 @@ const OrgProfileView = () => {
<LinkIconButton
Icon={LinkIcon}
onClick={() => {
navigator.clipboard.writeText(permalink);
navigator.clipboard.writeText(orgBranding.fullDomain);
showToast("Copied to clipboard", "success");
}}>
{t("copy_link_org")}

View File

@ -4,13 +4,14 @@ import { Controller, useForm } from "react-hook-form";
import { z } from "zod";
import { extractDomainFromWebsiteUrl } from "@calcom/ee/organizations/lib/utils";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import slugify from "@calcom/lib/slugify";
import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { trpc } from "@calcom/trpc/react";
import { Avatar, Button, Form, ImageUploader, TextField, Alert } from "@calcom/ui";
import { ArrowRight } from "@calcom/ui/components/icon";
import { Avatar, Button, Form, ImageUploader, TextField, Alert, Label } from "@calcom/ui";
import { ArrowRight, Plus } from "@calcom/ui/components/icon";
import type { NewTeamFormValues } from "../lib/types";
@ -26,6 +27,7 @@ export const CreateANewTeamForm = () => {
const parsedQuery = querySchema.safeParse(router.query);
console.log({ parsedQuery });
const [serverErrorMessage, setServerErrorMessage] = useState<string | null>(null);
const orgBranding = useOrgBrandingValues();
const returnToParam =
(parsedQuery.success ? getSafeRedirectUrl(parsedQuery.data.returnTo) : "/settings/teams") ||
@ -107,7 +109,10 @@ export const CreateANewTeamForm = () => {
name="slug"
placeholder="acme"
label={t("team_url")}
addOnLeading={`${extractDomainFromWebsiteUrl}/team/`}
addOnLeading={`${
orgBranding?.fullDomain.replace("https://", "").replace("http://", "") ??
`${extractDomainFromWebsiteUrl}/team/`
}`}
defaultValue={value}
onChange={(e) => {
newTeamFormMethods.setValue("slug", slugify(e?.target.value), {
@ -125,21 +130,29 @@ export const CreateANewTeamForm = () => {
control={newTeamFormMethods.control}
name="logo"
render={({ field: { value } }) => (
<div className="flex items-center">
<Avatar alt="" imageSrc={value || null} gravatarFallbackMd5="newTeam" size="lg" />
<div className="ms-4">
<ImageUploader
target="avatar"
id="avatar-upload"
buttonMsg={t("update")}
handleAvatarChange={(newAvatar: string) => {
newTeamFormMethods.setValue("logo", newAvatar);
createTeamMutation.reset();
}}
<>
<Label>{t("team_logo")}</Label>
<div className="flex items-center">
<Avatar
alt=""
imageSrc={value}
fallback={<Plus className="text-subtle h-6 w-6" />}
size="lg"
/>
<div className="ms-4">
<ImageUploader
target="avatar"
id="avatar-upload"
buttonMsg={t("update")}
handleAvatarChange={(newAvatar: string) => {
newTeamFormMethods.setValue("logo", newAvatar);
createTeamMutation.reset();
}}
imageSrc={value}
/>
</div>
</div>
</div>
</>
)}
/>
</div>

View File

@ -5,7 +5,6 @@ import { useState } from "react";
import InviteLinkSettingsModal from "@calcom/ee/teams/components/InviteLinkSettingsModal";
import MemberInvitationModal from "@calcom/ee/teams/components/MemberInvitationModal";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { subdomainSuffix } from "@calcom/features/ee/organizations/lib/orgDomains";
import classNames from "@calcom/lib/classNames";
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@ -104,7 +103,7 @@ export default function TeamListItem(props: Props) {
<span className="text-muted block text-xs">
{team.slug
? orgBranding
? `${orgBranding.slug}.${subdomainSuffix()}/${team.slug}`
? `${orgBranding.fullDomain}${team.slug}`
: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/team/${team.slug}`
: "Unpublished team"}
</span>
@ -235,7 +234,11 @@ export default function TeamListItem(props: Props) {
color="secondary"
onClick={() => {
navigator.clipboard.writeText(
process.env.NEXT_PUBLIC_WEBSITE_URL + "/team/" + team.slug
`${
orgBranding
? `${orgBranding.fullDomain}`
: process.env.NEXT_PUBLIC_WEBSITE_URL + "/team/"
}${team.slug}`
);
showToast(t("link_copied"), "success");
}}
@ -271,7 +274,11 @@ export default function TeamListItem(props: Props) {
<DropdownItem
type="button"
target="_blank"
href={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/team/${team.slug}`}
href={`${
orgBranding
? `${orgBranding.fullDomain}`
: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/team/`
}${team.slug}`}
StartIcon={ExternalLink}>
{t("preview_team") as string}
</DropdownItem>

View File

@ -7,7 +7,6 @@ import { useForm } from "react-hook-form";
import { z } from "zod";
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { subdomainSuffix } from "@calcom/features/ee/organizations/lib/orgDomains";
import { useFlagMap } from "@calcom/features/flags/context/provider";
import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@ -139,9 +138,7 @@ export default function CreateEventTypeDialog({
});
const flags = useFlagMap();
const urlPrefix = orgBranding
? `${orgBranding.slug}.${subdomainSuffix()}`
: process.env.NEXT_PUBLIC_WEBSITE_URL;
const urlPrefix = orgBranding?.fullDomain ?? process.env.NEXT_PUBLIC_WEBSITE_URL;
return (
<Dialog

View File

@ -362,7 +362,7 @@ function UserDropdown({ small }: UserDropdownProps) {
/>
</span>
{!small && (
<span className="flex flex-grow items-center">
<span className="flex flex-grow items-center gap-2">
<span className="line-clamp-1 flex-grow text-sm leading-none">
<span className="text-emphasis block font-medium">{user.name || "Nameless User"}</span>
</span>
@ -778,13 +778,11 @@ type SideBarProps = {
function SideBarContainer({ bannersHeight }: SideBarContainerProps) {
const { status, data } = useSession();
const router = useRouter();
// Make sure that Sidebar is rendered optimistically so that a refresh of pages when logged in have SideBar from the beginning.
// This improves the experience of refresh on app store pages(when logged in) which are SSG.
// Though when logged out, app store pages would temporarily show SideBar until session status is confirmed.
if (status !== "loading" && status !== "authenticated") return null;
if (router.route.startsWith("/v2/settings/")) return null;
return <SideBar bannersHeight={bannersHeight} user={data?.user} />;
}
@ -819,9 +817,7 @@ function SideBar({ bannersHeight, user }: SideBarProps) {
},
{
name: "settings",
href: user?.organizationId
? `/settings/teams/${user.organizationId}/profile`
: "/settings/my-account/profile",
href: user?.organizationId ? `/settings/organizations/profile` : "/settings/my-account/profile",
icon: Settings,
},
];
@ -834,20 +830,16 @@ function SideBar({ bannersHeight, user }: SideBarProps) {
<header className="items-center justify-between md:hidden lg:flex">
{orgBranding ? (
<Link href="/event-types" className="px-1.5">
{orgBranding ? (
<div className="flex items-center gap-2 font-medium">
<Avatar
alt={`${orgBranding.name} logo`}
imageSrc={getPlaceholderAvatar(orgBranding.logo, orgBranding.name)}
size="xsm"
/>
<p className="text line-clamp-1 text-sm">
<span>{orgBranding.name}</span>
</p>
</div>
) : (
<Logo small />
)}
<div className="flex items-center gap-2 font-medium">
<Avatar
alt={`${orgBranding.name} logo`}
imageSrc={getPlaceholderAvatar(orgBranding.logo, orgBranding.name)}
size="xsm"
/>
<p className="text line-clamp-1 text-sm">
<span>{orgBranding.name}</span>
</p>
</div>
</Link>
) : (
<div data-testid="user-dropdown-trigger">

View File

@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import { orgDomainConfig, getOrgDomain } from "@calcom/features/ee/organizations/lib/orgDomains";
import { orgDomainConfig, getOrgSlug } from "@calcom/features/ee/organizations/lib/orgDomains";
import * as constants from "@calcom/lib/constants";
function setupEnvs({ WEBAPP_URL = "https://app.cal.com" } = {}) {
@ -32,25 +32,25 @@ describe("Org Domains Utils", () => {
});
});
describe("getOrgDomain", () => {
describe("getOrgSlug", () => {
it("should handle a prod web app url with a prod subdomain hostname", () => {
setupEnvs();
expect(getOrgDomain("acme.cal.com")).toEqual("acme");
expect(getOrgSlug("acme.cal.com")).toEqual("acme");
});
it("should handle a prod web app url with a staging subdomain hostname", () => {
setupEnvs();
expect(getOrgDomain("acme.cal.dev")).toEqual(null);
expect(getOrgSlug("acme.cal.dev")).toEqual(null);
});
it("should handle a local web app with port url with a local subdomain hostname", () => {
setupEnvs({ WEBAPP_URL: "http://app.cal.local:3000" });
expect(getOrgDomain("acme.cal.local:3000")).toEqual("acme");
expect(getOrgSlug("acme.cal.local:3000")).toEqual("acme");
});
it("should handle a local web app with port url with a non-local subdomain hostname", () => {
setupEnvs({ WEBAPP_URL: "http://app.cal.local:3000" });
expect(getOrgDomain("acme.cal.com:3000")).toEqual(null);
expect(getOrgSlug("acme.cal.com:3000")).toEqual(null);
});
});
});

View File

@ -25,7 +25,7 @@ const vercelCreateDomain = async (domain: string) => {
const response = await fetch(
`https://api.vercel.com/v8/projects/${process.env.PROJECT_ID_VERCEL}/domains?teamId=${process.env.TEAM_ID_VERCEL}`,
{
body: `{\n "name": "${domain}.${subdomainSuffix()}"\n}`,
body: JSON.stringify({ name: `${domain}.${subdomainSuffix()}` }),
headers: {
Authorization: `Bearer ${process.env.AUTH_BEARER_TOKEN_VERCEL}`,
"Content-Type": "application/json",

View File

@ -1,3 +1,4 @@
import { subdomainSuffix, getOrgFullDomain } from "@calcom/features/ee/organizations/lib/orgDomains";
import { prisma } from "@calcom/prisma";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
@ -26,11 +27,15 @@ export const getBrandHandler = async ({ ctx }: VerifyCodeOptions) => {
});
const metadata = teamMetadataSchema.parse(team?.metadata);
const slug = team?.slug || metadata?.requestedSlug;
const slug = (team?.slug || metadata?.requestedSlug) as string;
const fullDomain = getOrgFullDomain(slug);
const domainSuffix = subdomainSuffix();
return {
...team,
metadata,
slug,
fullDomain,
domainSuffix,
};
};