Day5 - 커뮤니티 생성

RINM·2023년 1월 1일
0

NextJS - Reddit Clone

목록 보기
5/9

커뮤니티(sub) 생성 페이지

Frontend

커뮤니티 생성 페이지
Name, Title, Description을 입력받아 Backend에 전달
이후 생성된 커뮤니티 메이지로 이동

const handleSubmit = async (e:FormEvent) =>{
        e.preventDefault();
        try {
            const res= await axios.post('/subs',{
                name,
                title,
                description
            })
            console.log('res',res);
            router.push(`/r/${res.data.name}`)
        } catch (error: any) {
            console.error(error);
            seterrors(error.response.data||{});
        }
    }

Backend

Verify User

유저 정보는 여러 페이지에서 공통적으로 필요한 경우가 많다.
유저 정보를 처리하는 미들웨어로 따로 분리한다.

User Middleware

토큰을 통해 사용자를 확인

import { NextFunction, Request, Response } from "express";
import  jwt from "jsonwebtoken";
import User from "../entity/User";

export default async (req: Request,res:Response, next:NextFunction) => {
    try {
        //Verify User
        const token = req.cookies.token;
        if(!token) return next()
    
        const username: any = jwt.verify(token,process.env.JWT_SECRET)
        
        const user = await User.findOneBy({username});
    
        //save user info to res.lacals.user
        res.locals.user = user;
      
      	return next()

    } catch (error) {
        console.error(error);
        return res.status(400).json({error: "User Verification Failed"})
        
    }

}

Auth Middleware

user가 존재하지 않을 때 error throw

import { NextFunction, Request, Response } from "express";
import User from "../entity/User";

export default async (req: Request,res:Response, next:NextFunction) => {
    try {
        //Authenticate User
        const user: User | undefined = res.locals.user;

        if(!user) throw new Error("Unauthenticated")
        
        return next();
      
    } catch (error) {
        console.error(error);
        return res.status(401).json({error: "Authentication Failed"})
    }

}

Middleware 적용

middleware를 사용하려는 곳의 라우터에 적용
지정된 api 처리 전에 먼저 작동

router.post('/',userMiddleware,authMiddleware,createSub)

backend에서 front의 쿠키를 가져와 사용할 수 있게 하는 모듈

app.use(cookieParser())

Query Builder

typeorm의 query builder를 사용하여 제출된 커뮤니티 이름이 이미 사용 중인지 확인한다.

//check if name or title is already used
const sub = await AppDataSource.getRepository(Sub)
	.createQueryBuilder("sub")
	.where("lower(sub.name) = :name",{name: name.toLowerCase()})
	.getOne()

인증에 따른 페이지 접근 제한

로그인하지 않은 사용자는 /sub/create에 접근할 수 없게 설정
로그인하지 않은 경우 /login으로 이동

Frontend

GetServerSideProps

서버에 사용자 인증을 요청
인증 에러 발생시 로그인 페이지로 이동

export const getServerSideProps : GetServerSideProps =async ({req,res}) => {
    try {
        const cookie = req.headers.cookie;

        //cookie missing
        if(!cookie) throw new Error("Missing auth token");

        //user authentication on backend
        await axios.get("/auth/me",{headers:{cookie}})

        return {props: {}}

    } catch (error) {
        //move to login page
        res.writeHead(307,{Location:"/login"}).end()
        
        return {props: {}}
    }
}

Backend

/auth/me API 생성
미들웨어를 거쳐서 user 정보가 전달된다.

const me = async (req: Request,res:Response) => {
    return res.json(res.locals.user)
}
router.get('/me',userMiddleware,authMiddleware,me)

0개의 댓글