Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
80 changes: 80 additions & 0 deletions src/main/java/com/blog/token/application/TokenServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.blog.token.application;

import com.blog.token.domain.Token;
import com.blog.token.domain.TokenRepository;
import com.blog.token.domain.TokenService;
import com.blog.token.infrastructure.JwtTokenProvider;
import com.blog.token.presentation.dto.RefreshTokenRequest;
import com.blog.token.presentation.dto.TokenResponse;
import com.blog.user.domain.User;
import com.blog.user.domain.UserRepository;
import com.blog.user.presentation.dto.UserResponse;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;

@Service
public class TokenServiceImpl implements TokenService {

private final TokenRepository tokenRepository;
private final UserRepository userRepository;
private final JwtTokenProvider jwtTokenProvider;

public TokenServiceImpl(TokenRepository tokenRepository, UserRepository userRepository, JwtTokenProvider jwtTokenProvider) {
this.tokenRepository = tokenRepository;
this.userRepository = userRepository;
this.jwtTokenProvider = jwtTokenProvider;
}

@Override
public TokenResponse refresh(RefreshTokenRequest request) {
String refreshToken = request.getRefreshToken();

if (!jwtTokenProvider.validateToken(refreshToken)) {
throw new RuntimeException("유효하지 않은 리프레시 토큰입니다.");
}

Long userId = Long.parseLong(jwtTokenProvider.parseUserId(refreshToken));
Token saved = tokenRepository.findByUserId(userId);

if (saved == null || !saved.getRefreshToken().equals(refreshToken)) {
throw new RuntimeException("토큰이 일치하지 않거나 존재하지 않습니다.");
}

tokenRepository.deleteByUserId(userId);

User user = userRepository.findById(userId);
if (user == null) {
throw new RuntimeException("사용자를 찾을 수 없습니다.");
}

String newAccessToken = jwtTokenProvider.createAccessToken(user);
String newRefreshToken = jwtTokenProvider.createRefreshToken(user);
Timestamp expiresAt = jwtTokenProvider.getRefreshTokenExpiry();

Token newToken = new Token(user.getUserId(), newRefreshToken, expiresAt, new Timestamp(System.currentTimeMillis()));
tokenRepository.save(newToken);

UserResponse userResponse = new UserResponse();
userResponse.setUserId(user.getUserId());
userResponse.setEmail(user.getEmail());
userResponse.setName(user.getName());
userResponse.setNickname(user.getNickname());
userResponse.setProfileImage(user.getProfileImage());

if (user.getCreatedAt() != null) {
userResponse.setCreatedAt(user.getCreatedAt().toString());
}
if (user.getUpdatedAt() != null) {
userResponse.setUpdatedAt(user.getUpdatedAt().toString());
}

TokenResponse response = new TokenResponse();
response.setAccessToken(newAccessToken);
response.setRefreshToken(newRefreshToken);
response.setExpiresAt(expiresAt.toString());
response.setUser(userResponse);

return response;
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/blog/token/domain/TokenService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.blog.token.domain;

import com.blog.token.presentation.dto.RefreshTokenRequest;
import com.blog.token.presentation.dto.TokenResponse;

public interface TokenService {
TokenResponse refresh(RefreshTokenRequest request);
}
20 changes: 20 additions & 0 deletions src/main/java/com/blog/token/presentation/TokenController.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
package com.blog.token.presentation;

import com.blog.token.domain.TokenService;
import com.blog.token.presentation.dto.RefreshTokenRequest;
import com.blog.token.presentation.dto.TokenResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/auth")
public class TokenController {

private final TokenService tokenService;

public TokenController(TokenService tokenService) {
this.tokenService = tokenService;
}

@PostMapping("/refresh")
public ResponseEntity<TokenResponse> refresh(@RequestBody RefreshTokenRequest request) {
TokenResponse response = tokenService.refresh(request);
return ResponseEntity.ok(response);
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/blog/user/application/UserProfileService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.blog.user.application;

import com.blog.user.presentation.dto.UserResponse;
import com.blog.user.presentation.dto.UserUpdateRequest;

//사용자 정보 관리 전용 인터페이스
public interface UserProfileService {
UserResponse getUser(Long userId); // 조회
UserResponse updateUser(Long userId, UserUpdateRequest request); // 수정
void deleteUser(Long userId); // 삭제
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.blog.user.application;

import com.blog.user.domain.User;
import com.blog.user.domain.UserRepository;
import com.blog.user.presentation.dto.UserResponse;
import com.blog.user.presentation.dto.UserUpdateRequest;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;

@Service
public class UserProfileServiceImpl implements UserProfileService {

private final UserRepository userRepository;

public UserProfileServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}

@Override
public UserResponse getUser(Long userId) {
User user = userRepository.findById(userId);
if (user == null || !user.isActive()) {
throw new RuntimeException("존재하지 않는 사용자입니다.");
}

UserResponse response = new UserResponse();
response.setUserId(user.getUserId());
response.setEmail(user.getEmail());
response.setName(user.getName());
response.setNickname(user.getNickname());
response.setProfileImage(user.getProfileImage());
response.setCreatedAt(user.getCreatedAt().toString());

return response;
}

@Override
public UserResponse updateUser(Long userId, UserUpdateRequest request) {
Timestamp updatedAt = new Timestamp(System.currentTimeMillis());
userRepository.update(userId, request.getNickname(), request.getProfileImage(), updatedAt);

User updated = userRepository.findById(userId);
if (updated == null) {
throw new RuntimeException("사용자 정보를 수정할 수 없습니다.");
}

UserResponse response = new UserResponse();
response.setUserId(updated.getUserId());
response.setEmail(updated.getEmail());
response.setNickname(updated.getNickname());
response.setProfileImage(updated.getProfileImage());
response.setUpdatedAt(updated.getUpdatedAt().toString());

return response;
}

@Override
public void deleteUser(Long userId) {
userRepository.softDelete(userId);
}
}
4 changes: 3 additions & 1 deletion src/main/java/com/blog/user/domain/UserRepository.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.blog.user.domain;

import java.sql.Timestamp;

public interface UserRepository {
User findByEmail(String email); // 로그인용
User findById(Long userId); // 유저 조회용
void save(User user); // 회원가입용
void update(User user); // 정보 수정용
void update(Long userId, String nickname, String profileImage, Timestamp updatedAt); // 정보 수정용
void softDelete(Long userId); // 탈퇴용
}
123 changes: 37 additions & 86 deletions src/main/java/com/blog/user/infrastructure/UserRepositoryImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,119 +2,70 @@

import com.blog.user.domain.User;
import com.blog.user.domain.UserRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.sql.*;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;

@Repository
public class UserRepositoryImpl implements UserRepository {

private final DataSource dataSource;
private final JdbcTemplate jdbcTemplate;

public UserRepositoryImpl(DataSource dataSource) {
this.dataSource = dataSource;
public UserRepositoryImpl(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

@Override
public void save(User user) {
String sql = "INSERT INTO users (email, password, name, nickname, birth_date, profile_image, introduction, auth_method, created_at, updated_at, is_active) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
jdbcTemplate.update(sql,
user.getEmail(),
user.getPassword(),
user.getName(),
user.getNickname(),
user.getBirthDate(),
user.getProfileImage(),
user.getIntroduction(),
user.getAuthMethod(),
user.getCreatedAt(),
user.getUpdatedAt(),
user.isActive()
);
}

@Override
public User findByEmail(String email) {
String sql = "SELECT * FROM users WHERE email = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {

ps.setString(1, email);
ResultSet rs = ps.executeQuery();

if (rs.next()) {
return mapRowToUser(rs);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return null;
return jdbcTemplate.query(sql, new Object[]{email}, userRowMapper())
.stream().findFirst().orElse(null);
}

@Override
public User findById(Long userId) {
String sql = "SELECT * FROM users WHERE user_id = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {

ps.setLong(1, userId);
ResultSet rs = ps.executeQuery();

if (rs.next()) {
return mapRowToUser(rs);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return null;
}

@Override
public void save(User user) {
String sql = "INSERT INTO users (email, password, name, nickname, birth_date, profile_image, introduction, auth_method, created_at, updated_at, is_active) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {

ps.setString(1, user.getEmail());
ps.setString(2, user.getPassword());
ps.setString(3, user.getName());
ps.setString(4, user.getNickname());
ps.setString(5, user.getBirthDate());
ps.setString(6, user.getProfileImage());
ps.setString(7, user.getIntroduction());
ps.setString(8, user.getAuthMethod());
ps.setTimestamp(9, user.getCreatedAt());
ps.setTimestamp(10, user.getUpdatedAt());
ps.setBoolean(11, user.isActive());

ps.executeUpdate();

ResultSet keys = ps.getGeneratedKeys();
if (keys.next()) {
user.setUserId(keys.getLong(1));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return jdbcTemplate.query(sql, new Object[]{userId}, userRowMapper())
.stream().findFirst().orElse(null);
}

@Override
public void update(User user) {
String sql = "UPDATE users SET nickname = ?, profile_image = ?, introduction = ?, updated_at = ? WHERE user_id = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {

ps.setString(1, user.getNickname());
ps.setString(2, user.getProfileImage());
ps.setString(3, user.getIntroduction());
ps.setTimestamp(4, user.getUpdatedAt());
ps.setLong(5, user.getUserId());

ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
public void update(Long userId, String nickname, String profileImage, Timestamp updatedAt) {
String sql = "UPDATE users SET nickname = ?, profile_image = ?, updated_at = ? WHERE user_id = ?";
jdbcTemplate.update(sql, nickname, profileImage, updatedAt, userId);
}

@Override
public void softDelete(Long userId) {
String sql = "UPDATE users SET is_active = false WHERE user_id = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {

ps.setLong(1, userId);
ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}
jdbcTemplate.update(sql, userId);
}

private User mapRowToUser(ResultSet rs) throws SQLException {
return new User(
private RowMapper<User> userRowMapper() {
return (rs, rowNum) -> new User(
rs.getLong("user_id"),
rs.getString("email"),
rs.getString("password"),
Expand Down
Loading