본문 바로가기

웹개발

게시판-자기 글 수정, 삭제, 비밀글

<자기 글 수정, 삭제>

자기 글인 경우에 수정, 삭제 버튼이 활성화되게 하였다.

posts 테이블에 writer라는 속성을 넣어서 글을 쓸 때 username을 넣도록 하였다.

그리고 read에서 iswriter라는 변수를 ejs 파일로 전달하였다.

const iswriter = req.session.user && req.session.user.username === post.writer;
res.render('board/read', { post: post, iswriter: iswriter });

이렇게 전달한 iswriter를 read.ejs 파일에서 받아서 조건문을 설정하였다.

<% if (iswriter) { %>
        <form action="/board/edit/<%= post.idx %>" method="get">
            <button type="submit">글 수정</button>
        </form>

        <form action="/board/delete/<%= post.idx %>" method="post">
            <button type="submit">글 삭제</button>

        </form>
    <% } %>

이렇게 iswriter가 참일 때 수정과 삭제 버튼을 만들었다.

edit은 edit 페이지로 이동하도록 하였고, delete는 post로 요청을 보내서 페이지 이동 없이 처리를 하였다.

edit부터 살펴보면,

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>게시글 수정</title>
</head>
<body>
    <h1>게시글 수정</h1>
    <form action="/board/update/<%= post.idx %>" method="post">
        <label for="title">제목:</label>
        <input type="text" id="title" name="title" value="<%= post.title %>" required>
        <br>
        <label for="content">내용:</label>
        <textarea id="content" name="content" rows="10" required><%= post.content %></textarea>
        <br>

        <button type="submit">수정 완료</button>
    </form>
</body>
</html>

이렇게 게시글을 수정할 수 있는 양식을 놓고 update로 post 요청을 보냈다. 

router.get('/edit/:id', async (req, res) => {
    const postId = req.params.id;
    const post = await db.posts.findByPk(postId);
    res.render('board/edit', { post });
});

router.post('/update/:id', async (req, res) => {
    const postId = req.params.id;
    const { title, content} = req.body;
    const result = await db.posts.update({ title, content }, { where: { idx: postId } });
    res.redirect('/board');
});

edit 링크는 edit.ejs 파일을 렌더링하고, edit.ejs 파일 안에서 update 링크로 post 요청을 보내면, posts.update 함수로 

입력받은 title과 content로 업데이트를 하고 board로 redirect 했다.

router.post('/delete/:id', (req, res) => {
    const postId = req.params.id;
    db.posts.destroy({
        where:{idx:postId}
    }).then(function(result){
        res.redirect('/board');
    })
})

delete은 전이랑 크게 달라지지 않았다.

 

 

<비밀글>

비밀글 기능을 만들기 위해 posts 테이블에 secret과 password 속성을 추가하였다.

module.exports = function(sequelize, DataTypes){ 
    return sequelize.define('posts', {
      idx: {
        type : DataTypes.INTEGER,
        autoIncrement: true,
        primaryKey: true,
        allowNull: false
      },
      title: {
        type: DataTypes.STRING(255),
        allowNull: false
      },
      content: {
        type: DataTypes.TEXT,
        allowNull: false
      },
      writer: {
        type: DataTypes.STRING(255),
        allowNull: false
      },
      secret: {
        type: DataTypes.BOOLEAN,
        defaultValue: false,
      },
      password: {
        type: DataTypes.STRING,
        allowNull: true,
      }
    });
}

secret은 비밀글인지 나타내는 bool 변수이고,

password는 비밀글이 아닌 경우 null이기 때문에 allowNull을 true로 설정했다.

 

그리고 write를 할 때 비밀글인지, 비밀번호를 입력하게 하기 위해서 write.ejs 파일을 수정하였다.

<label for="secret">비밀글:</label>
<input type="checkbox" id="secret" name="secret">

<label for="password">비밀번호 (비밀글일 경우):</label>
<input type="password" id="password" name="password">

이렇게 추가하였다. 

router.post('/write', async(req, res) => {
    const { title, content, secret, password } = req.body;

    if(!req.session.user){
        res.redirect('/auth/login');
    }

    const hashedPassword = secret && password ? await bcrypt.hash(password, 10) : null;

    db.posts.create({
        title: title,
        content: content,
        writer: req.session.user.username,
        secret: secret === 'on',
        password: hashedPassword
    }).then(function(result){
        res.redirect('/board');
    })
});

라우터에서는 전에 로그인 비밀번호를 암호화했던 것과 같은 방식으로 비밀번호를 암호화해주고,

create를 할 때 secret과 password 속성을 추가했다. 

 

읽을 때, read 부분이 좀 많이 달라졌는데,

우선 get 방식의 read/id부터 보면, 처음 게시판에서 글을 클릭해서 들어오는 링크인데 

router.get('/read/:id', async(req, res) => {
    const postId = req.params.id;
    const post = await db.posts.findByPk(postId)
    const iswriter = req.session.user && req.session.user.username === post.writer;

    if (post.secret && (!req.session.user || req.session.user.username !== post.writer || 1 === 1)) {
        return res.render('board/secret', { postId: post.idx });
    }

    res.render('board/read', { post: post, iswriter: iswriter });
});

iswriter로 자기 글인지 판단하고, 비밀글이고, 자기 글이 아니거나 로그인되어 있지 않은 경우 secret 파일로 이동한다.

(1 === 1 은 원래 있으면 안되지만, 기능을 테스트해 볼 때 계정 2개로 왔다갔다 하면서 하기 너무 오래 걸려서 잠시 저렇게 해두었다.)

그리고 만약 자기글이거나 비밀글이 아니면, 바로 read.ejs 파일이 렌더링 되어서 글을 볼 수 있다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="/public/main.css" rel="stylesheet" />
</head>
<body>
    <h1>비밀글입니다. 비밀번호를 입력하세요.</h1>
    <form action="/board/read/<%= postId %>/secret" method="post">
        <label for="password">비밀번호:</label>
        <input type="password" id="password" name="password">
        <button type="submit">확인</button>
    </form>
</body>
</html>

secret.ejs 파일이다. 비밀번호를 입력하면, read/id/secret링크로 post 요청을 보낸다.

router.post('/read/:id/secret', async (req, res) => {
    const postId = req.params.id;
    const { password } = req.body;
    const post = await db.posts.findByPk(postId);

    if (!post) {
        return res.status(404).send('게시글을 찾을 수 없습니다.');
    }

    if (await bcrypt.compare(password, post.password)) {
        const iswriter = req.session.user && req.session.user.username === post.writer;
        return res.render('board/read', { post: post, iswriter: iswriter });
    } else {
        return res.render('board/secret', { postId: post.id, error: '비밀번호가 틀렸습니다.' });
    }
});

라우터에서 해당 요청을 보면, id로 테이블에서 게시글 데이터를 가져오고, bcrypt.compare 함수로 비밀번호가 맞는지 확인한다. 비밀번호가 들리면 그대로 다시 secret.ejs 파일을 렌더링하고, 비밀번호가 맞으면 read.ejs를 렌더링한다.

 

그리고 추가로 board의 main.ejs 파일에서 글 목록을 보여줄 때 비밀글인 경우 미리 표시가 되도록 하기 위해서

<ul>
        <% posts.forEach(function(post) { %>
            <li><a href="/board/read/<%= post.idx %>"><%= post.title %></a></li>
            <% if (post.secret) { %>
                <span>(비밀글)</span>
            <% } %>
        <% }); %>
    </ul>

main.ejs 파일을 이렇게 약간 수정하였다.

'웹개발' 카테고리의 다른 글

게시판-추천  (0) 2023.10.26
게시판-댓글  (0) 2023.10.26
게시판-이메일 인증, 아이디 찾기  (0) 2023.10.25
게시판-회원가입, 로그인  (0) 2023.10.24
게시판-CRUD  (0) 2023.10.24