revert: Process Base64 Avatar Image (#22185)
* Revert "chore: add test for updateProfilePhotoGoogle (#22169)" This reverts commit67032ddaf1. * Revert "fix: Process base64 avatar image (#22165)" This reverts commitd8d8bc4d00.
This commit is contained in:
1 parent
4963d247dc
commit
c98c06062b
9 files changed
+23
-165
No files matched your search
@@ -1,114 +0,0 @@
|
||||
import { oauth2_v2 } from "@googleapis/oauth2";
|
||||
import type { OAuth2Client } from "googleapis-common";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
|
||||
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";
|
||||
|
||||
import { updateProfilePhotoGoogle } from "./updateProfilePhotoGoogle";
|
||||
|
||||
vi.mock("@googleapis/oauth2", () => ({
|
||||
oauth2_v2: {
|
||||
Oauth2: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@calcom/lib/logger", () => ({
|
||||
default: {
|
||||
error: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@calcom/lib/server/avatar", () => ({
|
||||
uploadAvatar: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@calcom/lib/server/resizeBase64Image", () => ({
|
||||
resizeBase64Image: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@calcom/lib/server/repository/user", () => ({
|
||||
UserRepository: {
|
||||
updateAvatar: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe("updateProfilePhotoGoogle", () => {
|
||||
const mockOAuth2Client = {} as OAuth2Client;
|
||||
const userId = 123;
|
||||
|
||||
let mockOauth2Instance: any;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
mockOauth2Instance = {
|
||||
userinfo: {
|
||||
get: vi.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
(oauth2_v2.Oauth2 as any).mockImplementation(() => mockOauth2Instance);
|
||||
(uploadAvatar as any).mockResolvedValue("/api/avatar/processed-123.png");
|
||||
(resizeBase64Image as any).mockResolvedValue("data:image/png;base64,resized-data");
|
||||
(UserRepository.updateAvatar as any).mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it("should update avatar with valid URL", async () => {
|
||||
const validUrl = "https://example.com/avatar.jpg";
|
||||
mockOauth2Instance.userinfo.get.mockResolvedValue({
|
||||
data: { picture: validUrl },
|
||||
});
|
||||
|
||||
await updateProfilePhotoGoogle(mockOAuth2Client, userId);
|
||||
|
||||
expect(UserRepository.updateAvatar).toHaveBeenCalledWith({
|
||||
id: userId,
|
||||
avatarUrl: validUrl,
|
||||
});
|
||||
expect(uploadAvatar).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should process base64 data", async () => {
|
||||
const base64Data =
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=";
|
||||
mockOauth2Instance.userinfo.get.mockResolvedValue({
|
||||
data: { picture: base64Data },
|
||||
});
|
||||
|
||||
await updateProfilePhotoGoogle(mockOAuth2Client, userId);
|
||||
|
||||
expect(resizeBase64Image).toHaveBeenCalledWith(base64Data);
|
||||
expect(uploadAvatar).toHaveBeenCalledWith({
|
||||
avatar: "data:image/png;base64,resized-data",
|
||||
userId,
|
||||
});
|
||||
expect(UserRepository.updateAvatar).toHaveBeenCalledWith({
|
||||
id: userId,
|
||||
avatarUrl: "/api/avatar/processed-123.png",
|
||||
});
|
||||
});
|
||||
|
||||
it("should do nothing when no picture provided", async () => {
|
||||
mockOauth2Instance.userinfo.get.mockResolvedValue({
|
||||
data: {},
|
||||
});
|
||||
|
||||
await updateProfilePhotoGoogle(mockOAuth2Client, userId);
|
||||
|
||||
expect(UserRepository.updateAvatar).not.toHaveBeenCalled();
|
||||
expect(uploadAvatar).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should handle errors gracefully", async () => {
|
||||
const error = new Error("OAuth API failed");
|
||||
mockOauth2Instance.userinfo.get.mockRejectedValue(error);
|
||||
|
||||
await updateProfilePhotoGoogle(mockOAuth2Client, userId);
|
||||
|
||||
expect(logger.error).toHaveBeenCalledWith("Error updating avatarUrl from google calendar connect", error);
|
||||
expect(UserRepository.updateAvatar).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,32 +1,16 @@
|
||||
import { oauth2_v2 } from "@googleapis/oauth2";
|
||||
import type { OAuth2Client } from "googleapis-common";
|
||||
|
||||
import { isBase64Image } from "@calcom/lib/isBase64Image";
|
||||
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();
|
||||
const avatarUrl = userDetails.data?.picture;
|
||||
if (!avatarUrl) {
|
||||
return;
|
||||
if (userDetails.data?.picture) {
|
||||
await UserRepository.updateAvatar({ id: userId, avatarUrl: userDetails.data.picture });
|
||||
}
|
||||
|
||||
// Handle base64 data
|
||||
if (isBase64Image(avatarUrl)) {
|
||||
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,12 +4,7 @@ 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,
|
||||
SCOPE_USERINFO_PROFILE,
|
||||
WEBAPP_URL,
|
||||
WEBAPP_URL_FOR_OAUTH,
|
||||
} from "@calcom/lib/constants";
|
||||
import { GOOGLE_CALENDAR_SCOPES, 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";
|
||||
@@ -19,7 +14,6 @@ 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) {
|
||||
@@ -101,9 +95,10 @@ async function getHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
|
||||
// Only attempt to update the user's profile photo if the user has granted the required scope
|
||||
if (grantedScopes.includes(SCOPE_USERINFO_PROFILE)) {
|
||||
await updateProfilePhotoGoogle(oAuth2Client, req.session.user.id);
|
||||
}
|
||||
// TODO: Use the avatarUrl when setting the profile picture
|
||||
// if (grantedScopes.includes(SCOPE_USERINFO_PROFILE)) {
|
||||
// await updateProfilePhotoGoogle(oAuth2Client, req.session.user.id);
|
||||
// }
|
||||
|
||||
const selectedCalendarWhereUnique = {
|
||||
userId: req.session.user.id,
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Checks if a string is a supported base64 image format
|
||||
*/
|
||||
export function isBase64Image(input: string | null | undefined): boolean {
|
||||
if (!input) return false;
|
||||
|
||||
return (
|
||||
input.startsWith("data:image/png;base64,") ||
|
||||
input.startsWith("data:image/jpeg;base64,") ||
|
||||
input.startsWith("data:image/jpg;base64,")
|
||||
);
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billlin
|
||||
import { FeaturesRepository } from "@calcom/features/flags/features.repository";
|
||||
import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { isBase64Image } from "@calcom/lib/isBase64Image";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { uploadAvatar } from "@calcom/lib/server/avatar";
|
||||
import { checkUsername } from "@calcom/lib/server/checkUsername";
|
||||
@@ -153,7 +152,7 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions)
|
||||
}
|
||||
|
||||
// if defined AND a base 64 string, upload and update the avatar URL
|
||||
if (input.avatarUrl && isBase64Image(input.avatarUrl)) {
|
||||
if (input.avatarUrl && input.avatarUrl.startsWith("data:image/png;base64,")) {
|
||||
data.avatarUrl = await uploadAvatar({
|
||||
avatar: await resizeBase64Image(input.avatarUrl),
|
||||
userId: user.id,
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { Prisma } from "@prisma/client";
|
||||
|
||||
import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
|
||||
import { getMetadataHelpers } from "@calcom/lib/getMetadataHelpers";
|
||||
import { isBase64Image } from "@calcom/lib/isBase64Image";
|
||||
import { uploadLogo } from "@calcom/lib/server/avatar";
|
||||
import { isOrganisationAdmin } from "@calcom/lib/server/queries/organisations";
|
||||
import { resizeBase64Image } from "@calcom/lib/server/resizeBase64Image";
|
||||
@@ -162,7 +161,12 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
|
||||
metadata: mergeMetadata({ ...input.metadata }),
|
||||
};
|
||||
|
||||
if (input.banner && isBase64Image(input.banner)) {
|
||||
if (
|
||||
input.banner &&
|
||||
(input.banner.startsWith("data:image/png;base64,") ||
|
||||
input.banner.startsWith("data:image/jpeg;base64,") ||
|
||||
input.banner.startsWith("data:image/jpg;base64,"))
|
||||
) {
|
||||
const banner = await resizeBase64Image(input.banner, { maxSize: 1500 });
|
||||
data.bannerUrl = await uploadLogo({
|
||||
logo: banner,
|
||||
@@ -173,7 +177,12 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
|
||||
data.bannerUrl = null;
|
||||
}
|
||||
|
||||
if (input.logoUrl && isBase64Image(input.logoUrl)) {
|
||||
if (
|
||||
input.logoUrl &&
|
||||
(input.logoUrl.startsWith("data:image/png;base64,") ||
|
||||
input.logoUrl.startsWith("data:image/jpeg;base64,") ||
|
||||
input.logoUrl.startsWith("data:image/jpg;base64,"))
|
||||
) {
|
||||
data.logoUrl = await uploadLogo({
|
||||
logo: await resizeBase64Image(input.logoUrl),
|
||||
teamId: currentOrgId,
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { Prisma, PrismaPromise, User, Membership, Profile } from "@prisma/c
|
||||
|
||||
import { ensureOrganizationIsReviewed } from "@calcom/ee/organizations/lib/ensureOrganizationIsReviewed";
|
||||
import { checkAdminOrOwner } from "@calcom/features/auth/lib/checkAdminOrOwner";
|
||||
import { isBase64Image } from "@calcom/lib/isBase64Image";
|
||||
import { uploadAvatar } from "@calcom/lib/server/avatar";
|
||||
import { checkRegularUsername } from "@calcom/lib/server/checkRegularUsername";
|
||||
import { isOrganisationAdmin, isOrganisationOwner } from "@calcom/lib/server/queries/organisations";
|
||||
@@ -120,7 +119,7 @@ export const updateUserHandler = async ({ ctx, input }: UpdateUserOptions) => {
|
||||
timeZone: input.timeZone,
|
||||
};
|
||||
|
||||
if (input.avatar && isBase64Image(input.avatar)) {
|
||||
if (input.avatar && input.avatar.startsWith("data:image/png;base64,")) {
|
||||
const avatar = await resizeBase64Image(input.avatar);
|
||||
data.avatarUrl = await uploadAvatar({
|
||||
avatar,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { generateTeamCheckoutSession } from "@calcom/features/ee/teams/lib/payments";
|
||||
import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { isBase64Image } from "@calcom/lib/isBase64Image";
|
||||
import { uploadLogo } from "@calcom/lib/server/avatar";
|
||||
import { ProfileRepository } from "@calcom/lib/server/repository/profile";
|
||||
import { resizeBase64Image } from "@calcom/lib/server/resizeBase64Image";
|
||||
@@ -107,7 +106,7 @@ export const createHandler = async ({ ctx, input }: CreateOptions) => {
|
||||
},
|
||||
});
|
||||
// Upload logo, create doesn't allow logo removal
|
||||
if (input.logo && isBase64Image(input.logo)) {
|
||||
if (input.logo && input.logo.startsWith("data:image/png;base64,")) {
|
||||
const logoUrl = await uploadLogo({
|
||||
logo: await resizeBase64Image(input.logo),
|
||||
teamId: createdTeam.id,
|
||||
|
||||
@@ -4,7 +4,6 @@ import { getOrgFullOrigin } from "@calcom/ee/organizations/lib/orgDomains";
|
||||
import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
|
||||
import type { IntervalLimit } from "@calcom/lib/intervalLimits/intervalLimitSchema";
|
||||
import { validateIntervalLimitOrder } from "@calcom/lib/intervalLimits/validateIntervalLimitOrder";
|
||||
import { isBase64Image } from "@calcom/lib/isBase64Image";
|
||||
import { uploadLogo } from "@calcom/lib/server/avatar";
|
||||
import { isTeamAdmin } from "@calcom/lib/server/queries/teams";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
@@ -71,7 +70,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
|
||||
rrTimestampBasis: input.rrTimestampBasis,
|
||||
};
|
||||
|
||||
if (input.logo && isBase64Image(input.logo)) {
|
||||
if (input.logo && input.logo.startsWith("data:image/png;base64,")) {
|
||||
data.logoUrl = await uploadLogo({ teamId: input.id, logo: input.logo });
|
||||
} else if (typeof input.logo !== "undefined" && !input.logo) {
|
||||
data.logoUrl = null;
|
||||
|
||||
Reference in new issue
Block a user