fix: Process base64 avatar image (#22165)

* fix: process base64 avatar image

* better name

* more

* fix import
This commit is contained in:
Benny Joo authored and GitHub committed 2025-06-30 21:08:46 +01:00
1 parent 55cc1aea59
commit d8d8bc4d00
6 files changed
+55 -11

No files matched your search

@@ -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;