Skip to content

Commit

Permalink
Merge branch 'groupInvite'
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/java/com/tukorea/planding/domain/group/service/GroupInviteService.java
  • Loading branch information
SangWoon123 committed May 17, 2024
2 parents 87ba29c + b347294 commit 785ba6e
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,43 @@
import com.tukorea.planding.common.CommonResponse;
import com.tukorea.planding.common.CommonUtils;
import com.tukorea.planding.domain.group.dto.request.GroupInviteRequest;
import com.tukorea.planding.domain.group.dto.response.GroupInviteResponse;
import com.tukorea.planding.domain.group.service.GroupInviteService;
import com.tukorea.planding.domain.group.dto.response.GroupInviteMessageResponse;
import com.tukorea.planding.domain.user.dto.UserInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Tag(name = "Invitation", description = "๊ทธ๋ฃน ์ดˆ๋Œ€๊ด€๋ จ")
@RestController
@RequestMapping("/api/v1/invitation")
@RequiredArgsConstructor
@RequestMapping("/api/v1/invitation")
public class GroupInviteController {

private final GroupInviteService groupInviteService;

@Operation(summary = "๋‹ค๋ฅธ์œ ์ €๋ฅผ ๊ทธ๋ฃน์œผ๋กœ ์ดˆ๋Œ€")
@PostMapping()
public CommonResponse<GroupInviteResponse> inviteGroupRoom(@AuthenticationPrincipal UserInfo userInfo, @RequestBody GroupInviteRequest invitedUser) {
GroupInviteResponse groupInviteResponse = groupInviteService.inviteGroupRoom(userInfo, invitedUser);
return CommonUtils.success(groupInviteResponse);
public CommonResponse<GroupInviteMessageResponse> invite(@AuthenticationPrincipal UserInfo userInfo, @RequestBody GroupInviteRequest groupInviteRequest) {
return CommonUtils.success(groupInviteService.inviteGroupRoom(userInfo, groupInviteRequest));
}

//TODO ์ฟผ๋ฆฌ์ŠคํŠธ๋งUrl ๋ณ€๊ฒฝ ๊ณ ๋ฏผ ex) api/v1/invitation/accept?{code}
@Operation(summary = "์ดˆ๋Œ€ ์Šน๋‚™")
@GetMapping("/{code}/accept")
public CommonResponse<GroupInviteResponse> acceptInvitation(@AuthenticationPrincipal UserInfo userInfo, @PathVariable String code) {
GroupInviteResponse groupInviteResponse = groupInviteService.acceptInvitation(userInfo, code);
return CommonUtils.success(groupInviteResponse);
}

@Operation(summary = "์ดˆ๋Œ€ ๊ฑฐ์ ˆ")
@GetMapping("/{code}/decline")
public CommonResponse<?> declineInvitation(@AuthenticationPrincipal UserInfo userInfo, @PathVariable String code) {
groupInviteService.declineInvitation(userInfo, code);
return CommonUtils.success("์ดˆ๋Œ€๋ฅผ ๊ฑฐ์ ˆํ•˜์˜€์Šต๋‹ˆ๋‹ค.");
@GetMapping("/accept/{groupId}/{code}")
public CommonResponse<?> accept(@AuthenticationPrincipal UserInfo userInfo, @PathVariable(name = "groupId") Long groupId, @PathVariable(name = "code") String code) {
groupInviteService.acceptInvitation(userInfo, code, groupId);
return CommonUtils.success("์ˆ˜๋ฝ์™„๋ฃŒ");
}

@Operation(summary = "์ดˆ๋Œ€๋ฅผ ๋ฐ›์€ ๋ชฉ๋ก", description = "์•„์ง ์ดˆ๋Œ€์˜ ์ƒํƒœ๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š์€ ๊ฒฝ์šฐ๋งŒ")
@GetMapping()
public CommonResponse<List<GroupInviteResponse>> getInvitations(@AuthenticationPrincipal UserInfo userInfo) {
List<GroupInviteResponse> groupInviteResponse = groupInviteService.getInvitations(userInfo);
public CommonResponse<List<GroupInviteMessageResponse>> getInvitations(@AuthenticationPrincipal UserInfo userInfo) {
List<GroupInviteMessageResponse> groupInviteResponse = groupInviteService.getInvitations(userInfo);
return CommonUtils.success(groupInviteResponse);
}


@DeleteMapping("/decline/{code}")
public CommonResponse<?> declineInvitation(@AuthenticationPrincipal UserInfo userInfo, @PathVariable(name = "code") String code) {
groupInviteService.declineInvitation(userInfo, code);
return CommonUtils.success("๊ฑฐ์ ˆํ•˜์˜€์Šต๋‹ˆ๋‹ค.");
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.tukorea.planding.domain.group.dto;

import lombok.Builder;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;

import java.time.Clock;

@Getter
@Builder
public class GroupInviteEvent extends ApplicationEvent {

private final String userCode;
Expand All @@ -15,11 +19,4 @@ public GroupInviteEvent(Object source, String userCode, String groupName) {
this.groupName = groupName;
}

public String getUserCode() {
return userCode;
}

public String getGroupName() {
return groupName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.tukorea.planding.domain.group.dto.response;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@Data
@NoArgsConstructor
public class GroupInviteMessageResponse {
private String inviteCode;
private Long groupRoomId;
private String invitedUserCode;
private Long invitingUserId;

public static GroupInviteMessageResponse create(String inviteCode, Long groupRoomId, String invitedUserCode, Long invitingUserId) {
return new GroupInviteMessageResponse(inviteCode, groupRoomId, invitedUserCode, invitingUserId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import lombok.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@

public interface GroupRoomRepository extends JpaRepository<GroupRoom, Long>, GroupRoomRepositoryCustom {
Optional<GroupRoom> findByGroupCode(String groupCode);
boolean existsById(Long groupRoomId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
public interface GroupRoomRepositoryCustom {
List<GroupRoom> findGroupRoomsByUserId(Long userId);
List<User> getGroupUsers(Long groupId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@
public interface UserGroupRepositoryCustom {
boolean existsByGroupRoomIdAndUserId(Long groupRoomId, Long userId);
List<User> findUserByIsConnectionFalse(Long groupRoomId);
public UserGroup findUserByGroupId(Long userId, Long groupRoomId);
UserGroup findUserByGroupId(Long userId, Long groupRoomId);
boolean existsByUserCodeAndGroupId(String userCode, Long groupId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,14 @@ public UserGroup findUserByGroupId(Long userId, Long groupRoomId) {
.and(userGroup.user.id.eq(userId)))
.fetchFirst();
}

@Override
public boolean existsByUserCodeAndGroupId(String userCode, Long groupId) {
long count = queryFactory.selectFrom(userGroup)
.where(userGroup.user.userCode.eq(userCode)
.and(userGroup.groupRoom.id.eq(groupId)))
.fetchCount();

return count > 0;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
package com.tukorea.planding.domain.group.service;

import com.tukorea.planding.domain.group.dto.GroupInviteEvent;
import com.tukorea.planding.domain.group.dto.request.GroupInviteRequest;
<<<<<<<HEAD
import com.tukorea.planding.domain.group.entity.GroupRoom;
import com.tukorea.planding.domain.group.entity.UserGroup;
import com.tukorea.planding.domain.group.service.query.GroupQueryService;
import com.tukorea.planding.domain.group.dto.response.GroupInviteMessageResponse;
import com.tukorea.planding.domain.notify.service.NotificationService;
=======
import com.tukorea.planding.domain.group.dto.response.GroupInviteMessageResponse;
import com.tukorea.planding.domain.group.entity.GroupRoom;
import com.tukorea.planding.domain.group.entity.UserGroup;
import com.tukorea.planding.domain.group.service.query.GroupQueryService;
>>>>>>>groupInvite
import com.tukorea.planding.domain.user.dto.UserInfo;
import com.tukorea.planding.domain.user.entity.User;
import com.tukorea.planding.domain.user.service.UserQueryService;
Expand All @@ -31,34 +39,33 @@ public class GroupInviteService {
@Transactional
public GroupInviteMessageResponse inviteGroupRoom(UserInfo userInfo, GroupInviteRequest groupInviteRequest) {
// ์ดˆ๋Œ€ํ•˜๋Š” ์‚ฌ์šฉ์ž์™€ ์ดˆ๋Œ€ ๋Œ€์ƒ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ™์€์ง€ ํ™•์ธ
if (userInfo.getUserCode().equals(groupInviteRequest.getUserCode())) {
if (userInfo.getUserCode().equals(groupInviteRequest.userCode())) {
throw new BusinessException(ErrorCode.CANNOT_INVITE_YOURSELF);
}

// ๊ทธ๋ฃน์ด ์กด์žฌํ•˜๋Š”์ง€
if (!groupQueryService.existById(groupInviteRequest.getGroupId())) {
if (!groupQueryService.existById(groupInviteRequest.groupId())) {
throw new BusinessException(ErrorCode.GROUP_ROOM_NOT_FOUND);
}

//๊ทธ๋ฃน์— ์†ํ•ด์žˆ๋Š”์ง€
// ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฏธ ๊ทธ๋ฃน์— ์†ํ•ด ์žˆ๋Š”์ง€ ํ™•์ธ
if (groupQueryService.existGroupInUser(groupInviteRequest.getUserCode(), groupInviteRequest.getGroupId())) {
throw new BusinessException(ErrorCode.USER_ALREADY_IN_GROUP);
GroupRoom group = groupQueryService.getGroupById(groupInviteRequest.groupId());
if (!group.getOwner().equals(userInfo.getUserCode())) {
throw new BusinessException(ErrorCode.UNAUTHORIZED_GROUP_ROOM_INVITATION);
}

GroupRoom groupRoom = groupQueryService.getGroupById(groupInviteRequest.getGroupId());

if (groupQueryService.existGroupInUser(groupInviteRequest.userCode(), groupInviteRequest.groupId())) {
throw new BusinessException(ErrorCode.USER_ALREADY_IN_GROUP);
}

GroupInviteMessageResponse groupInviteMessageResponse = GroupInviteMessageResponse.create(
"INV" + UUID.randomUUID()
, groupInviteRequest.getGroupId()
, groupInviteRequest.getUserCode()
, userInfo.getId());
GroupInviteMessageResponse groupInviteMessageResponse = GroupInviteMessageResponse.create("IN" + UUID.randomUUID(), groupInviteRequest.groupId(), groupInviteRequest.userCode(), userInfo.getId());

redisGroupInviteService.createInvitation(groupInviteRequest.userCode(), groupInviteMessageResponse);

redisGroupInviteService.createInvitation(groupInviteRequest.getUserCode(), groupInviteMessageResponse);
GroupInviteEvent event = GroupInviteEvent.builder()
.groupName(group.getName())
.userCode(groupInviteRequest.userCode())
.build();

notificationService.notifyInvitation(groupInviteRequest.getUserCode(), groupRoom.getName());
notificationService.handleGroupInvitedEvent(event);

return groupInviteMessageResponse;
}
Expand All @@ -79,9 +86,7 @@ public List<GroupInviteMessageResponse> getInvitations(UserInfo userInfo) {
}

@Transactional
public void declineInvitation(UserInfo userInfo, String code) {
User user = userQueryService.getUserByUserCode(userInfo.getUserCode());
redisGroupInviteService.deleteInvitation(userInfo.getUserCode(), code);
public void declineInvitation(UserInfo userInfo, String inviteCode) {
redisGroupInviteService.deleteInvitation(userInfo.getUserCode(), inviteCode);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.tukorea.planding.domain.group.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tukorea.planding.domain.group.dto.response.GroupInviteMessageResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class RedisGroupInviteService {

private final StringRedisTemplate redisTemplate;
private final ObjectMapper objectMapper;

// ์ดˆ๋Œ€ ์ƒ์„ฑ
public void createInvitation(String userCode, GroupInviteMessageResponse inviteDTO) {
String key = "userInvites:" + userCode; // ์œ ์ €๋ณ„ ํ‚ค
String field = inviteDTO.getInviteCode(); // ์ดˆ๋Œ€ ์ฝ”๋“œ๋ฅผ ํ•„๋“œ๋กœ ์‚ฌ์šฉ
String value = convertObjectToJson(inviteDTO); // ์ดˆ๋Œ€ ์ •๋ณด๋ฅผ JSON ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜

if (value != null) {
redisTemplate.opsForHash().put(key, field, value);
redisTemplate.expire(key, 3, TimeUnit.HOURS);
}
}

// ์œ ์ €๋ณ„ ๋ชจ๋“  ์ดˆ๋Œ€ ์กฐํšŒ
public List<GroupInviteMessageResponse> getAllInvitations(String userCode) {
String key = "userInvites:" + userCode;
List<Object> values = redisTemplate.opsForHash().values(key);

return values.stream()
.map(value -> convertJsonToObject((String) value, GroupInviteMessageResponse.class))
.collect(Collectors.toList());
}

// ํŠน์ • ์ดˆ๋Œ€ ์‚ญ์ œ
public void deleteInvitation(String userCode, String inviteCode) {
String key = "userInvites:" + userCode;
redisTemplate.opsForHash().delete(key, inviteCode);
}

private String convertObjectToJson(Object obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
return null;
}
}

private <T> T convertJsonToObject(String json, Class<T> clazz) {
try {
return objectMapper.readValue(json, clazz);
} catch (IOException e) {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.tukorea.planding.domain.group.entity.GroupRoom;
import com.tukorea.planding.domain.group.repository.normal.GroupRoomRepository;
import com.tukorea.planding.domain.group.repository.normal.GroupRoomRepositoryCustom;
import com.tukorea.planding.domain.group.repository.usergroup.UserGroupRepository;
import com.tukorea.planding.domain.user.entity.User;
import com.tukorea.planding.global.error.BusinessException;
import com.tukorea.planding.global.error.ErrorCode;
Expand All @@ -18,6 +19,7 @@
public class GroupQueryService {

private final GroupRoomRepository groupRoomRepository;
private final UserGroupRepository userGroupRepository;


public GroupRoom createGroup(GroupRoom groupRoom) {
Expand All @@ -37,8 +39,15 @@ public void delete(GroupRoom groupRoom) {
groupRoomRepository.delete(groupRoom);
}

public boolean existById(Long groupId) {
return groupRoomRepository.existsById(groupId);
}

public List<User> getGroupUsers(Long groupId) {
return groupRoomRepository.getGroupUsers(groupId);
}

public boolean existGroupInUser(String userCode, Long groupId) {
return userGroupRepository.existsByUserCodeAndGroupId(userCode, groupId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ private void checkAccessTokenAndAuthentication(HttpServletRequest request, HttpS


saveAuthentication(userRepository.findByUserCode(userCode)
.orElseThrow(() -> new BusinessException(ErrorCode.UNAUTHORIZED_SCHEDULE)));
.orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND)));

filterChain.doFilter(request, response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public enum ErrorCode {
USER_ALREADY_INVITED("GROUP-005", "์ด๋ฏธ ๊ทธ๋ฃน๋ฃธ์— ์ดˆ๋Œ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.", HttpStatus.UNAUTHORIZED),
FAVORITE_ALREADY_ADD("GROUP-006", "์ด๋ฏธ ์ฆ๊ฒจ์ฐพ๊ธฐ์— ๋“ฑ๋กํ•˜์˜€์Šต๋‹ˆ๋‹ค.", HttpStatus.UNAUTHORIZED),
FAVORITE_ALREADY_DELETE("GROUP-007", "์ฆ๊ฒจ์ฐพ๊ธฐ์— ๋“ฑ๋ก๋œ ๊ทธ๋ฃน์ด ์•„๋‹™๋‹ˆ๋‹ค.", HttpStatus.UNAUTHORIZED),
USER_ALREADY_IN_GROUP("GROUP-008", "์ด๋ฏธ ๊ทธ๋ฃน์— ์กด์žฌํ•˜๋Š” ์œ ์ €์ž…๋‹ˆ๋‹ค.", HttpStatus.CONFLICT),

/**
* Invite Error
Expand Down

0 comments on commit 785ba6e

Please sign in to comment.