feat: add public profiles

This commit is contained in:
David Nguyen
2024-06-06 14:46:48 +10:00
parent d11a68fc4c
commit 5514dad4d8
43 changed files with 2067 additions and 137 deletions

View File

@@ -0,0 +1,55 @@
import { prisma } from '@documenso/prisma';
import type { UserProfile } from '@documenso/prisma/client';
import { AppError, AppErrorCode } from '../../errors/app-error';
import { updatePublicProfile } from './update-public-profile';
export type GetUserPublicProfileOptions = {
userId: number;
};
type GetUserPublicProfileResponse = {
profile: UserProfile;
url: string | null;
};
export const getUserPublicProfile = async ({
userId,
}: GetUserPublicProfileOptions): Promise<GetUserPublicProfileResponse> => {
const user = await prisma.user.findFirst({
where: {
id: userId,
},
include: {
profile: true,
},
});
if (!user) {
throw new AppError(AppErrorCode.NOT_FOUND, 'User not found');
}
// Create and return the public profile.
if (!user.profile) {
const { url, profile } = await updatePublicProfile({
userId: user.id,
data: {
enabled: false,
},
});
if (!profile) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Failed to create public profile');
}
return {
profile,
url,
};
}
return {
profile: user.profile,
url: user.url,
};
};

View File

@@ -4,28 +4,65 @@ import { AppError, AppErrorCode } from '../../errors/app-error';
export type UpdatePublicProfileOptions = {
userId: number;
url: string;
data: {
url?: string;
bio?: string;
enabled?: boolean;
};
};
export const updatePublicProfile = async ({ userId, url }: UpdatePublicProfileOptions) => {
const isUrlTaken = await prisma.user.findFirst({
select: {
id: true,
},
export const updatePublicProfile = async ({ userId, data }: UpdatePublicProfileOptions) => {
if (Object.values(data).length === 0) {
throw new AppError(AppErrorCode.INVALID_BODY, 'Missing data to update');
}
const { url, bio, enabled } = data;
const user = await prisma.user.findFirst({
where: {
id: {
not: userId,
},
url,
id: userId,
},
});
if (isUrlTaken) {
throw new AppError(
AppErrorCode.PROFILE_URL_TAKEN,
'Profile username is taken',
'The profile username is already taken',
);
if (!user) {
throw new AppError(AppErrorCode.NOT_FOUND, 'User not found');
}
const finalUrl = url ?? user.url;
if (!finalUrl && enabled) {
throw new AppError(AppErrorCode.INVALID_REQUEST, 'Cannot enable a profile without a URL');
}
if (url) {
const isUrlTakenByAnotherUser = await prisma.user.findFirst({
select: {
id: true,
},
where: {
id: {
not: userId,
},
url,
},
});
const isUrlTakenByAnotherTeam = await prisma.team.findFirst({
select: {
id: true,
},
where: {
url,
},
});
if (isUrlTakenByAnotherUser || isUrlTakenByAnotherTeam) {
throw new AppError(
AppErrorCode.PROFILE_URL_TAKEN,
'Profile username is taken',
'The profile username is already taken',
);
}
}
return await prisma.user.update({
@@ -34,16 +71,21 @@ export const updatePublicProfile = async ({ userId, url }: UpdatePublicProfileOp
},
data: {
url,
userProfile: {
profile: {
upsert: {
create: {
bio: '',
bio,
enabled,
},
update: {
bio: '',
bio,
enabled,
},
},
},
},
include: {
profile: true,
},
});
};