chore: add sharp as depdency on apiv1 (#22204)

* fix: Process base64 avatar image (#22165)

* fix: process base64 avatar image

* better name

* more

* fix import

* Attempt to fix sharp dependency issue by upgrading next

---------

Co-authored-by: Benny Joo <sldisek783@gmail.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
This commit is contained in:
Morgan
2025-07-03 12:52:14 +01:00
committed by GitHub
co-authored by Benny Joo Alex van Andel
parent d23d68bf2d
commit 5769553659
10 changed files with 58 additions and 142 deletions
+1 -1
View File
@@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />
// 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.
-3
View File
@@ -5,9 +5,6 @@ const plugins = [withAxiom];
/** @type {import("next").NextConfig} */
const nextConfig = {
experimental: {
instrumentationHook: true,
},
transpilePackages: [
"@calcom/app-store",
"@calcom/dayjs",
+1 -1
View File
@@ -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",
@@ -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);
}
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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;
+1 -126
View File
@@ -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"