From cc99e1697b8daaa8172428c5897110aecf5a078d Mon Sep 17 00:00:00 2001 From: Leo Giovanetti Date: Mon, 3 Jul 2023 05:06:12 -0300 Subject: [PATCH] fix: Creating team and preview URL fixes [CAL-1997] [CAL-1998] (#9648) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Creating team and preview URL fixes * Renamed function in tests too * fix: Signup from org wizard invitation and other tweaks [CAL-1973] [CAL-1993] [CAL-1994] (#9693) * Fixing signup from org invitation and other tweaks * feat: Organizations no middleware rewrite (#9548) Co-authored-by: Leo Giovanetti Co-authored-by: zomars Co-authored-by: Peer Richelsen * Revert "fix: redirect to 404 page for invalid email verification token" (#9703) * New Crowdin translations by Github Action * refactor: Skip license checks for development (#9375) * Allow closing the embed on clicking the black transparent area (#9706) * New Crowdin translations by Github Action * perf: [CAL-1928] Deduplicate eventTypes.getByViewer query (#9700) Co-authored-by: alannnc Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> * perf: Remove useless data on EvenTypes getByViewer endpoint (#9704) * feat: [CAL-910] Pre-select country for phone number (CALCOM-5759) (#9526) Co-authored-by: gitstart-calcom * Fix settings layout + org headings (#9712) * Simplifying prop * Removing restriction to choose username * Formatting --------- Co-authored-by: Efraín Rochín Co-authored-by: zomars Co-authored-by: Peer Richelsen Co-authored-by: Crowdin Bot Co-authored-by: alannnc Co-authored-by: Hariom Balhara Co-authored-by: Afzal Sayed <14029371+afzalsayed96@users.noreply.github.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: GitStart-Cal.com <121884634+gitstart-calcom@users.noreply.github.com> Co-authored-by: gitstart-calcom Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com> * Fix conditional before hook * Fix lints --------- Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: Efraín Rochín Co-authored-by: zomars Co-authored-by: Peer Richelsen Co-authored-by: Crowdin Bot Co-authored-by: alannnc Co-authored-by: Hariom Balhara Co-authored-by: Afzal Sayed <14029371+afzalsayed96@users.noreply.github.com> Co-authored-by: GitStart-Cal.com <121884634+gitstart-calcom@users.noreply.github.com> Co-authored-by: gitstart-calcom Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com> --- .../ui/UsernameAvailability/index.tsx | 6 +- apps/web/pages/event-types/index.tsx | 13 ++--- apps/web/pages/signup.tsx | 29 +++++++++- .../components/AboutOrganizationForm.tsx | 1 + .../ee/organizations/context/provider.ts | 4 +- .../ee/organizations/lib/orgDomains.ts | 8 ++- .../pages/settings/appearance.tsx | 55 ------------------- .../organizations/pages/settings/profile.tsx | 20 +++---- .../teams/components/CreateANewTeamForm.tsx | 43 ++++++++++----- .../ee/teams/components/TeamListItem.tsx | 15 +++-- .../components/CreateEventTypeDialog.tsx | 5 +- packages/features/shell/Shell.tsx | 32 ++++------- packages/features/test/orgDomains.test.ts | 12 ++-- .../viewer/organizations/create.handler.ts | 2 +- .../viewer/organizations/getBrand.handler.ts | 7 ++- 15 files changed, 117 insertions(+), 135 deletions(-) diff --git a/apps/web/components/ui/UsernameAvailability/index.tsx b/apps/web/components/ui/UsernameAvailability/index.tsx index 0630b0c256..19483d6f21 100644 --- a/apps/web/components/ui/UsernameAvailability/index.tsx +++ b/apps/web/components/ui/UsernameAvailability/index.tsx @@ -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://", ""); } diff --git a/apps/web/pages/event-types/index.tsx b/apps/web/pages/event-types/index.tsx index 2453b7248a..7f6f64faed 100644 --- a/apps/web/pages/event-types/index.tsx +++ b/apps/web/pages/event-types/index.tsx @@ -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
    {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 && ( - {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}`} )} diff --git a/apps/web/pages/signup.tsx b/apps/web/pages/signup.tsx index 84f7f69475..9ff81360cc 100644 --- a/apps/web/pages/signup.tsx +++ b/apps/web/pages/signup.tsx @@ -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) { +type SignupProps = inferSSRProps; + +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}
    @@ -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, }, }; }; diff --git a/packages/features/ee/organizations/components/AboutOrganizationForm.tsx b/packages/features/ee/organizations/components/AboutOrganizationForm.tsx index 1ba3142edc..24ee3218b3 100644 --- a/packages/features/ee/organizations/components/AboutOrganizationForm.tsx +++ b/packages/features/ee/organizations/components/AboutOrganizationForm.tsx @@ -65,6 +65,7 @@ export const AboutOrganizationForm = () => { fallback={} asChild className="items-center" + imageSrc={image} size="lg" />
    diff --git a/packages/features/ee/organizations/context/provider.ts b/packages/features/ee/organizations/context/provider.ts index 1162186d6e..e32e001611 100644 --- a/packages/features/ee/organizations/context/provider.ts +++ b/packages/features/ee/organizations/context/provider.ts @@ -12,7 +12,9 @@ export type OrganizationBranding = | ({ logo?: string | null | undefined; name?: string; - slug?: string; + slug: string; + fullDomain: string; + domainSuffix: string; } & z.infer) | null | undefined; diff --git a/packages/features/ee/organizations/lib/orgDomains.ts b/packages/features/ee/organizations/lib/orgDomains.ts index 141719b2cd..2c8da147de 100644 --- a/packages/features/ee/organizations/lib/orgDomains.ts +++ b/packages/features/ee/organizations/lib/orgDomains.ts @@ -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()}/`; +} diff --git a/packages/features/ee/organizations/pages/settings/appearance.tsx b/packages/features/ee/organizations/pages/settings/appearance.tsx index 3b9137d623..d447bc77f8 100644 --- a/packages/features/ee/organizations/pages/settings/appearance.tsx +++ b/packages/features/ee/organizations/pages/settings/appearance.tsx @@ -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 = () => { )} />
    -
    - -
    -
    -
    - -

    - {t("team_disable_cal_branding_description", { appName: APP_NAME })} -

    -
    - -
    - ( - { - form.setValue("hideBranding", isChecked); - }} - /> - )} - /> -
    -
    -
    -
    - -

    {t("hide_book_a_team_member_description")}

    -
    -
    - ( - { - form.setValue("hideBookATeamMember", isChecked); - }} - /> - )} - /> -
    -
    -
    diff --git a/packages/features/ee/organizations/pages/settings/profile.tsx b/packages/features/ee/organizations/pages/settings/profile.tsx index e12d6657fa..8640a81c85 100644 --- a/packages/features/ee/organizations/pages/settings/profile.tsx +++ b/packages/features/ee/organizations/pages/settings/profile.tsx @@ -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 = () => { { - navigator.clipboard.writeText(permalink); + navigator.clipboard.writeText(orgBranding.fullDomain); showToast("Copied to clipboard", "success"); }}> {t("copy_link_org")} diff --git a/packages/features/ee/teams/components/CreateANewTeamForm.tsx b/packages/features/ee/teams/components/CreateANewTeamForm.tsx index b5f9fc03b3..7eaaf56860 100644 --- a/packages/features/ee/teams/components/CreateANewTeamForm.tsx +++ b/packages/features/ee/teams/components/CreateANewTeamForm.tsx @@ -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(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 } }) => ( -
    - -
    - { - newTeamFormMethods.setValue("logo", newAvatar); - createTeamMutation.reset(); - }} + <> + +
    + } + size="lg" /> +
    + { + newTeamFormMethods.setValue("logo", newAvatar); + createTeamMutation.reset(); + }} + imageSrc={value} + /> +
    -
    + )} />
    diff --git a/packages/features/ee/teams/components/TeamListItem.tsx b/packages/features/ee/teams/components/TeamListItem.tsx index 281b3484c5..f40d6a3885 100644 --- a/packages/features/ee/teams/components/TeamListItem.tsx +++ b/packages/features/ee/teams/components/TeamListItem.tsx @@ -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) { {team.slug ? orgBranding - ? `${orgBranding.slug}.${subdomainSuffix()}/${team.slug}` + ? `${orgBranding.fullDomain}${team.slug}` : `${process.env.NEXT_PUBLIC_WEBSITE_URL}/team/${team.slug}` : "Unpublished team"} @@ -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) { {t("preview_team") as string} diff --git a/packages/features/eventtypes/components/CreateEventTypeDialog.tsx b/packages/features/eventtypes/components/CreateEventTypeDialog.tsx index 0877a82bf4..f03109f78b 100644 --- a/packages/features/eventtypes/components/CreateEventTypeDialog.tsx +++ b/packages/features/eventtypes/components/CreateEventTypeDialog.tsx @@ -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 ( {!small && ( - + {user.name || "Nameless User"} @@ -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 ; } @@ -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) {
    {orgBranding ? ( - {orgBranding ? ( -
    - -

    - {orgBranding.name} -

    -
    - ) : ( - - )} +
    + +

    + {orgBranding.name} +

    +
    ) : (
    diff --git a/packages/features/test/orgDomains.test.ts b/packages/features/test/orgDomains.test.ts index 5e459f42b6..2fece9b37d 100644 --- a/packages/features/test/orgDomains.test.ts +++ b/packages/features/test/orgDomains.test.ts @@ -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); }); }); }); diff --git a/packages/trpc/server/routers/viewer/organizations/create.handler.ts b/packages/trpc/server/routers/viewer/organizations/create.handler.ts index e63de91bb4..d004180925 100644 --- a/packages/trpc/server/routers/viewer/organizations/create.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/create.handler.ts @@ -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", diff --git a/packages/trpc/server/routers/viewer/organizations/getBrand.handler.ts b/packages/trpc/server/routers/viewer/organizations/getBrand.handler.ts index ebc9fba7ee..2cb920857a 100644 --- a/packages/trpc/server/routers/viewer/organizations/getBrand.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/getBrand.handler.ts @@ -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, }; };