Skip to content

Commit

Permalink
Merge pull request #20 from Team-Shaka/feat/19
Browse files Browse the repository at this point in the history
Feat/19 시큐리티 세팅 및 Invitation 관련 로직 추가, 초대장 조회 API 구현
  • Loading branch information
HyoBN authored May 2, 2024
2 parents b22f699 + 9980511 commit 5d334af
Show file tree
Hide file tree
Showing 16 changed files with 388 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package treehouse.server.api.invitation.business;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
import treehouse.server.api.invitation.presentation.dto.InvitationResponseDTO;
import treehouse.server.global.entity.Invitation.Invitation;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.entity.User.UserRole;
import treehouse.server.global.entity.User.UserStatus;

import java.util.List;

@Component
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class InvitationMapper {

public InvitationResponseDTO.getInvitation toGetInvitation (Invitation invitation, List<String> treeMemberProfileImages) {
return InvitationResponseDTO.getInvitation.builder()
.invitationId(invitation.getId())
.treehouseName(invitation.getTreeHouse().getName())
.senderName(invitation.getSender().getName())
.senderProfileImageUrl(invitation.getSender().getProfileImageUrl())
.treehouseSize(invitation.getTreeHouse().getMemberList().size())
.treehouseMemberProfileImages(treeMemberProfileImages)
.build();
}
public InvitationResponseDTO.getInvitations toGetInvitations(List<InvitationResponseDTO.getInvitation> invitationDtos) {
return InvitationResponseDTO.getInvitations.builder()
.invitations(invitationDtos)
.build();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package treehouse.server.api.invitation.business;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import treehouse.server.api.invitation.implement.InvitationCommandAdapter;
import treehouse.server.api.invitation.implement.InvitationQueryAdapter;
import treehouse.server.api.invitation.presentation.dto.InvitationRequestDTO;
import treehouse.server.api.invitation.presentation.dto.InvitationResponseDTO;
import treehouse.server.global.entity.Invitation.Invitation;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.entity.member.Member;
import treehouse.server.global.entity.redis.RefreshToken;
import treehouse.server.global.entity.treeHouse.TreeHouse;
import treehouse.server.global.exception.GlobalErrorCode;
import treehouse.server.global.exception.ThrowClass.AuthException;
import treehouse.server.global.exception.ThrowClass.GeneralException;
import treehouse.server.global.redis.service.RedisService;
import treehouse.server.global.security.jwt.dto.TokenDTO;
import treehouse.server.global.security.provider.TokenProvider;

import java.util.List;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Slf4j
public class InvitationService {


private final InvitationQueryAdapter invitationQueryAdapter;

private final InvitationCommandAdapter invitationCommandAdapter;
private final InvitationMapper invitationMapper;
private static final Integer treeMemberRandomProfileSize = 3;


@Transactional
public InvitationResponseDTO.getInvitations getInvitations(User user) {

log.error("User name : ", user.getName());
log.error("User id : ", user.getId());
List<Invitation> invitations = invitationQueryAdapter.findAllByPhone(user.getPhone());
log.error("size : ", invitations.size());

List<InvitationResponseDTO.getInvitation> invitationDtos = invitations.stream()
.map(invitation -> {
TreeHouse treeHouse = invitation.getTreeHouse();
List<Member> treeMembers = treeHouse.getMemberList();
List<String> randomProfileImages = treeMembers.stream()
.map(Member::getProfileImageUrl)
.limit(treeMemberRandomProfileSize)
.toList();
return invitationMapper.toGetInvitation(invitation, randomProfileImages);
})
.collect(Collectors.toList());
return invitationMapper.toGetInvitations(invitationDtos);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package treehouse.server.api.invitation.implement;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import treehouse.server.api.invitation.persistence.InvitationRepository;
import treehouse.server.global.annotations.Adapter;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.entity.User.UserRole;
import treehouse.server.global.entity.redis.RefreshToken;
import treehouse.server.global.redis.service.RedisService;
import treehouse.server.global.security.jwt.dto.TokenDTO;
import treehouse.server.global.security.provider.TokenProvider;

import java.util.List;

@Adapter
@Slf4j
@RequiredArgsConstructor
public class InvitationCommandAdapter {

private final InvitationRepository invitationRepository;


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package treehouse.server.api.invitation.implement;

import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import treehouse.server.api.invitation.persistence.InvitationRepository;
import treehouse.server.api.invitation.presentation.dto.InvitationRequestDTO;
import treehouse.server.global.annotations.Adapter;
import treehouse.server.global.entity.Invitation.Invitation;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.exception.GlobalErrorCode;
import treehouse.server.global.exception.ThrowClass.UserException;

import java.util.List;
import java.util.Optional;

@Adapter
@RequiredArgsConstructor
public class InvitationQueryAdapter {

private final InvitationRepository invitationRepository;

public List<Invitation> findAllByPhone(String phone) {
return invitationRepository.findAllByPhone(phone);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package treehouse.server.api.invitation.persistence;

import org.springframework.data.jpa.repository.JpaRepository;
import treehouse.server.global.entity.Invitation.Invitation;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.entity.treeHouse.TreeHouse;

import java.util.List;
import java.util.Optional;

public interface InvitationRepository extends JpaRepository<Invitation, Long> {

List<Invitation> findAllByPhone(String phone);

Invitation findByPhoneAndTreeHouse(String phone, TreeHouse treeHouse);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package treehouse.server.api.invitation.presentation;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import treehouse.server.api.invitation.business.InvitationService;
import treehouse.server.api.invitation.presentation.dto.InvitationRequestDTO;
import treehouse.server.api.invitation.presentation.dto.InvitationResponseDTO;
import treehouse.server.global.common.CommonResponse;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.security.handler.annotation.AuthMember;

@RestController
@RequiredArgsConstructor
@Slf4j
@Validated
@Tag(name = "😎 Invitation API", description = "초대장 관련 API 입니다. 초대장 조회, 전송 등의 API가 포함됩니다.")
@RequestMapping("/invi")
public class InvitationApi {

private final InvitationService invitationService;

@GetMapping("/invitation")
@Operation(summary = "초대장 조회", description = "내가 받은 초대장을 조회합니다.")
public CommonResponse<InvitationResponseDTO.getInvitations> getInvitations(
@AuthMember @Parameter(hidden = true) User user
) {
return CommonResponse.onSuccess(invitationService.getInvitations(user));
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package treehouse.server.api.invitation.presentation.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;


public class InvitationRequestDTO {




}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package treehouse.server.api.invitation.presentation.dto;

import lombok.*;

import java.util.List;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class InvitationResponseDTO {

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class getInvitation {
private Long invitationId;
private String treehouseName;
private String senderName;
private String senderProfileImageUrl;
private Integer treehouseSize;
private List<String> treehouseMemberProfileImages;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class getInvitations {
List<InvitationResponseDTO.getInvitation> invitations;
}

}
16 changes: 15 additions & 1 deletion src/main/java/treehouse/server/api/user/business/UserMapper.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
package treehouse.server.api.user.business;

import jakarta.annotation.PostConstruct;
import lombok.*;
import org.springframework.stereotype.Component;
import treehouse.server.api.user.presentation.dto.UserResponseDTO;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.entity.User.UserRole;
import treehouse.server.global.entity.User.UserStatus;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Component
//@NoArgsConstructor(access = AccessLevel.PRIVATE)
@RequiredArgsConstructor
public class UserMapper {

private final UserService userService;
private static UserService staticUserService;
@PostConstruct
public void init(){
this.staticUserService = this.userService;
}

public static User toUserSecurity(String id){
return staticUserService.findById(Long.valueOf(id));
}

public static UserResponseDTO.checkName toCheckNameDTO(boolean isDuplicated){
return UserResponseDTO.checkName.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public UserResponseDTO.checkName checkName(UserRequestDTO.checkName request){
return UserMapper.toCheckNameDTO(userQueryAdapter.checkName(request));
}

@Transactional(readOnly = true)
public User findById(Long id){
return userQueryAdapter.findById(id);
}

@Transactional
public UserResponseDTO.registerUser register(UserRequestDTO.registerUser request){
User user = UserMapper.toUser(request.getUserName(), request.getPhoneNumber());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ public Optional<User> findByPhoneNumber(String phone){
public User findById(Long id){
return userRepository.findById(id).orElseThrow(()->new UserException(GlobalErrorCode.MEMBER_NOT_FOUND));
}

public Optional<User> optionalUserFindById(Long id){
return userRepository.findById(id);
}
}
27 changes: 27 additions & 0 deletions src/main/java/treehouse/server/global/config/GlobalWebConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package treehouse.server.global.config;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import treehouse.server.global.security.handler.annotation.resolver.AuthMemberArgumentResolver;

import java.util.List;

@Configuration
@RequiredArgsConstructor
public class GlobalWebConfig implements WebMvcConfigurer {

private final AuthMemberArgumentResolver authMemberArgumentResolver;

/**
* 컨트롤러 메서드의 특정 파라미터를 지원하는 커스텀한 ArgumentResolver를 추가
* @param resolverList
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolverList) {
resolverList.add(authMemberArgumentResolver);
}
}
18 changes: 17 additions & 1 deletion src/main/java/treehouse/server/global/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package treehouse.server.global.config;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -15,8 +18,21 @@ public OpenAPI SpringCodeBaseAPI() {
.description("Treehouse API 명세서")
.version("1.0.0");

String jwtSchemeName = "JWT TOKEN";
// API 요청헤더에 인증정보 포함
SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtSchemeName);
// SecuritySchemes 등록
Components components = new Components()
.addSecuritySchemes(jwtSchemeName, new SecurityScheme()
.name(jwtSchemeName)
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT"));

return new OpenAPI()
.addServersItem(new Server().url("/"))
.info(info);
.info(info)
.addSecurityItem(securityRequirement)
.components(components);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import jakarta.persistence.*;
import lombok.*;
import treehouse.server.global.entity.User.User;
import treehouse.server.global.entity.common.BaseDateTimeEntity;
import treehouse.server.global.entity.member.Member;
import treehouse.server.global.entity.treeHouse.TreeHouse;
Expand All @@ -29,6 +30,10 @@ public class Invitation extends BaseDateTimeEntity {
@JoinColumn(name = "senderId")
@ManyToOne(fetch = FetchType.LAZY)
private Member sender;

@JoinColumn(name = "receiverId")
@ManyToOne(fetch = FetchType.LAZY)
private User receiver;
@JoinColumn(name = "treeId")
@ManyToOne(fetch = FetchType.LAZY)
private TreeHouse treeHouse;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
package treehouse.server.global.security.handler.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME) // 런타임 중에 어노테이션 정보를 조회하고 처리할 수 있도록 설정
@Target(ElementType.PARAMETER) // 어노테이션을 파라미터에만 적용
public @interface AuthMember {
}
Loading

0 comments on commit 5d334af

Please sign in to comment.