>(user: TUser) {
- return user.hideBranding && user.plan !== "FREE";
+export function isBrandingHidden(hideBrandingSetting: boolean, belongsToActiveTeam: boolean) {
+ return belongsToActiveTeam && hideBrandingSetting;
}
diff --git a/apps/web/pages/[user]/[type].tsx b/apps/web/pages/[user]/[type].tsx
index 162b66ee93..6c05231379 100644
--- a/apps/web/pages/[user]/[type].tsx
+++ b/apps/web/pages/[user]/[type].tsx
@@ -10,8 +10,9 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent";
import prisma from "@calcom/prisma";
import { User } from "@calcom/prisma/client";
-import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
+import { EventTypeMetaDataSchema, teamMetadataSchema } from "@calcom/prisma/zod-utils";
+import { isBrandingHidden } from "@lib/isBrandingHidden";
import { inferSSRProps } from "@lib/types/inferSSRProps";
import { EmbedProps } from "@lib/withEmbedSsr";
@@ -110,6 +111,11 @@ async function getUserPageProps(context: GetStaticPropsContext) {
},
],
},
+ teams: {
+ include: {
+ team: true,
+ },
+ },
},
});
@@ -150,6 +156,13 @@ async function getUserPageProps(context: GetStaticPropsContext) {
locations: privacyFilteredLocations(locations),
descriptionAsSafeHTML: eventType.description ? md.render(eventType.description) : null,
});
+ // Check if the user you are logging into has any active teams
+ const hasActiveTeam =
+ user.teams.filter((m) => {
+ const metadata = teamMetadataSchema.safeParse(m.team.metadata);
+ if (metadata.success && metadata.data?.subscriptionId) return false;
+ return true;
+ }).length > 0;
return {
props: {
@@ -167,6 +180,7 @@ async function getUserPageProps(context: GetStaticPropsContext) {
away: user?.away,
isDynamic: false,
trpcState: ssg.dehydrate(),
+ isBrandingHidden: isBrandingHidden(user.hideBranding, hasActiveTeam),
},
revalidate: 10, // seconds
};
@@ -262,6 +276,7 @@ async function getDynamicGroupPageProps(context: GetStaticPropsContext) {
isDynamic: true,
away: false,
trpcState: ssg.dehydrate(),
+ isBrandingHidden: false, // I think we should always show branding for dynamic groups - saves us checking every single user
},
revalidate: 10, // seconds
};
diff --git a/apps/web/pages/api/auth/[...nextauth].tsx b/apps/web/pages/api/auth/[...nextauth].tsx
index 98a64cc779..f7716fdccc 100644
--- a/apps/web/pages/api/auth/[...nextauth].tsx
+++ b/apps/web/pages/api/auth/[...nextauth].tsx
@@ -20,6 +20,7 @@ import { defaultCookies } from "@calcom/lib/default-cookies";
import rateLimit from "@calcom/lib/rateLimit";
import { serverConfig } from "@calcom/lib/serverConfig";
import prisma from "@calcom/prisma";
+import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import CalComAdapter from "@lib/auth/next-auth-custom-adapter";
import { randomString } from "@lib/random";
@@ -63,6 +64,11 @@ const providers: Provider[] = [
password: true,
twoFactorEnabled: true,
twoFactorSecret: true,
+ teams: {
+ include: {
+ team: true,
+ },
+ },
},
});
@@ -116,6 +122,13 @@ const providers: Provider[] = [
intervalInMs: 60 * 1000, // 1 minute
});
await limiter.check(10, user.email); // 10 requests per minute
+ // Check if the user you are logging into has any active teams
+ const hasActiveTeams =
+ user.teams.filter((m) => {
+ const metadata = teamMetadataSchema.safeParse(m.team.metadata);
+ if (metadata.success && metadata.data?.subscriptionId) return false;
+ return true;
+ }).length > 0;
// authentication success- but does it meet the minimum password requirements?
if (user.role === "ADMIN" && !isPasswordValid(credentials.password, false, true)) {
@@ -125,6 +138,7 @@ const providers: Provider[] = [
email: user.email,
name: user.name,
role: "USER",
+ belongsToActiveTeam: hasActiveTeams,
};
}
@@ -134,6 +148,7 @@ const providers: Provider[] = [
email: user.email,
name: user.name,
role: user.role,
+ belongsToActiveTeam: hasActiveTeams,
};
},
}),
@@ -272,6 +287,7 @@ export default NextAuth({
email: user.email,
role: user.role,
impersonatedByUID: user?.impersonatedByUID,
+ belongsToActiveTeam: user?.belongsToActiveTeam,
};
}
@@ -307,6 +323,7 @@ export default NextAuth({
email: existingUser.email,
role: existingUser.role,
impersonatedByUID: token.impersonatedByUID as number,
+ belongsToActiveTeam: token?.belongsToActiveTeam as boolean,
};
}
@@ -324,6 +341,7 @@ export default NextAuth({
username: token.username as string,
role: token.role as UserPermissionRole,
impersonatedByUID: token.impersonatedByUID as number,
+ belongsToActiveTeam: token?.belongsToActiveTeam as boolean,
},
};
return calendsoSession;
diff --git a/apps/web/pages/d/[link]/[slug].tsx b/apps/web/pages/d/[link]/[slug].tsx
index bd80efe31a..b9ac03a44e 100644
--- a/apps/web/pages/d/[link]/[slug].tsx
+++ b/apps/web/pages/d/[link]/[slug].tsx
@@ -166,6 +166,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
previousPage: context.req.headers.referer ?? null,
booking,
users: [user.username],
+ isBrandingHidden: user.hideBranding,
},
};
};
diff --git a/apps/web/pages/settings/my-account/appearance.tsx b/apps/web/pages/settings/my-account/appearance.tsx
index 3acb39548b..87b479178d 100644
--- a/apps/web/pages/settings/my-account/appearance.tsx
+++ b/apps/web/pages/settings/my-account/appearance.tsx
@@ -1,3 +1,4 @@
+import { useSession } from "next-auth/react";
import { Controller, useForm } from "react-hook-form";
import { APP_NAME } from "@calcom/lib/constants";
@@ -41,7 +42,7 @@ const SkeletonLoader = () => {
const AppearanceView = () => {
const { t } = useLocale();
-
+ const session = useSession();
const utils = trpc.useContext();
const { data: user, isLoading } = trpc.viewer.me.useQuery();
@@ -180,6 +181,7 @@ const AppearanceView = () => {
formMethods.setValue("hideBranding", checked, { shouldDirty: true })
}
diff --git a/apps/web/pages/team/[slug]/[type].tsx b/apps/web/pages/team/[slug]/[type].tsx
index d6b8fdbe6a..1df4456864 100644
--- a/apps/web/pages/team/[slug]/[type].tsx
+++ b/apps/web/pages/team/[slug]/[type].tsx
@@ -43,6 +43,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
name: true,
slug: true,
logo: true,
+ hideBranding: true,
eventTypes: {
where: {
slug: typeParam,
@@ -160,6 +161,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
previousPage: context.req.headers.referer ?? null,
booking,
trpcState: ssg.dehydrate(),
+ isBrandingHidden: team.hideBranding,
},
};
};
diff --git a/packages/features/ee/impersonation/lib/ImpersonationProvider.ts b/packages/features/ee/impersonation/lib/ImpersonationProvider.ts
index 11d5c753aa..407ad41311 100644
--- a/packages/features/ee/impersonation/lib/ImpersonationProvider.ts
+++ b/packages/features/ee/impersonation/lib/ImpersonationProvider.ts
@@ -11,7 +11,8 @@ const teamIdschema = z.object({
const auditAndReturnNextUser = async (
impersonatedUser: Pick,
- impersonatedByUID: number
+ impersonatedByUID: number,
+ hasTeam?: boolean
) => {
// Log impersonations for audit purposes
await prisma.impersonations.create({
@@ -36,6 +37,7 @@ const auditAndReturnNextUser = async (
name: impersonatedUser.name,
role: impersonatedUser.role,
impersonatedByUID,
+ belongsToActiveTeam: hasTeam,
};
return obj;
@@ -103,7 +105,11 @@ const ImpersonationProvider = CredentialsProvider({
if (impersonatedUser.disableImpersonation) {
throw new Error("This user has disabled Impersonation.");
}
- return auditAndReturnNextUser(impersonatedUser, session?.user.id as number);
+ return auditAndReturnNextUser(
+ impersonatedUser,
+ session?.user.id as number,
+ impersonatedUser.teams.length > 0 // If the user has any teams, they belong to an active team and we can set the hasActiveTeam ctx to true
+ );
}
if (!teamId) throw new Error("You do not have permission to do this.");
@@ -137,7 +143,11 @@ const ImpersonationProvider = CredentialsProvider({
throw new Error("You do not have permission to do this.");
}
- return auditAndReturnNextUser(impersonatedUser, session?.user.id as number);
+ return auditAndReturnNextUser(
+ impersonatedUser,
+ session?.user.id as number,
+ impersonatedUser.teams.length > 0 // If the user has any teams, they belong to an active team and we can set the hasActiveTeam ctx to true
+ );
},
});
diff --git a/packages/types/next-auth.d.ts b/packages/types/next-auth.d.ts
index 0907804546..94c3fba101 100644
--- a/packages/types/next-auth.d.ts
+++ b/packages/types/next-auth.d.ts
@@ -14,6 +14,7 @@ declare module "next-auth" {
emailVerified?: PrismaUser["emailVerified"];
email_verified?: boolean;
impersonatedByUID?: number;
+ belongsToActiveTeam?: boolean;
username?: PrismaUser["username"];
role?: PrismaUser["role"];
}