Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/main/java/lobby/controller/CreateRoomController.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
roomPlayerDAO.enterIfAbsent(roomResult.getId(), hostUserId);

LobbyWebSocket.broadcastRoomList();

session.setAttribute("ROOM_AUTH_" + roomId, true);

response.sendRedirect(
request.getContextPath() + "/room?roomId=" + URLEncoder.encode(roomId, StandardCharsets.UTF_8)
request.getContextPath() + "/room/enter?roomId=" + URLEncoder.encode(roomId, StandardCharsets.UTF_8)
+ "&playType=" + URLEncoder.encode(playType, StandardCharsets.UTF_8));

} catch (Exception e) {
e.printStackTrace();
throw new ServletException("방 생성 실패", e);
Expand Down
36 changes: 35 additions & 1 deletion src/main/java/room/controller/EnterRoomController.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import javax.servlet.http.HttpSession;

import lobby.ws.LobbyWebSocket;
import room.dao.RoomDAO;
import room.dao.RoomDAOImpl;
import room.dao.RoomPlayerDAO;
import room.dao.RoomPlayerDAOImpl;

Expand All @@ -20,28 +22,60 @@ public class EnterRoomController extends HttpServlet {
private static final long serialVersionUID = 1L;

private final RoomPlayerDAO roomPlayerDao = new RoomPlayerDAOImpl();
private final RoomDAO roomDAO = new RoomDAOImpl();

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
handler(request, response);
}

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
handler(request, response);
}

protected void handler(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

String ctx = request.getContextPath();

try {
String roomId = request.getParameter("roomId");
String playType = request.getParameter("playType");
String roomPwd = request.getParameter("roomPwd");
boolean isPrivate = roomDAO.isPrivateRoom(roomId);
String hostUserId = roomDAO.findHostUserIdByRoomId(roomId);

if (roomId == null || roomId.isBlank() || playType == null || playType.isBlank()) {
response.sendRedirect(ctx + "/lobby?error=missing_room_id");
response.sendRedirect(ctx + "/lobby?error=missing_room_info");
return;
}
Comment thread
gaeunnlee marked this conversation as resolved.

HttpSession session = request.getSession(false);

String userId = (session == null) ? null : (String)session.getAttribute("loginUserId");
boolean isHost = userId.equals(hostUserId);

if (userId == null || userId.isBlank()) {
response.sendRedirect(ctx + "/lobby?error=enter_failed");
return;
}
Comment thread
gaeunnlee marked this conversation as resolved.
Outdated

if (isPrivate && !isHost) {
if (roomPwd == null || roomPwd.isBlank()) {
response.sendRedirect(ctx + "/lobby?error=need_password");
return;
}

if (!roomDAO.matchRoomPassword(roomId, roomPwd)) {
response.sendRedirect(ctx + "/lobby?error=wrong_password");
return;
}
session.setAttribute("ROOM_AUTH_" + roomId, true);
}
Comment thread
gaeunnlee marked this conversation as resolved.

roomPlayerDao.enterIfAbsent(roomId, userId);

System.out.println("[ENTER] ctx=" + request.getContextPath() + " roomId=" + roomId + " userId=" + userId);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/room/controller/ExitRoomController.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)

try {
roomService.exitAndHandleHost(roomId, userId);
session.removeAttribute("ROOM_AUTH_" + roomId);
System.out.println("[EXIT] ctx=" + request.getContextPath() + " roomId=" + roomId + " userId=" + userId);
LobbyWebSocket.broadcastRoomList();
response.sendRedirect(ctx + "/lobby");
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/room/controller/ViewRoomController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package room.controller;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
Expand Down Expand Up @@ -31,6 +33,15 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
return;
}

boolean isPrivate = roomDAO.isPrivateRoom(roomId);
Boolean isRoomAuthed = (Boolean)session.getAttribute("ROOM_AUTH_" + roomId);

if (isPrivate && (isRoomAuthed == null || !isRoomAuthed)) {
response.sendRedirect("/room/enter?roomId=" + URLEncoder.encode(roomId, StandardCharsets.UTF_8)
+ "&playType=" + URLEncoder.encode(playType, StandardCharsets.UTF_8));
Comment thread
gaeunnlee marked this conversation as resolved.
Outdated
return;
}

request.setAttribute("roomId", roomId);
request.setAttribute("playType", playType);

Expand Down
22 changes: 22 additions & 0 deletions src/main/java/room/dao/RoomDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,26 @@ RoomDTO createRoom(
*/
String findHostUserIdByRoomId(String roomId) throws Exception;

/**
* 비공개 방 비밀번호 검증
*
* @param roomId 방 ID
* @param inputPwd 사용자가 입력한 비밀번호 (평문)
*
* @return true - 비밀번호 일치
* false - 비밀번호 불일치 또는 존재하지 않는 방
*
* 동작 규칙
* - 공개방(isPublic="0")은 호출 대상이 아님
* - 비공개방(isPublic="1")에 대해서만 room_pwd와 비교
*/
boolean matchRoomPassword(String roomId, String inputPwd) throws Exception;

/**
* 방이 비공개방(비밀번호가 설정된 방)인지 여부 조
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
*
* @param roomId 조회할 방 ID
*/
boolean isPrivateRoom(String roomId) throws Exception;

}
46 changes: 46 additions & 0 deletions src/main/java/room/dao/RoomDAOImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,52 @@ public String findHostUserIdByRoomId(String roomId) throws Exception {
}
}

public boolean matchRoomPassword(String roomId, String inputPwd) throws Exception {
final String query = """
SELECT COUNT(*)
FROM room
WHERE id = ?
AND is_public = '1'
AND room_pwd = ?
""";

try (Connection conn = DB.getConnection();
PreparedStatement pstmt = conn.prepareStatement(query)) {

pstmt.setString(1, roomId);
pstmt.setString(2, inputPwd);

try (ResultSet rs = pstmt.executeQuery()) {
rs.next();
return rs.getInt(1) == 1;
}
}
}

@Override
public boolean isPrivateRoom(String roomId) throws Exception {

String query = """
SELECT COUNT(*)
FROM room
WHERE id = ?
AND room_pwd IS NOT NULL
""";

try (Connection conn = DB.getConnection();
PreparedStatement pstmt = conn.prepareStatement(query)) {

pstmt.setString(1, roomId);

try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
return rs.getInt(1) > 0;
}
return false;
}
}
}

private RoomDTO mapToRoom(ResultSet rs) throws SQLException {
return RoomDTO.builder()
.id(rs.getString("id"))
Expand Down
4 changes: 2 additions & 2 deletions src/main/webapp/WEB-INF/views/room/create.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,11 @@
<div class="row">
<label>공개 여부</label>
<label>
<input type="radio" name="isPublic" value="1" checked onclick="togglePwd(false)" />
<input type="radio" name="isPublic" value="0" checked onclick="togglePwd(false)" />
공개
</label>
<label>
<input type="radio" name="isPublic" value="0" onclick="togglePwd(true)" />
<input type="radio" name="isPublic" value="1" onclick="togglePwd(true)" />
비공개 🔒
</label>
</div>
Expand Down
39 changes: 38 additions & 1 deletion src/main/webapp/static/lobby/lobby.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@
function toRowHtml(r) {
const roomId = r.id ?? "";
const roomName = r.roomName ?? "-";
const isPublic = (String(r.isPublic) === "1") ? "공개" : "비공개 🔒";
const isPublic = (String(r.isPublic) === "0") ? "공개" : "비공개 🔒";
const playType = (String(r.playType) === "0") ? "개인전" : "팀전";
const current = r.currentUserCnt ?? 0;
const total = r.totalUserCnt ?? 0;
const isPublicId = (String(r.isPublic) === "0") ? "public" : "private";


const disabledAttr = IS_LOGIN ? "" : "disabled";
Expand All @@ -98,12 +99,48 @@
<form class="enter-room-form" action="${CTX}/room/enter"" method="post">
<input type="hidden" name="playType" value="${escapeHtml(r.playType)}" />
<input type="hidden" name="roomId" value="${escapeHtml(roomId)}" />
<input type="hidden" name="isPublic" value="${escapeHtml(isPublicId)}" />
<button type="submit" ${disabledAttr} ${titleAttr}>입장</button>
</form>
</td>
</tr>
`;
}

document.addEventListener("submit", function (e) {
const form = e.target;

if (!(form instanceof HTMLFormElement)) return;
if (!form.classList.contains("enter-room-form")) return;

const isPublicEl = form.querySelector("input[name='isPublic']");
const isPublic = isPublicEl ? isPublicEl.value : "public";

if (isPublic === "public") return;

e.preventDefault();

const pwd = prompt("비밀번호를 입력하세요");
if (pwd === null) return; // 취소

const trimmed = pwd.trim();
if (!trimmed) {
alert("비밀번호를 입력해주세요.");
return;
}

let pwdInput = form.querySelector("input[name='password']");
if (!pwdInput) {
pwdInput = document.createElement("input");
pwdInput.type = "hidden";
pwdInput.name = "roomPwd";
Comment thread
gaeunnlee marked this conversation as resolved.
Outdated
form.appendChild(pwdInput);
}
pwdInput.value = trimmed;

form.submit();
});


function escapeHtml(str) {
return String(str)
Expand Down