커밋 메시지
This commit is contained in:
@ -38,7 +38,6 @@ header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
background-color: #f1f1f1;
|
||||
padding: 20px;
|
||||
height: calc(100vh - 60px);
|
||||
}
|
||||
@ -48,10 +47,14 @@ header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
background-color: #ccc;
|
||||
|
||||
}
|
||||
|
||||
.login-section {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.login-button {
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
@ -82,6 +85,7 @@ hr{
|
||||
/*메인*/
|
||||
|
||||
|
||||
/* 테이블 스타일 */
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
@ -89,16 +93,17 @@ table {
|
||||
}
|
||||
|
||||
table th, table td {
|
||||
border: 1px solid #ccc;
|
||||
border: none; /* 모든 테두리 제거 */
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
border-right:none;
|
||||
border-left:none;
|
||||
border-top:none;
|
||||
border-bottom:none;
|
||||
|
||||
}
|
||||
|
||||
/* 세로줄, 가로줄 모두 제거 */
|
||||
table td, table th {
|
||||
border: none; /* 완전히 모든 테두리 제거 */
|
||||
}
|
||||
|
||||
|
||||
.write-button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -1,17 +1,21 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { BrowserRouter as Router, Route, Routes, Link, useNavigate } from 'react-router-dom';
|
||||
import { Route, Routes, Link, useNavigate } from 'react-router-dom';
|
||||
import Register from './register';
|
||||
import Login from './login';
|
||||
import MyPosts from './MyPosts';
|
||||
import EditProfile from './EditProfile';
|
||||
import BoardList from './BoardList';
|
||||
import CreatePost from './CreatePost';
|
||||
import FindId from './FindId';
|
||||
import FindPassword from './FindPassword';
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
const [user, setUser] = useState(null); // 로그인된 사용자 정보를 저장하는 상태
|
||||
const [postCount, setPostCount] = useState(0);
|
||||
const [error, setError] = useState(null); // API 호출 중 발생한 에러 상태
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
// 로그인 상태 유지
|
||||
useEffect(() => {
|
||||
@ -19,12 +23,14 @@ function App() {
|
||||
try {
|
||||
const response = await fetch('http://localhost:8080/users/current-user', {
|
||||
method: 'GET',
|
||||
credentials: 'include', // 세션 기반 쿠키 전송
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const user = await response.json();
|
||||
setUser(user);
|
||||
} else if (response.status === 401) {
|
||||
setUser(null); // 인증 실패 시 로그아웃 상태로 설정
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('현재 사용자 정보 불러오기 실패:', error);
|
||||
@ -55,61 +61,67 @@ function App() {
|
||||
}, [user]);
|
||||
|
||||
return (
|
||||
<Router>
|
||||
<div className="container">
|
||||
{/* 고정된 헤더 */}
|
||||
<header>
|
||||
<div className="home-link">홈 ></div>
|
||||
<div className="banner">메인 배너</div>
|
||||
</header>
|
||||
<div className="container">
|
||||
{/* 고정된 헤더 */}
|
||||
<header>
|
||||
<div className="home-link">홈 ></div>
|
||||
<div className="banner">메인 배너</div>
|
||||
</header>
|
||||
|
||||
{/* 고정된 사이드바 */}
|
||||
<aside className="aside-container">
|
||||
<RenderAside user={user} setUser={setUser} postCount={postCount} error={error} />
|
||||
<div className="aside-section">
|
||||
<ul className="category">
|
||||
<li>카테고리</li>
|
||||
<hr width="100%" color="black"></hr>
|
||||
<Link to="/">전체게시판</Link><br />
|
||||
<Link to="/shared">공유게시판</Link><br />
|
||||
<Link to="/questions">질문게시판</Link><br />
|
||||
<Link to="/free">자유게시판</Link>
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
{/* 고정된 사이드바 */}
|
||||
<aside className="aside-container">
|
||||
<RenderAside user={user} setUser={setUser} postCount={postCount} error={error} />
|
||||
<div className="aside-section">
|
||||
<ul className="category">
|
||||
<li>카테고리</li>
|
||||
<hr width="100%" color="black"></hr>
|
||||
<Link to="/">전체게시판</Link><br />
|
||||
<Link to="/shared">공지게시판</Link><br />
|
||||
<Link to="/questions">질문게시판</Link><br />
|
||||
<Link to="/free">자유게시판</Link>
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{/* 동적 콘텐츠 영역 */}
|
||||
<main>
|
||||
<Routes>
|
||||
<Route path="/" element={<BoardList />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="/login" element={<Login setUser={setUser} />} />
|
||||
<Route path="/my-posts" element={<MyPosts user={user} />} />
|
||||
<Route path="/edit-profile" element={<EditProfile user={user} />} />
|
||||
<Route path="/create-post" element={<CreatePost user={user} />} /> {/* 글쓰기 페이지 */}
|
||||
</Routes>
|
||||
</main>
|
||||
{/* 동적 콘텐츠 영역 */}
|
||||
<main>
|
||||
<Routes>
|
||||
<Route path="/" element={<BoardList />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="/login" element={<Login setUser={setUser} />} />
|
||||
<Route path="/find-id" element={<FindId />} />
|
||||
<Route path="/find-password" element={<FindPassword />} />
|
||||
|
||||
{/* 로그인 후에만 접근 가능한 페이지 */}
|
||||
{user && (
|
||||
<>
|
||||
<Route path="/my-posts" element={<MyPosts user={user} />} />
|
||||
<Route path="/edit-profile" element={<EditProfile user={user} />} />
|
||||
<Route path="/create-post" element={<CreatePost user={user} />} />
|
||||
</>
|
||||
)}
|
||||
</Routes>
|
||||
</main>
|
||||
|
||||
{/* 글쓰기 링크 */}
|
||||
<Link to="/create-post">글쓰기</Link>
|
||||
</div>
|
||||
</Router>
|
||||
{/* 글쓰기 링크 - 로그인한 사용자만 글쓰기가 가능함 */}
|
||||
{user && <Link to="/create-post">글쓰기</Link>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RenderAside({ user, setUser, postCount, error }) {
|
||||
const navigate = useNavigate(); // useNavigate는 Router 내부에서만 사용 가능
|
||||
const navigate = useNavigate(); // useNavigate 훅 사용
|
||||
|
||||
// 로그아웃 처리
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
const response = await fetch('http://localhost:8080/users/logout', {
|
||||
method: 'POST',
|
||||
credentials: 'include', // 세션 무효화 요청
|
||||
credentials: 'include', // 세션 무효화 요청
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
localStorage.removeItem('token'); // 로그아웃 시 세션 쿠키를 이용하므로 토큰 대신 상태 초기화
|
||||
localStorage.removeItem('token');
|
||||
setUser(null);
|
||||
alert('로그아웃 되었습니다.');
|
||||
navigate('/login'); // 로그아웃 후 로그인 페이지로 이동
|
||||
@ -125,24 +137,34 @@ function RenderAside({ user, setUser, postCount, error }) {
|
||||
return <div>오류 발생: {error}</div>;
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return (
|
||||
<ul className="login-menu">
|
||||
<Link to="/login">로그인</Link><br />
|
||||
<Link to="/register">회원가입</Link><br />
|
||||
<Link to="/find-id">아이디/비밀번호 찾기</Link><br />
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="aside-section">
|
||||
<p>닉네임: {user.userNickname}</p>
|
||||
<p>아이디: {user.userId}</p>
|
||||
<p>내가 쓴 글 개수: {postCount}</p>
|
||||
<Link to="/my-posts">내가 쓴 글</Link><br />
|
||||
<Link to="/edit-profile">개인정보 수정</Link><br />
|
||||
<button onClick={handleLogout}>로그아웃</button>
|
||||
{!user ? (
|
||||
<div className="login-section">
|
||||
<ul className="login-menu">
|
||||
<Link to="/login">로그인</Link><br />
|
||||
<Link to="/register">회원가입</Link><br />
|
||||
<Link to="/find-id">아이디 찾기</Link><br />
|
||||
<Link to="/find-password">비밀번호 찾기</Link><br />
|
||||
</ul>
|
||||
</div>
|
||||
) : (
|
||||
<div className="user-info">
|
||||
{user.userImage && (
|
||||
<img
|
||||
src={`data:image/jpeg;base64,${user.userImage}`}
|
||||
alt="프로필 이미지"
|
||||
style={{ width: '100px', height: '100px', borderRadius: '50%' }}
|
||||
/>
|
||||
)}
|
||||
<p>닉네임: {user.userNickname}</p>
|
||||
<p>아이디: {user.userId}</p>
|
||||
<p>내가 쓴 글 개수: {postCount}</p>
|
||||
<Link to="/my-posts">내가 쓴 글</Link><br />
|
||||
<Link to="/edit-profile">개인정보 수정</Link><br />
|
||||
<button onClick={handleLogout}>로그아웃</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,23 +1,25 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import './App.css'; // CSS 파일 추가
|
||||
|
||||
function BoardList() {
|
||||
const [boards, setBoards] = useState([]);
|
||||
const [error, setError] = useState(null); // 에러 상태 추가
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchBoards = async () => {
|
||||
try {
|
||||
const response = await fetch('http://localhost:8080/boards');
|
||||
if (!response.ok) {
|
||||
// 에러가 발생한 경우 JSON 응답에서 메시지만 추출
|
||||
const errorData = await response.json();
|
||||
setError(errorData.message || '서버에서 오류가 발생했습니다.');
|
||||
} else {
|
||||
const data = await response.json();
|
||||
setBoards(data);
|
||||
|
||||
// 최신 글이 위로 오도록 정렬 (내림차순)
|
||||
const sortedData = data.sort((a, b) => new Date(b.updatedDate) - new Date(a.updatedDate));
|
||||
setBoards(sortedData);
|
||||
}
|
||||
} catch (err) {
|
||||
// 네트워크 오류가 발생했을 때 처리
|
||||
setError('네트워크 오류가 발생했습니다.');
|
||||
}
|
||||
};
|
||||
@ -26,18 +28,34 @@ function BoardList() {
|
||||
}, []);
|
||||
|
||||
if (error) {
|
||||
// 에러가 있을 때 에러 메시지를 출력
|
||||
return <div>오류: {error}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>게시판 목록</h2>
|
||||
<ul>
|
||||
{boards.map((board) => (
|
||||
<li key={board.boardNumber}>{board.boardTitle}</li>
|
||||
))}
|
||||
</ul>
|
||||
<table className="board-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>번호</th>
|
||||
<th>제목</th>
|
||||
<th>내용</th>
|
||||
<th>업데이트 날짜</th>
|
||||
<th>작성자</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{boards.map((board) => (
|
||||
<tr key={board.boardNumber}>
|
||||
<td>{board.boardNumber}</td>
|
||||
<td>{board.boardTitle}</td>
|
||||
<td>{board.boardWrite.length > 10 ? board.boardWrite.substring(0, 10) + '...' : board.boardWrite}</td>
|
||||
<td>{new Date(board.updatedDate).toLocaleString()}</td>
|
||||
<td>{board.user.userNickname}</td> {/* userNickname 필드가 있는지 확인 필요 */}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
function CreatePost() {
|
||||
const [title, setTitle] = useState('');
|
||||
const [content, setContent] = useState('');
|
||||
const [category, setCategory] = useState(1); // 카테고리 기본값 설정
|
||||
const [category, setCategory] = useState(1);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
@ -11,7 +13,7 @@ function CreatePost() {
|
||||
const newPost = {
|
||||
boardTitle: title,
|
||||
boardWrite: content,
|
||||
boardCategory: category // 선택된 카테고리 값
|
||||
boardCategory: category
|
||||
};
|
||||
|
||||
try {
|
||||
@ -20,16 +22,25 @@ function CreatePost() {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(newPost),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
alert('글 작성 완료');
|
||||
setTitle('');
|
||||
setContent('');
|
||||
if (!response.ok) {
|
||||
console.error(`Error: ${response.status}`); // 상태 코드를 출력하여 문제 확인
|
||||
if (response.status === 401) {
|
||||
alert('로그인이 필요합니다.');
|
||||
navigate('/login'); // 로그인 페이지로 이동
|
||||
} else if (response.status === 400) {
|
||||
alert('잘못된 요청입니다.');
|
||||
} else {
|
||||
alert('글 작성 실패');
|
||||
}
|
||||
} else {
|
||||
alert('글 작성 실패');
|
||||
alert('글 작성이 완료되었습니다.');
|
||||
navigate('/'); // 메인 페이지로 이동
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('글 작성 오류:', error);
|
||||
}
|
||||
@ -57,7 +68,7 @@ function CreatePost() {
|
||||
<label>카테고리:</label>
|
||||
<select value={category} onChange={(e) => setCategory(Number(e.target.value))}>
|
||||
<option value={1}>자유게시판</option>
|
||||
<option value={2}>공유게시판</option>
|
||||
<option value={2}>공지게시판</option>
|
||||
<option value={3}>질문게시판</option>
|
||||
</select>
|
||||
<br />
|
||||
|
@ -1,57 +1,102 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
function EditProfile({ user }) {
|
||||
const [nickname, setNickname] = useState(user ? user.userNickname : '');
|
||||
const [password, setPassword] = useState('');
|
||||
function EditProfile({ user }) {
|
||||
const [nickname, setNickname] = useState(user ? user.userNickname : '');
|
||||
const [name, setName] = useState(user ? user.userName : '');
|
||||
const [userId] = useState(user ? user.userId : ''); // ID는 수정하지 않음
|
||||
const [password, setPassword] = useState('');
|
||||
const [confirmPassword, setConfirmPassword] = useState('');
|
||||
const [profileImage, setProfileImage] = useState(null);
|
||||
|
||||
const handleUpdate = async (e) => {
|
||||
e.preventDefault();
|
||||
const handleUpdate = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const updatedData = { userNickname: nickname, userPassword: password };
|
||||
|
||||
try {
|
||||
const response = await fetch(`http://localhost:8080/users/${user.userId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(updatedData),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
alert('프로필이 업데이트되었습니다.');
|
||||
} else {
|
||||
alert('업데이트 실패');
|
||||
if (password !== confirmPassword) {
|
||||
alert('비밀번호가 일치하지 않습니다.');
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('업데이트 에러:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>프로필 수정</h2>
|
||||
<form onSubmit={handleUpdate}>
|
||||
<label>닉네임:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={nickname}
|
||||
onChange={(e) => setNickname(e.target.value)}
|
||||
required
|
||||
/><br />
|
||||
const formData = new FormData();
|
||||
formData.append('userNickname', nickname);
|
||||
formData.append('userName', name);
|
||||
formData.append('userPassword', password);
|
||||
formData.append('profileImage', profileImage); // 이미지 파일 추가
|
||||
|
||||
<label>비밀번호:</label>
|
||||
<input
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
/><br />
|
||||
try {
|
||||
const response = await fetch(`http://localhost:8080/users/${userId}`, {
|
||||
method: 'PUT',
|
||||
body: formData,
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
<button type="submit">수정하기</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (response.ok) {
|
||||
alert('프로필이 업데이트되었습니다.');
|
||||
} else {
|
||||
alert('업데이트 실패');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('업데이트 에러:', error);
|
||||
}
|
||||
};
|
||||
|
||||
export default EditProfile;
|
||||
const handleImageChange = (e) => {
|
||||
setProfileImage(e.target.files[0]);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>프로필 수정</h2>
|
||||
<form onSubmit={handleUpdate}>
|
||||
<label>프로필 사진:</label>
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
onChange={handleImageChange}
|
||||
/><br />
|
||||
|
||||
<label>닉네임:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={nickname}
|
||||
onChange={(e) => setNickname(e.target.value)}
|
||||
required
|
||||
/><br />
|
||||
|
||||
<label>이름:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
required
|
||||
/><br />
|
||||
|
||||
<label>아이디:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={userId}
|
||||
disabled
|
||||
/><br />
|
||||
|
||||
<label>비밀번호:</label>
|
||||
<input
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
/><br />
|
||||
|
||||
<label>비밀번호 확인:</label>
|
||||
<input
|
||||
type="password"
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
required
|
||||
/><br />
|
||||
|
||||
<button type="submit">수정하기</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default EditProfile;
|
||||
|
42
frontend/src/FindId.js
Normal file
42
frontend/src/FindId.js
Normal file
@ -0,0 +1,42 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
function FindId() {
|
||||
const [nickname, setNickname] = useState('');
|
||||
const [message, setMessage] = useState('');
|
||||
|
||||
const handleFindId = async (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
const response = await fetch('http://localhost:8080/users/find-id', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({ nickname }),
|
||||
});
|
||||
const result = await response.text();
|
||||
setMessage(result);
|
||||
} catch (error) {
|
||||
setMessage('아이디 찾기 중 오류 발생.');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>아이디 찾기</h2>
|
||||
<form onSubmit={handleFindId}>
|
||||
<label>닉네임:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={nickname}
|
||||
onChange={(e) => setNickname(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<button type="submit">아이디 찾기</button>
|
||||
</form>
|
||||
{message && <p>{message}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default FindId;
|
50
frontend/src/FindPassword.js
Normal file
50
frontend/src/FindPassword.js
Normal file
@ -0,0 +1,50 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
function FindPassword() {
|
||||
const [nickname, setNickname] = useState('');
|
||||
const [userId, setUserId] = useState('');
|
||||
const [message, setMessage] = useState('');
|
||||
|
||||
const handleFindPassword = async (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
const response = await fetch('http://localhost:8080/users/find-password', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({ nickname, userId }),
|
||||
});
|
||||
const result = await response.text();
|
||||
setMessage(result);
|
||||
} catch (error) {
|
||||
setMessage('비밀번호 찾기 중 오류 발생.');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>비밀번호 찾기</h2>
|
||||
<form onSubmit={handleFindPassword}>
|
||||
<label>닉네임:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={nickname}
|
||||
onChange={(e) => setNickname(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<label>아이디:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={userId}
|
||||
onChange={(e) => setUserId(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<button type="submit">비밀번호 찾기</button>
|
||||
</form>
|
||||
{message && <p>{message}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default FindPassword;
|
@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import './App.js'; // 테이블 스타일 적용
|
||||
|
||||
function MyPosts({ user }) {
|
||||
const [posts, setPosts] = useState([]);
|
||||
@ -18,11 +19,29 @@ function MyPosts({ user }) {
|
||||
<div>
|
||||
<h2>{user?.userNickname}님의 게시물</h2>
|
||||
{posts.length > 0 ? (
|
||||
<ul>
|
||||
{posts.map((post) => (
|
||||
<li key={post.boardNumber}>{post.boardTitle}</li>
|
||||
))}
|
||||
</ul>
|
||||
<table className="board-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>번호</th>
|
||||
<th>제목</th>
|
||||
<th>내용</th>
|
||||
<th>업데이트 날짜</th>
|
||||
<th>작성자</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{posts.map((post) => (
|
||||
<tr key={post.boardNumber}>
|
||||
<td>{post.boardNumber}</td>
|
||||
<td>{post.boardTitle}</td>
|
||||
<td>{post.boardWrite.length > 10 ? post.boardWrite.substring(0, 10) + '...' : post.boardWrite}</td>
|
||||
{/* 날짜와 시간 모두 표시 */}
|
||||
<td>{new Date(post.updatedDate).toLocaleString()}</td>
|
||||
<td>{user.userNickname}</td> {/* 작성자는 항상 현재 사용자 */}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
) : (
|
||||
<p>게시물이 없습니다.</p>
|
||||
)}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { BrowserRouter as Router } from 'react-router-dom'; // React Router 추가
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
@ -7,7 +8,9 @@ import reportWebVitals from './reportWebVitals';
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<Router> {/* App 컴포넌트를 Router로 감싸기 */}
|
||||
<App />
|
||||
</Router>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
|
@ -16,7 +16,7 @@ function Login({ setUser }) {
|
||||
return;
|
||||
}
|
||||
|
||||
const credentials = { userId, userPassword: password }; // 서버에 맞춘 데이터 이름
|
||||
const credentials = { userId, userPassword: password };
|
||||
setLoading(true);
|
||||
setErrorMessage(''); // 에러 메시지 초기화
|
||||
|
||||
@ -27,19 +27,19 @@ function Login({ setUser }) {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(credentials),
|
||||
credentials: 'include', // 세션 쿠키 전송
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// 로그인 성공 시 사용자 정보 요청
|
||||
const userResponse = await fetch('http://localhost:8080/users/current-user', {
|
||||
method: 'GET',
|
||||
credentials: 'include', // 세션 기반 요청
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
if (userResponse.ok) {
|
||||
const user = await userResponse.json();
|
||||
setUser(user); // 로그인된 사용자 정보를 상태에 저장
|
||||
setUser(user);
|
||||
alert('로그인 성공');
|
||||
navigate('/');
|
||||
} else {
|
||||
|
@ -10,7 +10,7 @@ public class WebConfig implements WebMvcConfigurer {
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOrigins("http://localhost:3000") // React 애플리케이션의 주소
|
||||
.allowedOrigins("http://localhost:3000")
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE")
|
||||
.allowedHeaders("*")
|
||||
.allowCredentials(true);
|
||||
|
@ -16,12 +16,12 @@ import com.example.demo.service.UserService;
|
||||
public class BoardController {
|
||||
|
||||
private final BoardService boardService;
|
||||
private final UserService userService; // UserService를 추가하여 사용자를 조회
|
||||
private final UserService userService;
|
||||
|
||||
@Autowired
|
||||
public BoardController(BoardService boardService, UserService userService) {
|
||||
this.boardService = boardService;
|
||||
this.userService = userService; // UserService 주입
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
// 전체 게시글 가져오기
|
||||
@ -42,6 +42,7 @@ public class BoardController {
|
||||
return boardService.getPostsByUserId(userId);
|
||||
}
|
||||
|
||||
// 게시글 생성 (세션에서 로그인된 사용자 정보 사용)`
|
||||
@PostMapping("/create")
|
||||
public ResponseEntity<?> createPost(@RequestBody Board board, HttpSession session) {
|
||||
try {
|
||||
@ -55,11 +56,31 @@ public class BoardController {
|
||||
board.setUser(loggedInUser);
|
||||
|
||||
// 게시글 저장
|
||||
Board createdBoard = boardService.saveBoard(board);
|
||||
Board createdBoard = boardService.saveBoard(board, loggedInUser.getUserId()); // 두 번째 인자로 loggedInUser.getUserId() 전달
|
||||
return ResponseEntity.ok("게시글 작성 완료");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("게시글 작성 중 오류 발생: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Board 생성 시 로그인된 사용자의 ID를 사용하여 CRT_USER, UDT_USER 설정
|
||||
@PostMapping
|
||||
public ResponseEntity<Board> createBoard(@RequestBody Board board, HttpSession session) {
|
||||
String loggedInUser = (String) session.getAttribute("userId");
|
||||
board.setUpdatedBy(loggedInUser);
|
||||
Board createdBoard = boardService.saveBoard(board, loggedInUser);
|
||||
return new ResponseEntity<>(createdBoard, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
// Board 수정 시 UDT_USER 업데이트
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<Board> updateBoard(@PathVariable Long id, @RequestBody Board boardDetails, HttpSession session) {
|
||||
String loggedInUser = (String) session.getAttribute("userId");
|
||||
boardDetails.setUpdatedBy(loggedInUser);
|
||||
Board updatedBoard = boardService.saveBoard(boardDetails, loggedInUser);
|
||||
return ResponseEntity.ok(updatedBoard);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.example.demo.controller;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -17,23 +18,38 @@ public class UserController {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
// 전체 사용자 목록 가져오기
|
||||
@GetMapping
|
||||
public List<User> getUsers() {
|
||||
return userService.getAllUsers();
|
||||
}
|
||||
|
||||
// POST 요청을 처리하는 메서드 (회원가입)
|
||||
// 사용자 생성 (회원가입)
|
||||
@PostMapping("/register")
|
||||
public ResponseEntity<?> createUser(@RequestBody User user) {
|
||||
public ResponseEntity<?> createUser(@RequestBody User user, HttpSession session) {
|
||||
try {
|
||||
// 로그인된 사용자 ID를 세션에서 가져오기
|
||||
User loggedInUser = (User) session.getAttribute("user");
|
||||
if (loggedInUser == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("로그인이 필요합니다.");
|
||||
}
|
||||
|
||||
// 사용자 생성 시 필수 필드 확인 (유효성 검사)
|
||||
if (user.getUserId() == null || user.getUserPassword() == null || user.getUserName() == null) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("필수 필드가 누락되었습니다.");
|
||||
}
|
||||
|
||||
// 생성자 정보 설정
|
||||
user.setCreatedBy(loggedInUser.getUserId());
|
||||
user.setUpdatedBy(loggedInUser.getUserId());
|
||||
User createdUser = userService.saveUser(user);
|
||||
return ResponseEntity.ok("회원가입 성공");
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("사용자 생성 중 오류 발생: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("회원가입 실패: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 로그인 요청 처리
|
||||
// 로그인 처리
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<?> login(@RequestBody User user, HttpSession session) {
|
||||
User authenticatedUser = userService.authenticate(user.getUserId(), user.getUserPassword());
|
||||
@ -46,7 +62,6 @@ public class UserController {
|
||||
return ResponseEntity.ok("로그인 성공");
|
||||
}
|
||||
|
||||
|
||||
// 로그아웃 처리
|
||||
@PostMapping("/logout")
|
||||
public ResponseEntity<?> logout(HttpSession session) {
|
||||
@ -64,15 +79,95 @@ public class UserController {
|
||||
return ResponseEntity.ok(user);
|
||||
}
|
||||
|
||||
// Update an existing user (UPDATE)
|
||||
// 사용자 정보 업데이트 (닉네임, 이름 등)
|
||||
@PutMapping("/{id}")
|
||||
public User updateUser(@PathVariable String id, @RequestBody User userDetails) {
|
||||
return userService.updateUser(id, userDetails);
|
||||
public ResponseEntity<?> updateUserProfile(
|
||||
@PathVariable String id,
|
||||
@RequestPart("userNickname") String nickname,
|
||||
@RequestPart("userName") String name,
|
||||
@RequestPart("userPassword") String password,
|
||||
@RequestPart(value = "profileImage", required = false) MultipartFile profileImage,
|
||||
HttpSession session) {
|
||||
|
||||
try {
|
||||
// 로그인된 사용자 확인
|
||||
User loggedInUser = (User) session.getAttribute("user");
|
||||
if (loggedInUser == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("로그인이 필요합니다.");
|
||||
}
|
||||
|
||||
// 사용자 정보 업데이트 처리
|
||||
// 이미지 파일 처리 로직 추가 필요
|
||||
userService.updateUserProfile(id, nickname, name, password, profileImage);
|
||||
return ResponseEntity.ok("프로필이 업데이트되었습니다.");
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("프로필 업데이트 실패: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Delete a user (DELETE)
|
||||
|
||||
// 비밀번호 업데이트 (별도 API)
|
||||
@PutMapping("/{id}/password")
|
||||
public ResponseEntity<?> updatePassword(@PathVariable String id, @RequestBody String newPassword, HttpSession session) {
|
||||
try {
|
||||
// 로그인된 사용자 확인
|
||||
User loggedInUser = (User) session.getAttribute("user");
|
||||
if (loggedInUser == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("로그인이 필요합니다.");
|
||||
}
|
||||
|
||||
// 비밀번호 업데이트
|
||||
userService.updatePassword(id, newPassword);
|
||||
return ResponseEntity.ok("비밀번호 업데이트 성공");
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("비밀번호 업데이트 실패: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 사용자 삭제
|
||||
@DeleteMapping("/{id}")
|
||||
public void deleteUser(@PathVariable String id) {
|
||||
userService.deleteUser(id);
|
||||
public ResponseEntity<?> deleteUser(@PathVariable String id, HttpSession session) {
|
||||
try {
|
||||
// 로그인된 사용자 확인
|
||||
User loggedInUser = (User) session.getAttribute("user");
|
||||
if (loggedInUser == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("로그인이 필요합니다.");
|
||||
}
|
||||
|
||||
userService.deleteUser(id);
|
||||
return ResponseEntity.ok("사용자 삭제 성공");
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("사용자 삭제 실패: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 닉네임으로 아이디 찾기
|
||||
@PostMapping("/find-id")
|
||||
public ResponseEntity<?> findIdByNickname(@RequestParam String nickname) {
|
||||
try {
|
||||
String userId = userService.findUserIdByNickname(nickname);
|
||||
if (userId != null) {
|
||||
return ResponseEntity.ok("해당 닉네임의 아이디는 " + userId + "입니다.");
|
||||
} else {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("해당 닉네임으로 등록된 아이디가 없습니다.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("아이디 찾기 중 오류 발생: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 닉네임과 아이디로 비밀번호 찾기
|
||||
@PostMapping("/find-password")
|
||||
public ResponseEntity<?> findPasswordByNicknameAndId(@RequestParam String nickname, @RequestParam String userId) {
|
||||
try {
|
||||
String userPassword = userService.findUserPasswordByNicknameAndId(nickname, userId);
|
||||
if (userPassword != null) {
|
||||
return ResponseEntity.ok("해당 닉네임과 아이디의 비밀번호는 " + userPassword + "입니다.");
|
||||
} else {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("닉네임 또는 아이디가 일치하지 않습니다.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("비밀번호 찾기 중 오류 발생: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,21 +19,36 @@ public class Board {
|
||||
@Column(name = "BOARD_TITLE", nullable = false)
|
||||
private String boardTitle;
|
||||
|
||||
// VARCHAR2(4000)으로 설정된 필드
|
||||
@Column(name = "BOARD_WRITE", nullable = false, length = 4000)
|
||||
private String boardWrite;
|
||||
|
||||
@Column(name = "BOARD_DATE")
|
||||
private LocalDateTime boardDate;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "USER_ID", nullable = false)
|
||||
private User user;
|
||||
|
||||
// 자동으로 게시글 작성 시간을 현재 시간으로 설정
|
||||
@Column(name = "CRT_DT", nullable = false)
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
@Column(name = "CRT_USER", nullable = false)
|
||||
private String createdBy;
|
||||
|
||||
@Column(name = "UDT_DT", nullable = false)
|
||||
private LocalDateTime updatedDate;
|
||||
|
||||
@Column(name = "UDT_USER", nullable = false)
|
||||
private String updatedBy;
|
||||
|
||||
// @PrePersist: 엔티티가 처음 저장될 때 자동으로 날짜 필드를 설정
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
this.boardDate = LocalDateTime.now();
|
||||
this.createdDate = LocalDateTime.now();
|
||||
this.updatedDate = LocalDateTime.now();
|
||||
}
|
||||
|
||||
// @PreUpdate: 엔티티가 업데이트될 때 자동으로 날짜 필드를 변경
|
||||
@PreUpdate
|
||||
protected void onUpdate() {
|
||||
this.updatedDate = LocalDateTime.now();
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
@ -69,14 +84,6 @@ public class Board {
|
||||
this.boardWrite = boardWrite;
|
||||
}
|
||||
|
||||
public LocalDateTime getBoardDate() {
|
||||
return boardDate;
|
||||
}
|
||||
|
||||
public void setBoardDate(LocalDateTime boardDate) {
|
||||
this.boardDate = boardDate;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
@ -84,4 +91,36 @@ public class Board {
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedDate() {
|
||||
return createdDate;
|
||||
}
|
||||
|
||||
public void setCreatedDate(LocalDateTime createdDate) {
|
||||
this.createdDate = createdDate;
|
||||
}
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedDate() {
|
||||
return updatedDate;
|
||||
}
|
||||
|
||||
public void setUpdatedDate(LocalDateTime updatedDate) {
|
||||
this.updatedDate = updatedDate;
|
||||
}
|
||||
|
||||
public String getUpdatedBy() {
|
||||
return updatedBy;
|
||||
}
|
||||
|
||||
public void setUpdatedBy(String updatedBy) {
|
||||
this.updatedBy = updatedBy;
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,20 @@
|
||||
package com.example.demo.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.persistence.*;
|
||||
import java.sql.Blob;
|
||||
import java.util.List;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "USER_TB")
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@Column(name = "USER_ID")
|
||||
@Column(name = "USER_ID", nullable = false)
|
||||
private String userId;
|
||||
|
||||
@Column(name = "USER_NAME", nullable = false)
|
||||
private String userName;
|
||||
|
||||
@Column(name = "USER_NICKNAME", unique = true, nullable = false)
|
||||
@Column(name = "USER_NICKNAME", nullable = false, unique = true)
|
||||
private String userNickname;
|
||||
|
||||
@Column(name = "USER_PW", nullable = false)
|
||||
@ -23,16 +22,39 @@ public class User {
|
||||
|
||||
@Lob
|
||||
@Column(name = "USER_IMAGE")
|
||||
private Blob userImage;
|
||||
private byte[] userImage;
|
||||
|
||||
@Column(name = "USER_LV")
|
||||
private Integer userLevel = 1;
|
||||
@Column(name = "USER_LV", nullable = false, columnDefinition = "NUMBER DEFAULT 1")
|
||||
private Integer userLevel;
|
||||
|
||||
@JsonIgnore // 이 필드를 직렬화할 때 무시
|
||||
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
|
||||
private List<Board> boards;
|
||||
@Column(name = "CRT_DT", nullable = false)
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
@Column(name = "CRT_USER", nullable = false)
|
||||
private String createdBy;
|
||||
|
||||
@Column(name = "UDT_DT", nullable = false)
|
||||
private LocalDateTime updatedDate;
|
||||
|
||||
@Column(name = "UDT_USER", nullable = false)
|
||||
private String updatedBy;
|
||||
|
||||
// 레코드가 생성될 때 자동으로 설정
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
this.createdDate = LocalDateTime.now();
|
||||
this.createdBy = "System"; // 실제 사용자 정보로 변경 가능
|
||||
}
|
||||
|
||||
// 레코드가 수정될 때 자동으로 설정
|
||||
@PreUpdate
|
||||
protected void onUpdate() {
|
||||
this.updatedDate = LocalDateTime.now();
|
||||
this.updatedBy = "System"; // 실제 사용자 정보로 변경 가능
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
@ -65,11 +87,11 @@ public class User {
|
||||
this.userPassword = userPassword;
|
||||
}
|
||||
|
||||
public Blob getUserImage() {
|
||||
public byte[] getUserImage() {
|
||||
return userImage;
|
||||
}
|
||||
|
||||
public void setUserImage(Blob userImage) {
|
||||
public void setUserImage(byte[] userImage) {
|
||||
this.userImage = userImage;
|
||||
}
|
||||
|
||||
@ -81,11 +103,35 @@ public class User {
|
||||
this.userLevel = userLevel;
|
||||
}
|
||||
|
||||
public List<Board> getBoards() {
|
||||
return boards;
|
||||
public LocalDateTime getCreatedDate() {
|
||||
return createdDate;
|
||||
}
|
||||
|
||||
public void setBoards(List<Board> boards) {
|
||||
this.boards = boards;
|
||||
public void setCreatedDate(LocalDateTime createdDate) {
|
||||
this.createdDate = createdDate;
|
||||
}
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedDate() {
|
||||
return updatedDate;
|
||||
}
|
||||
|
||||
public void setUpdatedDate(LocalDateTime updatedDate) {
|
||||
this.updatedDate = updatedDate;
|
||||
}
|
||||
|
||||
public String getUpdatedBy() {
|
||||
return updatedBy;
|
||||
}
|
||||
|
||||
public void setUpdatedBy(String updatedBy) {
|
||||
this.updatedBy = updatedBy;
|
||||
}
|
||||
}
|
||||
|
@ -5,4 +5,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import com.example.demo.entity.User;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, String> {
|
||||
User findByUserNickname(String nickname);
|
||||
User findByUserNicknameAndUserId(String nickname, String userId);
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
package com.example.demo.service;
|
||||
|
||||
import com.example.demo.entity.User;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.example.demo.entity.Board;
|
||||
import com.example.demo.repository.BoardRepository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@ -28,7 +30,22 @@ public class BoardService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Board saveBoard(Board board) {
|
||||
public Board saveBoard(Board board, String loggedInUser) {
|
||||
if (board.getCreatedDate() == null) {
|
||||
board.setCreatedBy(loggedInUser); // 새로 생성될 경우 생성자 정보 설정
|
||||
}
|
||||
board.setUpdatedBy(loggedInUser); // 수정자 정보 설정
|
||||
return boardRepository.save(board);
|
||||
}
|
||||
|
||||
// createBoard 메서드 수정
|
||||
public void createBoard(Board board, User user) {
|
||||
board.setUser(user); // ManyToOne 관계의 user 설정
|
||||
board.setCreatedDate(LocalDateTime.now()); // 생성 시간 설정
|
||||
board.setUpdatedDate(LocalDateTime.now()); // 업데이트 시간 설정
|
||||
board.setCreatedBy(user.getUserId()); // 생성자 설정
|
||||
board.setUpdatedBy(user.getUserId()); // 수정자 설정
|
||||
|
||||
boardRepository.save(board); // 데이터베이스에 저장
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
package com.example.demo.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.example.demo.entity.User;
|
||||
import com.example.demo.repository.UserRepository;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Service
|
||||
public class UserService {
|
||||
@ -43,7 +45,33 @@ public class UserService {
|
||||
return null; // 인증 실패 시 null 반환
|
||||
}
|
||||
|
||||
// Update an existing user
|
||||
// 사용자 프로필 업데이트 메서드
|
||||
public void updateUserProfile(String id, String nickname, String name, String password, MultipartFile profileImage) {
|
||||
Optional<User> userOptional = userRepository.findById(id);
|
||||
if (userOptional.isPresent()) {
|
||||
User user = userOptional.get();
|
||||
user.setUserNickname(nickname);
|
||||
user.setUserName(name);
|
||||
user.setUserPassword(password);
|
||||
|
||||
// 프로필 이미지가 있을 경우 처리
|
||||
if (profileImage != null && !profileImage.isEmpty()) {
|
||||
try {
|
||||
byte[] imageBytes = profileImage.getBytes();
|
||||
user.setUserImage(imageBytes); // 이미지 저장 (Byte 배열로 저장하는 경우)
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("프로필 이미지 처리 중 오류 발생", e);
|
||||
}
|
||||
}
|
||||
// 변경 사항 저장
|
||||
userRepository.save(user);
|
||||
} else {
|
||||
throw new RuntimeException("User not found with id " + id);
|
||||
}
|
||||
}
|
||||
|
||||
// 사용자 업데이트
|
||||
@Transactional
|
||||
public User updateUser(String id, User userDetails) {
|
||||
Optional<User> userOptional = userRepository.findById(id);
|
||||
if (userOptional.isPresent()) {
|
||||
@ -51,13 +79,39 @@ public class UserService {
|
||||
user.setUserName(userDetails.getUserName());
|
||||
user.setUserNickname(userDetails.getUserNickname());
|
||||
user.setUserPassword(userDetails.getUserPassword());
|
||||
user.setUserImage(userDetails.getUserImage());
|
||||
user.setUserLevel(userDetails.getUserLevel());
|
||||
user.setUpdatedBy(userDetails.getUpdatedBy());
|
||||
return userRepository.save(user);
|
||||
} else {
|
||||
throw new RuntimeException("User not found with id " + id);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete a user
|
||||
// 비밀번호 업데이트 메서드 추가
|
||||
public void updatePassword(String id, String newPassword) {
|
||||
Optional<User> userOptional = userRepository.findById(id);
|
||||
if (userOptional.isPresent()) {
|
||||
User user = userOptional.get();
|
||||
user.setUserPassword(newPassword); // 새로운 비밀번호 설정
|
||||
userRepository.save(user); // 변경 사항 저장
|
||||
} else {
|
||||
throw new RuntimeException("User not found with id " + id);
|
||||
}
|
||||
}
|
||||
|
||||
// 닉네임으로 사용자 아이디 찾기
|
||||
public String findUserIdByNickname(String nickname) {
|
||||
User user = userRepository.findByUserNickname(nickname);
|
||||
return user != null ? user.getUserId() : null;
|
||||
}
|
||||
|
||||
// 닉네임과 아이디로 비밀번호 찾기
|
||||
public String findUserPasswordByNicknameAndId(String nickname, String userId) {
|
||||
User user = userRepository.findByUserNicknameAndUserId(nickname, userId);
|
||||
return user != null ? user.getUserPassword() : null;
|
||||
}
|
||||
|
||||
public void deleteUser(String id) {
|
||||
userRepository.deleteById(id);
|
||||
}
|
||||
|
@ -7,6 +7,11 @@ spring.datasource.password=1004@
|
||||
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
|
||||
spring.jpa.properties.hibernate.default_schema=HYUNWOO00
|
||||
|
||||
spring.servlet.multipart.enabled=true
|
||||
spring.servlet.multipart.max-file-size=10MB
|
||||
spring.servlet.multipart.max-request-size=10MB
|
||||
|
||||
|
||||
spring.mvc.static-path-pattern=/resources/**
|
||||
spring.resources.static-locations=classpath:/demo/
|
||||
spring.mvc.pathmatch.matching-strategy=ant-path-matcher
|
||||
|
Reference in New Issue
Block a user