diff --git a/src/main/java/com/neighbors/tohero/SantaApplication.java b/src/main/java/com/neighbors/tohero/ToHeroApplication.java similarity index 83% rename from src/main/java/com/neighbors/tohero/SantaApplication.java rename to src/main/java/com/neighbors/tohero/ToHeroApplication.java index 1def97e..31d65da 100644 --- a/src/main/java/com/neighbors/tohero/SantaApplication.java +++ b/src/main/java/com/neighbors/tohero/ToHeroApplication.java @@ -8,10 +8,10 @@ @SpringBootApplication @EnableJpaAuditing @EntityScan(basePackages = "com.neighbors.tohero.infrastructure.entity") -public class SantaApplication { +public class ToHeroApplication { public static void main(String[] args) { - SpringApplication.run(SantaApplication.class, args); + SpringApplication.run(ToHeroApplication.class, args); } } diff --git a/src/main/java/com/neighbors/tohero/application/baseResponse/BaseResponseMessage.java b/src/main/java/com/neighbors/tohero/application/baseResponse/BaseResponseMessage.java index aaa7ad6..bf8802f 100644 --- a/src/main/java/com/neighbors/tohero/application/baseResponse/BaseResponseMessage.java +++ b/src/main/java/com/neighbors/tohero/application/baseResponse/BaseResponseMessage.java @@ -39,8 +39,11 @@ public enum BaseResponseMessage { //address 주소_검색_쿼리의_길이는_1부터_50까지만_가능합니다("주소 검색 쿼리의 길이는 1부터 50까지만 가능합니다"), 일치하는_관할서_정보가_없습니다("일치하는 관할서 정보가 없습니다"), - 주소_검색이_성공적으로_응답되었습니다("주소 검색이 성공적으로 응답되었습니다"); + 주소_검색이_성공적으로_응답되었습니다("주소 검색이 성공적으로 응답되었습니다"), + //letter + 편지가_성공적으로_생성_되었습니다("편지가 성공적으로 생성 되었습니다"), + 편지_생성이_실패_했습니다("편지 생성이 실패했습니다"); private final String message; diff --git a/src/main/java/com/neighbors/tohero/application/letter/dto/CreateLetterRequest.java b/src/main/java/com/neighbors/tohero/application/letter/dto/CreateLetterRequest.java index a4645ef..ae6eac5 100644 --- a/src/main/java/com/neighbors/tohero/application/letter/dto/CreateLetterRequest.java +++ b/src/main/java/com/neighbors/tohero/application/letter/dto/CreateLetterRequest.java @@ -1,6 +1,30 @@ package com.neighbors.tohero.application.letter.dto; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.neighbors.tohero.common.enums.TargetJob; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import org.hibernate.validator.constraints.Length; + public record CreateLetterRequest ( + @NotBlank + @Length(min =1, max = 1000) + String content, + + @JsonInclude(JsonInclude.Include.NON_NULL) + TargetJob targetJob, + + @JsonInclude(JsonInclude.Include.NON_NULL) + Long addressId, + + @JsonInclude(JsonInclude.Include.NON_NULL) + @Length(min = 1, max = 100) + String heroName, + + @JsonInclude(JsonInclude.Include.NON_NULL) + Boolean readingAlarm, + @NotNull + boolean isPublic ){ } diff --git a/src/main/java/com/neighbors/tohero/application/letter/dto/CreateLetterResponse.java b/src/main/java/com/neighbors/tohero/application/letter/dto/CreateLetterResponse.java new file mode 100644 index 0000000..0de485b --- /dev/null +++ b/src/main/java/com/neighbors/tohero/application/letter/dto/CreateLetterResponse.java @@ -0,0 +1,6 @@ +package com.neighbors.tohero.application.letter.dto; + +public record CreateLetterResponse( + long createdLetterId +) { +} diff --git a/src/main/java/com/neighbors/tohero/application/letter/service/LetterService.java b/src/main/java/com/neighbors/tohero/application/letter/service/LetterService.java index 41685dd..1fdf98c 100644 --- a/src/main/java/com/neighbors/tohero/application/letter/service/LetterService.java +++ b/src/main/java/com/neighbors/tohero/application/letter/service/LetterService.java @@ -1,15 +1,86 @@ package com.neighbors.tohero.application.letter.service; import com.neighbors.tohero.application.baseResponse.BaseResponse; +import com.neighbors.tohero.application.baseResponse.BaseResponseMessage; +import com.neighbors.tohero.application.baseResponse.BaseResponseStatus; import com.neighbors.tohero.application.letter.dto.CreateLetterRequest; +import com.neighbors.tohero.application.letter.dto.CreateLetterResponse; +import com.neighbors.tohero.common.enums.Role; +import com.neighbors.tohero.common.exception.address.AddressException; +import com.neighbors.tohero.common.exception.letter.LetterException; +import com.neighbors.tohero.common.jwt.JwtUserDetails; +import com.neighbors.tohero.domain.domain.address.service.GetAddress; +import com.neighbors.tohero.domain.domain.letter.service.CreateLetter; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; + @Service @RequiredArgsConstructor public class LetterService { - public BaseResponse createLetter(CreateLetterRequest createLetterRequest) { - return null; + private final CreateLetter createLetter; + private final GetAddress getAddress; + + public BaseResponse createLetter(final JwtUserDetails jwtUserDetail, final CreateLetterRequest createLetterRequest) { + + throwExceptionIfAddressIsNotExist(createLetterRequest.addressId()); + + if(jwtUserDetail.getRole() == Role.GUEST){ + return createGuestLetter(jwtUserDetail.getNickname(), createLetterRequest); + } + long createdLetterId = createLetter.createLetter( + jwtUserDetail.getUserId(), + jwtUserDetail.getNickname(), + createLetterRequest + ); + + throwIfLetterNotCreate(createdLetterId); + + return new BaseResponse<>( + BaseResponseStatus.OK, + BaseResponseMessage.편지가_성공적으로_생성_되었습니다.getMessage(), + new CreateLetterResponse(createdLetterId) + ); + } + + private BaseResponse createGuestLetter(final String nickname, final CreateLetterRequest createLetterRequest) { + long createdLetterId = createLetter.createGuestLetter( + nickname, + createLetterRequest.content(), + createLetterRequest.targetJob(), + createLetterRequest.addressId(), + createLetterRequest.heroName(), + createLetterRequest.isPublic() + ); + + throwIfLetterNotCreate(createdLetterId); + + return new BaseResponse<>( + BaseResponseStatus.OK, + BaseResponseMessage.편지가_성공적으로_생성_되었습니다.getMessage(), + new CreateLetterResponse(createdLetterId) + ); + } + + private void throwExceptionIfAddressIsNotExist(final Long addressId){ + if(addressId == null) {return ;} + if(!getAddress.existAddressById(addressId)){ + throw new AddressException( + BaseResponseStatus.NO_RESULT, + BaseResponseMessage.일치하는_관할서_정보가_없습니다.getMessage() + ); + } + } + + private void throwIfLetterNotCreate(final long createdLetterId){ + if(createdLetterId == 0){ + throw new LetterException( + BaseResponseStatus.BAD_REQUEST, + BaseResponseMessage.편지_생성이_실패_했습니다.getMessage() + ); + } } } diff --git a/src/main/java/com/neighbors/tohero/application/mainPage/dto/OpenedLetter.java b/src/main/java/com/neighbors/tohero/application/mainPage/dto/OpenedLetter.java index 5363e18..0bc0a52 100644 --- a/src/main/java/com/neighbors/tohero/application/mainPage/dto/OpenedLetter.java +++ b/src/main/java/com/neighbors/tohero/application/mainPage/dto/OpenedLetter.java @@ -8,6 +8,6 @@ public record OpenedLetter( String content ){ public static OpenedLetter from(Letter letter){ - return new OpenedLetter(letter.getTargetName(), letter.getFromUserName(), letter.getLetterContent()); + return new OpenedLetter(letter.getTargetName(), letter.getWriter(), letter.getLetterContent()); } } diff --git a/src/main/java/com/neighbors/tohero/common/config/SecurityConfig.java b/src/main/java/com/neighbors/tohero/common/config/SecurityConfig.java index 087e52b..276f762 100644 --- a/src/main/java/com/neighbors/tohero/common/config/SecurityConfig.java +++ b/src/main/java/com/neighbors/tohero/common/config/SecurityConfig.java @@ -19,6 +19,7 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; +import java.util.ArrayList; import java.util.List; @Configuration @@ -55,9 +56,6 @@ SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { .formLogin(AbstractHttpConfigurer::disable) //form login 비활성화 .httpBasic(AbstractHttpConfigurer::disable)//http 기본 인증 비활성화 .cors(Customizer.withDefaults()) - .authorizeHttpRequests(auth -> auth - .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll() - .anyRequest().authenticated()) .sessionManagement(session -> { session.sessionCreationPolicy(SessionCreationPolicy.STATELESS); }) @@ -75,7 +73,11 @@ SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // 쿠키 포함 허용 - config.setAllowedOrigins(List.of("http://localhost:5173", "https://glittery-madeleine-215e2f.netlify.app")); // 허용할 도메인 + // 여러 도메인 허용 + List allowedOrigins = new ArrayList<>(); + allowedOrigins.add("https://glittery-madeleine-215e2f.netlify.app"); + allowedOrigins.add("https://tohero.co.kr"); + config.setAllowedOrigins(allowedOrigins); // 여러 도메인 추가 config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); // 허용할 HTTP 메서드 config.setAllowedHeaders(List.of("*")); // 모든 헤더 허용 config.setExposedHeaders(List.of("Authorization")); // 노출할 헤더 diff --git a/src/main/java/com/neighbors/tohero/common/config/SwaggerConfig.java b/src/main/java/com/neighbors/tohero/common/config/SwaggerConfig.java index 17c266b..f0fe4ce 100644 --- a/src/main/java/com/neighbors/tohero/common/config/SwaggerConfig.java +++ b/src/main/java/com/neighbors/tohero/common/config/SwaggerConfig.java @@ -29,7 +29,7 @@ public OpenAPI openAPI() { .addSecurityItem(securityRequirement) .components(components) .servers(Arrays.asList(new Server().url("https://tohero.co.kr"), - new Server().url("http://localhost:8080"),new Server().url("https://tohero.co.kr"))); + new Server().url("http://localhost:8080"))); } private Info apiInfo() { return new Info() diff --git a/src/main/java/com/neighbors/tohero/common/exception/letter/LetterException.java b/src/main/java/com/neighbors/tohero/common/exception/letter/LetterException.java new file mode 100644 index 0000000..061397f --- /dev/null +++ b/src/main/java/com/neighbors/tohero/common/exception/letter/LetterException.java @@ -0,0 +1,15 @@ +package com.neighbors.tohero.common.exception.letter; + +import com.neighbors.tohero.application.baseResponse.BaseResponseStatus; + +public class LetterException extends RuntimeException { + + private final BaseResponseStatus status; + private final String message; + + public LetterException(BaseResponseStatus status, String message) { + super(message); + this.status = status; + this.message = message; + } +} diff --git a/src/main/java/com/neighbors/tohero/common/jwt/JwtProvider.java b/src/main/java/com/neighbors/tohero/common/jwt/JwtProvider.java index 1ca26f7..9069bb0 100644 --- a/src/main/java/com/neighbors/tohero/common/jwt/JwtProvider.java +++ b/src/main/java/com/neighbors/tohero/common/jwt/JwtProvider.java @@ -35,7 +35,7 @@ public AuthTokens createToken(JwtUserDetails jwtUserDetails) { claims.put("role", jwtUserDetails.getRole()); if(jwtUserDetails.getRole() == Role.USER) { - claims.put("id", jwtUserDetails.getUserId()); + claims.put("userId", jwtUserDetails.getUserId()); claims.put("email", jwtUserDetails.getEmail()); } @@ -105,7 +105,7 @@ public void loggingToken(String token) { public Long getId(String token) { Claims claims = getBody(token); - return Long.parseLong(claims.get("id").toString()); + return Long.parseLong(claims.get("userId").toString()); } private Claims getBody(String token) { @@ -131,4 +131,14 @@ public JwtUserDetails getJwtUserDetails(String token) { .build(); } + + public JwtUserDetails getGuestJwtUserDetails(String token) { + Claims claims = getBody(token); + + return JwtUserDetails.builder() + .nickname(String.valueOf(claims.getSubject())) + .role(Role.valueOf(claims.get("role").toString())) + .build(); + + } } \ No newline at end of file diff --git a/src/main/java/com/neighbors/tohero/common/security/AuthenticationUtil.java b/src/main/java/com/neighbors/tohero/common/security/AuthenticationUtil.java index cfe32db..a262bab 100644 --- a/src/main/java/com/neighbors/tohero/common/security/AuthenticationUtil.java +++ b/src/main/java/com/neighbors/tohero/common/security/AuthenticationUtil.java @@ -1,5 +1,6 @@ package com.neighbors.tohero.common.security; +import com.neighbors.tohero.common.enums.Role; import com.neighbors.tohero.common.jwt.JwtProvider; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -29,8 +30,8 @@ public void setAuthenticationFromRequest(HttpServletRequest request) { }); } - private Boolean isRequestAvailableToGuest(HttpServletRequest request) { - return request.getRequestURI().contains("/realEstate") && request.getMethod().equals("GET"); + private Boolean isRequestAvailableToGuest(String token) { + return jwtProvider.getGuestJwtUserDetails(token).getRole() == Role.GUEST; } private Optional makeAuthentication(HttpServletRequest request, String token) { @@ -40,12 +41,15 @@ private Optional makeAuthentication(HttpServletRequest reque UserAuthentication authentication = null; if(isTokenValid(token)) { - String role = jwtProvider.getJwtUserDetails(token).getRole().toString(); - log.info("[AuthenticationUtil.makeAuthentication : {} 권한 부여]", role); - authentication = UserAuthentication.from(jwtProvider.getJwtUserDetails(token)); - } else if (isRequestAvailableToGuest(request)) { - log.info("[AuthenticationUtil.makeAuthentication : Guest 권한 부여]"); -// authentication = UserAuthentication.makeGuestAuthentication(); + if (isRequestAvailableToGuest(token)) { + log.info("[AuthenticationUtil.makeAuthentication : Guest 권한 부여]"); + String nickname = jwtProvider.getGuestJwtUserDetails(token).getNickname(); + authentication = UserAuthentication.makeGuestAuthentication(nickname); + } + else { + log.info("[AuthenticationUtil.makeAuthentication : User 권한 부여]"); + authentication = UserAuthentication.from(jwtProvider.getJwtUserDetails(token)); + } } if(authentication != null) { diff --git a/src/main/java/com/neighbors/tohero/common/security/UserAuthentication.java b/src/main/java/com/neighbors/tohero/common/security/UserAuthentication.java index 078aec8..d01a9a1 100644 --- a/src/main/java/com/neighbors/tohero/common/security/UserAuthentication.java +++ b/src/main/java/com/neighbors/tohero/common/security/UserAuthentication.java @@ -17,8 +17,8 @@ public static UserAuthentication from(JwtUserDetails jwtUserDetails) { return new UserAuthentication(jwtUserDetails, null, jwtUserDetails.getRole().getAuthority()); } -// public static UserAuthentication makeGuestAuthentication() { -// return new UserAuthentication(JwtUserDetails.makeGuestJwtDetails(), null, Role.GUEST.getAuthority()); -// } + public static UserAuthentication makeGuestAuthentication(String nickname) { + return new UserAuthentication(JwtUserDetails.makeGuestJwtDetails(nickname), null, Role.GUEST.getAuthority()); + } } diff --git a/src/main/java/com/neighbors/tohero/domain/domain/address/model/Address.java b/src/main/java/com/neighbors/tohero/domain/domain/address/model/Address.java index a130b72..d75f40d 100644 --- a/src/main/java/com/neighbors/tohero/domain/domain/address/model/Address.java +++ b/src/main/java/com/neighbors/tohero/domain/domain/address/model/Address.java @@ -1,5 +1,6 @@ package com.neighbors.tohero.domain.domain.address.model; +import com.neighbors.tohero.common.enums.TargetJob; import lombok.AllArgsConstructor; import lombok.Getter; @@ -11,8 +12,9 @@ public class Address { private String roadAddress; private String phoneNumber; private String queryPath; + private TargetJob targetJob; - public static Address of(long addressId, String officeName, String roadAddress, String phoneNumber, String queryPath){ - return new Address(addressId, officeName, roadAddress, phoneNumber, queryPath); + public static Address of(long addressId, String officeName, String roadAddress, String phoneNumber, String queryPath, TargetJob targetJob){ + return new Address(addressId, officeName, roadAddress, phoneNumber, queryPath, targetJob); } } diff --git a/src/main/java/com/neighbors/tohero/domain/domain/address/service/GetAddress.java b/src/main/java/com/neighbors/tohero/domain/domain/address/service/GetAddress.java index 814afad..924541f 100644 --- a/src/main/java/com/neighbors/tohero/domain/domain/address/service/GetAddress.java +++ b/src/main/java/com/neighbors/tohero/domain/domain/address/service/GetAddress.java @@ -21,4 +21,8 @@ public List
searchAddressByOfficeName(String queryPath, TargetJob targe public List
searchAddressByRoadAddress(String queryRoadAddress, TargetJob targetJob){ return addressRepository.searchAddressByRoadAddress(queryRoadAddress, targetJob); } + + public boolean existAddressById(long addressId) { + return addressRepository.existAddressById(addressId); + } } diff --git a/src/main/java/com/neighbors/tohero/domain/domain/letter/service/CreateLetter.java b/src/main/java/com/neighbors/tohero/domain/domain/letter/service/CreateLetter.java new file mode 100644 index 0000000..10bb050 --- /dev/null +++ b/src/main/java/com/neighbors/tohero/domain/domain/letter/service/CreateLetter.java @@ -0,0 +1,86 @@ +package com.neighbors.tohero.domain.domain.letter.service; + +import com.neighbors.tohero.application.letter.dto.CreateLetterRequest; +import com.neighbors.tohero.common.annotaion.DomainService; +import com.neighbors.tohero.common.enums.TargetJob; +import com.neighbors.tohero.common.exception.address.AddressException; +import com.neighbors.tohero.domain.domain.address.model.Address; +import com.neighbors.tohero.domain.domain.mainPage.model.Letter; +import com.neighbors.tohero.domain.domain.user.model.User; +import com.neighbors.tohero.domain.query.AddressRepository; +import com.neighbors.tohero.domain.query.LetterRepository; +import com.neighbors.tohero.domain.query.UserRepository; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class CreateLetter { + + private final LetterRepository letterRepository; + private final UserRepository userRepository; + private final AddressRepository addressRepository; + + public long createLetter(long userId, String writer, CreateLetterRequest createLetterRequest){ + User user = userRepository.getUser(repo -> repo.findByUserId(userId)); + Letter newLetter; + try{ + Address address = addressRepository.getAddressById(createLetterRequest.addressId()); + newLetter = Letter.builder() + .letterContent(createLetterRequest.content()) + .isOpened(false) + .targetName(createLetterRequest.heroName()) + .isPublic(createLetterRequest.isPublic()) + .readingAlarm(createLetterRequest.readingAlarm()) + .address(address) + .writer(user.getUserName()) + .user(user) + .build(); + }catch(AddressException | NullPointerException e){ + newLetter = Letter.builder() + .letterContent(createLetterRequest.content()) + .isOpened(false) + .targetName(createLetterRequest.heroName()) + .isPublic(createLetterRequest.isPublic()) + .readingAlarm(createLetterRequest.readingAlarm()) + .address(null) + .writer(user.getUserName()) + .user(user) + .build(); + } + + Letter createdLetter = letterRepository.createLetter(newLetter); + return createdLetter.getLetterId(); + } + + public long createGuestLetter(String writer, String content, TargetJob targetJob, Long addressId, String heroName, boolean isPublic){ + Letter newLetter; + if(addressId == null){ + newLetter = Letter.builder() + .letterContent(content) + .isOpened(false) + .targetName(heroName) + .isPublic(isPublic) + .readingAlarm(false) + .address(null) + .writer(writer) + .user(null) + .build(); + } + else{ + Address address = addressRepository.getAddressById(addressId); + newLetter = Letter.builder() + .letterContent(content) + .isOpened(false) + .targetName(heroName) + .isPublic(isPublic) + .readingAlarm(false) + .address(address) + .writer(writer) + .user(null) + .build(); + } + + Letter createdLetter = letterRepository.createLetter(newLetter); + return createdLetter.getLetterId(); + } +} diff --git a/src/main/java/com/neighbors/tohero/domain/domain/mainPage/model/Letter.java b/src/main/java/com/neighbors/tohero/domain/domain/mainPage/model/Letter.java index 1e38f9f..93737db 100644 --- a/src/main/java/com/neighbors/tohero/domain/domain/mainPage/model/Letter.java +++ b/src/main/java/com/neighbors/tohero/domain/domain/mainPage/model/Letter.java @@ -1,16 +1,27 @@ package com.neighbors.tohero.domain.domain.mainPage.model; +import com.neighbors.tohero.domain.domain.address.model.Address; +import com.neighbors.tohero.domain.domain.user.model.User; +import com.neighbors.tohero.infrastructure.entity.LetterEntity; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; @Getter +@Builder @AllArgsConstructor public class Letter { private long letterId; private String letterContent; private boolean isOpened; - private String fromUserName; private String targetName; + private boolean isPublic; + private boolean readingAlarm; + + private Address address; + + private String writer; + private User user; public String getTargetName(){ if(targetName == null) { @@ -19,7 +30,57 @@ public String getTargetName(){ return targetName; } - public static Letter of(long letterId, String letterContent, boolean isOpened, String fromUserName, String targetName) { - return new Letter(letterId, letterContent, isOpened, fromUserName, targetName); + public static Letter createNonUserAndAddress(LetterEntity letterEntity) { + return new Letter( + letterEntity.getLetterId(), + letterEntity.getLetterContent(), + letterEntity.isOpened(), + letterEntity.getTargetName(), + letterEntity.getIsPublic(), + letterEntity.getReadingAlarm(), + null,letterEntity.getWriter(),null + ); + } + + public static Letter createNonUser(LetterEntity letterEntity, Address address) { + return new Letter( + letterEntity.getLetterId(), + letterEntity.getLetterContent(), + letterEntity.isOpened(), + letterEntity.getTargetName(), + letterEntity.getIsPublic(), + letterEntity.getReadingAlarm(), + address + ,letterEntity.getWriter(), + null + ); + } + + public static Letter createNonAddress(LetterEntity letterEntity, User user) { + return new Letter( + letterEntity.getLetterId(), + letterEntity.getLetterContent(), + letterEntity.isOpened(), + letterEntity.getTargetName(), + letterEntity.getIsPublic(), + letterEntity.getReadingAlarm(), + null, + letterEntity.getUser().getNickName(), + user + ); + } + + public static Letter from(LetterEntity letterEntity, Address address, User user) { + return new Letter( + letterEntity.getLetterId(), + letterEntity.getLetterContent(), + letterEntity.isOpened(), + letterEntity.getTargetName(), + letterEntity.getIsPublic(), + letterEntity.getReadingAlarm(), + address, + letterEntity.getUser().getNickName(), + user + ); } } diff --git a/src/main/java/com/neighbors/tohero/domain/query/AddressRepository.java b/src/main/java/com/neighbors/tohero/domain/query/AddressRepository.java index a8291db..605a507 100644 --- a/src/main/java/com/neighbors/tohero/domain/query/AddressRepository.java +++ b/src/main/java/com/neighbors/tohero/domain/query/AddressRepository.java @@ -8,4 +8,6 @@ public interface AddressRepository { List
searchAddressByOfficeName(String queryPath, TargetJob targetJob); List
searchAddressByRoadAddress(String queryRoadAddress, TargetJob targetJob); + boolean existAddressById(long addressId); + Address getAddressById(long addressId); } diff --git a/src/main/java/com/neighbors/tohero/domain/query/LetterRepository.java b/src/main/java/com/neighbors/tohero/domain/query/LetterRepository.java index 472d13e..9694185 100644 --- a/src/main/java/com/neighbors/tohero/domain/query/LetterRepository.java +++ b/src/main/java/com/neighbors/tohero/domain/query/LetterRepository.java @@ -9,4 +9,5 @@ public interface LetterRepository { long getTotalLetterNumber(); List getPageableLetter(Pageable pageable); + Letter createLetter(Letter letter); } diff --git a/src/main/java/com/neighbors/tohero/infrastructure/entity/AddressEntity.java b/src/main/java/com/neighbors/tohero/infrastructure/entity/AddressEntity.java index e8ab6ae..b587aa7 100644 --- a/src/main/java/com/neighbors/tohero/infrastructure/entity/AddressEntity.java +++ b/src/main/java/com/neighbors/tohero/infrastructure/entity/AddressEntity.java @@ -3,11 +3,15 @@ import com.neighbors.tohero.common.enums.TargetJob; import com.neighbors.tohero.infrastructure.entity.base.BaseEntity; import jakarta.persistence.*; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; @Entity @Table(name = "`Address`") @Getter +@AllArgsConstructor +@NoArgsConstructor public class AddressEntity extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -29,4 +33,8 @@ public class AddressEntity extends BaseEntity { @Column(name = "target_job") @Enumerated(value = EnumType.ORDINAL) private TargetJob targetJob; + + public static AddressEntity of(long addressId, String branchOffice, String roadAddress, String phoneNumber, String queryPath, TargetJob targetJob) { + return new AddressEntity(addressId, branchOffice, roadAddress, phoneNumber, queryPath, targetJob); + } } diff --git a/src/main/java/com/neighbors/tohero/infrastructure/entity/LetterEntity.java b/src/main/java/com/neighbors/tohero/infrastructure/entity/LetterEntity.java index 90e390f..54b672d 100644 --- a/src/main/java/com/neighbors/tohero/infrastructure/entity/LetterEntity.java +++ b/src/main/java/com/neighbors/tohero/infrastructure/entity/LetterEntity.java @@ -2,11 +2,18 @@ import com.neighbors.tohero.infrastructure.entity.base.BaseEntity; import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; @Entity @Table(name = "`Letter`") @Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor public class LetterEntity extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -22,6 +29,9 @@ public class LetterEntity extends BaseEntity { @Column(name = "target_name", nullable = true) private String targetName; + @Column(name = "writer", nullable = true) + private String writer; + @ManyToOne @JoinColumn(name = "address_id", nullable = true) private AddressEntity address; @@ -32,4 +42,7 @@ public class LetterEntity extends BaseEntity { @Column(name = "is_public") private Boolean isPublic; + + @Column(name = "reading_alarm") + private Boolean readingAlarm; } diff --git a/src/main/java/com/neighbors/tohero/infrastructure/entity/UserEntity.java b/src/main/java/com/neighbors/tohero/infrastructure/entity/UserEntity.java index 8b23df4..2c8a9fc 100644 --- a/src/main/java/com/neighbors/tohero/infrastructure/entity/UserEntity.java +++ b/src/main/java/com/neighbors/tohero/infrastructure/entity/UserEntity.java @@ -1,13 +1,16 @@ package com.neighbors.tohero.infrastructure.entity; import com.neighbors.tohero.common.enums.Role; +import com.neighbors.tohero.domain.domain.user.model.User; import com.neighbors.tohero.infrastructure.entity.base.BaseEntity; import jakarta.persistence.*; +import lombok.AllArgsConstructor; import lombok.Getter; @Entity @Table(name = "`User`") @Getter +@AllArgsConstructor public class UserEntity extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -36,7 +39,11 @@ public void changeNickname(final String nickName){ this.nickName = nickName; } - public static UserEntity of(String nickName, String email, Role role) { + public static UserEntity returnNewObjectOf(String nickName, String email, Role role) { return new UserEntity(nickName, email, role); } + + public static UserEntity from(User user) { + return new UserEntity(user.getUserId(), user.getUserName(), user.getEmail(), user.getRole()); + } } diff --git a/src/main/java/com/neighbors/tohero/infrastructure/mapper/AddressMapper.java b/src/main/java/com/neighbors/tohero/infrastructure/mapper/AddressMapper.java index 95bcae6..30ac582 100644 --- a/src/main/java/com/neighbors/tohero/infrastructure/mapper/AddressMapper.java +++ b/src/main/java/com/neighbors/tohero/infrastructure/mapper/AddressMapper.java @@ -12,7 +12,22 @@ public Address toDomain(AddressEntity addressEntity) { addressEntity.getBranchOffice(), addressEntity.getRoadAddress(), addressEntity.getPhoneNumber(), - addressEntity.getQueryPath() + addressEntity.getQueryPath(), + addressEntity.getTargetJob() + ); + } + + public AddressEntity toEntity(Address address) { + if(address == null) { + return null; + } + return AddressEntity.of( + address.getAddressId(), + address.getOfficeName(), + address.getRoadAddress(), + address.getPhoneNumber(), + address.getQueryPath(), + address.getTargetJob() ); } } diff --git a/src/main/java/com/neighbors/tohero/infrastructure/mapper/LetterMapper.java b/src/main/java/com/neighbors/tohero/infrastructure/mapper/LetterMapper.java index a117c1d..082fb1f 100644 --- a/src/main/java/com/neighbors/tohero/infrastructure/mapper/LetterMapper.java +++ b/src/main/java/com/neighbors/tohero/infrastructure/mapper/LetterMapper.java @@ -2,17 +2,39 @@ import com.neighbors.tohero.domain.domain.mainPage.model.Letter; import com.neighbors.tohero.infrastructure.entity.LetterEntity; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @Component +@RequiredArgsConstructor public class LetterMapper { + + private final AddressMapper addressMapper; + private final UserMapper userMapper; + public Letter toDomain(LetterEntity letterEntity) { - return Letter.of( - letterEntity.getLetterId(), - letterEntity.getLetterContent(), - letterEntity.isOpened(), - letterEntity.getUser().getNickName(), - letterEntity.getTargetName() - ); + if(letterEntity.getUser() == null && letterEntity.getAddress() == null){ + return Letter.createNonUserAndAddress(letterEntity); + } + if(letterEntity.getUser() == null){ + return Letter.createNonUser(letterEntity, addressMapper.toDomain(letterEntity.getAddress())); + } + if(letterEntity.getAddress() == null){ + return Letter.createNonAddress(letterEntity, userMapper.toDomain(letterEntity.getUser())); + } + return Letter.from(letterEntity, addressMapper.toDomain(letterEntity.getAddress()), userMapper.toDomain(letterEntity.getUser())); + } + + public LetterEntity toEntity(Letter letter) { + return LetterEntity.builder() + .letterContent(letter.getLetterContent()) + .isOpened(false) + .targetName(letter.getTargetName()) + .writer(letter.getWriter()) + .address(addressMapper.toEntity(letter.getAddress())) + .user(userMapper.toEntity(letter.getUser())) + .isPublic(letter.isPublic()) + .readingAlarm(letter.isReadingAlarm()) + .build(); } } diff --git a/src/main/java/com/neighbors/tohero/infrastructure/mapper/UserMapper.java b/src/main/java/com/neighbors/tohero/infrastructure/mapper/UserMapper.java index 74718ea..6f227d0 100644 --- a/src/main/java/com/neighbors/tohero/infrastructure/mapper/UserMapper.java +++ b/src/main/java/com/neighbors/tohero/infrastructure/mapper/UserMapper.java @@ -6,14 +6,19 @@ @Component public class UserMapper { - public UserEntity toEntity(User user){ - return UserEntity.of( + public UserEntity toNewEntity(User user){ + return UserEntity.returnNewObjectOf( user.getUserName(), user.getEmail(), user.getRole() ); } + public UserEntity toEntity(User user){ + if(user == null) return null; + return UserEntity.from(user); + } + public User toDomain(UserEntity userEntity){ return User.of( userEntity.getUserId(), diff --git a/src/main/java/com/neighbors/tohero/infrastructure/query/impl/AddressRepositoryImpl.java b/src/main/java/com/neighbors/tohero/infrastructure/query/impl/AddressRepositoryImpl.java index b42719a..3bb10ae 100644 --- a/src/main/java/com/neighbors/tohero/infrastructure/query/impl/AddressRepositoryImpl.java +++ b/src/main/java/com/neighbors/tohero/infrastructure/query/impl/AddressRepositoryImpl.java @@ -1,6 +1,9 @@ package com.neighbors.tohero.infrastructure.query.impl; +import com.neighbors.tohero.application.baseResponse.BaseResponseMessage; +import com.neighbors.tohero.application.baseResponse.BaseResponseStatus; import com.neighbors.tohero.common.enums.TargetJob; +import com.neighbors.tohero.common.exception.address.AddressException; import com.neighbors.tohero.domain.domain.address.model.Address; import com.neighbors.tohero.domain.query.AddressRepository; import com.neighbors.tohero.infrastructure.entity.AddressEntity; @@ -35,4 +38,20 @@ public List
searchAddressByRoadAddress(String queryRoadAddress, TargetJ .map(addressMapper::toDomain) .toList(); } + + @Override + public boolean existAddressById(long addressId) { + return addressEntityRepository.existsById(addressId); + } + + @Override + public Address getAddressById(long addressId) { + AddressEntity addressEntity = addressEntityRepository.findById(addressId) + .orElseThrow(() -> new AddressException( + BaseResponseStatus.NO_RESULT, + BaseResponseMessage.일치하는_관할서_정보가_없습니다.getMessage() + )); + + return addressMapper.toDomain(addressEntity); + } } diff --git a/src/main/java/com/neighbors/tohero/infrastructure/query/impl/LetterRepositoryImpl.java b/src/main/java/com/neighbors/tohero/infrastructure/query/impl/LetterRepositoryImpl.java index a0005e1..912bd49 100644 --- a/src/main/java/com/neighbors/tohero/infrastructure/query/impl/LetterRepositoryImpl.java +++ b/src/main/java/com/neighbors/tohero/infrastructure/query/impl/LetterRepositoryImpl.java @@ -31,4 +31,11 @@ public List getPageableLetter(Pageable pageable) { .map(letterMapper::toDomain) .toList(); } + + @Override + public Letter createLetter(Letter letter) { + LetterEntity newLetterEntity = letterMapper.toEntity(letter); + LetterEntity createdLetterEntity = letterEntityRepository.save(newLetterEntity); + return letterMapper.toDomain(createdLetterEntity); + } } diff --git a/src/main/java/com/neighbors/tohero/infrastructure/query/impl/UserRepositoryImpl.java b/src/main/java/com/neighbors/tohero/infrastructure/query/impl/UserRepositoryImpl.java index be34cf9..8b98412 100644 --- a/src/main/java/com/neighbors/tohero/infrastructure/query/impl/UserRepositoryImpl.java +++ b/src/main/java/com/neighbors/tohero/infrastructure/query/impl/UserRepositoryImpl.java @@ -26,7 +26,7 @@ public User createUser(User user) { try{ return getUser(repo -> repo.findByEmail(user.getEmail())); }catch(UserException e){ - UserEntity userEntity = userMapper.toEntity(user); + UserEntity userEntity = userMapper.toNewEntity(user); userEntityRepository.save(userEntity); UserEntity createdUserEntity = userEntityRepository.findByEmail(user.getEmail()) diff --git a/src/main/java/com/neighbors/tohero/infrastructure/repository/LetterEntityRepository.java b/src/main/java/com/neighbors/tohero/infrastructure/repository/LetterEntityRepository.java index 56a62ac..8131bc0 100644 --- a/src/main/java/com/neighbors/tohero/infrastructure/repository/LetterEntityRepository.java +++ b/src/main/java/com/neighbors/tohero/infrastructure/repository/LetterEntityRepository.java @@ -10,7 +10,7 @@ @Repository public interface LetterEntityRepository extends JpaRepository { - @Query("SELECT n FROM LetterEntity n JOIN FETCH n.user WHERE n.isPublic = true") + @Query("SELECT n FROM LetterEntity n WHERE n.isPublic = true") Slice findPagedLetterEntity(Pageable pageable); @Query("SELECT COUNT(n) FROM LetterEntity n WHERE n.isPublic = true") diff --git a/src/main/java/com/neighbors/tohero/presentation/controller/LetterController.java b/src/main/java/com/neighbors/tohero/presentation/controller/LetterController.java index 1f58541..7a36697 100644 --- a/src/main/java/com/neighbors/tohero/presentation/controller/LetterController.java +++ b/src/main/java/com/neighbors/tohero/presentation/controller/LetterController.java @@ -3,8 +3,11 @@ import com.neighbors.tohero.application.baseResponse.BaseResponse; import com.neighbors.tohero.application.letter.dto.CreateLetterRequest; import com.neighbors.tohero.application.letter.service.LetterService; +import com.neighbors.tohero.common.jwt.JwtUserDetails; +import io.swagger.v3.oas.annotations.Parameter; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -19,8 +22,11 @@ public class LetterController { private final LetterService letterService; @PostMapping("/letter") - public ResponseEntity createLetter(@RequestBody @Validated CreateLetterRequest createLetterRequest) { + public ResponseEntity createLetter( + @Parameter(hidden=true) @AuthenticationPrincipal JwtUserDetails jwtUserDetail, + @RequestBody @Validated CreateLetterRequest createLetterRequest + ) { return ResponseEntity.ok() - .body(letterService.createLetter(createLetterRequest)); + .body(letterService.createLetter(jwtUserDetail, createLetterRequest)); } } diff --git a/src/main/java/com/neighbors/tohero/presentation/controller/UserController.java b/src/main/java/com/neighbors/tohero/presentation/controller/UserController.java index 1106b71..3907728 100644 --- a/src/main/java/com/neighbors/tohero/presentation/controller/UserController.java +++ b/src/main/java/com/neighbors/tohero/presentation/controller/UserController.java @@ -16,13 +16,13 @@ @RestController @RequiredArgsConstructor -@RequestMapping("") +@RequestMapping("/user") public class UserController { private final UserService userService; @Operation(summary = "유저 API", description = "유저 이름 변경 API입니다.") - @PutMapping("/user/name") + @PutMapping("/name") public ResponseEntity updateUserName( @Parameter(hidden=true) @AuthenticationPrincipal JwtUserDetails jwtUserDetail, @ParameterObject @Validated UpdateUserName updateUserName @@ -32,7 +32,7 @@ public ResponseEntity updateUserName( } @Operation(summary = "유저 API", description = "사용자 인증 API입니다.") - @PostMapping("/user/auth") + @PostMapping("/auth") public ResponseEntity authenticateUser(@RequestBody @Validated AuthenticateUserRequest authenticateUserRequest){ return ResponseEntity.ok() .body(userService.authenticateUser(authenticateUserRequest)); diff --git a/src/main/java/com/neighbors/tohero/presentation/exception_handler/AddressExceptionControllerAdvice.java b/src/main/java/com/neighbors/tohero/presentation/exception_handler/AddressExceptionControllerAdvice.java new file mode 100644 index 0000000..3a0c67f --- /dev/null +++ b/src/main/java/com/neighbors/tohero/presentation/exception_handler/AddressExceptionControllerAdvice.java @@ -0,0 +1,26 @@ +package com.neighbors.tohero.presentation.exception_handler; + +import com.neighbors.tohero.application.baseResponse.BaseResponse; +import com.neighbors.tohero.application.baseResponse.BaseResponseStatus; +import com.neighbors.tohero.common.exception.address.AddressException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class AddressExceptionControllerAdvice { + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(AddressException.class) + public ResponseEntity handle_NoticeException(AddressException e) { + BaseResponse response = new BaseResponse( + BaseResponseStatus.NO_RESULT, + e.getMessage() + ); + + return ResponseEntity.badRequest() + .body(response); + } +}