Commit 6b56633c authored by Yoon, Daeki's avatar Yoon, Daeki 😅
Browse files

아바타 파일 업로드 로직 구현

parent a0a0c03e
import { connect } from "mongoose";
import { mongoUri } from "../src/config";
import { Role, User } from "../src/models";
import { userDb } from "../src/db";
const roles = [
["admin", 1],
["manager", 10],
["staff", 100],
["user", 1000],
["guest", 10000],
];
connect(mongoUri)
.then(async (mongoose) => {
const adminRole = await Role.findOne({ name: "admin" });
await userDb.createUser({
email: "admin@example.com",
name: "admin",
role: adminRole?._id,
password: "asdfasdf",
});
await mongoose.disconnect();
})
.catch((error) => console.log("롤 초기 생성 에러", error));
......@@ -50,7 +50,11 @@ export const hasRole = (roleName: string) => {
if (!req.auth) {
return res.status(401).send("로그인이 필요합니다");
}
const { userId } = req.auth;
if (!(await userDb.isValidUserId(userId))) {
return res.status(401).send("유효한 사용자가 아닙니다");
}
const userRole = await roleDb.findRoleByUserId(userId);
const maxRole = await roleDb.findRoleByName(roleName);
if (maxRole && Number(maxRole.priority) >= Number(userRole.priority)) {
......
import { NextFunction, Request, Response } from "express";
import formidable from "formidable";
import { isEmpty } from "../helpers";
import { asyncWrap } from "../helpers/asyncWrap";
import { TypedRequest } from "../types";
interface TypedRequest extends Request {
auth: any;
user: any;
files: any;
}
export const uploadAvatar = asyncWrap(async (reqExp, res, next) => {
const req = reqExp as TypedRequest;
const form = formidable({ multiples: false, uploadDir: "uploads" });
export const fileUpload = asyncWrap(async (req, res, next) => {
const typedReq = req as TypedRequest;
const form = formidable();
await new Promise((resolve, reject) => {
form.parse(req, (err, fields, files) => {
if (err) {
......@@ -20,15 +13,11 @@ export const fileUpload = asyncWrap(async (req, res, next) => {
return;
}
console.log("fields", fields);
console.log("files", files);
typedReq.body = fields;
// console.log("fields", fields);
// console.log("files", files);
req.body = fields;
req.files = files;
if (isEmpty(files)) {
typedReq.files = null;
} else {
typedReq.files = files;
}
resolve(files);
});
});
......
import { NextFunction, Request, Response } from "express";
import { userDb } from "../db";
import formidable from "formidable";
import fs from "fs/promises";
import { fileDb, userDb } from "../db";
import { asyncWrap } from "../helpers/asyncWrap";
import { FileInfo } from "../models";
import { TypedRequest } from "../types";
import { TypedRequestAuth } from "./auth.controller";
interface TypedRequest extends Request {
auth: any;
user: any;
files: any;
}
export const createUser = asyncWrap(async (reqExp, res) => {
const req = reqExp as TypedRequest;
const user = req.body;
console.log("user body", user);
console.log("files ", req.files);
const newUser = await userDb.createUser(user);
return res.json(newUser);
// console.log("user body", user);
// console.log("files ", req.files);
const file = req.files.avatar as formidable.File;
let avatar;
try {
// 1) 아바타 이미지 저장
if (file) {
avatar = new FileInfo({
name: file.originalFilename,
url: file.newFilename,
isNew: true,
});
await fileDb.save(avatar);
// 2) 사용자에 아바타 항목 추가
user.avatar = avatar;
}
// 3) 사용자 만들기
const newUser = await userDb.createUser(user);
// 주의: ref는 반드시 save를 해야 디비에 생성이 됩니다.
return res.json(newUser);
} catch (error: any) {
console.log("error in create user:", error);
// 오류 발생시 저장된 파일 제거
if (file) {
avatar && (await fileDb.deleteFileById(avatar._id.toString()));
await fs.unlink(file.filepath);
}
res.status(422).send(error.message || "사용자 생성 오류");
}
});
export const deleteUser = asyncWrap(async (req, res) => {
......
import formidable from "formidable";
import { HydratedDocument } from "mongoose";
import { FileInfo, IFileInfo } from "../models";
export const createFile = async (file: formidable.File) => {
const newFile = new FileInfo({
name: file.originalFilename,
url: file.newFilename,
});
const retFile = await newFile.save();
return retFile;
};
export const deleteFileById = async (fileId: string) => {
return await FileInfo.findByIdAndDelete(fileId);
};
export const save = async (fileInfo: HydratedDocument<IFileInfo>) => {
return await fileInfo.save();
};
export * as roleDb from "./role.db";
export * as fileDb from "./file.db";
export * as questionDb from "./question.db";
export * as roleDb from "./role.db";
export * as surveyDb from "./survey.db";
export * as userDb from "./user.db";
......@@ -15,6 +15,7 @@ export const createUser = async (user: IUser) => {
email: user.email,
password: hash,
role: userRole,
avatar: user.avatar,
isNew: true,
});
const retUser = await newUser.save();
......@@ -45,7 +46,10 @@ export const findUserByEmail = async (
};
export const getUsers = async () => {
const users = await User.find({});
const users = await User.find({}).populate({
path: "avatar",
select: "_id name url",
});
return users;
};
......@@ -57,3 +61,12 @@ export const isUser = async (email: string) => {
return false;
}
};
export const isValidUserId = async (userId: string) => {
const user = await User.findById(userId);
if (user) {
return true;
} else {
return false;
}
};
import { model, Schema } from "mongoose";
interface IFile {
export interface IFileInfo {
name: string;
path: string;
url: string;
}
const schema = new Schema<IFile>(
const schema = new Schema<IFileInfo>(
{
name: { type: String },
path: { type: String },
url: { type: String },
},
{ timestamps: true, toJSON: { versionKey: false } }
);
export default model<IFile>("File", schema);
export default model<IFileInfo>("FileInfo", schema);
export { default as File } from "./file.model";
export { default as FileInfo, IFileInfo } from "./fileinfo.model";
export { default as Question, IQuestion } from "./question.model";
export { default as Role } from "./role.model";
export { default as Survey, ISurvey } from "./survey.model";
......
......@@ -24,7 +24,7 @@ const schema = new Schema<IUser>(
name: { type: String },
password: { type: String, required: true, select: false },
role: { type: Schema.Types.ObjectId, ref: "Role" },
avatar: { type: Schema.Types.ObjectId, ref: "File" },
avatar: { type: Schema.Types.ObjectId, ref: "FileInfo" },
},
{
toJSON: {
......
......@@ -6,7 +6,12 @@ const router = express.Router();
router
.route("/")
.get(authCtrl.requireLogin, userCtrl.getUsers)
.post(authCtrl.requireLogin, fileCtrl.fileUpload, userCtrl.createUser);
.post(
authCtrl.requireLogin,
authCtrl.hasRole("admin"),
fileCtrl.uploadAvatar,
userCtrl.createUser
);
router
.route("/:userId")
......
import { Request } from "express";
import { Files } from "formidable";
export interface TypedRequest extends Request {
auth: any;
user: any;
files: Files;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment