mirror of
https://github.com/bubblecup-12/VogelSocialMedia.git
synced 2025-07-08 13:38:47 +00:00
242 lines
6.3 KiB
TypeScript
242 lines
6.3 KiB
TypeScript
import express, { Request, Response } from "express";
|
|
import { JwtPayload } from "jsonwebtoken";
|
|
import { PrismaClient } from "../../prisma/app/generated/prisma/client";
|
|
import dotenv from "dotenv";
|
|
import { StatusCodes } from "http-status-codes";
|
|
import multer from "multer";
|
|
import { minioClient } from "../server";
|
|
|
|
const app = express();
|
|
app.use(express.json());
|
|
const prisma = new PrismaClient();
|
|
// load environment variables from .env file
|
|
dotenv.config();
|
|
|
|
type PublicUser = {
|
|
id: string;
|
|
username: string;
|
|
bio: string | null;
|
|
profilePictureUrl: string | null;
|
|
followers: number;
|
|
following: number;
|
|
posts: number;
|
|
};
|
|
const getUser: (userId: string) => Promise<PublicUser | undefined> = async (
|
|
userId: string
|
|
) => {
|
|
const user = await prisma.user.findUnique({
|
|
where: { id: userId },
|
|
include: { profilePicture: true },
|
|
});
|
|
if (user) {
|
|
let profilePictureUrl: string | null = null;
|
|
if (user.profilePicture) {
|
|
profilePictureUrl = await minioClient.presignedGetObject(
|
|
user.profilePicture.bucket,
|
|
user.profilePicture.objectName,
|
|
60 * 10
|
|
);
|
|
}
|
|
const followerCount = await prisma.follow.count({
|
|
where: {
|
|
followedUserId: userId,
|
|
},
|
|
});
|
|
|
|
const followingCount = await prisma.follow.count({
|
|
where: {
|
|
followingUserId: userId,
|
|
},
|
|
});
|
|
const postCount = await prisma.post.count({
|
|
where: {
|
|
userId: userId,
|
|
},
|
|
});
|
|
const publicUser: PublicUser = {
|
|
id: user.id,
|
|
username: user.username,
|
|
bio: user.bio,
|
|
profilePictureUrl,
|
|
followers: followerCount,
|
|
following: followingCount,
|
|
posts: postCount,
|
|
};
|
|
return publicUser;
|
|
}
|
|
return undefined;
|
|
};
|
|
|
|
export const uploadProfilePicture = async (req: Request, res: Response) => {
|
|
const user: JwtPayload = req.user!;
|
|
const file = req.file as Express.Multer.File;
|
|
const BUCKET = "images"; // Name of the bucket where the images are stored
|
|
try {
|
|
const objectName = `${user.sub}/profile.${file.mimetype.split("/")[1]}`;
|
|
await minioClient.putObject(BUCKET, objectName, file.buffer);
|
|
const url = await minioClient.presignedGetObject(
|
|
BUCKET,
|
|
objectName,
|
|
60 * 10
|
|
);
|
|
const oldImage = await prisma.user.findUnique({
|
|
where: { id: user.sub },
|
|
select: { profilePictureId: true },
|
|
});
|
|
|
|
const media = await prisma.media.create({
|
|
data: {
|
|
originalFilename: file.originalname,
|
|
objectName: objectName,
|
|
mimeType: file.mimetype,
|
|
size: file.size,
|
|
bucket: BUCKET,
|
|
uploader: { connect: { id: user.sub } },
|
|
},
|
|
});
|
|
|
|
await prisma.user.update({
|
|
where: { id: user.sub },
|
|
data: {
|
|
profilePicture: {
|
|
connect: { id: media.id },
|
|
},
|
|
},
|
|
});
|
|
|
|
if (oldImage?.profilePictureId && oldImage.profilePictureId !== media.id) {
|
|
await prisma.media.delete({
|
|
where: { id: oldImage.profilePictureId },
|
|
});
|
|
}
|
|
|
|
res.status(StatusCodes.CREATED).json({
|
|
originalName: file.originalname,
|
|
objectName: objectName,
|
|
size: file.size,
|
|
mimetype: file.mimetype,
|
|
url: url,
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
|
|
error: "Upload failed",
|
|
details: [{ message: "Internal server error" }],
|
|
});
|
|
}
|
|
};
|
|
|
|
export const getProfilePicture = async (req: Request, res: Response) => {
|
|
const username: string = req.params.username;
|
|
if (!username) {
|
|
res.status(StatusCodes.BAD_REQUEST).json({
|
|
error: "no username",
|
|
details: [{ message: "Username is required" }],
|
|
});
|
|
return;
|
|
}
|
|
try {
|
|
const user = await prisma.user.findUnique({
|
|
where: { username },
|
|
include: { profilePicture: true },
|
|
});
|
|
|
|
if (!user) {
|
|
res.status(StatusCodes.NOT_FOUND).json({
|
|
error: "User not found",
|
|
details: [
|
|
{ message: `User with username '${username}' does not exist.` },
|
|
],
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (!user.profilePicture) {
|
|
res.status(StatusCodes.NOT_FOUND).json({
|
|
error: "No profile picture",
|
|
details: [{ message: "This user does not have a profile picture." }],
|
|
});
|
|
return;
|
|
}
|
|
|
|
const profilePictureUrl = await minioClient.presignedGetObject(
|
|
user.profilePicture.bucket,
|
|
user.profilePicture.objectName,
|
|
60 * 10 // 10 minutes expiration
|
|
);
|
|
|
|
res.status(StatusCodes.OK).json({ url: profilePictureUrl });
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
|
|
error: "Retrieving image failed",
|
|
details: ["Internal server error"],
|
|
});
|
|
return;
|
|
}
|
|
};
|
|
|
|
export const updateBio = async (req: Request, res: Response) => {
|
|
const user: JwtPayload = req.user!;
|
|
const bio: string = req.body.bio;
|
|
try {
|
|
const updatedUser = await prisma.user.update({
|
|
where: { id: user.sub },
|
|
data: {
|
|
bio: bio,
|
|
},
|
|
});
|
|
const publicUser: PublicUser | undefined = await getUser(user.sub!);
|
|
res.status(StatusCodes.OK).json({
|
|
message: "User found",
|
|
data: publicUser,
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
|
|
error: "Updating bio failed",
|
|
details: [{ message: "Internal Server error" }],
|
|
});
|
|
}
|
|
};
|
|
// Endpoint to get user data
|
|
export const getProfile = async (req: Request, res: Response) => {
|
|
const username: string = req.params.username as string;
|
|
if (!username) {
|
|
res.status(StatusCodes.BAD_REQUEST).json({
|
|
error: "no username",
|
|
details: [{ message: "Username is required" }],
|
|
});
|
|
return;
|
|
}
|
|
try {
|
|
const user = await prisma.user.findUnique({
|
|
where: { username },
|
|
include: { profilePicture: true },
|
|
});
|
|
|
|
if (!user) {
|
|
res.status(StatusCodes.NOT_FOUND).json({
|
|
error: "User not found",
|
|
details: [
|
|
{ message: `User with username '${username}' does not exist.` },
|
|
],
|
|
});
|
|
return;
|
|
}
|
|
|
|
const publicUser: PublicUser | undefined = await getUser(user.id);
|
|
|
|
res.status(StatusCodes.OK).json({
|
|
message: "User found",
|
|
data: publicUser,
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
|
|
error: "Retrieving image failed",
|
|
details: ["Error while retrieving the image"],
|
|
});
|
|
return;
|
|
}
|
|
};
|