diff --git a/build.gradle b/build.gradle index c3e199d2..43202b9f 100644 --- a/build.gradle +++ b/build.gradle @@ -31,12 +31,6 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' - // CHAT - // web socket - implementation 'org.springframework.boot:spring-boot-starter-websocket' - implementation 'org.webjars:webjars-locator-core' - implementation 'org.webjars:sockjs-client:1.5.1' - implementation 'org.webjars:stomp-websocket:2.3.4' // kafka // implementation 'org.springframework.kafka:spring-kafka' diff --git a/src/main/java/org/myteam/server/aop/CommonCountAspect.java b/src/main/java/org/myteam/server/aop/CommonCountAspect.java index 13c2231f..2c6e42f4 100644 --- a/src/main/java/org/myteam/server/aop/CommonCountAspect.java +++ b/src/main/java/org/myteam/server/aop/CommonCountAspect.java @@ -7,7 +7,7 @@ import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.springframework.stereotype.Component; diff --git a/src/main/java/org/myteam/server/auth/service/TokenService.java b/src/main/java/org/myteam/server/auth/service/TokenService.java index e2d3d766..acd5068b 100644 --- a/src/main/java/org/myteam/server/auth/service/TokenService.java +++ b/src/main/java/org/myteam/server/auth/service/TokenService.java @@ -5,10 +5,14 @@ import java.time.Duration; import java.util.UUID; +import org.myteam.server.chat.info.domain.UserInfo; import org.myteam.server.global.exception.ErrorCode; import org.myteam.server.global.exception.PlayHiveJwtException; import org.myteam.server.global.security.jwt.JwtProvider; -import org.myteam.server.global.util.redis.RedisService; +import org.myteam.server.global.util.redis.service.RedisService; +import org.myteam.server.global.util.redis.service.RedisUserInfoService; +import org.myteam.server.member.entity.Member; +import org.myteam.server.member.service.MemberReadService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,6 +28,8 @@ public class TokenService { private final JwtProvider jwtProvider; private final RedisService redisService; + private final RedisUserInfoService redisUserInfoService; + private final MemberReadService memberReadService; /** * Refresh Token 검증 @@ -40,7 +46,13 @@ public void regenerateAccessToken(HttpServletRequest request, HttpServletRespons existRefreshToken(refreshToken); expireRefreshToken(refreshToken); - generateAccessToken(refreshToken, response); + String newAccessToken = generateAccessToken(refreshToken, response); + log.info("member: {} regenerated new Access Token", publicId); + Member member = memberReadService.findById(publicId); + + redisUserInfoService.saveUserInfo(newAccessToken, + new UserInfo(member.getPublicId(), member.getNickname(), member.getImgUrl())); + log.info("member: {} caching user info", publicId); } private void existRefreshToken(String refreshToken) { @@ -57,7 +69,7 @@ private void expireRefreshToken(String refreshToken) { } } - private void generateAccessToken(String refreshToken, HttpServletResponse response) { + private String generateAccessToken(String refreshToken, HttpServletResponse response) { UUID publicId = jwtProvider.getPublicId(refreshToken); String role = jwtProvider.getRole(refreshToken); String status = jwtProvider.getStatus(refreshToken); @@ -66,5 +78,7 @@ private void generateAccessToken(String refreshToken, HttpServletResponse respon status); response.addHeader(HEADER_AUTHORIZATION, TOKEN_PREFIX + newAccessToken); + + return newAccessToken; } } diff --git a/src/main/java/org/myteam/server/board/repository/BoardQueryRepository.java b/src/main/java/org/myteam/server/board/repository/BoardQueryRepository.java index 1a706e31..bd9b909e 100644 --- a/src/main/java/org/myteam/server/board/repository/BoardQueryRepository.java +++ b/src/main/java/org/myteam/server/board/repository/BoardQueryRepository.java @@ -38,7 +38,7 @@ import org.myteam.server.global.domain.Category; import org.myteam.server.global.util.domain.TimePeriod; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.home.dto.HotBoardDto; import org.myteam.server.home.dto.NewBoardDto; diff --git a/src/main/java/org/myteam/server/board/service/BoardCountService.java b/src/main/java/org/myteam/server/board/service/BoardCountService.java index d45ae26d..97c3a83b 100644 --- a/src/main/java/org/myteam/server/board/service/BoardCountService.java +++ b/src/main/java/org/myteam/server/board/service/BoardCountService.java @@ -1,7 +1,7 @@ package org.myteam.server.board.service; import lombok.RequiredArgsConstructor; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.report.domain.DomainType; import org.springframework.stereotype.Service; diff --git a/src/main/java/org/myteam/server/board/service/BoardService.java b/src/main/java/org/myteam/server/board/service/BoardService.java index 31c33d33..75ab3c30 100644 --- a/src/main/java/org/myteam/server/board/service/BoardService.java +++ b/src/main/java/org/myteam/server/board/service/BoardService.java @@ -19,7 +19,7 @@ import org.myteam.server.global.exception.ErrorCode; import org.myteam.server.global.exception.PlayHiveException; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.member.entity.Member; import org.myteam.server.member.service.MemberReadService; diff --git a/src/main/java/org/myteam/server/board/util/RedisBoardRankingReader.java b/src/main/java/org/myteam/server/board/util/RedisBoardRankingReader.java index 9ff6a60b..b78a1b22 100644 --- a/src/main/java/org/myteam/server/board/util/RedisBoardRankingReader.java +++ b/src/main/java/org/myteam/server/board/util/RedisBoardRankingReader.java @@ -3,7 +3,7 @@ import lombok.RequiredArgsConstructor; import org.myteam.server.global.util.redis.CommonCountDto; import org.myteam.server.global.util.redis.RankingCacheReader; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.report.domain.DomainType; import org.springframework.stereotype.Component; diff --git a/src/main/java/org/myteam/server/chat/controller/BanController.java b/src/main/java/org/myteam/server/chat/block/controller/BlockController.java similarity index 50% rename from src/main/java/org/myteam/server/chat/controller/BanController.java rename to src/main/java/org/myteam/server/chat/block/controller/BlockController.java index 6dab49de..7998bfc8 100644 --- a/src/main/java/org/myteam/server/chat/controller/BanController.java +++ b/src/main/java/org/myteam/server/chat/block/controller/BlockController.java @@ -1,13 +1,17 @@ -package org.myteam.server.chat.controller; +package org.myteam.server.chat.block.controller; import lombok.RequiredArgsConstructor; -import org.myteam.server.chat.dto.request.BanRequest; -import org.myteam.server.chat.dto.response.BanResponse; -import org.myteam.server.chat.service.BanService; +import org.myteam.server.chat.block.dto.request.BlockRequest.*; +import org.myteam.server.chat.block.dto.response.BlockResponse.*; +import org.myteam.server.chat.block.dto.response.BlockedMembersResponse; +import org.myteam.server.chat.block.service.BlockReadService; +import org.myteam.server.chat.block.service.BlockService; import org.myteam.server.global.web.response.ResponseDto; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.UUID; + import static org.myteam.server.global.web.response.ResponseStatus.SUCCESS; /** @@ -16,16 +20,17 @@ @RestController @RequiredArgsConstructor @RequestMapping("/api/bans") -public class BanController { +public class BlockController { - private final BanService banService; + private final BlockService blockService; + private final BlockReadService blockReadService; /** * 유저 밴하기 */ @PostMapping - public ResponseEntity> banUser(@RequestBody BanRequest request) { - BanResponse response = banService.banUser(request); + public ResponseEntity> banUser(@RequestBody BlockUserRequest request) { + SuccessBlockResponse response = blockService.banUser(request); return ResponseEntity.ok(new ResponseDto( SUCCESS.name(), "Ban Success", @@ -36,22 +41,22 @@ public ResponseEntity> banUser(@RequestBody BanRequest /** * 유저 밴 해제 */ - @DeleteMapping("/{username}") - public ResponseEntity> unbanUser(@PathVariable String username) { - String deleteName = banService.unbanUser(username); + @DeleteMapping("/{blockedId}") + public ResponseEntity> unbanUser(@PathVariable UUID blockedId) { + blockService.unblockUser(blockedId); return ResponseEntity.ok(new ResponseDto( SUCCESS.name(), "Delete Ban Successfully", - deleteName + null )); } /** * 특정 유저 밴 정보 조회 */ - @GetMapping("/{username}") - public ResponseEntity> getBanByUsername(@PathVariable String username) { - BanResponse response = banService.findBanByUsername(username); + @GetMapping("/{blockerId}/blocked") + public ResponseEntity> getBanByPublicId(@PathVariable UUID blockerId) { + BlockedMembersResponse response = blockReadService.getBlockedUsers(blockerId); return ResponseEntity.ok(new ResponseDto( SUCCESS.name(), "Find Ban Reason Successfully", diff --git a/src/main/java/org/myteam/server/chat/domain/BanReason.java b/src/main/java/org/myteam/server/chat/block/domain/BanReason.java similarity index 92% rename from src/main/java/org/myteam/server/chat/domain/BanReason.java rename to src/main/java/org/myteam/server/chat/block/domain/BanReason.java index 6adf85c8..181d6771 100644 --- a/src/main/java/org/myteam/server/chat/domain/BanReason.java +++ b/src/main/java/org/myteam/server/chat/block/domain/BanReason.java @@ -1,4 +1,4 @@ -package org.myteam.server.chat.domain; +package org.myteam.server.chat.block.domain; public enum BanReason { HARASSMENT("회원에 대한 상습 비방"), diff --git a/src/main/java/org/myteam/server/chat/block/domain/MemberBlock.java b/src/main/java/org/myteam/server/chat/block/domain/MemberBlock.java new file mode 100644 index 00000000..873574cd --- /dev/null +++ b/src/main/java/org/myteam/server/chat/block/domain/MemberBlock.java @@ -0,0 +1,63 @@ +package org.myteam.server.chat.block.domain; + +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.myteam.server.global.domain.BaseTime; +import org.myteam.server.member.entity.Member; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "member_block", + uniqueConstraints = @UniqueConstraint(columnNames = {"blocker_id", "blocked_id"})) +public class MemberBlock extends BaseTime { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "blocker_id", nullable = false) + private Member blocker; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "blocked_id", nullable = false) + private Member blocked; + + @ElementCollection(fetch = FetchType.LAZY) + @Enumerated(EnumType.STRING) + private List reasons = new ArrayList<>(); // 밴 사유 + + private String message; + + @Builder + private MemberBlock(Member blocker, Member blocked, List reasons, LocalDateTime bannedAt, String message) { + this.blocker = blocker; + this.blocked = blocked; + if (reasons != null) { + this.reasons.addAll(reasons); + } + this.message = message; + } + + /** + * 차단 엔티티 생성 + */ + public static MemberBlock createMemberBlock(Member blocker, Member blocked, List reasons, String message) { + return MemberBlock.builder() + .blocker(blocker) + .blocked(blocked) + .reasons(reasons) + .bannedAt(LocalDateTime.now()) + .message(message) + .build(); + } + +} diff --git a/src/main/java/org/myteam/server/chat/block/domain/Topic.java b/src/main/java/org/myteam/server/chat/block/domain/Topic.java new file mode 100644 index 00000000..4266dedb --- /dev/null +++ b/src/main/java/org/myteam/server/chat/block/domain/Topic.java @@ -0,0 +1,5 @@ +package org.myteam.server.chat.block.domain; + +public class Topic { + public static final String TOPIC_PREFIX = "/topic/chat.match-"; +} diff --git a/src/main/java/org/myteam/server/chat/block/dto/request/BlockRequest.java b/src/main/java/org/myteam/server/chat/block/dto/request/BlockRequest.java new file mode 100644 index 00000000..1341b3f8 --- /dev/null +++ b/src/main/java/org/myteam/server/chat/block/dto/request/BlockRequest.java @@ -0,0 +1,35 @@ +package org.myteam.server.chat.block.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.myteam.server.chat.block.domain.BanReason; + +import java.util.List; +import java.util.UUID; + +public record BlockRequest() { + + @Getter + @NoArgsConstructor + @AllArgsConstructor + public class BlockUserRequest { + private UUID blockedId; + private List reasons; + private String message; + } + + @Getter + @NoArgsConstructor + @AllArgsConstructor + public class UnblockUserRequest { + private UUID blockedId; + } + + @Getter + @NoArgsConstructor + @AllArgsConstructor + public class BlockCheckRequest { + private UUID blockedId; + } +} diff --git a/src/main/java/org/myteam/server/chat/block/dto/response/BlockResponse.java b/src/main/java/org/myteam/server/chat/block/dto/response/BlockResponse.java new file mode 100644 index 00000000..631ae37b --- /dev/null +++ b/src/main/java/org/myteam/server/chat/block/dto/response/BlockResponse.java @@ -0,0 +1,36 @@ +package org.myteam.server.chat.block.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.myteam.server.chat.block.domain.MemberBlock; + +import java.util.UUID; + +public record BlockResponse() { + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static final class SuccessBlockResponse { + private UUID blocker; + private UUID blocked; + + public static SuccessBlockResponse createBlockResponse(MemberBlock block) { + return SuccessBlockResponse.builder() + .blocker(block.getBlocker().getPublicId()) + .blocked(block.getBlocked().getPublicId()) + .build(); + } + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static final class BlockedMemberInfo { + private UUID blocked; + } +} diff --git a/src/main/java/org/myteam/server/chat/block/dto/response/BlockedMembersResponse.java b/src/main/java/org/myteam/server/chat/block/dto/response/BlockedMembersResponse.java new file mode 100644 index 00000000..469e556f --- /dev/null +++ b/src/main/java/org/myteam/server/chat/block/dto/response/BlockedMembersResponse.java @@ -0,0 +1,11 @@ +package org.myteam.server.chat.block.dto.response; + +import java.util.List; +import java.util.UUID; + +public record BlockedMembersResponse(List blocked) { + + public static BlockedMembersResponse from(List blockedIds) { + return new BlockedMembersResponse(blockedIds); + } +} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/block/repository/MemberBlockQueryRepository.java b/src/main/java/org/myteam/server/chat/block/repository/MemberBlockQueryRepository.java new file mode 100644 index 00000000..dbe150d1 --- /dev/null +++ b/src/main/java/org/myteam/server/chat/block/repository/MemberBlockQueryRepository.java @@ -0,0 +1,8 @@ +package org.myteam.server.chat.block.repository; + +import java.util.List; +import java.util.UUID; + +public interface MemberBlockQueryRepository { + List existsByBlockerPublicId(UUID blockerPublicId); +} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/block/repository/MemberBlockRepository.java b/src/main/java/org/myteam/server/chat/block/repository/MemberBlockRepository.java new file mode 100644 index 00000000..354aa33f --- /dev/null +++ b/src/main/java/org/myteam/server/chat/block/repository/MemberBlockRepository.java @@ -0,0 +1,14 @@ +package org.myteam.server.chat.block.repository; + +import org.myteam.server.chat.block.domain.MemberBlock; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; +import java.util.UUID; + +@Repository +public interface MemberBlockRepository extends JpaRepository, MemberBlockQueryRepository { + boolean existsByBlockerPublicIdAndBlockedPublicId(UUID blocker, UUID blocked); + Optional findByBlockerPublicIdAndBlockedPublicId(UUID blocker, UUID blocked); +} diff --git a/src/main/java/org/myteam/server/chat/block/repository/impl/MemberBlockQueryRepositoryImpl.java b/src/main/java/org/myteam/server/chat/block/repository/impl/MemberBlockQueryRepositoryImpl.java new file mode 100644 index 00000000..5e90368e --- /dev/null +++ b/src/main/java/org/myteam/server/chat/block/repository/impl/MemberBlockQueryRepositoryImpl.java @@ -0,0 +1,28 @@ +package org.myteam.server.chat.block.repository.impl; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.myteam.server.chat.block.domain.QMemberBlock; +import org.myteam.server.chat.block.repository.MemberBlockQueryRepository; +import org.myteam.server.member.entity.QMember; + +import java.util.List; +import java.util.UUID; + +@RequiredArgsConstructor +public class MemberBlockQueryRepositoryImpl implements MemberBlockQueryRepository { + + private final JPAQueryFactory queryFactory; + + QMemberBlock memberBlock = QMemberBlock.memberBlock; + QMember member = QMember.member; + + @Override + public List existsByBlockerPublicId(UUID blockerPublicId) { + return queryFactory + .select(memberBlock.blocked.publicId) + .from(memberBlock) + .where(memberBlock.blocker.publicId.eq(blockerPublicId)) + .fetch(); + } +} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/block/service/BlockReadService.java b/src/main/java/org/myteam/server/chat/block/service/BlockReadService.java new file mode 100644 index 00000000..6860b225 --- /dev/null +++ b/src/main/java/org/myteam/server/chat/block/service/BlockReadService.java @@ -0,0 +1,31 @@ +package org.myteam.server.chat.block.service; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.myteam.server.chat.block.dto.response.BlockedMembersResponse; +import org.myteam.server.chat.block.dto.response.BlockedMembersResponse.*; +import org.myteam.server.chat.block.repository.MemberBlockRepository; +import org.myteam.server.member.service.SecurityReadService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; + +@Slf4j +@Service +@AllArgsConstructor +@Transactional(readOnly = true) +public class BlockReadService { + + private final MemberBlockRepository memberBlockRepository; + + /** + * 특정 유저가 차단한 유저 목록 조회 + */ + public BlockedMembersResponse getBlockedUsers(UUID blockerId) { + log.debug("차단 목록 조회 요청: blockerId={}", blockerId); + List blockedIds = memberBlockRepository.existsByBlockerPublicId(blockerId); + return BlockedMembersResponse.from(blockedIds); + } +} diff --git a/src/main/java/org/myteam/server/chat/block/service/BlockService.java b/src/main/java/org/myteam/server/chat/block/service/BlockService.java new file mode 100644 index 00000000..7ea4eefa --- /dev/null +++ b/src/main/java/org/myteam/server/chat/block/service/BlockService.java @@ -0,0 +1,66 @@ +package org.myteam.server.chat.block.service; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.myteam.server.chat.block.domain.MemberBlock; +import org.myteam.server.chat.block.dto.request.BlockRequest.*; +import org.myteam.server.chat.block.dto.response.BlockResponse.*; +import org.myteam.server.chat.block.repository.MemberBlockRepository; +import org.myteam.server.global.exception.ErrorCode; +import org.myteam.server.global.exception.PlayHiveException; +import org.myteam.server.member.entity.Member; +import org.myteam.server.member.service.MemberReadService; +import org.myteam.server.member.service.SecurityReadService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.UUID; + +@Slf4j +@Service +@AllArgsConstructor +@Transactional +public class BlockService { + + private final MemberBlockRepository memberBlockRepository; + private final SecurityReadService securityReadService; + private final MemberReadService memberReadService; + + /** + * 유저 밴 적용 + */ + public SuccessBlockResponse banUser(BlockUserRequest request) { + Member blocker = securityReadService.getMember(); + Member blocked = memberReadService.findById(request.getBlockedId()); + log.info("This user: {} has received a blocking request.", blocker.getPublicId()); + + // 이미 밴된 유저인지 확인 + if (memberBlockRepository.existsByBlockerPublicIdAndBlockedPublicId(blocker.getPublicId(), request.getBlockedId())) { + log.error("This user: {} is already ban this user: {}", blocker.getPublicId(), blocked.getPublicId()); + throw new PlayHiveException(ErrorCode.BAN_ALREADY_EXISTS); + } + + MemberBlock block = MemberBlock.createMemberBlock(blocker, blocked, request.getReasons(), request.getMessage()); + memberBlockRepository.save(block); + + return SuccessBlockResponse.createBlockResponse(block); + } + + /** + * 차단 해제 + */ + public void unblockUser(UUID blockedId) { + Member blocker = securityReadService.getMember(); + Member blocked = memberReadService.findById(blockedId); + log.info("This user: {} has received a unblocking request.", blocker.getPublicId()); + + MemberBlock block = memberBlockRepository.findByBlockerPublicIdAndBlockedPublicId( + blocker.getPublicId(), blocked.getPublicId()) + .orElseThrow(() -> { + log.error("This user: {} is not banned this user: {}", blocker.getPublicId(), blocked.getPublicId()); + throw new PlayHiveException(ErrorCode.BAN_NOT_FOUND); + }); + + memberBlockRepository.delete(block); + } +} diff --git a/src/main/java/org/myteam/server/chat/config/KafkaConfig.java b/src/main/java/org/myteam/server/chat/config/KafkaConfig.java deleted file mode 100644 index eff08f5a..00000000 --- a/src/main/java/org/myteam/server/chat/config/KafkaConfig.java +++ /dev/null @@ -1,98 +0,0 @@ -//package org.myteam.server.chat.config; -// -// -//import org.apache.kafka.clients.admin.AdminClientConfig; -//import org.apache.kafka.clients.consumer.ConsumerConfig; -//import org.apache.kafka.clients.producer.ProducerConfig; -//import org.apache.kafka.common.serialization.StringDeserializer; -//import org.apache.kafka.common.serialization.StringSerializer; -//import org.myteam.server.chat.domain.Chat; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -//import org.springframework.kafka.annotation.EnableKafka; -//import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; -//import org.springframework.kafka.core.*; -//import org.springframework.kafka.support.serializer.JsonDeserializer; -//import org.springframework.kafka.support.serializer.JsonSerializer; -// -//import java.util.HashMap; -//import java.util.Map; -// -//@EnableKafka -//@Configuration -//public class KafkaConfig { -// -// private static final String BOOTSTRAP_SERVERS = "kafka:9092"; -// private static final String DEFAULT_GROUP_ID = "chat-group"; -// -// @Bean -// public KafkaAdmin kafkaAdmin() { -// Map configs = new HashMap<>(); -// configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, BOOTSTRAP_SERVERS); -// return new KafkaAdmin(configs); -// } -// -// /** -// * Kafka ProducerFactory를 생성하는 Bean 메서드 -// */ -// @Bean -// public ProducerFactory producerFactory() { -// return new DefaultKafkaProducerFactory<>(producerConfigurations()); -// } -// -// /** -// * Kafka Producer 구성을 위한 설정값들을 포함한 맵을 반환하는 메서드 -// */ -// @Bean -// public Map producerConfigurations() { -// Map producerConfigurations = new HashMap<>(); -// -// producerConfigurations.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, BOOTSTRAP_SERVERS); -// producerConfigurations.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); -// producerConfigurations.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class); -// producerConfigurations.put(JsonSerializer.ADD_TYPE_INFO_HEADERS, false); // JSON 타입 헤더 제거 (선택사항) -// -// return producerConfigurations; -// } -// -// /** -// * KafkaTemplate을 생성하는 Bean 메서드 -// */ -// @Bean -// public KafkaTemplate kafkaTemplate() { -// return new KafkaTemplate<>(producerFactory()); -// } -// -// /** -// * Kafka ConsumerFactory를 생성하는 Bean 메서드 -// */ -// @Bean -// public ConsumerFactory consumerFactory() { -// JsonDeserializer deserializer = new JsonDeserializer<>(Chat.class); -// deserializer.addTrustedPackages("*"); // 모든 패키지 신뢰 (필요 시 제한적으로 변경) -// -// Map consumerConfigurations = Map.of( -// ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, BOOTSTRAP_SERVERS, -// ConsumerConfig.GROUP_ID_CONFIG, DEFAULT_GROUP_ID, -// ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class, -// ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, deserializer, -// ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest" -// ); -// -// return new DefaultKafkaConsumerFactory<>(consumerConfigurations, new StringDeserializer(), deserializer); -// } -// -// /** -// * KafkaListener 컨테이너 팩토리를 생성하는 Bean 메서드 -// */ -// @Bean -// public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() { -// ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); -// factory.setConsumerFactory(consumerFactory()); -// -// factory.setConcurrency(3); // 병렬 처리 설정 (기본값 1) -// factory.getContainerProperties().setPollTimeout(3000L); // 폴링 시간 설정 (선택사항) -// -// return factory; -// } -//} diff --git a/src/main/java/org/myteam/server/chat/config/WebSocketConfig.java b/src/main/java/org/myteam/server/chat/config/WebSocketConfig.java deleted file mode 100644 index 9c4bcdb6..00000000 --- a/src/main/java/org/myteam/server/chat/config/WebSocketConfig.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.myteam.server.chat.config; - - -import lombok.RequiredArgsConstructor; -import org.myteam.server.chat.interceptor.StompHandler; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.messaging.simp.config.ChannelRegistration; -import org.springframework.messaging.simp.config.MessageBrokerRegistry; -import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; -import org.springframework.web.socket.config.annotation.StompEndpointRegistry; -import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; -import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration; - -@EnableWebSocketMessageBroker -@Configuration -@RequiredArgsConstructor -@Profile({"!test", "!container"}) -public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { - - private final StompHandler stompHandler; - - @Override - public void configureMessageBroker(MessageBrokerRegistry registry) { - registry.setApplicationDestinationPrefixes("/play-hive"); - registry.enableSimpleBroker("/room"); - } - - @Override - public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/ws-stomp") - .setAllowedOrigins("http://localhost:3000") - .withSockJS(); - registry.addEndpoint("/ws-stomp") - .setAllowedOrigins("http://localhost:3000"); - } - - // STOMP에서 64KB 이상의 데이터 전송을 못하는 문제 해결 - @Override - public void configureWebSocketTransport(WebSocketTransportRegistration registry) { - registry.setMessageSizeLimit(160 * 64 * 1024); - registry.setSendTimeLimit(100 * 10000); - registry.setSendBufferSizeLimit(3 * 512 * 1024); - } - - @Override - public void configureClientInboundChannel(ChannelRegistration registration) { - registration.interceptors(stompHandler); - } -} diff --git a/src/main/java/org/myteam/server/chat/controller/ChatController.java b/src/main/java/org/myteam/server/chat/controller/ChatController.java deleted file mode 100644 index 9b9c3211..00000000 --- a/src/main/java/org/myteam/server/chat/controller/ChatController.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.myteam.server.chat.controller; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.myteam.server.chat.domain.Chat; -import org.myteam.server.chat.dto.request.ChatMessage; -import org.myteam.server.chat.dto.request.RoomRequest; -import org.myteam.server.chat.dto.response.ChatRoomResponse; -import org.myteam.server.chat.service.ChatReadService; -import org.myteam.server.chat.service.ChatService; -import org.myteam.server.global.web.response.ResponseDto; -import org.springframework.http.ResponseEntity; -import org.springframework.messaging.handler.annotation.DestinationVariable; -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static org.myteam.server.global.web.response.ResponseStatus.SUCCESS; - -@Slf4j -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/chat") -public class ChatController { - - private final ChatReadService chatReadService; - private final ChatService chatService; - - /** - * TODO: Kafka를 통해 메시지 전송 - * 원인: EC2 프리티어 램 메모리 이슈로 인한 인스턴스 정지로 Kafka 현재 사용 불가능 - */ - @MessageMapping("/{roomId}") - @SendTo("/room/{roomId}") - public ChatMessage chat(@DestinationVariable Long roomId, ChatMessage message) { - log.info("Sending message to room {}: {}", roomId, message); - - Chat chat = chatService.createChat(roomId, message.getSender(), message.getSenderEmail(), message.getMessage()); - - return ChatMessage.builder() - .roomId(roomId) - .sender(chat.getSender()) - .senderEmail(chat.getSenderEmail()) - .message(chat.getMessage()) - .build(); - } - - /** - * TODO: 필요없지 않을까? 왜냐면 경기 일정은 데이터 내려주는게 다르다보니.. - * 채팅방 생성 - */ - @PostMapping("/room") - public ResponseEntity> createChatRoom(@RequestBody RoomRequest requestDto) { - log.info("createChatRoom: {}", requestDto.getRoomName()); - - ChatRoomResponse newRoomResponse = chatService.createChatRoom(requestDto.getRoomName()); - - return ResponseEntity.ok(new ResponseDto<>( - SUCCESS.name(), - "Successfully create room", - newRoomResponse - )); - } - - /** - * TODO: 필요없지 않을까? 삭제는 비즈니스 로직에만 필요. 이거는 테스트를 위해 남겨둠 - * 채팅방 삭제 - */ - @DeleteMapping("/room/{roomId}") - public ResponseEntity> deleteChatRoom(@PathVariable Long roomId) { - log.info("deleteChatRoom: {}", roomId); - - String deleteChatRoomName = chatService.deleteChatRoom(roomId); - - return ResponseEntity.ok(new ResponseDto<>( - SUCCESS.name(), - "Successfully delete room", - deleteChatRoomName - )); - } - - /** - * TODO: 필요없지 않을까? 왜냐면 경기 일정은 데이터 내려주는게 다르다보니.. - * 모든 채팅방 조회 - */ - @GetMapping("/room") - public ResponseEntity>> getChatRoom() { - log.info("get Room"); - - List chatRooms = chatReadService.findAllRooms(); - - return ResponseEntity.ok(new ResponseDto<>( - SUCCESS.name(), - "Successfully find rooms", - chatRooms - )); - } -} diff --git a/src/main/java/org/myteam/server/chat/controller/FilterController.java b/src/main/java/org/myteam/server/chat/controller/FilterController.java deleted file mode 100644 index 94039348..00000000 --- a/src/main/java/org/myteam/server/chat/controller/FilterController.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.myteam.server.chat.controller; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.myteam.server.chat.dto.request.FilterDataRequest; -import org.myteam.server.chat.service.FilterWriteService; -import org.myteam.server.global.web.response.ResponseDto; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import static org.myteam.server.global.web.response.ResponseStatus.SUCCESS; - -@Slf4j -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/filter") -public class FilterController { - - private final FilterWriteService filterWriteService; - - /** - * 필터 데이터 추가 - */ - @PostMapping - public ResponseEntity> addFilterData(@RequestBody FilterDataRequest filterData) { - log.info("addFilterData: {}", filterData); - - filterWriteService.addFilteredWord(filterData.getFilterData()); - - return ResponseEntity.ok(new ResponseDto<>( - SUCCESS.name(), - "Successfully Filter data added", - filterData.getFilterData() - )); - } - - /** - * 필터 데이터 삭제 - */ - @DeleteMapping - public ResponseEntity> deleteFilterData(@RequestBody FilterDataRequest filterData) { - log.info("deleteFilterData: {}", filterData); - - filterWriteService.removeFilteredWord(filterData.getFilterData()); - - return ResponseEntity.ok(new ResponseDto<>( - SUCCESS.name(), - "Successfully Filter data deleted", - filterData.getFilterData() - )); - } -} diff --git a/src/main/java/org/myteam/server/chat/domain/Ban.java b/src/main/java/org/myteam/server/chat/domain/Ban.java deleted file mode 100644 index ee492ff7..00000000 --- a/src/main/java/org/myteam/server/chat/domain/Ban.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.myteam.server.chat.domain; - -import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -/** - * 밴(Ban) 엔티티. - * 특정 유저가 밴된 정보를 나타내며, 밴 사유와 밴된 시점 등을 포함한다. - */ -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Ban { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String username; // 밴 대상 사용자명 - - @ElementCollection(fetch = FetchType.LAZY) - @Enumerated(EnumType.STRING) - private List reasons = new ArrayList<>(); // 밴 사유 - - private String message; - - private LocalDateTime bannedAt; // 밴된 시점팅 - - // TODO: active로 관리할지.. tuple을 delete하는 로직으로 갈지.. - private boolean active; // 밴 활성화 플래그 - - @Builder - public Ban(String username, List reasons, LocalDateTime bannedAt, String message, boolean active) { - this.username = username; - this.bannedAt = bannedAt; - if (reasons != null) { - this.reasons.addAll(reasons); - } - this.message = message; - this.active = active; - } - - /** - * 밴 엔티티 생성 - */ - public static Ban createBan(String username, List reasons, String message) { - return Ban.builder() - .username(username) - .reasons(reasons) - .message(message) - .bannedAt(LocalDateTime.now()) - .active(true) - .build(); - } - - /** - * 밴 해제 로직 - */ - public void deactivateBan() { - this.active = false; - } -} diff --git a/src/main/java/org/myteam/server/chat/domain/Chat.java b/src/main/java/org/myteam/server/chat/domain/Chat.java deleted file mode 100644 index fbb47241..00000000 --- a/src/main/java/org/myteam/server/chat/domain/Chat.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.myteam.server.chat.domain; - -import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.data.annotation.CreatedDate; - -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Chat { - private ChatRoom room; - - private String sender; - - private String senderEmail; - - @Column(columnDefinition = "TEXT") - private String message; - - @Column(updatable = false) - private LocalDateTime sendDate = LocalDateTime.now(); - - @Builder - public Chat(ChatRoom room, String sender, String senderEmail, String message) { - this.room = room; - this.sender = sender; - this.senderEmail = senderEmail; - this.message = message; - } - - /** - * 채팅 생성 - * @param room 채팅 방 - * @param sender 보낸이 - * @param message 내용 - * @return Chat Entity - */ - public static Chat createChat(ChatRoom room, String sender, String senderEmail, String message) { - return Chat.builder() - .room(room) - .sender(sender) - .senderEmail(senderEmail) - .message(message) - .build(); - } - -} diff --git a/src/main/java/org/myteam/server/chat/domain/ChatRoom.java b/src/main/java/org/myteam/server/chat/domain/ChatRoom.java deleted file mode 100644 index 0c2356ec..00000000 --- a/src/main/java/org/myteam/server/chat/domain/ChatRoom.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.myteam.server.chat.domain; - -import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class ChatRoom { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "room_id") - private Long id; - private String name; - - @Builder - public ChatRoom(String name) { - this.name = name; - } - - public static ChatRoom createRoom(String name) { - return ChatRoom.builder() - .name(name) - .build(); - } -} diff --git a/src/main/java/org/myteam/server/chat/domain/FilterData.java b/src/main/java/org/myteam/server/chat/domain/FilterData.java deleted file mode 100644 index 8a48060f..00000000 --- a/src/main/java/org/myteam/server/chat/domain/FilterData.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.myteam.server.chat.domain; - -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Entity -@Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor -public class FilterData { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String word; - - public FilterData(String word) { - this.word = word; - } -} - diff --git a/src/main/java/org/myteam/server/chat/dto/request/BanRequest.java b/src/main/java/org/myteam/server/chat/dto/request/BanRequest.java deleted file mode 100644 index feb43466..00000000 --- a/src/main/java/org/myteam/server/chat/dto/request/BanRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.myteam.server.chat.dto.request; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.myteam.server.chat.domain.BanReason; - -import java.util.List; - -/** - * 밴 요청을 받기 위한 DTO - */ -@Getter -@NoArgsConstructor -public class BanRequest { - - private String username; // 밴할 사용자명 - private List reasons; // 밴 사유 - private String message; // 그때의 채팅 -} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/dto/request/ChatMessage.java b/src/main/java/org/myteam/server/chat/dto/request/ChatMessage.java deleted file mode 100644 index a038c074..00000000 --- a/src/main/java/org/myteam/server/chat/dto/request/ChatMessage.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.myteam.server.chat.dto.request; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class ChatMessage { - - private String sender; - private Long roomId; - private String senderEmail; - private String message; - private LocalDateTime sendDate; - -} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/dto/request/FilterDataRequest.java b/src/main/java/org/myteam/server/chat/dto/request/FilterDataRequest.java deleted file mode 100644 index 72d5eaab..00000000 --- a/src/main/java/org/myteam/server/chat/dto/request/FilterDataRequest.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.myteam.server.chat.dto.request; - - -import lombok.Getter; - -@Getter -public class FilterDataRequest { - private String filterData; -} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/dto/request/RoomRequest.java b/src/main/java/org/myteam/server/chat/dto/request/RoomRequest.java deleted file mode 100644 index 2155ba04..00000000 --- a/src/main/java/org/myteam/server/chat/dto/request/RoomRequest.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.myteam.server.chat.dto.request; - -import lombok.Getter; - -@Getter -public class RoomRequest { - private String roomName; -} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/dto/response/BanResponse.java b/src/main/java/org/myteam/server/chat/dto/response/BanResponse.java deleted file mode 100644 index 23910a2e..00000000 --- a/src/main/java/org/myteam/server/chat/dto/response/BanResponse.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.myteam.server.chat.dto.response; - -import lombok.Builder; -import lombok.Getter; -import org.myteam.server.chat.domain.Ban; -import org.myteam.server.chat.domain.BanReason; - -import java.time.format.DateTimeFormatter; -import java.util.List; - -/** - * 밴 정보를 반환하기 위한 DTO - */ -@Getter -@Builder -public class BanResponse { - private Long id; - private String username; - private List reason; - private String bannedAt; - - public static BanResponse createBanResponse(Ban ban) { - return BanResponse.builder() - .id(ban.getId()) - .username(ban.getUsername()) - .reason(ban.getReasons()) - .bannedAt(ban.getBannedAt().format(DateTimeFormatter.ofPattern("YYYY-MM-DD"))) - .build(); - } -} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/dto/response/ChatRoomResponse.java b/src/main/java/org/myteam/server/chat/dto/response/ChatRoomResponse.java deleted file mode 100644 index 7862d41d..00000000 --- a/src/main/java/org/myteam/server/chat/dto/response/ChatRoomResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.myteam.server.chat.dto.response; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class ChatRoomResponse { - private Long id; - private String name; -} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/info/domain/UserInfo.java b/src/main/java/org/myteam/server/chat/info/domain/UserInfo.java new file mode 100644 index 00000000..d759601d --- /dev/null +++ b/src/main/java/org/myteam/server/chat/info/domain/UserInfo.java @@ -0,0 +1,16 @@ +package org.myteam.server.chat.info.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UserInfo { + private UUID publicId; + private String nickname; + private String profileImage; +} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/interceptor/StompHandler.java b/src/main/java/org/myteam/server/chat/interceptor/StompHandler.java deleted file mode 100644 index 1fc15f36..00000000 --- a/src/main/java/org/myteam/server/chat/interceptor/StompHandler.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.myteam.server.chat.interceptor; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.myteam.server.chat.service.BanService; -import org.myteam.server.global.exception.ErrorCode; -import org.myteam.server.global.exception.PlayHiveException; -import org.myteam.server.global.security.jwt.JwtProvider; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.simp.stomp.StompCommand; -import org.springframework.messaging.simp.stomp.StompHeaderAccessor; -import org.springframework.messaging.support.ChannelInterceptor; -import org.springframework.messaging.support.MessageHeaderAccessor; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; - -@Slf4j -@RequiredArgsConstructor -@Component -@Order(Ordered.HIGHEST_PRECEDENCE + 99) -public class StompHandler implements ChannelInterceptor { - - private final JwtProvider jwtProvider; - private final BanService banService; - - @Override - public Message preSend(Message message, MessageChannel messageChannel) { - - StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); - - StompCommand command = accessor.getCommand(); - if (command == StompCommand.CONNECT) { - String authorizationHeader = getAuthorizationHeader(accessor); - - if (authorizationHeader == null || authorizationHeader.isEmpty()) { - log.warn("Authorization header missing or not Bearer type: {}", authorizationHeader); - throw new PlayHiveException(ErrorCode.MISSING_AUTH_HEADER); - } - - handleConnect(accessor, authorizationHeader); - } else if (command == StompCommand.ERROR) { - // ERROR 프레임의 경우 - throw new PlayHiveException(ErrorCode.INVALID_TOKEN); - } - - return message; - } - - /** - * STOMP CONNECT 프레임 처리 로직 - */ - private void handleConnect(StompHeaderAccessor accessor, String authorizationHeader) { - - if (!authorizationHeader.startsWith("[Bearer ")) { - log.warn("Authorization header missing or not Bearer type: {}", authorizationHeader); - throw new PlayHiveException(ErrorCode.MISSING_AUTH_HEADER); - } - - String token = extractToken(authorizationHeader); - - if (!jwtProvider.validToken(token)) { - log.warn("Invalid JWT token: {}", token); - throw new PlayHiveException(ErrorCode.INVALID_TOKEN); - } - - Authentication authentication = jwtProvider.getAuthentication(token); - SecurityContextHolder.getContext().setAuthentication(authentication); - accessor.setUser(authentication); - - String username = accessor.getUser() != null ? accessor.getUser().getName() : null; - if (banService.isBannedUser(username)) { - log.warn("Banned user tried to connect: {}", username); - throw new PlayHiveException(ErrorCode.BAN_USER); - } - - log.info("Authenticated user connected: {}", username); - } - - /** - * STOMP 헤더에서 "Authorization" 값을 얻는다. - */ - private String getAuthorizationHeader(StompHeaderAccessor accessor) { - String authHeaders = String.valueOf(accessor.getNativeHeader("Authorization")); - if (authHeaders == null || authHeaders.isEmpty()) { - return null; - } - return authHeaders; - } - - /** - * "[Bearer xxxxx]" 형태에서 실제 토큰 부분만 추출 - */ - private String extractToken(String authorizationHeader) { - String[] parts = authorizationHeader.split(" "); - if (parts.length < 2) { - throw new PlayHiveException(ErrorCode.MISSING_AUTH_HEADER); - } - - String rawToken = parts[1]; - return rawToken.substring(0, rawToken.length() - 1); // "]" 제거 - } -} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/mapper/ChatRoomMapper.java b/src/main/java/org/myteam/server/chat/mapper/ChatRoomMapper.java deleted file mode 100644 index 8644c810..00000000 --- a/src/main/java/org/myteam/server/chat/mapper/ChatRoomMapper.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.myteam.server.chat.mapper; - -import org.myteam.server.chat.domain.ChatRoom; -import org.myteam.server.chat.dto.response.ChatRoomResponse; - -import java.util.List; -import java.util.stream.Collectors; - -public class ChatRoomMapper { - public static ChatRoomResponse toDto(ChatRoom chatRoom) { - return ChatRoomResponse.builder() - .id(chatRoom.getId()) - .name(chatRoom.getName()) - .build(); - } - - public static List toDtoList(List chatRooms) { - return chatRooms.stream() - .map(ChatRoomMapper::toDto) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/org/myteam/server/chat/repository/BanRepository.java b/src/main/java/org/myteam/server/chat/repository/BanRepository.java deleted file mode 100644 index b7969813..00000000 --- a/src/main/java/org/myteam/server/chat/repository/BanRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.myteam.server.chat.repository; - -import org.myteam.server.chat.domain.Ban; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -@Repository -public interface BanRepository extends JpaRepository { - - Optional findByUsername(String username); - - boolean existsByUsername(String username); -} diff --git a/src/main/java/org/myteam/server/chat/repository/ChatRoomRepository.java b/src/main/java/org/myteam/server/chat/repository/ChatRoomRepository.java deleted file mode 100644 index a64bab03..00000000 --- a/src/main/java/org/myteam/server/chat/repository/ChatRoomRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.myteam.server.chat.repository; - -import org.myteam.server.chat.domain.ChatRoom; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface ChatRoomRepository extends JpaRepository { -} diff --git a/src/main/java/org/myteam/server/chat/repository/FilterDataRepository.java b/src/main/java/org/myteam/server/chat/repository/FilterDataRepository.java deleted file mode 100644 index 01033b31..00000000 --- a/src/main/java/org/myteam/server/chat/repository/FilterDataRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.myteam.server.chat.repository; - -import org.myteam.server.chat.domain.FilterData; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface FilterDataRepository extends JpaRepository { - - boolean existsByWord(String value); - - String deleteByWord(String word); -} - diff --git a/src/main/java/org/myteam/server/chat/service/BanService.java b/src/main/java/org/myteam/server/chat/service/BanService.java deleted file mode 100644 index 54da3ac0..00000000 --- a/src/main/java/org/myteam/server/chat/service/BanService.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.myteam.server.chat.service; - -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.myteam.server.chat.domain.Ban; -import org.myteam.server.chat.domain.BanReason; -import org.myteam.server.chat.dto.request.BanRequest; -import org.myteam.server.chat.dto.response.BanResponse; -import org.myteam.server.chat.repository.BanRepository; -import org.myteam.server.global.exception.ErrorCode; -import org.myteam.server.global.exception.PlayHiveException; -import org.myteam.server.util.slack.service.SlackService; -import org.springframework.stereotype.Service; - -import java.time.format.DateTimeFormatter; -import java.util.stream.Collectors; - -@Slf4j -@Service -@AllArgsConstructor -public class BanService { - - private final BanRepository banRepository; - private final SlackService slackService; - - /** - * 유저 밴 적용 - */ - public BanResponse banUser(BanRequest request) { - String username = request.getUsername(); - log.info("This user: {} has received a blocking request.", username); - // 이미 밴된 유저인지 확인 - if (banRepository.existsByUsername(username)) { - throw new PlayHiveException(ErrorCode.BAN_ALREADY_EXISTS); - } - - Ban ban = Ban.createBan(username, request.getReasons(), request.getMessage()); - Ban savedBan = banRepository.save(ban); - - String reasons = request.getReasons() - .stream() - .map(BanReason::getReason) - .collect(Collectors.joining(", ")); - String message = String.format("%s (차단 사유: %s)", username, reasons); - slackService.sendSlackNotification(message); - - return BanResponse.createBanResponse(savedBan); - } - - /** - * 유저 밴 해제 (삭제) - */ - public String unbanUser(String username) { - log.info("This user: {} has received a unblocking request.", username); - - Ban ban = banRepository.findByUsername(username) - .orElseThrow(() -> new PlayHiveException(ErrorCode.BAN_NOT_FOUND)); - - banRepository.delete(ban); - - return ban.getUsername(); - } - - /** - * 특정 유저 밴 정보 조회 - */ - public BanResponse findBanByUsername(String username) { - log.info("find ban user: {}", username); - - Ban ban = banRepository.findByUsername(username) - .orElseThrow(() -> new PlayHiveException(ErrorCode.BAN_NOT_FOUND)); - - return BanResponse.createBanResponse(ban); - } - - /** - * 밴 유저 조회 - */ - public boolean isBannedUser(String username) { - if (banRepository.existsByUsername(username)) { - return true; - } - return false; - } -} diff --git a/src/main/java/org/myteam/server/chat/service/ChatReadService.java b/src/main/java/org/myteam/server/chat/service/ChatReadService.java deleted file mode 100644 index de9fde99..00000000 --- a/src/main/java/org/myteam/server/chat/service/ChatReadService.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.myteam.server.chat.service; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.myteam.server.chat.domain.ChatRoom; -import org.myteam.server.chat.dto.response.ChatRoomResponse; -import org.myteam.server.chat.mapper.ChatRoomMapper; -import org.myteam.server.chat.repository.ChatRoomRepository; -import org.myteam.server.global.exception.ErrorCode; -import org.myteam.server.global.exception.PlayHiveException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -@Slf4j -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class ChatReadService { - - private final ChatRoomRepository roomRepository; - - /** - * TODO: 필요가 없을 듯. 경기 일정 보내주는 것은 다르기때문에 현재는 테스트 때문에 남겨둠. - * 모든 채팅방 조회 - */ - public List findAllRooms() { - List chatRooms = roomRepository.findAll(); - return ChatRoomMapper.toDtoList(chatRooms); - } - - /** - * ID로 채팅방 조회 - */ - public ChatRoom findRoomById(Long id) { - return roomRepository.findById(id) - .orElseThrow(() -> new PlayHiveException(ErrorCode.ROOM_NOT_FOUND)); - } -} diff --git a/src/main/java/org/myteam/server/chat/service/ChatService.java b/src/main/java/org/myteam/server/chat/service/ChatService.java deleted file mode 100644 index fff13276..00000000 --- a/src/main/java/org/myteam/server/chat/service/ChatService.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.myteam.server.chat.service; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.myteam.server.chat.domain.BadWordFilter; -import org.myteam.server.chat.domain.Chat; -import org.myteam.server.chat.domain.ChatRoom; -import org.myteam.server.chat.dto.response.ChatRoomResponse; -import org.myteam.server.chat.mapper.ChatRoomMapper; -import org.myteam.server.chat.repository.ChatRoomRepository; -import org.myteam.server.global.exception.ErrorCode; -import org.myteam.server.global.exception.PlayHiveException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Slf4j -@Service -@RequiredArgsConstructor -@Transactional -public class ChatService { - - private final ChatRoomRepository roomRepository; -// private final KafkaProducerService kafkaProducerService; -// private final TopicManagementService topicManagementService; - private final BadWordFilter badWordFilter; - - /** - * 채팅방 생성 - */ - public ChatRoomResponse createChatRoom(String roomName) { - ChatRoom newRoom = ChatRoom.builder() - .name(roomName) - .build(); - - roomRepository.save(newRoom); - log.info("Chat room '{}' created.", roomName); - - // Kafka 토픽 생성 - String topicName = "room-" + newRoom.getId(); -// topicManagementService.createTopic(topicName, 3, (short) 1); - log.info("Kafka topic '{}' created for chat room '{}'.", topicName, roomName); - - return ChatRoomMapper.toDto(newRoom); - } - - /** - * 채팅방 삭제 - */ - public String deleteChatRoom(Long roomId) { - ChatRoom chatRoom = roomRepository.findById(roomId) - .orElseThrow(() -> new PlayHiveException(ErrorCode.ROOM_NOT_FOUND)); - - // Kafka 토픽 삭제 -// try { -// topicManagementService.deleteTopic("room-" + roomId); -// log.info("Deleted Kafka topic: room-{}", roomId); -// } catch (Exception e) { -// log.error("Failed to delete Kafka topic for room ID: {}. Error: {}", roomId, e.getMessage()); -// throw new PlayHiveException(ErrorCode.KAFKA_TOPIC_DELETE_FAILED); -// } - - // 채팅방 삭제 - roomRepository.delete(chatRoom); - log.info("Deleted chat room with ID: {}", roomId); - - return chatRoom.getName(); - } - - /** - * 채팅 생성 - */ - public Chat createChat(Long roomId, String sender, String senderEmail, String message) { - message = validateAndTrimMessage(message); - - ChatRoom room = roomRepository.findById(roomId) - .orElseThrow(() -> new PlayHiveException(ErrorCode.ROOM_NOT_FOUND)); - - String filteredMessage = badWordFilter.filterMessage(message); - Chat chat = Chat.createChat(room, sender, senderEmail, filteredMessage); - - // Kafka에 메시지 전송 -// kafkaProducerService.sendMessage("room-" + roomId, chat); - - return chat; - } - - public String validateAndTrimMessage(String message) { - if (message != null && message.length() > 500) { - log.warn("Message length exceeds 500 characters. Trimming the message."); - return message.substring(0, 500); - } - return message; - } -} diff --git a/src/main/java/org/myteam/server/chat/service/FilterWriteService.java b/src/main/java/org/myteam/server/chat/service/FilterWriteService.java deleted file mode 100644 index 44266811..00000000 --- a/src/main/java/org/myteam/server/chat/service/FilterWriteService.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.myteam.server.chat.service; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.myteam.server.chat.domain.BadWordFilter; -import org.myteam.server.chat.domain.FilterData; -import org.myteam.server.chat.repository.FilterDataRepository; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; - -@Slf4j -@Service -@RequiredArgsConstructor -@Transactional -public class FilterWriteService { - - private final FilterDataRepository filterDataRepository; - private final BadWordFilter badWordFilter; - - /** - * 애플리케이션 시작 시 필터링 단어 로드 - */ - @EventListener(ApplicationReadyEvent.class) - public void loadFilteredWords() { - List words = filterDataRepository.findAll() - .stream() - .map(FilterData::getWord) - .collect(Collectors.toList()); - badWordFilter.loadFilteredWords(words); - log.info("Filtered words loaded: {}", words); - } - - public void addFilteredWord(String word) { - filterDataRepository.save(new FilterData(word)); - badWordFilter.addFilteredWord(word); - log.info("Successfully add Filter"); - } - - public void removeFilteredWord(String word) { - filterDataRepository.deleteByWord(word); - badWordFilter.removeFilteredWord(word); - log.info("Successfully delete Filter"); - } -} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/service/KafkaConsumerService.java b/src/main/java/org/myteam/server/chat/service/KafkaConsumerService.java deleted file mode 100644 index eca245c4..00000000 --- a/src/main/java/org/myteam/server/chat/service/KafkaConsumerService.java +++ /dev/null @@ -1,29 +0,0 @@ -//package org.myteam.server.chat.service; -// -//import lombok.RequiredArgsConstructor; -//import lombok.extern.slf4j.Slf4j; -//import org.apache.kafka.clients.consumer.ConsumerRecord; -//import org.myteam.server.chat.domain.Chat; -//import org.springframework.kafka.annotation.KafkaListener; -//import org.springframework.messaging.simp.SimpMessagingTemplate; -//import org.springframework.stereotype.Service; -// -//@Slf4j -//@Service -//@RequiredArgsConstructor -//public class KafkaConsumerService { -// private final SimpMessagingTemplate messagingTemplate; -// -// @KafkaListener(topicPattern = "room-.*", groupId = "chat-group", containerFactory = "kafkaListenerContainerFactory") -// public void consumeMessage(ConsumerRecord record) { -// String topic = record.topic(); -// Chat chat = record.value(); -// -// log.info("Consumed message from topic {}: {}", topic, chat); -// -// // WebSocket으로 클라이언트에게 메시지 전달 -// String roomId = topic.split("-")[1]; -// messagingTemplate.convertAndSend("/topic/room/" + roomId, chat); -// -// } -//} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/chat/service/KafkaProducerService.java b/src/main/java/org/myteam/server/chat/service/KafkaProducerService.java deleted file mode 100644 index a10212d9..00000000 --- a/src/main/java/org/myteam/server/chat/service/KafkaProducerService.java +++ /dev/null @@ -1,23 +0,0 @@ -//package org.myteam.server.chat.service; -// -//import lombok.RequiredArgsConstructor; -//import lombok.extern.slf4j.Slf4j; -//import org.myteam.server.chat.domain.Chat; -//import org.springframework.kafka.core.KafkaTemplate; -//import org.springframework.stereotype.Service; -// -//@Slf4j -//@Service -//@RequiredArgsConstructor -//public class KafkaProducerService { -// -// private final KafkaTemplate kafkaTemplate; -// -// /** -// * Kafka로 메시지 전송 -// */ -// public void sendMessage(String topic, Chat chat) { -// kafkaTemplate.send(topic, chat); -// log.info("Sent message: {} to topic: {}", chat, topic); -// } -//} diff --git a/src/main/java/org/myteam/server/chat/service/TopicManagementService.java b/src/main/java/org/myteam/server/chat/service/TopicManagementService.java deleted file mode 100644 index 5e8f2d2b..00000000 --- a/src/main/java/org/myteam/server/chat/service/TopicManagementService.java +++ /dev/null @@ -1,48 +0,0 @@ -//package org.myteam.server.chat.service; -// -//import lombok.RequiredArgsConstructor; -//import lombok.extern.slf4j.Slf4j; -//import org.apache.kafka.clients.admin.AdminClient; -//import org.apache.kafka.clients.admin.NewTopic; -//import org.apache.kafka.common.KafkaException; -//import org.springframework.kafka.core.KafkaAdmin; -//import org.springframework.stereotype.Service; -// -//import java.util.Collections; -//import java.util.concurrent.ExecutionException; -// -//@Slf4j -//@Service -//@RequiredArgsConstructor -//public class TopicManagementService { -// -// private final KafkaAdmin kafkaAdmin; -// -// /** -// * 동적 토픽 생성 -// */ -// public void createTopic(String topicName, int partitions, short replicationFactor) { -// try (AdminClient adminClient = AdminClient.create(kafkaAdmin.getConfigurationProperties())) { -// NewTopic topic = new NewTopic(topicName, partitions, replicationFactor); -// adminClient.createTopics(Collections.singletonList(topic)).all().get(); -// log.info("Topic '{}' created successfully with {} partitions and replication factor {}.", -// topicName, partitions, replicationFactor); -// } catch (ExecutionException | InterruptedException e) { -// log.error("Failed to create topic '{}': {}", topicName, e.getMessage()); -// Thread.currentThread().interrupt(); // 인터럽트 복원 -// } -// } -// -// /** -// * 동적 토픽 삭제 -// */ -// public void deleteTopic(String topicName) { -// try (AdminClient adminClient = AdminClient.create(kafkaAdmin.getConfigurationProperties())) { -// adminClient.deleteTopics(Collections.singletonList(topicName)).all().get(); -// log.info("Topic '{}' deleted successfully.", topicName); -// } catch (ExecutionException | InterruptedException e) { -// log.error("Failed to delete topic '{}': {}", topicName, e.getMessage()); -// Thread.currentThread().interrupt(); // 인터럽트 복원 -// } -// } -//} \ No newline at end of file diff --git a/src/main/java/org/myteam/server/comment/service/CommentService.java b/src/main/java/org/myteam/server/comment/service/CommentService.java index 4b81933f..610297a7 100644 --- a/src/main/java/org/myteam/server/comment/service/CommentService.java +++ b/src/main/java/org/myteam/server/comment/service/CommentService.java @@ -1,12 +1,10 @@ package org.myteam.server.comment.service; import java.util.List; -import java.util.Map; import java.util.UUID; -import java.util.stream.Collectors; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.myteam.server.chat.domain.BadWordFilter; import org.myteam.server.comment.domain.Comment; import org.myteam.server.comment.domain.CommentType; import org.myteam.server.comment.dto.request.CommentRequest.CommentDeleteRequest; @@ -16,9 +14,10 @@ import org.myteam.server.comment.repository.CommentRecommendRepository; import org.myteam.server.comment.repository.CommentRepository; import org.myteam.server.comment.util.CommentFactory; +import org.myteam.server.common.filter.util.BadWordFilter; import org.myteam.server.global.exception.ErrorCode; import org.myteam.server.global.exception.PlayHiveException; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.global.util.upload.MediaUtils; import org.myteam.server.member.entity.Member; @@ -26,7 +25,6 @@ import org.myteam.server.member.service.SecurityReadService; import org.myteam.server.report.domain.DomainType; import org.myteam.server.upload.service.StorageService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/org/myteam/server/chat/domain/BadWordFilter.java b/src/main/java/org/myteam/server/common/filter/util/BadWordFilter.java similarity index 94% rename from src/main/java/org/myteam/server/chat/domain/BadWordFilter.java rename to src/main/java/org/myteam/server/common/filter/util/BadWordFilter.java index c444b409..a235178a 100644 --- a/src/main/java/org/myteam/server/chat/domain/BadWordFilter.java +++ b/src/main/java/org/myteam/server/common/filter/util/BadWordFilter.java @@ -1,12 +1,17 @@ -package org.myteam.server.chat.domain; +package org.myteam.server.common.filter.util; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + @Slf4j @Component public class BadWordFilter { @@ -100,3 +105,4 @@ private String buildDelimiterPattern() { .collect(Collectors.joining("", "[", "]*")); } } + diff --git a/src/main/java/org/myteam/server/global/security/config/SecurityConfig.java b/src/main/java/org/myteam/server/global/security/config/SecurityConfig.java index cbe85f31..fb20ca67 100644 --- a/src/main/java/org/myteam/server/global/security/config/SecurityConfig.java +++ b/src/main/java/org/myteam/server/global/security/config/SecurityConfig.java @@ -1,22 +1,20 @@ package org.myteam.server.global.security.config; -import static org.myteam.server.global.security.jwt.JwtProvider.*; - import org.myteam.server.global.config.WebConfig; import org.myteam.server.global.security.filter.AuthenticationEntryPointHandler; import org.myteam.server.global.security.filter.CustomAccessDeniedHandler; import org.myteam.server.global.security.filter.JwtAuthenticationFilter; import org.myteam.server.global.security.filter.TokenAuthenticationFilter; -import org.myteam.server.global.security.handler.LogoutSuccessHandler; +import org.myteam.server.global.security.handler.CustomLogoutSuccessHandler; import org.myteam.server.global.security.jwt.JwtProvider; import org.myteam.server.global.security.service.CustomUserDetailsService; -import org.myteam.server.global.util.redis.RedisService; +import org.myteam.server.global.util.redis.service.RedisService; +import org.myteam.server.global.util.redis.service.RedisUserInfoService; import org.myteam.server.member.domain.MemberRole; import org.myteam.server.member.repository.MemberJpaRepository; import org.myteam.server.oauth2.handler.CustomOauth2SuccessHandler; import org.myteam.server.oauth2.handler.OAuth2LoginFailureHandler; import org.myteam.server.oauth2.service.CustomOAuth2UserService; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,11 +32,7 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; -import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -191,6 +185,7 @@ public class SecurityConfig { private final OAuth2LoginFailureHandler oAuth2LoginFailureHandler; private final ApplicationEventPublisher eventPublisher; private final RedisService redisService; + private final RedisUserInfoService redisUserInfoService; private final MemberJpaRepository memberJpaRepository; private final WebConfig webConfig; @@ -229,7 +224,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti // JWT 인증 및 토큰 검증 필터 추가 http .addFilterBefore( - new JwtAuthenticationFilter(authenticationManager(), jwtProvider, eventPublisher, redisService), + new JwtAuthenticationFilter(authenticationManager(), jwtProvider, eventPublisher, redisService, redisUserInfoService), UsernamePasswordAuthenticationFilter.class ) .addFilterBefore( @@ -251,7 +246,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti http.logout(logout -> logout .logoutUrl("/logout") .invalidateHttpSession(true) - .logoutSuccessHandler(new LogoutSuccessHandler(jwtProvider)) + .logoutSuccessHandler(new CustomLogoutSuccessHandler(jwtProvider, redisUserInfoService)) .permitAll() ); diff --git a/src/main/java/org/myteam/server/global/security/dto/CustomUserDetails.java b/src/main/java/org/myteam/server/global/security/dto/CustomUserDetails.java index 65b79d25..47222d63 100644 --- a/src/main/java/org/myteam/server/global/security/dto/CustomUserDetails.java +++ b/src/main/java/org/myteam/server/global/security/dto/CustomUserDetails.java @@ -46,6 +46,13 @@ public UUID getPublicId() { } public String getStatus() {return member.getStatus().name(); } + public String getNickname() { + return member.getNickname(); + } + + public String getImg() { + return member.getImgUrl(); + } @Override public boolean isAccountNonExpired() { diff --git a/src/main/java/org/myteam/server/global/security/filter/JwtAuthenticationFilter.java b/src/main/java/org/myteam/server/global/security/filter/JwtAuthenticationFilter.java index ac073298..6961e141 100644 --- a/src/main/java/org/myteam/server/global/security/filter/JwtAuthenticationFilter.java +++ b/src/main/java/org/myteam/server/global/security/filter/JwtAuthenticationFilter.java @@ -10,12 +10,14 @@ import java.util.Map; import java.util.UUID; +import org.myteam.server.chat.info.domain.UserInfo; import org.myteam.server.global.exception.ErrorCode; import org.myteam.server.global.exception.PlayHiveException; import org.myteam.server.global.security.dto.CustomUserDetails; import org.myteam.server.global.security.dto.UserLoginEvent; import org.myteam.server.global.security.jwt.JwtProvider; -import org.myteam.server.global.util.redis.RedisService; +import org.myteam.server.global.util.redis.service.RedisService; +import org.myteam.server.global.util.redis.service.RedisUserInfoService; import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatus; import org.springframework.security.authentication.AuthenticationManager; @@ -39,16 +41,19 @@ public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilte private final JwtProvider jwtProvider; private final ApplicationEventPublisher eventPublisher; private final RedisService redisService; + private final RedisUserInfoService redisUserInfoService; public JwtAuthenticationFilter(AuthenticationManager authenticationManager, - JwtProvider jwtProvider, - ApplicationEventPublisher eventPublisher, - RedisService redisService) { + JwtProvider jwtProvider, + ApplicationEventPublisher eventPublisher, + RedisService redisService, + RedisUserInfoService redisUserInfoService) { setFilterProcessesUrl("/login"); this.authenticationManager = authenticationManager; this.jwtProvider = jwtProvider; this.eventPublisher = eventPublisher; this.redisService = redisService; + this.redisUserInfoService = redisUserInfoService; } @Override @@ -121,6 +126,9 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR log.debug("print role: {}", role); redisService.putRefreshToken(publicId, refreshToken); + redisUserInfoService.saveUserInfo(accessToken, + new UserInfo(publicId, customUserDetails.getNickname(), customUserDetails.getImg())); + log.info("member: {} caching user info", publicId); response.addHeader(HEADER_AUTHORIZATION, TOKEN_PREFIX + accessToken); response.setStatus(HttpStatus.OK.value()); diff --git a/src/main/java/org/myteam/server/global/security/handler/LogoutSuccessHandler.java b/src/main/java/org/myteam/server/global/security/handler/CustomLogoutSuccessHandler.java similarity index 51% rename from src/main/java/org/myteam/server/global/security/handler/LogoutSuccessHandler.java rename to src/main/java/org/myteam/server/global/security/handler/CustomLogoutSuccessHandler.java index f2e0d438..9f54ce36 100644 --- a/src/main/java/org/myteam/server/global/security/handler/LogoutSuccessHandler.java +++ b/src/main/java/org/myteam/server/global/security/handler/CustomLogoutSuccessHandler.java @@ -1,27 +1,34 @@ package org.myteam.server.global.security.handler; +import static org.myteam.server.global.security.jwt.JwtProvider.HEADER_AUTHORIZATION; import static org.springframework.http.HttpMethod.*; +import lombok.RequiredArgsConstructor; import org.myteam.server.global.security.jwt.JwtProvider; +import org.myteam.server.global.util.redis.service.RedisUserInfoService; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @Slf4j -public class LogoutSuccessHandler - implements org.springframework.security.web.authentication.logout.LogoutSuccessHandler { - final JwtProvider jwtProvider; +public class CustomLogoutSuccessHandler implements LogoutSuccessHandler { + private final JwtProvider jwtProvider; + private final RedisUserInfoService redisUserInfoService; - public LogoutSuccessHandler(JwtProvider jwtProvider) { + public CustomLogoutSuccessHandler(JwtProvider jwtProvider, + RedisUserInfoService redisUserInfoService) { this.jwtProvider = jwtProvider; + this.redisUserInfoService = redisUserInfoService; } @Override - public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, - Authentication authentication) { + public void onLogoutSuccess(HttpServletRequest request, + HttpServletResponse response, + Authentication authentication) { log.info("LogoutSuccessHandler onLogoutSuccess() 메서드를 실행하였습니다"); String method = request.getMethod(); @@ -30,6 +37,11 @@ public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse resp return; } + String authorizationHeader = request.getHeader(HEADER_AUTHORIZATION); + String accessToken = jwtProvider.getAccessToken(authorizationHeader); + redisUserInfoService.deleteUserInfo(accessToken); + log.info("delete user info: {}", accessToken); + // 1. Security Context 해제 clearContextAndAddCookie(response); } diff --git a/src/main/java/org/myteam/server/global/util/redis/RedisCountService.java b/src/main/java/org/myteam/server/global/util/redis/service/RedisCountService.java similarity index 96% rename from src/main/java/org/myteam/server/global/util/redis/RedisCountService.java rename to src/main/java/org/myteam/server/global/util/redis/service/RedisCountService.java index 911e8740..a505136c 100644 --- a/src/main/java/org/myteam/server/global/util/redis/RedisCountService.java +++ b/src/main/java/org/myteam/server/global/util/redis/service/RedisCountService.java @@ -1,10 +1,13 @@ -package org.myteam.server.global.util.redis; +package org.myteam.server.global.util.redis.service; import static org.myteam.server.util.ClientUtils.toInt; import java.time.Duration; import java.util.Map; import lombok.extern.slf4j.Slf4j; +import org.myteam.server.global.util.redis.CommonCount; +import org.myteam.server.global.util.redis.CommonCountDto; +import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.recommend.RecommendActionType; import org.myteam.server.recommend.RecommendService; import org.myteam.server.report.domain.DomainType; diff --git a/src/main/java/org/myteam/server/global/util/redis/RedisService.java b/src/main/java/org/myteam/server/global/util/redis/service/RedisService.java similarity index 98% rename from src/main/java/org/myteam/server/global/util/redis/RedisService.java rename to src/main/java/org/myteam/server/global/util/redis/service/RedisService.java index b0cfeecf..990ae019 100644 --- a/src/main/java/org/myteam/server/global/util/redis/RedisService.java +++ b/src/main/java/org/myteam/server/global/util/redis/service/RedisService.java @@ -1,4 +1,4 @@ -package org.myteam.server.global.util.redis; +package org.myteam.server.global.util.redis.service; import java.time.Duration; import java.util.UUID; diff --git a/src/main/java/org/myteam/server/global/util/redis/service/RedisUserInfoService.java b/src/main/java/org/myteam/server/global/util/redis/service/RedisUserInfoService.java new file mode 100644 index 00000000..d5cf1be7 --- /dev/null +++ b/src/main/java/org/myteam/server/global/util/redis/service/RedisUserInfoService.java @@ -0,0 +1,58 @@ +package org.myteam.server.global.util.redis.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.myteam.server.chat.info.domain.UserInfo; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.time.Duration; +import java.util.Optional; + +@Slf4j +@Service +@RequiredArgsConstructor +public class RedisUserInfoService { + + private final RedisTemplate redisTemplate; + private static final String PREFIX = "token:"; + private static final int LIMIT_DAYS = 1; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + public void saveUserInfo(String token, UserInfo userInfo) { + try { + String key = PREFIX + token; + String value = objectMapper.writeValueAsString(userInfo); + + redisTemplate.opsForValue().set(key, value, Duration.ofDays(LIMIT_DAYS)); + log.info("Saved user info to Redis. Key={}, TTL={}", key, Duration.ofDays(LIMIT_DAYS)); + } catch (JsonProcessingException e) { + log.error("Failed to serialize userInfo", e); + } + } + + /** + * 채팅서버에서 사용 + * @param token + */ +// public Optional getUserInfo(String token) { +// String key = PREFIX + token; +// try { +// String value = (String) redisTemplate.opsForValue().get(key); +// if (value == null) return Optional.empty(); +// return Optional.of(objectMapper.readValue(value, UserInfo.class)); +// } catch (Exception e) { +// log.error("Failed to deserialize userInfo", e); +// return Optional.empty(); +// } +// } + + public void deleteUserInfo(String token) { + String key = PREFIX + token; + redisTemplate.delete(key); + log.info("Deleted user info from Redis. Key={}", key); + } +} diff --git a/src/main/java/org/myteam/server/improvement/repository/ImprovementQueryRepository.java b/src/main/java/org/myteam/server/improvement/repository/ImprovementQueryRepository.java index 61c123e8..03fe61f8 100644 --- a/src/main/java/org/myteam/server/improvement/repository/ImprovementQueryRepository.java +++ b/src/main/java/org/myteam/server/improvement/repository/ImprovementQueryRepository.java @@ -24,7 +24,7 @@ import org.myteam.server.comment.domain.QComment; import org.myteam.server.comment.domain.QImprovementComment; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.improvement.domain.ImprovementOrderType; import org.myteam.server.improvement.domain.ImprovementSearchType; diff --git a/src/main/java/org/myteam/server/improvement/service/ImprovementCountService.java b/src/main/java/org/myteam/server/improvement/service/ImprovementCountService.java index 7399d3c5..6866abd6 100644 --- a/src/main/java/org/myteam/server/improvement/service/ImprovementCountService.java +++ b/src/main/java/org/myteam/server/improvement/service/ImprovementCountService.java @@ -2,7 +2,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.report.domain.DomainType; import org.springframework.stereotype.Service; diff --git a/src/main/java/org/myteam/server/improvement/service/ImprovementReadService.java b/src/main/java/org/myteam/server/improvement/service/ImprovementReadService.java index 795f5230..1d6de9f8 100644 --- a/src/main/java/org/myteam/server/improvement/service/ImprovementReadService.java +++ b/src/main/java/org/myteam/server/improvement/service/ImprovementReadService.java @@ -8,7 +8,7 @@ import org.myteam.server.global.exception.PlayHiveException; import org.myteam.server.global.page.response.PageCustomResponse; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.improvement.domain.Improvement; import org.myteam.server.improvement.dto.request.ImprovementRequest.ImprovementServiceRequest; diff --git a/src/main/java/org/myteam/server/improvement/service/ImprovementService.java b/src/main/java/org/myteam/server/improvement/service/ImprovementService.java index 65546093..a1df4111 100644 --- a/src/main/java/org/myteam/server/improvement/service/ImprovementService.java +++ b/src/main/java/org/myteam/server/improvement/service/ImprovementService.java @@ -7,7 +7,7 @@ import org.myteam.server.global.exception.ErrorCode; import org.myteam.server.global.exception.PlayHiveException; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.global.util.upload.MediaUtils; import org.myteam.server.improvement.domain.Improvement; diff --git a/src/main/java/org/myteam/server/inquiry/repository/InquiryQueryRepository.java b/src/main/java/org/myteam/server/inquiry/repository/InquiryQueryRepository.java index 611c34c6..0fce7a29 100644 --- a/src/main/java/org/myteam/server/inquiry/repository/InquiryQueryRepository.java +++ b/src/main/java/org/myteam/server/inquiry/repository/InquiryQueryRepository.java @@ -21,7 +21,7 @@ import org.myteam.server.comment.domain.QComment; import org.myteam.server.comment.domain.QInquiryComment; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.inquiry.domain.InquiryOrderType; import org.myteam.server.inquiry.domain.InquirySearchType; diff --git a/src/main/java/org/myteam/server/inquiry/service/InquiryReadService.java b/src/main/java/org/myteam/server/inquiry/service/InquiryReadService.java index 310a37bb..a5e10427 100644 --- a/src/main/java/org/myteam/server/inquiry/service/InquiryReadService.java +++ b/src/main/java/org/myteam/server/inquiry/service/InquiryReadService.java @@ -8,7 +8,7 @@ import org.myteam.server.global.exception.PlayHiveException; import org.myteam.server.global.page.response.PageCustomResponse; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.inquiry.domain.Inquiry; import org.myteam.server.inquiry.dto.request.InquiryRequest.InquiryServiceRequest; diff --git a/src/main/java/org/myteam/server/match/match/dto/service/response/MatchResponse.java b/src/main/java/org/myteam/server/match/match/dto/service/response/MatchResponse.java index 1dc1b89c..e7abd7d9 100644 --- a/src/main/java/org/myteam/server/match/match/dto/service/response/MatchResponse.java +++ b/src/main/java/org/myteam/server/match/match/dto/service/response/MatchResponse.java @@ -9,6 +9,8 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import static org.myteam.server.chat.block.domain.Topic.TOPIC_PREFIX; + @Getter @NoArgsConstructor public class MatchResponse { @@ -26,6 +28,9 @@ public class MatchResponse { @Schema(description = "경기 유형 ID") private String category; + @Schema(description = "채팅방 이름") + private String topicName; + @Builder public MatchResponse(Long id, TeamResponse homeTeam, TeamResponse awayTeam, String place, String leagueName, LocalDateTime startTime, String category) { this.id = id; @@ -35,6 +40,7 @@ public MatchResponse(Long id, TeamResponse homeTeam, TeamResponse awayTeam, Stri this.leagueName = leagueName; this.startTime = startTime; this.category = category; + this.topicName = TOPIC_PREFIX + category + "-" + id; } public static MatchResponse createResponse(Match match) { diff --git a/src/main/java/org/myteam/server/match/match/service/MatchYoutubeService.java b/src/main/java/org/myteam/server/match/match/service/MatchYoutubeService.java index fe4b19d8..c67402a2 100644 --- a/src/main/java/org/myteam/server/match/match/service/MatchYoutubeService.java +++ b/src/main/java/org/myteam/server/match/match/service/MatchYoutubeService.java @@ -2,7 +2,7 @@ import org.myteam.server.global.exception.ErrorCode; import org.myteam.server.global.exception.PlayHiveException; -import org.myteam.server.global.util.redis.RedisService; +import org.myteam.server.global.util.redis.service.RedisService; import org.myteam.server.match.match.client.GoogleFeignClient; import org.myteam.server.match.match.dto.client.reponse.GoogleYoutubeResponse; import org.springframework.beans.factory.annotation.Value; diff --git a/src/main/java/org/myteam/server/member/service/MemberService.java b/src/main/java/org/myteam/server/member/service/MemberService.java index da752c6a..6b243067 100644 --- a/src/main/java/org/myteam/server/member/service/MemberService.java +++ b/src/main/java/org/myteam/server/member/service/MemberService.java @@ -10,7 +10,7 @@ import org.myteam.server.common.certification.mail.factory.MailStrategyFactory; import org.myteam.server.global.exception.ErrorCode; import org.myteam.server.global.exception.PlayHiveException; -import org.myteam.server.global.util.redis.RedisService; +import org.myteam.server.global.util.redis.service.RedisService; import org.myteam.server.member.controller.response.MemberResponse; import org.myteam.server.member.domain.MemberStatus; import org.myteam.server.member.domain.MemberType; @@ -72,7 +72,7 @@ public MemberResponse create(MemberSaveRequest memberSaveRequest) throws PlayHiv // 메일 전송 MailStrategy strategy = mailStrategyFactory.getStrategy(EmailType.WELCOME); - strategy.send(member.getEmail()); +// strategy.send(member.getEmail()); // dto 응답 return MemberResponse.createMemberResponse(member); diff --git a/src/main/java/org/myteam/server/news/news/service/NewsReadService.java b/src/main/java/org/myteam/server/news/news/service/NewsReadService.java index 0696481f..a69e7a83 100644 --- a/src/main/java/org/myteam/server/news/news/service/NewsReadService.java +++ b/src/main/java/org/myteam/server/news/news/service/NewsReadService.java @@ -7,7 +7,7 @@ import org.myteam.server.global.exception.PlayHiveException; import org.myteam.server.global.page.response.PageCustomResponse; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.member.service.SecurityReadService; import org.myteam.server.news.news.domain.News; diff --git a/src/main/java/org/myteam/server/news/newsCount/service/NewsCountService.java b/src/main/java/org/myteam/server/news/newsCount/service/NewsCountService.java index 5c61320a..c0047977 100644 --- a/src/main/java/org/myteam/server/news/newsCount/service/NewsCountService.java +++ b/src/main/java/org/myteam/server/news/newsCount/service/NewsCountService.java @@ -1,7 +1,7 @@ package org.myteam.server.news.newsCount.service; import lombok.RequiredArgsConstructor; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.news.newsCount.dto.service.response.NewsRecommendResponse; import org.myteam.server.report.domain.DomainType; diff --git a/src/main/java/org/myteam/server/notice/repository/NoticeQueryRepository.java b/src/main/java/org/myteam/server/notice/repository/NoticeQueryRepository.java index 0f2508a7..c277f845 100644 --- a/src/main/java/org/myteam/server/notice/repository/NoticeQueryRepository.java +++ b/src/main/java/org/myteam/server/notice/repository/NoticeQueryRepository.java @@ -22,7 +22,7 @@ import org.myteam.server.comment.domain.QComment; import org.myteam.server.comment.domain.QNoticeComment; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.notice.domain.NoticeSearchType; import org.myteam.server.notice.dto.response.NoticeResponse.NoticeDto; diff --git a/src/main/java/org/myteam/server/notice/service/NoticeCountService.java b/src/main/java/org/myteam/server/notice/service/NoticeCountService.java index 0998f9f9..ceb21973 100644 --- a/src/main/java/org/myteam/server/notice/service/NoticeCountService.java +++ b/src/main/java/org/myteam/server/notice/service/NoticeCountService.java @@ -2,7 +2,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.report.domain.DomainType; import org.springframework.stereotype.Service; diff --git a/src/main/java/org/myteam/server/notice/service/NoticeReadService.java b/src/main/java/org/myteam/server/notice/service/NoticeReadService.java index 38d1d673..4c221390 100644 --- a/src/main/java/org/myteam/server/notice/service/NoticeReadService.java +++ b/src/main/java/org/myteam/server/notice/service/NoticeReadService.java @@ -8,7 +8,7 @@ import org.myteam.server.global.exception.PlayHiveException; import org.myteam.server.global.page.response.PageCustomResponse; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.member.service.SecurityReadService; import org.myteam.server.notice.domain.Notice; diff --git a/src/main/java/org/myteam/server/notice/service/NoticeService.java b/src/main/java/org/myteam/server/notice/service/NoticeService.java index ddb9939d..e7b15aca 100644 --- a/src/main/java/org/myteam/server/notice/service/NoticeService.java +++ b/src/main/java/org/myteam/server/notice/service/NoticeService.java @@ -7,7 +7,7 @@ import org.myteam.server.global.exception.ErrorCode; import org.myteam.server.global.exception.PlayHiveException; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.global.util.upload.MediaUtils; import org.myteam.server.member.entity.Member; diff --git a/src/main/java/org/myteam/server/oauth2/handler/CustomOauth2SuccessHandler.java b/src/main/java/org/myteam/server/oauth2/handler/CustomOauth2SuccessHandler.java index 4a6d29f5..013b3076 100644 --- a/src/main/java/org/myteam/server/oauth2/handler/CustomOauth2SuccessHandler.java +++ b/src/main/java/org/myteam/server/oauth2/handler/CustomOauth2SuccessHandler.java @@ -10,10 +10,11 @@ import java.util.Collection; import java.util.Iterator; +import org.myteam.server.chat.info.domain.UserInfo; import org.myteam.server.global.security.dto.UserLoginEvent; import org.myteam.server.global.security.jwt.JwtProvider; -import org.myteam.server.global.util.cookie.CookieUtil; -import org.myteam.server.global.util.redis.RedisService; +import org.myteam.server.global.util.redis.service.RedisService; +import org.myteam.server.global.util.redis.service.RedisUserInfoService; import org.myteam.server.member.entity.Member; import org.myteam.server.member.repository.MemberJpaRepository; import org.myteam.server.oauth2.dto.CustomOAuth2User; @@ -40,15 +41,19 @@ public class CustomOauth2SuccessHandler extends SimpleUrlAuthenticationSuccessHa private final MemberJpaRepository memberJpaRepository; private final ApplicationEventPublisher eventPublisher; private final RedisService redisService; + private final RedisUserInfoService redisUserInfoService; public CustomOauth2SuccessHandler(JwtProvider jwtProvider, - MemberJpaRepository memberJpaRepository, - ApplicationEventPublisher eventPublisher, - RedisService redisService) { + MemberJpaRepository memberJpaRepository, + ApplicationEventPublisher eventPublisher, + RedisService redisService, + RedisUserInfoService redisUserInfoService) { + this.jwtProvider = jwtProvider; this.memberJpaRepository = memberJpaRepository; this.eventPublisher = eventPublisher; this.redisService = redisService; + this.redisUserInfoService = redisUserInfoService; } @Override @@ -117,6 +122,9 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo log.debug("print role: {}", role); redisService.putRefreshToken(member.getPublicId(), refreshToken); + redisUserInfoService.saveUserInfo(accessToken, + new UserInfo(member.getPublicId(), member.getNickname(), member.getImgUrl())); + log.info("member: {} caching user info", member.getPublicId()); response.addHeader(HEADER_AUTHORIZATION, TOKEN_PREFIX + accessToken); eventPublisher.publishEvent(new UserLoginEvent(this, member.getPublicId())); diff --git a/src/main/java/org/myteam/server/report/domain/Report.java b/src/main/java/org/myteam/server/report/domain/Report.java index d3bf50ea..9fb4af69 100644 --- a/src/main/java/org/myteam/server/report/domain/Report.java +++ b/src/main/java/org/myteam/server/report/domain/Report.java @@ -5,14 +5,10 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.myteam.server.chat.domain.BanReason; +import org.myteam.server.chat.block.domain.BanReason; import org.myteam.server.global.domain.BaseTime; import org.myteam.server.member.entity.Member; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/src/main/java/org/myteam/server/report/domain/ReportReason.java b/src/main/java/org/myteam/server/report/domain/ReportReason.java index 1dd49711..608013fa 100644 --- a/src/main/java/org/myteam/server/report/domain/ReportReason.java +++ b/src/main/java/org/myteam/server/report/domain/ReportReason.java @@ -2,7 +2,7 @@ import jakarta.persistence.*; import lombok.*; -import org.myteam.server.chat.domain.BanReason; +import org.myteam.server.chat.block.domain.BanReason; @Entity @Getter diff --git a/src/main/java/org/myteam/server/report/dto/request/ReportRequest.java b/src/main/java/org/myteam/server/report/dto/request/ReportRequest.java index 049b453c..6c9ef568 100644 --- a/src/main/java/org/myteam/server/report/dto/request/ReportRequest.java +++ b/src/main/java/org/myteam/server/report/dto/request/ReportRequest.java @@ -1,15 +1,13 @@ package org.myteam.server.report.dto.request; -import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import org.myteam.server.chat.domain.BanReason; +import org.myteam.server.chat.block.domain.BanReason; import org.myteam.server.report.domain.ReportType; -import java.util.List; import java.util.UUID; public record ReportRequest() { diff --git a/src/main/java/org/myteam/server/report/dto/response/ReportResponse.java b/src/main/java/org/myteam/server/report/dto/response/ReportResponse.java index b4e1133a..4b4dcee1 100644 --- a/src/main/java/org/myteam/server/report/dto/response/ReportResponse.java +++ b/src/main/java/org/myteam/server/report/dto/response/ReportResponse.java @@ -4,15 +4,12 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import org.myteam.server.chat.domain.BanReason; +import org.myteam.server.chat.block.domain.BanReason; import org.myteam.server.report.domain.Report; -import org.myteam.server.report.domain.ReportReason; import org.myteam.server.report.domain.ReportType; import java.time.LocalDateTime; -import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; public record ReportResponse() { diff --git a/src/main/java/org/myteam/server/report/repository/ReportQueryRepository.java b/src/main/java/org/myteam/server/report/repository/ReportQueryRepository.java index d06deb47..04c39112 100644 --- a/src/main/java/org/myteam/server/report/repository/ReportQueryRepository.java +++ b/src/main/java/org/myteam/server/report/repository/ReportQueryRepository.java @@ -2,13 +2,11 @@ import static org.myteam.server.report.domain.QReport.report; import static org.myteam.server.member.entity.QMember.member; -import static org.myteam.server.report.domain.QReportReason.reportReason; import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.myteam.server.chat.domain.BanReason; import org.myteam.server.member.entity.QMember; import org.myteam.server.report.domain.ReportType; import org.myteam.server.report.dto.response.ReportResponse.*; diff --git a/src/main/java/org/myteam/server/report/service/ReportService.java b/src/main/java/org/myteam/server/report/service/ReportService.java index 8cca7214..0ce5617a 100644 --- a/src/main/java/org/myteam/server/report/service/ReportService.java +++ b/src/main/java/org/myteam/server/report/service/ReportService.java @@ -2,14 +2,12 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.myteam.server.board.service.BoardReadService; import org.myteam.server.global.exception.ErrorCode; import org.myteam.server.global.exception.PlayHiveException; -import org.myteam.server.global.util.redis.RedisService; +import org.myteam.server.global.util.redis.service.RedisService; import org.myteam.server.member.entity.Member; import org.myteam.server.member.service.MemberReadService; import org.myteam.server.member.service.SecurityReadService; -import org.myteam.server.news.news.service.NewsReadService; import org.myteam.server.report.domain.DomainType; import org.myteam.server.report.domain.ReportType; import org.myteam.server.report.dto.request.ReportRequest.*; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index cd99dacb..60fbf741 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: profiles: - active: prod + active: test include: auth, mail, swagger application: name: myteam-server \ No newline at end of file diff --git a/src/test/java/org/myteam/server/auth/service/TokenServiceTest.java b/src/test/java/org/myteam/server/auth/service/TokenServiceTest.java index ee028dac..72e67883 100644 --- a/src/test/java/org/myteam/server/auth/service/TokenServiceTest.java +++ b/src/test/java/org/myteam/server/auth/service/TokenServiceTest.java @@ -11,6 +11,10 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.junit.jupiter.MockitoExtension; +import org.myteam.server.chat.info.domain.UserInfo; +import org.myteam.server.global.util.redis.service.RedisUserInfoService; +import org.myteam.server.member.entity.Member; +import org.myteam.server.member.service.MemberReadService; import org.myteam.server.support.IntegrationTestSupport; import org.myteam.server.global.exception.PlayHiveJwtException; import org.myteam.server.global.security.jwt.JwtProvider; @@ -21,8 +25,7 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import static org.myteam.server.global.exception.ErrorCode.EXPIRED_REFRESH_TOKEN; import static org.myteam.server.global.exception.ErrorCode.INVALID_REFRESH_TOKEN; import static org.myteam.server.global.security.jwt.JwtProvider.HEADER_AUTHORIZATION; @@ -33,6 +36,10 @@ class TokenServiceTest extends IntegrationTestSupport { @Autowired private TokenService tokenService; @MockBean + private MemberReadService memberReadService; + @MockBean + private RedisUserInfoService redisUserInfoService; + @MockBean private JwtProvider jwtProvider; @Mock private HttpServletRequest request; @@ -65,6 +72,12 @@ void setUp() { when(jwtProvider.getStatus(mockRefreshToken)).thenReturn("ACTIVE"); when(jwtProvider.generateToken(any(), any(), any(), anyString(), anyString())).thenReturn("newAccessToken"); + Member mockMember = mock(Member.class); + when(memberReadService.findById(mockPublicId)).thenReturn(mockMember); + + doNothing().when(redisUserInfoService) + .saveUserInfo(anyString(), any(UserInfo.class)); + // when tokenService.regenerateAccessToken(request, response); diff --git a/src/test/java/org/myteam/server/board/service/BoardCountServiceIntegrationTest.java b/src/test/java/org/myteam/server/board/service/BoardCountServiceIntegrationTest.java index 775bcf16..3a174008 100644 --- a/src/test/java/org/myteam/server/board/service/BoardCountServiceIntegrationTest.java +++ b/src/test/java/org/myteam/server/board/service/BoardCountServiceIntegrationTest.java @@ -23,7 +23,7 @@ import org.myteam.server.global.domain.Category; import org.myteam.server.global.security.dto.CustomUserDetails; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.member.domain.MemberRole; import org.myteam.server.member.domain.MemberStatus; diff --git a/src/test/java/org/myteam/server/bulkupdate/RedisBulkUpdateTest.java b/src/test/java/org/myteam/server/bulkupdate/RedisBulkUpdateTest.java index c1f16b61..cce3199f 100644 --- a/src/test/java/org/myteam/server/bulkupdate/RedisBulkUpdateTest.java +++ b/src/test/java/org/myteam/server/bulkupdate/RedisBulkUpdateTest.java @@ -16,7 +16,7 @@ import org.myteam.server.board.util.BoardCountStrategy; import org.myteam.server.global.domain.Category; import org.myteam.server.global.util.redis.RedisCountBulkUpdater; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.member.entity.Member; import org.myteam.server.util.CountStrategyFactory; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/test/java/org/myteam/server/news/newsCount/service/NewsCountServiceTest.java b/src/test/java/org/myteam/server/news/newsCount/service/NewsCountServiceTest.java index 8e07fe95..c08caa81 100644 --- a/src/test/java/org/myteam/server/news/newsCount/service/NewsCountServiceTest.java +++ b/src/test/java/org/myteam/server/news/newsCount/service/NewsCountServiceTest.java @@ -23,7 +23,7 @@ import org.myteam.server.global.domain.Category; import org.myteam.server.global.security.dto.CustomUserDetails; import org.myteam.server.global.util.redis.CommonCountDto; -import org.myteam.server.global.util.redis.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisCountService; import org.myteam.server.global.util.redis.ServiceType; import org.myteam.server.member.domain.MemberRole; import org.myteam.server.member.domain.MemberStatus; diff --git a/src/test/java/org/myteam/server/report/service/ReportCreateFailureTest.java b/src/test/java/org/myteam/server/report/service/ReportCreateFailureTest.java index 2cde48a8..f222fcbd 100644 --- a/src/test/java/org/myteam/server/report/service/ReportCreateFailureTest.java +++ b/src/test/java/org/myteam/server/report/service/ReportCreateFailureTest.java @@ -6,7 +6,7 @@ import org.myteam.server.support.IntegrationTestSupport; import org.myteam.server.board.domain.Board; import org.myteam.server.board.domain.CategoryType; -import org.myteam.server.chat.domain.BanReason; +import org.myteam.server.chat.block.domain.BanReason; import org.myteam.server.global.domain.Category; import org.myteam.server.global.exception.PlayHiveException; import org.myteam.server.member.entity.Member; diff --git a/src/test/java/org/myteam/server/report/service/ReportCreateSuccessTest.java b/src/test/java/org/myteam/server/report/service/ReportCreateSuccessTest.java index a39c7417..bdb57481 100644 --- a/src/test/java/org/myteam/server/report/service/ReportCreateSuccessTest.java +++ b/src/test/java/org/myteam/server/report/service/ReportCreateSuccessTest.java @@ -6,7 +6,7 @@ import org.myteam.server.support.IntegrationTestSupport; import org.myteam.server.board.domain.Board; import org.myteam.server.board.domain.CategoryType; -import org.myteam.server.chat.domain.BanReason; +import org.myteam.server.chat.block.domain.BanReason; import org.myteam.server.global.domain.Category; import org.myteam.server.member.entity.Member; import org.myteam.server.report.domain.ReportType; diff --git a/src/test/java/org/myteam/server/report/service/ReportDeleteSuccessTest.java b/src/test/java/org/myteam/server/report/service/ReportDeleteSuccessTest.java index 8cef4930..1f7a9f80 100644 --- a/src/test/java/org/myteam/server/report/service/ReportDeleteSuccessTest.java +++ b/src/test/java/org/myteam/server/report/service/ReportDeleteSuccessTest.java @@ -6,7 +6,7 @@ import org.myteam.server.support.IntegrationTestSupport; import org.myteam.server.board.domain.Board; import org.myteam.server.board.domain.CategoryType; -import org.myteam.server.chat.domain.BanReason; +import org.myteam.server.chat.block.domain.BanReason; import org.myteam.server.global.domain.Category; import org.myteam.server.member.entity.Member; import org.myteam.server.report.domain.Report; diff --git a/src/test/java/org/myteam/server/report/service/ReportReadServiceTest.java b/src/test/java/org/myteam/server/report/service/ReportReadServiceTest.java index 4eb95997..80f7ea8b 100644 --- a/src/test/java/org/myteam/server/report/service/ReportReadServiceTest.java +++ b/src/test/java/org/myteam/server/report/service/ReportReadServiceTest.java @@ -6,7 +6,7 @@ import org.myteam.server.support.IntegrationTestSupport; import org.myteam.server.board.domain.Board; import org.myteam.server.board.domain.CategoryType; -import org.myteam.server.chat.domain.BanReason; +import org.myteam.server.chat.block.domain.BanReason; import org.myteam.server.global.domain.Category; import org.myteam.server.global.exception.ErrorCode; import org.myteam.server.global.exception.PlayHiveException; diff --git a/src/test/java/org/myteam/server/report/service/ReportServiceTest.java b/src/test/java/org/myteam/server/report/service/ReportServiceTest.java index 38c12b9f..b7fbf8cd 100644 --- a/src/test/java/org/myteam/server/report/service/ReportServiceTest.java +++ b/src/test/java/org/myteam/server/report/service/ReportServiceTest.java @@ -6,7 +6,7 @@ import org.myteam.server.support.IntegrationTestSupport; import org.myteam.server.board.domain.Board; import org.myteam.server.board.domain.CategoryType; -import org.myteam.server.chat.domain.BanReason; +import org.myteam.server.chat.block.domain.BanReason; import org.myteam.server.comment.domain.Comment; import org.myteam.server.global.domain.Category; import org.myteam.server.global.exception.PlayHiveException; diff --git a/src/test/java/org/myteam/server/support/IntegrationTestSupport.java b/src/test/java/org/myteam/server/support/IntegrationTestSupport.java index aa870eb3..4e457c87 100644 --- a/src/test/java/org/myteam/server/support/IntegrationTestSupport.java +++ b/src/test/java/org/myteam/server/support/IntegrationTestSupport.java @@ -9,13 +9,12 @@ import org.myteam.server.board.service.BoardCountService; import org.myteam.server.board.service.BoardReadService; import org.myteam.server.board.util.RedisBoardRankingReader; -import org.myteam.server.chat.config.WebSocketConfig; -import org.myteam.server.chat.domain.BanReason; +import org.myteam.server.chat.block.domain.BanReason; import org.myteam.server.comment.service.CommentReadService; import org.myteam.server.common.certification.mail.core.MailStrategy; import org.myteam.server.common.certification.mail.domain.EmailType; -import org.myteam.server.global.util.redis.RedisCountService; -import org.myteam.server.global.util.redis.RedisService; +import org.myteam.server.global.util.redis.service.RedisCountService; +import org.myteam.server.global.util.redis.service.RedisService; import org.myteam.server.inquiry.service.InquiryReadService; import org.myteam.server.inquiry.service.InquiryService; import org.myteam.server.match.matchPrediction.domain.MatchPrediction; @@ -46,8 +45,7 @@ @ActiveProfiles("test") @ImportAutoConfiguration(exclude = { RedisAutoConfiguration.class, - RedisRepositoriesAutoConfiguration.class, - WebSocketConfig.class + RedisRepositoriesAutoConfiguration.class }) public abstract class IntegrationTestSupport extends TestDriverSupport {