add:utils:file:store | create utility for store file in system
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@ -54,4 +54,7 @@ server.exe
|
||||
|
||||
# debug and cached routes
|
||||
/src/routes.ts
|
||||
/src/modules/debug
|
||||
/src/modules/debug
|
||||
|
||||
# uploaded files
|
||||
/uploads
|
||||
@ -13,6 +13,7 @@
|
||||
"@prisma/client": "^6.7.0",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/jsonwebtoken": "^9.0.9",
|
||||
"@types/mime-types": "^3.0.1",
|
||||
"aws-sdk": "^2.1692.0",
|
||||
"bcrypt": "^5.1.1",
|
||||
"cookie": "^1.0.2",
|
||||
@ -20,6 +21,7 @@
|
||||
"ioredis": "^5.6.1",
|
||||
"joi": "^17.13.3",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"mime-types": "^3.0.1",
|
||||
"mock-aws-s3": "^4.0.2",
|
||||
"nock": "^14.0.4",
|
||||
"ua-parser-js": "^2.0.3"
|
||||
|
||||
0
src/constants/file
Normal file
0
src/constants/file
Normal file
26
src/helpers/files/saveFile/index.ts
Normal file
26
src/helpers/files/saveFile/index.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { mkdir, writeFile } from "fs/promises";
|
||||
import path from "path";
|
||||
import crypto from "crypto";
|
||||
import mime from "mime-types";
|
||||
|
||||
interface SaveFileOptions {
|
||||
folder: string;
|
||||
prefix?: string;
|
||||
}
|
||||
|
||||
export const saveFile = async (
|
||||
file: File,
|
||||
{ folder, prefix }: SaveFileOptions
|
||||
): Promise<string> => {
|
||||
const ext = mime.extension(file.type) || "bin";
|
||||
const uniqueName = `${prefix ?? ""}${crypto.randomUUID()}.${ext}`;
|
||||
|
||||
const relativeFolder = path.join("uploads", folder);
|
||||
const relativePath = path.join(relativeFolder, uniqueName);
|
||||
const absolutePath = path.join(process.cwd(), relativePath);
|
||||
|
||||
await mkdir(path.dirname(absolutePath), { recursive: true });
|
||||
await writeFile(absolutePath, Buffer.from(await file.arrayBuffer()));
|
||||
|
||||
return relativePath;
|
||||
};
|
||||
17
src/helpers/files/saveFile/modules/saveAvatar.ts
Normal file
17
src/helpers/files/saveFile/modules/saveAvatar.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { saveFile } from "..";
|
||||
import { AppError } from "../../../error/instances/app";
|
||||
|
||||
export const saveAvatar = async (file: File): Promise<string> => {
|
||||
const allowedTypes = ["image/png", "image/jpeg", "image/webp"];
|
||||
if (!allowedTypes.includes(file.type)) {
|
||||
throw new AppError(
|
||||
415,
|
||||
"Unsupported Media Type. File must be in .jpg, .png, or .webp format"
|
||||
);
|
||||
}
|
||||
|
||||
return await saveFile(file, {
|
||||
folder: "avatar",
|
||||
prefix: "usr-",
|
||||
});
|
||||
};
|
||||
@ -7,6 +7,7 @@ import { checkUserEmailAndUsernameAvailabillityService } from "./checkUserEmailA
|
||||
import { logoutService } from "../../auth/services/logout.service";
|
||||
import { loginFromSystemService } from "../../auth/services/loginFromSystem.service";
|
||||
import { UserHeaderInformation } from "../../../helpers/http/userHeader/getUserHeaderInformation/types";
|
||||
import { saveAvatar } from "../../../helpers/files/saveFile/modules/saveAvatar";
|
||||
|
||||
export const editUserService = async (
|
||||
cookie: string,
|
||||
@ -29,6 +30,11 @@ export const editUserService = async (
|
||||
"The username or email has already taken by another user."
|
||||
);
|
||||
|
||||
// Store the avatar to the file system if provided in the payload
|
||||
let storeAvatar: string | undefined = undefined;
|
||||
if (payload.profilePicture)
|
||||
storeAvatar = await saveAvatar(payload.profilePicture as File);
|
||||
|
||||
// Prepare the fields to update, only include fields that are provided in the payload
|
||||
const fieldsToUpdate: Partial<Prisma.UserUpdateInput> = {
|
||||
...(payload.username && payload.username !== jwtSession.user.username
|
||||
@ -47,9 +53,7 @@ export const editUserService = async (
|
||||
...(payload.bioProfile !== undefined
|
||||
? { bioProfile: payload.bioProfile }
|
||||
: {}),
|
||||
...(payload.profilePicture !== undefined
|
||||
? { profilePicture: payload.profilePicture }
|
||||
: {}),
|
||||
...(storeAvatar !== undefined ? { profilePicture: storeAvatar } : {}),
|
||||
...(payload.commentPicture !== undefined
|
||||
? { commentPicture: payload.commentPicture }
|
||||
: {}),
|
||||
@ -61,6 +65,7 @@ export const editUserService = async (
|
||||
// Update the user in the database, use username from the JWT session to find the user
|
||||
await updateUserRepo(jwtSession.user.username, fieldsToUpdate);
|
||||
|
||||
// Clear the session and re-login the user to get a new JWT token
|
||||
await logoutService(cookie);
|
||||
const newUserSession = await loginFromSystemService(
|
||||
jwtSession.userId,
|
||||
|
||||
Reference in New Issue
Block a user