diff --git a/apps/api/v1/next-env.d.ts b/apps/api/v1/next-env.d.ts index 4f11a03dc6..52e831b434 100644 --- a/apps/api/v1/next-env.d.ts +++ b/apps/api/v1/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/apps/api/v1/next.config.js b/apps/api/v1/next.config.js index d2d5c311f5..0ee86f8ae7 100644 --- a/apps/api/v1/next.config.js +++ b/apps/api/v1/next.config.js @@ -5,9 +5,6 @@ const plugins = [withAxiom]; /** @type {import("next").NextConfig} */ const nextConfig = { - experimental: { - instrumentationHook: true, - }, transpilePackages: [ "@calcom/app-store", "@calcom/dayjs", diff --git a/apps/api/v1/package.json b/apps/api/v1/package.json index e023241e99..935d6925e4 100644 --- a/apps/api/v1/package.json +++ b/apps/api/v1/package.json @@ -33,7 +33,7 @@ "@sentry/nextjs": "^9.15.0", "bcryptjs": "^2.4.3", "memory-cache": "^0.2.0", - "next": "^13.5.9", + "next": "^15.3.0", "next-api-middleware": "^1.0.1", "next-axiom": "^0.17.0", "next-swagger-doc": "^0.3.6", diff --git a/packages/app-store/_utils/oauth/updateProfilePhotoGoogle.ts b/packages/app-store/_utils/oauth/updateProfilePhotoGoogle.ts index 6f59810d13..40b81b597e 100644 --- a/packages/app-store/_utils/oauth/updateProfilePhotoGoogle.ts +++ b/packages/app-store/_utils/oauth/updateProfilePhotoGoogle.ts @@ -2,15 +2,34 @@ import { oauth2_v2 } from "@googleapis/oauth2"; import type { OAuth2Client } from "googleapis-common"; import logger from "@calcom/lib/logger"; +import { uploadAvatar } from "@calcom/lib/server/avatar"; import { UserRepository } from "@calcom/lib/server/repository/user"; +import { resizeBase64Image } from "@calcom/lib/server/resizeBase64Image"; export async function updateProfilePhotoGoogle(oAuth2Client: OAuth2Client, userId: number) { try { const oauth2 = new oauth2_v2.Oauth2({ auth: oAuth2Client }); const userDetails = await oauth2.userinfo.get(); - if (userDetails.data?.picture) { - await UserRepository.updateAvatar({ id: userId, avatarUrl: userDetails.data.picture }); + const avatarUrl = userDetails.data?.picture; + if (!avatarUrl) { + return; } + + // Handle base64 data + if ( + avatarUrl.startsWith("data:image/png;base64,") || + avatarUrl.startsWith("data:image/jpeg;base64,") || + avatarUrl.startsWith("data:image/jpg;base64,") + ) { + const resizedAvatarUrl = await uploadAvatar({ + avatar: await resizeBase64Image(avatarUrl), + userId, + }); + await UserRepository.updateAvatar({ id: userId, avatarUrl: resizedAvatarUrl }); + return; + } + + await UserRepository.updateAvatar({ id: userId, avatarUrl }); } catch (error) { logger.error("Error updating avatarUrl from google calendar connect", error); } diff --git a/packages/app-store/googlecalendar/api/callback.ts b/packages/app-store/googlecalendar/api/callback.ts index 9d9d545a90..85c3ba0be6 100644 --- a/packages/app-store/googlecalendar/api/callback.ts +++ b/packages/app-store/googlecalendar/api/callback.ts @@ -4,7 +4,12 @@ import type { NextApiRequest, NextApiResponse } from "next"; import GoogleCalendarService from "@calcom/app-store/googlecalendar/lib/CalendarService"; import { renewSelectedCalendarCredentialId } from "@calcom/lib/connectedCalendar"; -import { GOOGLE_CALENDAR_SCOPES, WEBAPP_URL, WEBAPP_URL_FOR_OAUTH } from "@calcom/lib/constants"; +import { + GOOGLE_CALENDAR_SCOPES, + SCOPE_USERINFO_PROFILE, + WEBAPP_URL, + WEBAPP_URL_FOR_OAUTH, +} from "@calcom/lib/constants"; import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl"; import { HttpError } from "@calcom/lib/http-error"; import { defaultHandler } from "@calcom/lib/server/defaultHandler"; @@ -14,6 +19,7 @@ import { Prisma } from "@calcom/prisma/client"; import getInstalledAppPath from "../../_utils/getInstalledAppPath"; import { decodeOAuthState } from "../../_utils/oauth/decodeOAuthState"; +import { updateProfilePhotoGoogle } from "../../_utils/oauth/updateProfilePhotoGoogle"; import { getGoogleAppKeys } from "../lib/getGoogleAppKeys"; async function getHandler(req: NextApiRequest, res: NextApiResponse) { @@ -95,10 +101,9 @@ async function getHandler(req: NextApiRequest, res: NextApiResponse) { } // Only attempt to update the user's profile photo if the user has granted the required scope - // TODO: Use the avatarUrl when setting the profile picture - // if (grantedScopes.includes(SCOPE_USERINFO_PROFILE)) { - // await updateProfilePhotoGoogle(oAuth2Client, req.session.user.id); - // } + if (grantedScopes.includes(SCOPE_USERINFO_PROFILE)) { + await updateProfilePhotoGoogle(oAuth2Client, req.session.user.id); + } const selectedCalendarWhereUnique = { userId: req.session.user.id, diff --git a/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts b/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts index ae92ff9ca4..1d93cdfade 100644 --- a/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts +++ b/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts @@ -152,7 +152,12 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions) } // if defined AND a base 64 string, upload and update the avatar URL - if (input.avatarUrl && input.avatarUrl.startsWith("data:image/png;base64,")) { + if ( + input.avatarUrl && + (input.avatarUrl.startsWith("data:image/png;base64,") || + input.avatarUrl.startsWith("data:image/jpeg;base64,") || + input.avatarUrl.startsWith("data:image/jpg;base64,")) + ) { data.avatarUrl = await uploadAvatar({ avatar: await resizeBase64Image(input.avatarUrl), userId: user.id, diff --git a/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts b/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts index 2e8150b7b3..ae8d6f4171 100644 --- a/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts @@ -119,7 +119,12 @@ export const updateUserHandler = async ({ ctx, input }: UpdateUserOptions) => { timeZone: input.timeZone, }; - if (input.avatar && input.avatar.startsWith("data:image/png;base64,")) { + if ( + input.avatar && + (input.avatar.startsWith("data:image/png;base64,") || + input.avatar.startsWith("data:image/jpeg;base64,") || + input.avatar.startsWith("data:image/jpg;base64,")) + ) { const avatar = await resizeBase64Image(input.avatar); data.avatarUrl = await uploadAvatar({ avatar, diff --git a/packages/trpc/server/routers/viewer/teams/create.handler.ts b/packages/trpc/server/routers/viewer/teams/create.handler.ts index 1f06448f9c..96f0e551cc 100644 --- a/packages/trpc/server/routers/viewer/teams/create.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/create.handler.ts @@ -106,7 +106,12 @@ export const createHandler = async ({ ctx, input }: CreateOptions) => { }, }); // Upload logo, create doesn't allow logo removal - if (input.logo && input.logo.startsWith("data:image/png;base64,")) { + if ( + input.logo && + (input.logo.startsWith("data:image/png;base64,") || + input.logo.startsWith("data:image/jpeg;base64,") || + input.logo.startsWith("data:image/jpg;base64,")) + ) { const logoUrl = await uploadLogo({ logo: await resizeBase64Image(input.logo), teamId: createdTeam.id, diff --git a/packages/trpc/server/routers/viewer/teams/update.handler.ts b/packages/trpc/server/routers/viewer/teams/update.handler.ts index 6b525e6b6a..75dd5d92f1 100644 --- a/packages/trpc/server/routers/viewer/teams/update.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/update.handler.ts @@ -70,7 +70,12 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => { rrTimestampBasis: input.rrTimestampBasis, }; - if (input.logo && input.logo.startsWith("data:image/png;base64,")) { + if ( + input.logo && + (input.logo.startsWith("data:image/png;base64,") || + input.logo.startsWith("data:image/jpeg;base64,") || + input.logo.startsWith("data:image/jpg;base64,")) + ) { data.logoUrl = await uploadLogo({ teamId: input.id, logo: input.logo }); } else if (typeof input.logo !== "undefined" && !input.logo) { data.logoUrl = null; diff --git a/yarn.lock b/yarn.lock index f93a474bec..e20a2416e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2607,7 +2607,7 @@ __metadata: "@sentry/nextjs": ^9.15.0 bcryptjs: ^2.4.3 memory-cache: ^0.2.0 - next: ^13.5.9 + next: ^15.3.0 next-api-middleware: ^1.0.1 next-axiom: ^0.17.0 next-swagger-doc: ^0.3.6 @@ -9025,13 +9025,6 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:13.5.11": - version: 13.5.11 - resolution: "@next/env@npm:13.5.11" - checksum: 1d19fb97ecdda14d2ea91b251e01b5e38046e42b161572c17abe55c1b77b329067fd3a5d120c35e22d84661f09d80bd2479ca355150cefc17c9a8120998f784a - languageName: node - linkType: hard - "@next/env@npm:13.5.7": version: 13.5.7 resolution: "@next/env@npm:13.5.7" @@ -9094,13 +9087,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:13.5.9": - version: 13.5.9 - resolution: "@next/swc-darwin-arm64@npm:13.5.9" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - "@next/swc-darwin-arm64@npm:14.0.4": version: 14.0.4 resolution: "@next/swc-darwin-arm64@npm:14.0.4" @@ -9129,13 +9115,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-x64@npm:13.5.9": - version: 13.5.9 - resolution: "@next/swc-darwin-x64@npm:13.5.9" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - "@next/swc-darwin-x64@npm:14.0.4": version: 14.0.4 resolution: "@next/swc-darwin-x64@npm:14.0.4" @@ -9164,13 +9143,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:13.5.9": - version: 13.5.9 - resolution: "@next/swc-linux-arm64-gnu@npm:13.5.9" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - "@next/swc-linux-arm64-gnu@npm:14.0.4": version: 14.0.4 resolution: "@next/swc-linux-arm64-gnu@npm:14.0.4" @@ -9199,13 +9171,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:13.5.9": - version: 13.5.9 - resolution: "@next/swc-linux-arm64-musl@npm:13.5.9" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - "@next/swc-linux-arm64-musl@npm:14.0.4": version: 14.0.4 resolution: "@next/swc-linux-arm64-musl@npm:14.0.4" @@ -9234,13 +9199,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:13.5.9": - version: 13.5.9 - resolution: "@next/swc-linux-x64-gnu@npm:13.5.9" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - "@next/swc-linux-x64-gnu@npm:14.0.4": version: 14.0.4 resolution: "@next/swc-linux-x64-gnu@npm:14.0.4" @@ -9269,13 +9227,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:13.5.9": - version: 13.5.9 - resolution: "@next/swc-linux-x64-musl@npm:13.5.9" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - "@next/swc-linux-x64-musl@npm:14.0.4": version: 14.0.4 resolution: "@next/swc-linux-x64-musl@npm:14.0.4" @@ -9304,13 +9255,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:13.5.9": - version: 13.5.9 - resolution: "@next/swc-win32-arm64-msvc@npm:13.5.9" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - "@next/swc-win32-arm64-msvc@npm:14.0.4": version: 14.0.4 resolution: "@next/swc-win32-arm64-msvc@npm:14.0.4" @@ -9339,13 +9283,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:13.5.9": - version: 13.5.9 - resolution: "@next/swc-win32-ia32-msvc@npm:13.5.9" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - "@next/swc-win32-ia32-msvc@npm:14.0.4": version: 14.0.4 resolution: "@next/swc-win32-ia32-msvc@npm:14.0.4" @@ -9360,13 +9297,6 @@ __metadata: languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:13.5.9": - version: 13.5.9 - resolution: "@next/swc-win32-x64-msvc@npm:13.5.9" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "@next/swc-win32-x64-msvc@npm:14.0.4": version: 14.0.4 resolution: "@next/swc-win32-x64-msvc@npm:14.0.4" @@ -36212,61 +36142,6 @@ __metadata: languageName: node linkType: hard -"next@npm:^13.5.9": - version: 13.5.11 - resolution: "next@npm:13.5.11" - dependencies: - "@next/env": 13.5.11 - "@next/swc-darwin-arm64": 13.5.9 - "@next/swc-darwin-x64": 13.5.9 - "@next/swc-linux-arm64-gnu": 13.5.9 - "@next/swc-linux-arm64-musl": 13.5.9 - "@next/swc-linux-x64-gnu": 13.5.9 - "@next/swc-linux-x64-musl": 13.5.9 - "@next/swc-win32-arm64-msvc": 13.5.9 - "@next/swc-win32-ia32-msvc": 13.5.9 - "@next/swc-win32-x64-msvc": 13.5.9 - "@swc/helpers": 0.5.2 - busboy: 1.6.0 - caniuse-lite: ^1.0.30001406 - postcss: 8.4.31 - styled-jsx: 5.1.1 - watchpack: 2.4.0 - peerDependencies: - "@opentelemetry/api": ^1.1.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - dependenciesMeta: - "@next/swc-darwin-arm64": - optional: true - "@next/swc-darwin-x64": - optional: true - "@next/swc-linux-arm64-gnu": - optional: true - "@next/swc-linux-arm64-musl": - optional: true - "@next/swc-linux-x64-gnu": - optional: true - "@next/swc-linux-x64-musl": - optional: true - "@next/swc-win32-arm64-msvc": - optional: true - "@next/swc-win32-ia32-msvc": - optional: true - "@next/swc-win32-x64-msvc": - optional: true - peerDependenciesMeta: - "@opentelemetry/api": - optional: true - sass: - optional: true - bin: - next: dist/bin/next - checksum: 117e091c48446da63c639f6d80bb5ba2cf25cfcfc54ca90293602af988e386852e8c004251ff978a085a36285474e92d0ddd9668aa800733754670a4b03bdd2a - languageName: node - linkType: hard - "next@npm:^15.3.0": version: 15.3.3 resolution: "next@npm:15.3.3"