diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index d3a4526..7eb83f2 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -2,7 +2,7 @@ name: ModernFarmer CI/CD on: push: - branches: ["dev"] + branches: ["feature_32/계정-삭제-api", "dev"] permissions: contents: read @@ -49,6 +49,7 @@ jobs: echo "${{ secrets.PROPERTIES_YML }}" > ./application.yml shell: bash + # 빌드(테스트 스킵) - name: Build with Gradle run: ./gradlew build -x test @@ -68,8 +69,9 @@ jobs: username: ubuntu key: ${{ secrets.EC2_PRIVATE_KEY }} script: | + docker stop ModernFarmerUser docker rm ModernFarmerUser docker rmi ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:1.0 docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:1.0 - docker run -d -p 80:8080 --name ModernFarmerUser ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:1.0 \ No newline at end of file + docker run -d -p 8081:8081 --name ModernFarmerUser ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:1.0 diff --git a/.jpb/jpb-settings.xml b/.jpb/jpb-settings.xml new file mode 100644 index 0000000..484f362 --- /dev/null +++ b/.jpb/jpb-settings.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index a8fb8ae..1248b44 100644 --- a/build.gradle +++ b/build.gradle @@ -21,11 +21,17 @@ repositories { mavenCentral() } +ext { + set('springCloudVersion', "2021.0.8") +} + dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' + implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' developmentOnly 'org.springframework.boot:spring-boot-devtools' @@ -39,6 +45,19 @@ dependencies { implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.2' runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.2' runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.2' + + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' + + // firebase sdk + implementation 'com.google.firebase:firebase-admin:6.8.1' + // okhttp + implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.2.2' +} + +dependencyManagement { + imports { + mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" + } } tasks.named('test') { diff --git a/src/main/java/modernfarmer/server/farmususer/FarmusUserApplication.java b/src/main/java/modernfarmer/server/farmususer/FarmusUserApplication.java index ecfda07..7d8e32d 100644 --- a/src/main/java/modernfarmer/server/farmususer/FarmusUserApplication.java +++ b/src/main/java/modernfarmer/server/farmususer/FarmusUserApplication.java @@ -2,8 +2,14 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableJpaAuditing +@EnableDiscoveryClient @SpringBootApplication +@EnableFeignClients public class FarmusUserApplication { public static void main(String[] args) { diff --git a/src/main/java/modernfarmer/server/farmususer/community/CommunityServiceFeignClient.java b/src/main/java/modernfarmer/server/farmususer/community/CommunityServiceFeignClient.java new file mode 100644 index 0000000..8046079 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/community/CommunityServiceFeignClient.java @@ -0,0 +1,20 @@ +package modernfarmer.server.farmususer.community; + + +import modernfarmer.server.farmususer.user.dto.response.BaseResponseDto; +import modernfarmer.server.farmususer.user.entity.BaseEntity; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient(url = "http://3.38.2.59:8082", name = "community-service") +public interface CommunityServiceFeignClient { + + @DeleteMapping("/api/community/posting/all-posting/{userId}") + void deleteAllPosting(@PathVariable("userId") Long userId); + + + + +} diff --git a/src/main/java/modernfarmer/server/farmususer/farm/FarmServiceFeignClient.java b/src/main/java/modernfarmer/server/farmususer/farm/FarmServiceFeignClient.java new file mode 100644 index 0000000..667dcf9 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/farm/FarmServiceFeignClient.java @@ -0,0 +1,14 @@ +package modernfarmer.server.farmususer.farm; + + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; + +@FeignClient(url = "http://3.36.221.140:8081", name = "farm-service") +public interface FarmServiceFeignClient { + + @DeleteMapping("/api/veggie/{userId}") + void deleteAllVeggies(@PathVariable("userId") Long userId); + +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/config/Firebase/FcmMessage.java b/src/main/java/modernfarmer/server/farmususer/global/config/Firebase/FcmMessage.java new file mode 100644 index 0000000..f19bfe7 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/config/Firebase/FcmMessage.java @@ -0,0 +1,31 @@ +package modernfarmer.server.farmususer.global.config.Firebase; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Builder +@AllArgsConstructor +@Getter +public class FcmMessage { + private boolean validate_only; + private Message message; + @Builder + @AllArgsConstructor + @Getter + public static class Message { + + private Notification notification; + + private String token; + } + @Builder + @AllArgsConstructor + @Getter + public static class Notification { + private String title; + private String body; + private String image; + + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/config/Firebase/FirebaseCloudMessageService.java b/src/main/java/modernfarmer/server/farmususer/global/config/Firebase/FirebaseCloudMessageService.java new file mode 100644 index 0000000..608bded --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/config/Firebase/FirebaseCloudMessageService.java @@ -0,0 +1,64 @@ +package modernfarmer.server.farmususer.global.config.Firebase; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.auth.oauth2.GoogleCredentials; +import lombok.RequiredArgsConstructor; +import okhttp3.*; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.List; + +@Component +@RequiredArgsConstructor +public class FirebaseCloudMessageService { + + private final String API_URL = "https://fcm.googleapis.com/v1/projects/tourcash-13092/messages:send"; // 프론트에서 제공한 url + private final ObjectMapper objectMapper; + + public void sendMessageTo(String targetToken, String title, String body) throws IOException { + String message = makeMessage(targetToken, title, body); + OkHttpClient client = new OkHttpClient(); + RequestBody requestBody = RequestBody.create(message, MediaType.get("application/json; charset=utf-8")); + Request request = new Request.Builder() + .url(API_URL) + .post(requestBody) + .addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + getAccessToken()) + .addHeader(HttpHeaders.CONTENT_TYPE, "application/json; UTF-8") + .build(); + Response response = client.newCall(request) + .execute(); + + System.out.println(response.body().string()); + + } + private String makeMessage(String targetToken, String title, String body) throws JsonProcessingException { + FcmMessage fcmMessage = FcmMessage.builder() + .message(FcmMessage.Message.builder() + .token(targetToken) + .notification(FcmMessage.Notification.builder() + .title(title) + .body(body) + .image(null) + .build() + ).build() + ) + .validate_only(false) + .build(); + return objectMapper.writeValueAsString(fcmMessage); + } + + + private String getAccessToken() throws IOException { + String firebaseConfigPath = "firebase/firebase_service_key.json"; // 프론트에서 받은 파일을 해당 위치에 넣기 + GoogleCredentials googleCredentials = GoogleCredentials + .fromStream(new ClassPathResource(firebaseConfigPath).getInputStream()) + .createScoped(List.of("https://www.googleapis.com/auth/cloud-platform")); + googleCredentials.refreshIfExpired(); + return googleCredentials.getAccessToken().getTokenValue(); + } + +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/config/redis/RedisConfig.java b/src/main/java/modernfarmer/server/farmususer/global/config/redis/RedisConfig.java index 721dceb..8e60cd9 100644 --- a/src/main/java/modernfarmer/server/farmususer/global/config/redis/RedisConfig.java +++ b/src/main/java/modernfarmer/server/farmususer/global/config/redis/RedisConfig.java @@ -24,8 +24,7 @@ public RedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setHostName(redisHost); redisStandaloneConfiguration.setPort(Integer.parseInt(redisPort)); - LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration); - return lettuceConnectionFactory; + return new LettuceConnectionFactory(redisStandaloneConfiguration); } @Bean diff --git a/src/main/java/modernfarmer/server/farmususer/global/config/s3/S3Config.java b/src/main/java/modernfarmer/server/farmususer/global/config/s3/S3Config.java new file mode 100644 index 0000000..9d58626 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/config/s3/S3Config.java @@ -0,0 +1,28 @@ +package modernfarmer.server.farmususer.global.config.s3; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class S3Config { + @Value("${cloud.aws.credentials.access-key}") + private String accessKey; + @Value("${cloud.aws.credentials.secret-key}") + private String secretKey; + @Value("${cloud.aws.region.static}") + private String region; + + @Bean + public AmazonS3Client amazonS3Client() { + BasicAWSCredentials awsCredentials= new BasicAWSCredentials(accessKey, secretKey); + return (AmazonS3Client) AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/global/config/s3/S3Uploader.java b/src/main/java/modernfarmer/server/farmususer/global/config/s3/S3Uploader.java new file mode 100644 index 0000000..f020922 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/config/s3/S3Uploader.java @@ -0,0 +1,68 @@ +package modernfarmer.server.farmususer.global.config.s3; + +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.PutObjectRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Optional; +import java.util.UUID; + +@Slf4j +@Component +public class S3Uploader { + private final AmazonS3Client amazonS3Client; + + @Value("${cloud.aws.s3.bucket}") + private String bucket; + + public S3Uploader(AmazonS3Client amazonS3Client) { + this.amazonS3Client = amazonS3Client; + } + + public String uploadFiles( + MultipartFile multipartFile, String dirName) throws IOException { + File uploadFile = convert(multipartFile).orElseThrow(() -> + new IllegalArgumentException("error: MultipartFile -> File convert fail")); + return upload(uploadFile, dirName); + } + + public String upload(File uploadFile, String filePath) { + String fileName = filePath + "/" + UUID.randomUUID() + uploadFile.getName(); + String uploadImageUrl = putS3(uploadFile, fileName); + removeNewFile(uploadFile); + return uploadImageUrl; + } + + private String putS3(File uploadFile, String fileName) { + amazonS3Client.putObject( + new PutObjectRequest(bucket, fileName, uploadFile) + .withCannedAcl(CannedAccessControlList.PublicRead)); + return amazonS3Client.getUrl(bucket, fileName).toString(); + } + + private void removeNewFile(File targetFile) { + if (targetFile.delete()) { + System.out.println("File delete success"); + return; + } + System.out.println("File delete fail"); + } + + private Optional convert(MultipartFile file) throws IOException { + File convertFile = new File(System.getProperty("user.dir") + "/" + file.getOriginalFilename()); + if (convertFile.createNewFile()) { + try (FileOutputStream fileOutputStream = new FileOutputStream(convertFile)) { + fileOutputStream.write(file.getBytes()); + } + return Optional.of(convertFile); + } + return Optional.empty(); + } +} \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/global/enums/Motivations.java b/src/main/java/modernfarmer/server/farmususer/global/enums/Motivations.java new file mode 100644 index 0000000..9027ad4 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/enums/Motivations.java @@ -0,0 +1,54 @@ +package modernfarmer.server.farmususer.global.enums; + +public class Motivations { + + public enum Motive_1 { + MOTIVE1_1("채소를 직접 길러\n식비를 줄여보세요!"), + MOTIVE1_2("직접 기른 채소로\n알뜰하고 현명한 식사를 해봐요!"), + MOTIVE1_3("오늘도 채솟값\n알뜰하게 아끼는 중!"), + MOTIVE1_4("홈파밍으로 지출은 줄이고\n성취감은 더해봐요"), + MOTIVE1_5("직접 기른 채소로\n매일 알뜰하게, 매일 특별하게!"); + + private final String motive1; + + Motive_1(String motive1) { + this.motive1 = motive1; + } + + public String getMotive() { + return motive1; + } + } + public enum Motive_2 { + MOTIVE2_1("직접 기른 채소를\n먹을 수 있는 그날까지!"), + MOTIVE2_2("신선함으로 가득 채워지는 식탁, \n늘 함께할게요!"), + MOTIVE2_3("눈으로 보는 재미, 입으로 맛보는\n홈파밍의 즐거움!"); + + private final String motive2; + + Motive_2(String motive2) { + this.motive2 = motive2; + } + + public String getMotive() { + return motive2; + } + } + public enum Motive_3 { + MOTIVE3_1("바쁜 일상에서 잠깐 벗어나\n텃밭을 가꿔봐요"), + MOTIVE3_2("홈파밍을 하며\n마음의 안정을 느껴봐요!"), + MOTIVE3_3("스트레스 받는 하루, \n홈파밍으로 힐링하세요"), + MOTIVE3_4("나만의 채소를 키우며\n소소한 성취감을 느껴보세요"), + MOTIVE3_5("성취감은 꾸준함에서! \n오늘도 함께 성장해요"); + + private final String motive3; + + Motive_3(String motive3) { + this.motive3 = motive3; + } + + public String getMotive() { + return motive3; + } + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/ErrorResponse.java b/src/main/java/modernfarmer/server/farmususer/global/exception/ErrorResponse.java new file mode 100644 index 0000000..34d9204 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/ErrorResponse.java @@ -0,0 +1,14 @@ +package modernfarmer.server.farmususer.global.exception; + +import lombok.*; +import org.springframework.http.HttpStatus; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@ToString +public class ErrorResponse { + + private HttpStatus code; + private String message; +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/GlobalExceptionHandler.java b/src/main/java/modernfarmer/server/farmususer/global/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..7cd1990 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/GlobalExceptionHandler.java @@ -0,0 +1,82 @@ +package modernfarmer.server.farmususer.global.exception; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; + +import javax.servlet.http.HttpServletRequest; +import java.util.Objects; + +@Slf4j +@RequiredArgsConstructor +@RestControllerAdvice +public class GlobalExceptionHandler { + private final HttpStatus BAD_REQUEST = HttpStatus.BAD_REQUEST; + + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleInputFieldException(MethodArgumentNotValidException e, HttpServletRequest request) { + log.error("MethodArgumentNotValidException : {} {} errMessage={}\n", + request.getMethod(), + request.getRequestURI(), + e.getMessage()); + FieldError mainError = e.getFieldErrors().get(0); + String[] errorInfo = Objects.requireNonNull(mainError.getDefaultMessage()).split(":"); + String message = errorInfo[0]; + return ResponseEntity.badRequest().body(new ErrorResponse(BAD_REQUEST, message)); + } + + @ExceptionHandler(BindException.class) + public ResponseEntity handleBindException(BindException e, HttpServletRequest request) { + log.error("BindException : {} {} errMessage={}\n", + request.getMethod(), + request.getRequestURI(), + e.getMessage()); + FieldError mainError = e.getFieldErrors().get(0); + String[] errorInfo = Objects.requireNonNull(mainError.getDefaultMessage()).split(":"); + String message = errorInfo[0]; + return ResponseEntity.badRequest().body(new ErrorResponse(BAD_REQUEST, message)); + } + + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + public ResponseEntity handleMethodArgumentTypeMismatchExceptionException(MethodArgumentTypeMismatchException e, HttpServletRequest request) { + log.error("MethodArgumentTypeMismatchException : {} {} errMessage={}\n", + request.getMethod(), + request.getRequestURI(), + e.getMessage()); + return ResponseEntity.badRequest().body(new ErrorResponse(BAD_REQUEST, e.getMessage())); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public ResponseEntity handleHttpRequestMethodNotSupportedExceptionException(HttpRequestMethodNotSupportedException e, HttpServletRequest request) { + log.error("HttpRequestMethodNotSupportedException : {} {} errMessage={}\n", + request.getMethod(), + request.getRequestURI(), + e.getMessage()); + + return ResponseEntity.badRequest().body(new ErrorResponse(HttpStatus.METHOD_NOT_ALLOWED, e.getMessage())); + } + + + + + + @ExceptionHandler(Exception.class) + public ResponseEntity unhandledException(Exception e, HttpServletRequest request) { + log.error("UnhandledException: {} {} errMessage={}\n", + request.getMethod(), + request.getRequestURI(), + e.getMessage() + ); + return ResponseEntity.internalServerError() + .body(new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, "서버와의 접속이 원활하지 않습니다.")); + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/fail/ErrorMessage.java b/src/main/java/modernfarmer/server/farmususer/global/exception/fail/ErrorMessage.java new file mode 100644 index 0000000..a38d996 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/fail/ErrorMessage.java @@ -0,0 +1,26 @@ +package modernfarmer.server.farmususer.global.exception.fail; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +import static org.springframework.http.HttpStatus.*; + +@Getter +public enum ErrorMessage { + + INTERVAL_SERVER_ERROR(1001, "요청을 처리하는 과정에서 서버가 예상하지 못한 오류가 발생하였습니다."), + REFRESH_NOTIFICATION_ERROR(1002, "Refresh Token 인증 오류"), + NO_USER_DATA(1003, "유저에 대한 정보가 없습니다."), + NO_MOTIVATION_DATA(1004, "동기에 대한 정보가 없습니다."), + FAIL_GET_INFORMATION(1005, "소셜에서 정보를 가져오는데 실패했습니다."); + + + + private final int code; + private final String message; + + ErrorMessage(int code, String message) { + this.code = code; + this.message = message; + } +} \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/global/exception/success/SuccessMessage.java b/src/main/java/modernfarmer/server/farmususer/global/exception/success/SuccessMessage.java new file mode 100644 index 0000000..91a2a86 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/global/exception/success/SuccessMessage.java @@ -0,0 +1,17 @@ +package modernfarmer.server.farmususer.global.exception.success; + +import lombok.Getter; + +@Getter +public enum SuccessMessage { + SUCCESS(200, "요청에 성공하였습니다."); + + private final int code; + private final String message; + + SuccessMessage(int code, String message) { + this.code = code; + this.message = message; + } + +} \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/user/controller/AuthController.java b/src/main/java/modernfarmer/server/farmususer/user/controller/AuthController.java index 4dd2702..35f4d71 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/controller/AuthController.java +++ b/src/main/java/modernfarmer/server/farmususer/user/controller/AuthController.java @@ -1,72 +1,40 @@ package modernfarmer.server.farmususer.user.controller; -import modernfarmer.server.farmususer.user.dto.response.ResponseDto; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import modernfarmer.server.farmususer.user.dto.response.BaseResponseDto; import modernfarmer.server.farmususer.user.dto.response.TokenResponseDto; import modernfarmer.server.farmususer.user.service.AuthService; import modernfarmer.server.farmususer.user.util.JwtTokenProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; +@Slf4j +@RequiredArgsConstructor @RestController @RequestMapping("/api/user/auth") public class AuthController { - private final Logger LOGGER = LoggerFactory.getLogger(AuthController.class); + private final AuthService authService; private final JwtTokenProvider jwtTokenProvider; - @Autowired - public AuthController(AuthService authService, JwtTokenProvider jwtTokenProvider){ - this.authService = authService; - this.jwtTokenProvider = jwtTokenProvider; - } - @PostMapping(value = "/kakao-login") - public TokenResponseDto kakaoLogin(HttpServletRequest request) { + public BaseResponseDto kakaoLogin(HttpServletRequest request) { String accessToken = jwtTokenProvider.resolveToken(request); - TokenResponseDto reissueTokenResponseDto = authService.kakaoLogin(accessToken); - - LOGGER.info("카카오 로그인 완료"); - - return reissueTokenResponseDto; + return authService.kakaoLogin(accessToken); } + - @DeleteMapping("/logout") - public ResponseDto logout(HttpServletRequest request) { - - - String userId = jwtTokenProvider.getUserId(request); - - ResponseDto logoutResponseDto = authService.logout(Long.valueOf(userId)); - - LOGGER.info("로그아웃 완료"); - - return logoutResponseDto; - } + @PostMapping(value = "/google-login") + public BaseResponseDto googleLogin(HttpServletRequest request) { - @GetMapping(value = "/reissue-token") - public TokenResponseDto reissueToken(HttpServletRequest request) { - - String userId = jwtTokenProvider.getUserId(request); - String refreshToken = jwtTokenProvider.resolveToken(request); - - TokenResponseDto reissueTokenResponseDto = authService.reissueToken(refreshToken, Long.valueOf(userId)); - - LOGGER.info("토큰 재발급 완료"); + String accessToken = jwtTokenProvider.resolveToken(request); - return reissueTokenResponseDto; + return authService.googleLogin(accessToken); } - - - - - - } \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/user/controller/FirebaseController.java b/src/main/java/modernfarmer/server/farmususer/user/controller/FirebaseController.java new file mode 100644 index 0000000..088a485 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/controller/FirebaseController.java @@ -0,0 +1,44 @@ +package modernfarmer.server.farmususer.user.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import modernfarmer.server.farmususer.user.dto.response.BaseResponseDto; +import modernfarmer.server.farmususer.user.service.FirebaseService; +import modernfarmer.server.farmususer.user.util.JwtTokenProvider; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; + +@Slf4j +@RestController +@RequestMapping("/api/firebase") +@RequiredArgsConstructor +public class FirebaseController { + + private final JwtTokenProvider jwtTokenProvider; + private final FirebaseService firebaseService; + + + @PostMapping(value = "/firebase-token") + public BaseResponseDto insertFirebaseToken(HttpServletRequest request) { + + String userId = jwtTokenProvider.getUserId(request); + String fireBaseToken = jwtTokenProvider.getFirebaseToken(request); + + return firebaseService.insertFirebaseToken(Long.valueOf(userId),fireBaseToken); + } + + + @DeleteMapping(value = "/firebase-token") + public BaseResponseDto deleteFirebaseToken(HttpServletRequest request) { + + String userId = jwtTokenProvider.getUserId(request); + String fireBaseToken = jwtTokenProvider.getFirebaseToken(request); + + return firebaseService.deleteFirebaseToken(Long.valueOf(userId),fireBaseToken); + } + +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/controller/OnBoardingController.java b/src/main/java/modernfarmer/server/farmususer/user/controller/OnBoardingController.java new file mode 100644 index 0000000..7457f4d --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/controller/OnBoardingController.java @@ -0,0 +1,44 @@ +package modernfarmer.server.farmususer.user.controller; + + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import modernfarmer.server.farmususer.user.dto.request.OnBoardingLevelRequest; +import modernfarmer.server.farmususer.user.dto.request.OnBoardingMotivationRequest; +import modernfarmer.server.farmususer.user.dto.response.BaseResponseDto; +import modernfarmer.server.farmususer.user.dto.response.OnBoardingLevelResponse; +import modernfarmer.server.farmususer.user.service.OnBoardingService; +import modernfarmer.server.farmususer.user.util.JwtTokenProvider; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import javax.servlet.http.HttpServletRequest; + +@RequiredArgsConstructor +@Slf4j +@RestController +@RequestMapping("/api/user/on-boarding") +public class OnBoardingController { + + private final JwtTokenProvider jwtTokenProvider; + private final OnBoardingService onBoardingService; + + + @PostMapping(value = "/motivation") + public BaseResponseDto onBoardingMotivation(HttpServletRequest request, @Validated @RequestBody OnBoardingMotivationRequest onBoardingMotivationRequest) { + + String userId = jwtTokenProvider.getUserId(request); + + return onBoardingService.onBoardingMotivation(Long.valueOf(userId),onBoardingMotivationRequest); + } + + @PostMapping(value = "/level") + public BaseResponseDto onBoardingLevel(HttpServletRequest request, @Validated @RequestBody OnBoardingLevelRequest onBoardingLevelRequest) { + + String userId = jwtTokenProvider.getUserId(request); + + return onBoardingService.onBoardingLevel(Long.valueOf(userId), onBoardingLevelRequest); + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/controller/UserController.java b/src/main/java/modernfarmer/server/farmususer/user/controller/UserController.java new file mode 100644 index 0000000..0c46347 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/controller/UserController.java @@ -0,0 +1,144 @@ +package modernfarmer.server.farmususer.user.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import modernfarmer.server.farmususer.global.exception.success.SuccessMessage; +import modernfarmer.server.farmususer.user.dto.request.ProduceNicknameRequest; +import modernfarmer.server.farmususer.user.dto.response.*; + +import modernfarmer.server.farmususer.user.service.UserService; +import modernfarmer.server.farmususer.user.util.JwtTokenProvider; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + + +@Slf4j +@RestController +@RequestMapping("/api/user") +@RequiredArgsConstructor +public class UserController { + + private final UserService userService; + private final JwtTokenProvider jwtTokenProvider; + +// @PostMapping(value = "/profileImage", produces = MediaType.APPLICATION_JSON_VALUE) +// public BaseResponseDto produceProfileImage(HttpServletRequest request, @RequestPart("file") MultipartFile multipartFile) throws IOException { +// +// String userId = jwtTokenProvider.getUserId(request); +// log.info(userId); +// BaseResponseDto responseDto = userService.emitProfileImage(Long.valueOf(userId), multipartFile); +// +// return responseDto; +// +// } + + @GetMapping + public BaseResponseDto getUser(HttpServletRequest request){ + + String userId = jwtTokenProvider.getUserId(request); + + return userService.getUser(Long.valueOf(userId)); + } + + @GetMapping("/level") + public String getUserLevel(@RequestHeader("user") Long userId){ + return userService.getUserLevel(userId); + } + + @GetMapping("/info") + public GetUserLevelAndNicknameResponseDto getUserLevelAndNickname(@RequestHeader("user") Long userId){ + return userService.getUserLevelAndNickname(userId); + } + + @PostMapping(value = "/nickname") + public BaseResponseDto emitNickname(HttpServletRequest request, @RequestBody ProduceNicknameRequest produceNicknameRequest){ + + String userId = jwtTokenProvider.getUserId(request); + + return userService.emitNickname(Long.valueOf(userId), produceNicknameRequest.getNickName()); + } + + @PostMapping(value = "/select-information", produces = MediaType.APPLICATION_JSON_VALUE) + public BaseResponseDto selectProfileImageAndNickname(HttpServletRequest request, @RequestPart(value = "file", required = false) MultipartFile multipartFile, @RequestParam("nickName")String nickName) throws IOException { + + String userId = jwtTokenProvider.getUserId(request); + + return userService.selectProfileImageAndNickname(Long.valueOf(userId), multipartFile,nickName); + + } + + @PatchMapping(value = "/sign-up/complete", produces = MediaType.APPLICATION_JSON_VALUE) + public BaseResponseDto signUpComplete(HttpServletRequest request) { + + String userId = jwtTokenProvider.getUserId(request); + + return userService.signUpComlete(Long.valueOf(userId)); + + } + + @GetMapping(value = "/profileImage") + public BaseResponseDto selectProfileImage(HttpServletRequest request){ + + String userId = jwtTokenProvider.getUserId(request); + + return userService.selectProfileImage(Long.valueOf(userId)); + } + + + @DeleteMapping(value = "/delete") + public BaseResponseDto deleteUser(HttpServletRequest request){ + + String userId = jwtTokenProvider.getUserId(request); + + return userService.deleteUser(Long.valueOf(userId)); + } + + @DeleteMapping("/logout") + public BaseResponseDto logout(HttpServletRequest request) { + + String userId = jwtTokenProvider.getUserId(request); + + return userService.logout(Long.valueOf(userId)); + } + + @GetMapping(value = "/reissue-token") + public BaseResponseDto reissueToken(HttpServletRequest request) { + + String userId = jwtTokenProvider.getUserId(request); + String refreshToken = jwtTokenProvider.resolveToken(request); + + return userService.reissueToken(refreshToken, Long.valueOf(userId)); + } + + @PatchMapping(value = "/delete/user-profile") + public BaseResponseDto deleteUserProfile(HttpServletRequest request) { + + String userId = jwtTokenProvider.getUserId(request); + + return userService.deleteUserProfile(Long.valueOf(userId)); + } + + + @GetMapping(value = "/all-user") + public BaseResponseDto allUser() { + + return userService.allUser(); + } + + @GetMapping(value = "/specific-user") + public BaseResponseDto specificUser(@RequestParam("userId") Long userId) { + + return userService.specificUser(userId); + } + + @GetMapping("/motivation") + public BaseResponseDto getMotivation( + @RequestHeader("user") Long userId + ){ + return BaseResponseDto.of(SuccessMessage.SUCCESS, userService.getUserMotivation(userId)); + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/request/OnBoardingLevelRequest.java b/src/main/java/modernfarmer/server/farmususer/user/dto/request/OnBoardingLevelRequest.java new file mode 100644 index 0000000..dc64cdb --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/request/OnBoardingLevelRequest.java @@ -0,0 +1,21 @@ +package modernfarmer.server.farmususer.user.dto.request; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.util.ArrayList; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class OnBoardingLevelRequest { + + @NotNull(message = "null 값을 가지면 안됩니다.") + private int time; + + @NotNull(message = "null 값을 가지면 안됩니다.") + private String skill; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/request/OnBoardingMotivationRequest.java b/src/main/java/modernfarmer/server/farmususer/user/dto/request/OnBoardingMotivationRequest.java new file mode 100644 index 0000000..5348364 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/request/OnBoardingMotivationRequest.java @@ -0,0 +1,18 @@ +package modernfarmer.server.farmususer.user.dto.request; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import javax.validation.constraints.NotNull; +import java.util.ArrayList; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class OnBoardingMotivationRequest { + + + @NotNull(message = "null 값을 가지면 안됩니다.") + private ArrayList motivation; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/request/ProduceNicknameRequest.java b/src/main/java/modernfarmer/server/farmususer/user/dto/request/ProduceNicknameRequest.java new file mode 100644 index 0000000..a71b618 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/request/ProduceNicknameRequest.java @@ -0,0 +1,14 @@ +package modernfarmer.server.farmususer.user.dto.request; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class ProduceNicknameRequest { + + private String nickName; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/AllUserDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/AllUserDto.java new file mode 100644 index 0000000..74e90a8 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/AllUserDto.java @@ -0,0 +1,19 @@ +package modernfarmer.server.farmususer.user.dto.response; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor(staticName = "of") +@Getter +public class AllUserDto { + + private Long Id; + private String nickName; + private String imageUrl; + + + +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/AllUserResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/AllUserResponseDto.java new file mode 100644 index 0000000..a7671b4 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/AllUserResponseDto.java @@ -0,0 +1,15 @@ +package modernfarmer.server.farmususer.user.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + + +@NoArgsConstructor +@AllArgsConstructor(staticName = "of") +@Getter +public class AllUserResponseDto { + List allUserDtoList; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/BaseResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/BaseResponseDto.java new file mode 100644 index 0000000..1fb57da --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/BaseResponseDto.java @@ -0,0 +1,38 @@ +package modernfarmer.server.farmususer.user.dto.response; + + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Builder; +import lombok.Getter; +import modernfarmer.server.farmususer.global.exception.fail.ErrorMessage; +import modernfarmer.server.farmususer.global.exception.success.SuccessMessage; + + +@Getter +@Builder +@JsonPropertyOrder({"code", "message", "data"}) +public class BaseResponseDto { + private final int code; + private final String message; + + @JsonInclude(JsonInclude.Include.NON_NULL) + private T data; + + public static BaseResponseDto of(SuccessMessage successMessage, T data){ + + return BaseResponseDto.builder() + .code(successMessage.getCode()) + .message(successMessage.getMessage()) + .data(data) + .build(); + } + + public static BaseResponseDto of(ErrorMessage errorMessage){ + + return BaseResponseDto.builder() + .code(errorMessage.getCode()) + .message(errorMessage.getMessage()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/GetUserLevelAndNicknameResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/GetUserLevelAndNicknameResponseDto.java new file mode 100644 index 0000000..1ec9d00 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/GetUserLevelAndNicknameResponseDto.java @@ -0,0 +1,15 @@ +package modernfarmer.server.farmususer.user.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor(staticName = "of") +@NoArgsConstructor +@Getter +public class GetUserLevelAndNicknameResponseDto { + + private String level; + private String nickname; + private String motivation; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/GetUserResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/GetUserResponseDto.java new file mode 100644 index 0000000..a773ad2 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/GetUserResponseDto.java @@ -0,0 +1,15 @@ +package modernfarmer.server.farmususer.user.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor(staticName = "of") +@Getter +public class GetUserResponseDto { + + private String nickName; + private String userImageUrl; + private long dDay; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/GoogleUserResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/GoogleUserResponseDto.java new file mode 100644 index 0000000..6ede66f --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/GoogleUserResponseDto.java @@ -0,0 +1,16 @@ +package modernfarmer.server.farmususer.user.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class GoogleUserResponseDto { + + private String id; + private String email; + private String picture; + private String name; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/KakaoUserResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/KakaoUserResponseDto.java index b2d1756..cd44f2f 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/dto/response/KakaoUserResponseDto.java +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/KakaoUserResponseDto.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.Setter; @@ -9,6 +10,7 @@ @Getter @Builder +@AllArgsConstructor public class KakaoUserResponseDto { private long id; @@ -16,33 +18,33 @@ public class KakaoUserResponseDto { public KakaoUserResponseDto(@JsonProperty("id") long id) { this.id = id; } -// private UserProfileDTO kakao_account; -// -// -// @Setter -// @Getter -// public class UserProfileDTO { -// private boolean profileNicknameNeedsAgreement; -// private boolean profileImageNeedsAgreement; -// private ProfileData profile; -// private boolean hasEmail; -// private boolean emailNeedsAgreement; -// private boolean isEmailValid; -// private boolean isEmailVerified; -// private String email; -// -// -// -// -// @Getter -// @Setter -// public class ProfileData { -// private String nickname; -// private String thumbnailImageUrl; -// private String profileImageUrl; -// private boolean isDefaultImage; -// } -// } + private UserProfileDTO kakao_account; + + + @Setter + @Getter + public class UserProfileDTO { + private boolean profileNicknameNeedsAgreement; + private boolean profileImageNeedsAgreement; + private ProfileData profile; + private boolean hasEmail; + private boolean emailNeedsAgreement; + private boolean isEmailValid; + private boolean isEmailVerified; + private String email; + + + + + @Getter + @Setter + public class ProfileData { + private String nickname; + private String thumbnail_image_Url; + private String profile_image_url; + private boolean isDefaultImage; + } + } diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/OnBoardingLevelResponse.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/OnBoardingLevelResponse.java new file mode 100644 index 0000000..38a4267 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/OnBoardingLevelResponse.java @@ -0,0 +1,14 @@ +package modernfarmer.server.farmususer.user.dto.response; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor(staticName = "of") +@Getter +public class OnBoardingLevelResponse { + + private String level; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/ResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/ProfileImageResponseDto.java similarity index 53% rename from src/main/java/modernfarmer/server/farmususer/user/dto/response/ResponseDto.java rename to src/main/java/modernfarmer/server/farmususer/user/dto/response/ProfileImageResponseDto.java index 49a0746..fb0a7da 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/dto/response/ResponseDto.java +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/ProfileImageResponseDto.java @@ -5,10 +5,9 @@ import lombok.experimental.SuperBuilder; @NoArgsConstructor -@AllArgsConstructor -@Data -@SuperBuilder -public class ResponseDto { - private int code; - private String message; -} \ No newline at end of file +@AllArgsConstructor(staticName = "of") +@Getter +public class ProfileImageResponseDto{ + + private String profileImage; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/RefreshTokenResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/RefreshTokenResponseDto.java new file mode 100644 index 0000000..e4eaa15 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/RefreshTokenResponseDto.java @@ -0,0 +1,14 @@ +package modernfarmer.server.farmususer.user.dto.response; + + +import lombok.*; + +@NoArgsConstructor +@AllArgsConstructor(staticName = "of") +@Getter +public class RefreshTokenResponseDto { + + private String accessToken; + + private String refreshToken; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/SpecificUserResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/SpecificUserResponseDto.java new file mode 100644 index 0000000..0f53b54 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/SpecificUserResponseDto.java @@ -0,0 +1,17 @@ +package modernfarmer.server.farmususer.user.dto.response; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor(staticName = "of") +@Getter +public class SpecificUserResponseDto { + + private Long Id; + private String nickName; + private String imageUrl; + +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/TokenResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/TokenResponseDto.java index e746e38..6904d6e 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/dto/response/TokenResponseDto.java +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/TokenResponseDto.java @@ -2,19 +2,16 @@ import lombok.*; +import lombok.experimental.SuperBuilder; @NoArgsConstructor -@AllArgsConstructor -@ToString -@Builder +@AllArgsConstructor(staticName = "of") @Getter public class TokenResponseDto { - private int code; - - private String message; - private String accessToken; private String refreshToken; + + private boolean early; } \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/user/dto/response/UserMotivationResponseDto.java b/src/main/java/modernfarmer/server/farmususer/user/dto/response/UserMotivationResponseDto.java new file mode 100644 index 0000000..65ca41f --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/dto/response/UserMotivationResponseDto.java @@ -0,0 +1,13 @@ +package modernfarmer.server.farmususer.user.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor(staticName = "of") +@NoArgsConstructor +@Getter +public class UserMotivationResponseDto { + + private String motivation; +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/entity/BaseEntity.java b/src/main/java/modernfarmer/server/farmususer/user/entity/BaseEntity.java new file mode 100644 index 0000000..a3c93bc --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/entity/BaseEntity.java @@ -0,0 +1,24 @@ +package modernfarmer.server.farmususer.user.entity; + +import lombok.Data; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import java.time.LocalDateTime; + +@Data +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public class BaseEntity { + + @CreatedDate + @Column + private LocalDateTime createdAt; + + @LastModifiedDate + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/user/entity/Motivation.java b/src/main/java/modernfarmer/server/farmususer/user/entity/Motivation.java new file mode 100644 index 0000000..273f867 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/entity/Motivation.java @@ -0,0 +1,33 @@ +package modernfarmer.server.farmususer.user.entity; + +import lombok.*; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.util.LinkedHashSet; +import java.util.Set; + +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +@Table(name = "motivation") +public class Motivation extends BaseEntity{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "motivation_id", nullable = false) + private Long id; + + + @Column(name = "motivation_reason", nullable = false, length = 40) + private String motivationReason; + + @OneToMany(mappedBy = "motivation", fetch = FetchType.LAZY) + private Set userMotivations = new LinkedHashSet<>(); + + + +} \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/user/entity/User.java b/src/main/java/modernfarmer/server/farmususer/user/entity/User.java index 7bf3e13..4e40753 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/entity/User.java +++ b/src/main/java/modernfarmer/server/farmususer/user/entity/User.java @@ -6,33 +6,56 @@ import javax.persistence.*; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; +import java.util.LinkedHashSet; +import java.util.Set; @Getter -@Setter @Entity @Builder -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Table(name = "users") -public class User { +public class User extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_id", nullable = false) private Long id; - @Size(max = 45) - @Column(name = "username", length = 45) - private String username; @Size(max = 45) + @Column(name = "nickname", length = 45) + private String nickname; + + @Size(max = 255) + @Column(name = "profile_image") + private String profileImage; + + @Size(max = 6) @NotNull - @Column(name = "usernumber", nullable = false, length = 45) - private String usernumber; + @Column(name = "roles", nullable = false, length = 6) + private String roles; - @Size(max = 45) + @Size(max = 30) @NotNull - @Column(name = "role", nullable = false, length = 45) - private String role; + @Column(name = "user_number", nullable = false, length = 30) + private String userNumber; + + + @Column(name = "early") + private boolean early; + + + @Size(max = 10) + @Column(name = "level", length = 10) + private String level; + + + @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) + private Set userFirebaseTokens = new LinkedHashSet<>(); + + @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) + private Set userMotivations = new LinkedHashSet<>(); + } \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/user/entity/UserFirebaseToken.java b/src/main/java/modernfarmer/server/farmususer/user/entity/UserFirebaseToken.java new file mode 100644 index 0000000..6f6968f --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/entity/UserFirebaseToken.java @@ -0,0 +1,36 @@ +package modernfarmer.server.farmususer.user.entity; + +import lombok.*; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.time.Instant; + +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Setter +@Entity +@Table(name = "user_firebase_token") +public class UserFirebaseToken extends BaseEntity{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "firebase_token_id", nullable = false) + private Long id; + + @Size(max = 100) + @NotNull + @Column(name = "token", nullable = false, length = 100) + private String token; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.REMOVE) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + +} \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/user/entity/UserMotivation.java b/src/main/java/modernfarmer/server/farmususer/user/entity/UserMotivation.java new file mode 100644 index 0000000..1a7e9c6 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/entity/UserMotivation.java @@ -0,0 +1,43 @@ +package modernfarmer.server.farmususer.user.entity; + +import lombok.*; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Setter +@Entity +@Table(name = "user_motivation") +public class UserMotivation extends BaseEntity{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_motivation_id", nullable = false) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @OnDelete(action = OnDeleteAction.CASCADE) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.REMOVE) + @JoinColumn(name = "motivation_id", nullable = false) + private Motivation motivation; + + + + + + + + + + +} \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/user/repository/MotivationRepository.java b/src/main/java/modernfarmer/server/farmususer/user/repository/MotivationRepository.java new file mode 100644 index 0000000..fcb6f50 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/repository/MotivationRepository.java @@ -0,0 +1,23 @@ +package modernfarmer.server.farmususer.user.repository; + + +import modernfarmer.server.farmususer.user.entity.Motivation; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface MotivationRepository extends JpaRepository { + + @Query("select m.id from Motivation as m where m.motivationReason = :motivationReason") + Long getMotivationId(@Param("motivationReason") String motivationReason); + + + Optional findByMotivationReason(String motivationReason); + + + +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/repository/UserFirebaseTokenRepository.java b/src/main/java/modernfarmer/server/farmususer/user/repository/UserFirebaseTokenRepository.java new file mode 100644 index 0000000..6febea8 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/repository/UserFirebaseTokenRepository.java @@ -0,0 +1,20 @@ +package modernfarmer.server.farmususer.user.repository; + + +import io.lettuce.core.dynamic.annotation.Param; +import modernfarmer.server.farmususer.user.entity.User; +import modernfarmer.server.farmususer.user.entity.UserFirebaseToken; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + + +@Repository +public interface UserFirebaseTokenRepository extends JpaRepository { + + + @Modifying + @Query("delete from UserFirebaseToken as uf where uf.user = :user and uf.token = :firebaseToken ") + void deleteFirebaseToken(@Param("user") User user, @Param("firebaseToken") String firebaseToken); +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/repository/UserMotivationRepository.java b/src/main/java/modernfarmer/server/farmususer/user/repository/UserMotivationRepository.java new file mode 100644 index 0000000..410998e --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/repository/UserMotivationRepository.java @@ -0,0 +1,11 @@ +package modernfarmer.server.farmususer.user.repository; + +import modernfarmer.server.farmususer.user.entity.User; +import modernfarmer.server.farmususer.user.entity.UserMotivation; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + + +@Repository +public interface UserMotivationRepository extends JpaRepository { +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/repository/UserRepository.java b/src/main/java/modernfarmer/server/farmususer/user/repository/UserRepository.java index 1082964..122251f 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/repository/UserRepository.java +++ b/src/main/java/modernfarmer/server/farmususer/user/repository/UserRepository.java @@ -2,20 +2,67 @@ import io.lettuce.core.dynamic.annotation.Param; import modernfarmer.server.farmususer.user.entity.User; +import org.jetbrains.annotations.NotNull; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.util.List; import java.util.Optional; @Repository public interface UserRepository extends JpaRepository { + Optional findByUserNumber(String usernumber); + @Query("SELECT a.roles FROM User AS a WHERE a.id = :userId") + String findUserRole(@Param("userId") Long userId); + + + @Modifying + @Query("delete from User as u where u.id = :userId") + void deleteUser(@Param("userId") Long userId); + + @Query("select u.profileImage from User as u where u.id = :userId") + String selectUserProfileImage(@Param("userId") Long userId); + + @Modifying + @Query("update User as u set u.nickname = :nickName where u.id = :userId") + void updateUserNickname(@Param("nickName") String nickName, @Param("userId") Long userId); + + @Modifying + @Query("update User as u set u.early = 0 where u.id = :userId") + void updateEarly( @Param("userId") Long userId); + + @Modifying + @Query("update User as u set u.profileImage = null where u.id = :userId") + void updateUserProfileDefault( @Param("userId") Long userId); + + +// @Modifying +// @Query("update User as u set u.profileImage = :profileImage where u.id = :userId") +// void emitUserProfileImage(@Param("userId") Long userId, @Param("profileImage") String profileImage); + + + @Modifying + @Query("update User as u set u.profileImage = :profileImage, u.nickname = :nickName where u.id = :userId") + void selectUserProfileAndNickname(@Param("userId") Long userId, @Param("profileImage") String profileImage, @Param("nickName") String nickName); + + + + @Modifying + @Query("update User as u set u.level= :level where u.id = :userId") + void insertUserLevel(@Param("userId") Long userId, @Param("level") String level); + + List findAllBy(); + + @NotNull + Optional findById(@NotNull Long userId); + + + - Optional findByUsernumber(String usernumber); - @Query("SELECT a.role FROM User AS a WHERE a.id = :userId") - User findUserRole(@Param("userId") Long userId); diff --git a/src/main/java/modernfarmer/server/farmususer/user/service/AuthService.java b/src/main/java/modernfarmer/server/farmususer/user/service/AuthService.java index 0033326..edebd64 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/service/AuthService.java +++ b/src/main/java/modernfarmer/server/farmususer/user/service/AuthService.java @@ -1,168 +1,148 @@ package modernfarmer.server.farmususer.user.service; + +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import modernfarmer.server.farmususer.global.exception.fail.ErrorMessage; +import modernfarmer.server.farmususer.global.exception.success.SuccessMessage; +import modernfarmer.server.farmususer.user.dto.response.BaseResponseDto; +import modernfarmer.server.farmususer.user.dto.response.GoogleUserResponseDto; import modernfarmer.server.farmususer.user.dto.response.KakaoUserResponseDto; -import modernfarmer.server.farmususer.user.dto.response.ResponseDto; import modernfarmer.server.farmususer.user.dto.response.TokenResponseDto; import modernfarmer.server.farmususer.user.entity.User; import modernfarmer.server.farmususer.user.repository.UserRepository; import modernfarmer.server.farmususer.user.util.JwtTokenProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; +import modernfarmer.server.farmususer.user.util.SocialLogin; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import java.util.Optional; + +@RequiredArgsConstructor @Slf4j @Service public class AuthService{ - public JwtTokenProvider jwtTokenProvider; - public RedisTemplate redisTemplate; + private final JwtTokenProvider jwtTokenProvider; - public UserRepository userRepository; + private final RedisTemplate redisTemplate; - private final WebClient webClient; - - @Autowired - public AuthService(WebClient webClient, UserRepository userRepository, JwtTokenProvider jwtTokenProvider, RedisTemplate redisTemplate) { - this.webClient = webClient; - this.userRepository = userRepository; - this.jwtTokenProvider = jwtTokenProvider; - this.redisTemplate = redisTemplate; - } + private final UserRepository userRepository; + private final SocialLogin socialLogin; - public TokenResponseDto kakaoLogin(String accessToken) { + public BaseResponseDto googleLogin(String accessToken) { User user; + boolean early; - Mono userInfoMono = getUserInfo(accessToken); - KakaoUserResponseDto userInfo = userInfoMono.block(); + Mono userInfoMono = socialLogin.getUserInfo(accessToken, "https://www.googleapis.com/oauth2/v2/userinfo", GoogleUserResponseDto.class); + GoogleUserResponseDto userInfo = userInfoMono.block(); + + if(userInfo == null){ -// LOGGER.info(String.valueOf(userInfo.getAccount_email())); -// LOGGER.info(String.valueOf(userInfo.getProfile_nickname())); -// LOGGER.info(String.valueOf(userInfo.getProfile_image())); + return BaseResponseDto.of(ErrorMessage.FAIL_GET_INFORMATION); -// LOGGER.info(String.valueOf(userInfo.getKakao_account().getEmail())); -// LOGGER.info(String.valueOf(userInfo.getKakao_account().getProfile().getProfileImageUrl())); -// LOGGER.info(String.valueOf(userInfo.getKakao_account().getProfile().getNickname())); + } - Optional userData = userRepository.findByUsernumber(String.valueOf(userInfo.getId())); + Optional userData = userRepository.findByUserNumber(String.valueOf(userInfo.getId())); if(userData.isEmpty()){ user = User.builder() - .usernumber(String.valueOf(userInfo.getId())) - .role("USER") -// .email(userInfo.getKakao_account().getEmail()) -// .nickname(userInfo.getKakao_account().getProfile().getNickname()) -// .userProfile(userInfo.getKakao_account().getProfile().getProfileImageUrl()) + .userNumber(String.valueOf(userInfo.getId())) + .roles("USER") + .early(true) .build(); userRepository.save(user); } - Optional userLoginData = userRepository.findByUsernumber(String.valueOf(userInfo.getId())); + Optional userLoginData = userRepository.findByUserNumber(String.valueOf(userInfo.getId())); + + if(userLoginData.isEmpty()){ + return BaseResponseDto.of(ErrorMessage.FAIL_GET_INFORMATION); - String refreshToken = "Bearer " +jwtTokenProvider.createRereshToken(userLoginData.get().getId()); + } - TokenResponseDto tokenResponseDto = TokenResponseDto.builder() - .message("OK") - .code(200) - .accessToken("Bearer " +jwtTokenProvider.createAccessToken( - userLoginData.get().getId(), - String.valueOf(userLoginData.get().getRole()))) - .refreshToken(refreshToken) - .build(); + String refreshToken = jwtTokenProvider.createRefreshToken(userLoginData.get().getId()); -// redisTemplate.opsForHash().put(jwtTokenProvider.createRereshToken(),"userId", String.valueOf(userLoginData.get().getId())); -// redisTemplate.opsForHash().put(jwtTokenProvider.createRereshToken(),"role", String.valueOf(userLoginData.get().getRole())); + early = userLoginData.get().isEarly(); redisTemplate.opsForValue().set(String.valueOf(userLoginData.get().getId()),refreshToken); - - return tokenResponseDto; + log.info("구글 로그인 완료"); + + return BaseResponseDto.of( + SuccessMessage.SUCCESS, + TokenResponseDto.of( + jwtTokenProvider.createAccessToken( + userLoginData.get().getId(), + String.valueOf(userLoginData.get().getRoles())), + refreshToken, + early + ) + ); } + public BaseResponseDto kakaoLogin(String accessToken) { - public ResponseDto logout(Long userId) { - deleteValueByKey(String.valueOf(userId)); - - ResponseDto responseDto = ResponseDto.builder() - .message("OK") - .code(200) - .build(); - return responseDto; - } - - public TokenResponseDto reissueToken(String refreshToken, Long userId) { - TokenResponseDto reissueTokenResponse; + User user; + boolean early; + Mono userInfoMono = socialLogin.getUserInfo(accessToken, "https://kapi.kakao.com/v2/user/me", KakaoUserResponseDto.class); + KakaoUserResponseDto userInfo = userInfoMono.block(); - if(!jwtTokenProvider.validateRefreshToken(refreshToken)){ + if(userInfo == null){ - reissueTokenResponse = TokenResponseDto.builder() - .code(417) - .message("재로그인하시오") - .build(); + return BaseResponseDto.of(ErrorMessage.FAIL_GET_INFORMATION); - return reissueTokenResponse; } - String redisRefreshToken = redisTemplate.opsForValue().get(userId); + Optional userData = userRepository.findByUserNumber(String.valueOf(userInfo.getId())); - if(redisRefreshToken.equals(refreshToken)){ - String userRole = String.valueOf(userRepository.findUserRole(userId)); - - reissueTokenResponse= TokenResponseDto - .builder() - .code(200) - .message("OK") - .accessToken(jwtTokenProvider.createAccessToken(Long.valueOf(userId),userRole)) - .refreshToken(refreshToken) + if(userData.isEmpty()){ + user = User.builder() + .userNumber(String.valueOf(userInfo.getId())) + .roles("USER") + .early(true) .build(); - return reissueTokenResponse; - + userRepository.save(user); } - reissueTokenResponse = TokenResponseDto.builder() - .code(403) - .message("접근이 올바르지 않습니다.") - .build(); - - return reissueTokenResponse; - - } + Optional userLoginData = userRepository.findByUserNumber(String.valueOf(userInfo.getId())); + if(userLoginData.isEmpty()){ + return BaseResponseDto.of(ErrorMessage.FAIL_GET_INFORMATION); + } - public void deleteValueByKey(String key) { - redisTemplate.delete(key); - } - - - + early = userLoginData.get().isEarly(); + String refreshToken = jwtTokenProvider.createRefreshToken(userLoginData.get().getId()); + redisTemplate.opsForValue().set(String.valueOf(userLoginData.get().getId()),refreshToken); - public Mono getUserInfo(String accessToken) { - return webClient - .get() - .uri("https://kapi.kakao.com/v2/user/me") // 카카오 사용자 정보 엔드포인트 - .headers(headers -> headers.setBearerAuth(accessToken)) - .retrieve() - .bodyToMono(KakaoUserResponseDto.class); + log.info("카카오 로그인 완료"); + + return BaseResponseDto.of( + SuccessMessage.SUCCESS, + TokenResponseDto.of( + jwtTokenProvider.createAccessToken( + userLoginData.get().getId(), + String.valueOf(userLoginData.get().getRoles())), + refreshToken, + early + ) + ); } + } \ No newline at end of file diff --git a/src/main/java/modernfarmer/server/farmususer/user/service/FirebaseService.java b/src/main/java/modernfarmer/server/farmususer/user/service/FirebaseService.java new file mode 100644 index 0000000..60531b5 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/service/FirebaseService.java @@ -0,0 +1,50 @@ +package modernfarmer.server.farmususer.user.service; + + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import modernfarmer.server.farmususer.global.exception.success.SuccessMessage; +import modernfarmer.server.farmususer.user.dto.response.BaseResponseDto; +import modernfarmer.server.farmususer.user.entity.User; +import modernfarmer.server.farmususer.user.entity.UserFirebaseToken; +import modernfarmer.server.farmususer.user.repository.UserFirebaseTokenRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Transactional +@Slf4j +@Service +public class FirebaseService { + + private final UserFirebaseTokenRepository userFirebaseTokenRepository; + + + public BaseResponseDto insertFirebaseToken(Long userId, String firebaseToken) { + + + UserFirebaseToken userFirebaseToken = UserFirebaseToken.builder() + .user(User.builder().id(userId).build()) + .token(firebaseToken) + .build(); + + userFirebaseTokenRepository.save(userFirebaseToken); + log.info("파이어 베이스 토큰 삽입 완료"); + return BaseResponseDto.of(SuccessMessage.SUCCESS, null); + } + + public BaseResponseDto deleteFirebaseToken(Long userId, String firebaseToken) { + + + userFirebaseTokenRepository.deleteFirebaseToken( + User.builder() + .id(userId) + .build(), + firebaseToken + ); + + log.info("파이어 베이스 토큰 삭제 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS, null); + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/service/OnBoardingService.java b/src/main/java/modernfarmer/server/farmususer/user/service/OnBoardingService.java new file mode 100644 index 0000000..12a9ae6 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/service/OnBoardingService.java @@ -0,0 +1,78 @@ +package modernfarmer.server.farmususer.user.service; + + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import modernfarmer.server.farmususer.global.exception.fail.ErrorMessage; +import modernfarmer.server.farmususer.global.exception.success.SuccessMessage; +import modernfarmer.server.farmususer.user.dto.request.OnBoardingLevelRequest; +import modernfarmer.server.farmususer.user.dto.request.OnBoardingMotivationRequest; +import modernfarmer.server.farmususer.user.dto.response.BaseResponseDto; +import modernfarmer.server.farmususer.user.dto.response.OnBoardingLevelResponse; +import modernfarmer.server.farmususer.user.entity.Motivation; +import modernfarmer.server.farmususer.user.entity.User; +import modernfarmer.server.farmususer.user.entity.UserMotivation; +import modernfarmer.server.farmususer.user.repository.MotivationRepository; +import modernfarmer.server.farmususer.user.repository.UserMotivationRepository; +import modernfarmer.server.farmususer.user.repository.UserRepository; +import modernfarmer.server.farmususer.user.util.LevelCheck; +import org.springframework.stereotype.Service; + + +import javax.transaction.Transactional; +import java.util.Optional; + + +@RequiredArgsConstructor +@Transactional +@Slf4j +@Service +public class OnBoardingService { + + private final UserRepository userRepository; + + private final UserMotivationRepository userMotivationRepository; + + private final MotivationRepository motivationRepository; + + private final LevelCheck levelCheck; + + public BaseResponseDto onBoardingMotivation(Long userId, OnBoardingMotivationRequest onBoardingMotivationRequest){ + + User user = User.builder().id(userId).build(); + + for(String motivations : onBoardingMotivationRequest.getMotivation()){ + + Optional motivation = motivationRepository.findByMotivationReason(motivations); + + if(motivation.isEmpty()){ + return BaseResponseDto.of(ErrorMessage.NO_MOTIVATION_DATA); + } + + UserMotivation userMotivation = UserMotivation + .builder() + .user(user) + .motivation(motivation.get()) + .build(); + + userMotivationRepository.save(userMotivation); + } + + log.info("동기 데이터 삽입 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS,null); + + } + + public BaseResponseDto onBoardingLevel(Long userId, OnBoardingLevelRequest onBoardingLevelRequest){ + + String level = levelCheck.recommendAlgorithms(onBoardingLevelRequest.getTime(), onBoardingLevelRequest.getSkill()); + + userRepository.insertUserLevel(userId, level); + + log.info("난이도 데이터 삽입 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS, OnBoardingLevelResponse.of(level)); + + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/service/UserService.java b/src/main/java/modernfarmer/server/farmususer/user/service/UserService.java new file mode 100644 index 0000000..cf63aad --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/service/UserService.java @@ -0,0 +1,251 @@ +package modernfarmer.server.farmususer.user.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import modernfarmer.server.farmususer.community.CommunityServiceFeignClient; +import modernfarmer.server.farmususer.farm.FarmServiceFeignClient; +import modernfarmer.server.farmususer.global.config.s3.S3Uploader; +import modernfarmer.server.farmususer.global.enums.Motivations; +import modernfarmer.server.farmususer.global.exception.fail.ErrorMessage; +import modernfarmer.server.farmususer.global.exception.success.SuccessMessage; +import modernfarmer.server.farmususer.user.dto.response.*; +import modernfarmer.server.farmususer.user.entity.User; +import modernfarmer.server.farmususer.user.entity.UserMotivation; +import modernfarmer.server.farmususer.user.repository.UserRepository; +import modernfarmer.server.farmususer.user.util.JwtTokenProvider; +import modernfarmer.server.farmususer.user.util.TimeCalculator; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + + +@RequiredArgsConstructor +@Transactional +@Slf4j +@Service +public class UserService { + + private final JwtTokenProvider jwtTokenProvider; + private final RedisTemplate redisTemplate; + private final UserRepository userRepository; + private final S3Uploader s3Uploader; + private final TimeCalculator timeCalculator; + private final CommunityServiceFeignClient communityServiceFeignClient; + private final FarmServiceFeignClient farmServiceFeignClient; + + +// public BaseResponseDto emitProfileImage(Long userId, MultipartFile multipartFile) throws IOException { +// +// String imageUrl = s3Uploader.uploadFiles(multipartFile, "userprofileimage"); +// log.info(imageUrl); +// +// userRepository.emitUserProfileImage(userId, imageUrl); +// +// return BaseResponseDto.of(SuccessMessage.SUCCESS,null); +// } + + public BaseResponseDto getUser(Long userId){ + + Optional user = userRepository.findById(userId); + + if(user.isEmpty()){ + return BaseResponseDto.of(ErrorMessage.NO_USER_DATA); + } + + long dDay = timeCalculator.calFromToday(user.get().getCreatedAt()); + + log.info("특정 유저 정보 가져오기 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS, GetUserResponseDto.of(user.get().getNickname(),user.get().getProfileImage(),dDay)); + } + + + + public BaseResponseDto emitNickname(Long userId, String nickName){ + + userRepository.updateUserNickname(nickName, userId); + + log.info("닉네임 수정 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS,null); + } + + public BaseResponseDto selectProfileImageAndNickname(Long userId, MultipartFile multipartFile, + String nickName) throws IOException { + + if(multipartFile.isEmpty()){ + + userRepository.updateUserNickname(nickName,userId); + + }else{ + String imageUrl = s3Uploader.uploadFiles(multipartFile, "userprofileimage"); + log.info(imageUrl); + userRepository.selectUserProfileAndNickname(userId,imageUrl,nickName); + + } + + log.info("유저 프로필 정보 수정 완료"); + return BaseResponseDto.of(SuccessMessage.SUCCESS,null); + + } + + + + public BaseResponseDto selectProfileImage(Long userId){ + + String userProfileImage = userRepository.selectUserProfileImage(userId); + + log.info("유저 프로필 이미지 조회 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS, ProfileImageResponseDto.of(userProfileImage)); + } + + public BaseResponseDto signUpComlete(Long userId){ + + userRepository.updateEarly(userId); + + log.info("유저 최종 회원가입 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS, null); + } + + + public BaseResponseDto deleteUser(Long userId){ + + userRepository.deleteUser(userId); + communityServiceFeignClient.deleteAllPosting(userId); + farmServiceFeignClient.deleteAllVeggies(userId); + + log.info("유저 계정 삭제 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS,null); + } + + + + public BaseResponseDto allUser() { + + List userList = userRepository.findAllBy(); + List userResponseList = userList.stream() + .map(user -> AllUserDto.of(user.getId(), user.getNickname(), user.getProfileImage())) + .collect(Collectors.toList()); + + log.info("모든 유저 데이터 조회 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS, AllUserResponseDto.of(userResponseList)); + + } + + public BaseResponseDto deleteUserProfile(Long userId) { + + userRepository.updateUserProfileDefault(userId); + + log.info("유저 프로필 삭제 완료"); + return BaseResponseDto.of(SuccessMessage.SUCCESS, null); + + } + + public BaseResponseDto specificUser(Long userId) { + + + Optional user = userRepository.findById(userId); + + if(user.isEmpty()){ + return BaseResponseDto.of(ErrorMessage.NO_USER_DATA); + } + + log.info("특정 유저 정보 조회 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS, + SpecificUserResponseDto.of(user.get().getId(), + user.get().getNickname(), + user.get().getProfileImage())); + + } + + + public BaseResponseDto logout(Long userId) { + + deleteValueByKey(String.valueOf(userId)); + + log.info("로그아웃 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS,null); + } + + public BaseResponseDto reissueToken(String refreshToken, Long userId) { + + String redisRefreshToken = redisTemplate.opsForValue().get(userId.toString()); + + if(refreshToken.equals(redisRefreshToken)){ + + String userRole = userRepository.findUserRole(userId); + + log.info("토큰 재발급 완료"); + + return BaseResponseDto.of(SuccessMessage.SUCCESS, + RefreshTokenResponseDto.of( + jwtTokenProvider.createAccessToken(userId, userRole), + refreshToken + )); + + } + return BaseResponseDto.of(ErrorMessage.REFRESH_NOTIFICATION_ERROR); + + } + + public String getUserLevel(Long userId) { + + User user = userRepository.findById(userId).orElseThrow(() -> new IllegalArgumentException("해당 유저가 없습니다. id=" + userId)); + return user.getLevel(); + } + + public GetUserLevelAndNicknameResponseDto getUserLevelAndNickname(Long userId) { + + User user = userRepository.findById(userId).orElseThrow(() -> new IllegalArgumentException("해당 유저가 없습니다. id=" + userId)); + return GetUserLevelAndNicknameResponseDto.of(user.getLevel(), user.getNickname(), getUserMotivation(userId).getMotivation()); + } + + public UserMotivationResponseDto getUserMotivation(Long userId) { + + User user = userRepository.findById(userId).orElseThrow(() -> new IllegalArgumentException("해당 유저가 없습니다. id=" + userId)); + + List result = new ArrayList<>(); + result.add(1L); + result.add(2L); + result.add(3L); + + log.info(result.toString()); + + List motivationResult = new ArrayList<>(); + + for (Long l : result) { + if (l == 1) { + Arrays.stream(Motivations.Motive_1.values()).forEach(m -> motivationResult.add(m.getMotive())); + } else if (l == 2) { + Arrays.stream(Motivations.Motive_2.values()).forEach(m -> motivationResult.add(m.getMotive())); + } else { + Arrays.stream(Motivations.Motive_3.values()).forEach(m -> motivationResult.add(m.getMotive())); + } + } + + log.info(motivationResult.toString()); + + // motivationResult에서 랜덤으로 하나를 뽑아서 리턴 + return UserMotivationResponseDto.of(motivationResult.get((int) (Math.random() * motivationResult.size()))); + } + + + + + + public void deleteValueByKey(String key) { + redisTemplate.delete(key); + } + +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/util/CustomerUser.java b/src/main/java/modernfarmer/server/farmususer/user/util/CustomerUser.java deleted file mode 100644 index 06665f0..0000000 --- a/src/main/java/modernfarmer/server/farmususer/user/util/CustomerUser.java +++ /dev/null @@ -1,4 +0,0 @@ -package modernfarmer.server.farmususer.user.util; - -public class CustomerUser { -} diff --git a/src/main/java/modernfarmer/server/farmususer/user/util/JwtTokenProvider.java b/src/main/java/modernfarmer/server/farmususer/user/util/JwtTokenProvider.java index b768403..b7f1c7e 100644 --- a/src/main/java/modernfarmer/server/farmususer/user/util/JwtTokenProvider.java +++ b/src/main/java/modernfarmer/server/farmususer/user/util/JwtTokenProvider.java @@ -5,6 +5,7 @@ import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; +import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -16,26 +17,27 @@ import java.util.Base64; import java.util.Date; + +@Slf4j @Component public class JwtTokenProvider { - private final Logger LOGGER = LoggerFactory.getLogger(JwtTokenProvider.class); @Value("${jwt.secret}") private String secretKey; - private final long accessTokenTime = 30L * 24L * 60 * 60 * 1000; // 1달 토큰 유효 + private final long accessTokenTime = 365L * 24 * 60 * 60 * 1000; // 1달 토큰 유효 - private final long refreshTokenTime = 1L * 60 * 1000 * 2; // 1달 토큰 유효 + private final long refreshTokenTime = 30L * 1000 * 2 * 1000; // 1달 토큰 유효 @PostConstruct protected void init() { - LOGGER.info("[init] JwtTokenProvider 내 secretKey 초기화 시작", StandardCharsets.UTF_8); + log.info("[init] JwtTokenProvider 내 secretKey 초기화 시작"); secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes(StandardCharsets.UTF_8)); - LOGGER.info("[init] JwtTokenProvider 내 secretKey 초기화 완료"); + log.info("[init] JwtTokenProvider 내 secretKey 초기화 완료"); } public String createAccessToken(Long userId, String roles) { // 토큰 생성 @@ -48,31 +50,31 @@ public String createAccessToken(Long userId, String roles) { // 토 .setClaims(claims) .setIssuedAt(now) .setExpiration(new Date(now.getTime() + accessTokenTime)) - .signWith(SignatureAlgorithm.HS256, secretKey) // 암호화 알고리즘, secret 값 세팅 + .signWith(SignatureAlgorithm.HS256, secretKey) .compact(); - LOGGER.info("[createToken] 토큰 생성 완료"); + log.info("[createToken] 토큰 생성 완료"); return token; } - public String createRereshToken(Long userId) { // 토큰 생성 + public String createRefreshToken(Long userId) { // 토큰 생성 Claims claims = Jwts.claims().setSubject(String.valueOf(userId)); Date now = new Date(); String token = Jwts.builder() + .setClaims(claims) .setIssuedAt(now) .setExpiration(new Date(now.getTime() + refreshTokenTime)) .signWith(SignatureAlgorithm.HS256, secretKey) // 암호화 알고리즘, secret 값 세팅 .compact(); - LOGGER.info("[createToken] 토큰 생성 완료"); + log.info("[createToken] 토큰 생성 완료"); return token; } public String resolveToken(HttpServletRequest request) { - LOGGER.info("[resolveToken] HTTP 헤더에서 Token 값 추출"); - String tokenHeader = request.getHeader("Authentication"); + String tokenHeader = request.getHeader("Authorization"); if (tokenHeader != null && tokenHeader.startsWith("Bearer ")) { return tokenHeader.substring(7); @@ -82,34 +84,18 @@ public String resolveToken(HttpServletRequest request) { } } - public String getUserRole(HttpServletRequest request) { - LOGGER.info("[resolveToken] HTTP 헤더에서 Token 값 추출"); - - String tokenRole = request.getHeader("role"); + public String getFirebaseToken(HttpServletRequest request) { - return tokenRole; + return request.getHeader("FirebaseToken"); } public String getUserId(HttpServletRequest request) { - LOGGER.info("[resolveToken] HTTP 헤더에서 Token 값 추출"); - String tokenUser = request.getHeader("user"); - - return tokenUser; + return request.getHeader("user"); } - public boolean validateRefreshToken(String token) { // 토큰 유효성 확인 - LOGGER.info("[validateRefreshToken] 토큰 유효 체크 시작"); - Jws claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); - - if (!claims.getBody().isEmpty()) { - LOGGER.info("[validateRefreshToken] 토큰 유효 체크 완료"); - return true; - } - return false; - } } diff --git a/src/main/java/modernfarmer/server/farmususer/user/util/LevelCheck.java b/src/main/java/modernfarmer/server/farmususer/user/util/LevelCheck.java new file mode 100644 index 0000000..44008f5 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/util/LevelCheck.java @@ -0,0 +1,47 @@ +package modernfarmer.server.farmususer.user.util; + + +import org.springframework.stereotype.Component; + +@Component +public class LevelCheck { + + public String recommendAlgorithms(int time,String skill) { + boolean isIntermediate = false; + boolean isMaster = false; + boolean isElementary = false; + boolean isBeginner = false; + + + if ("홈파밍 중급".equals(skill)) { + isIntermediate = true; + } else if ("홈파밍 고수".equals(skill)) { + isMaster = true; + } else if ("홈파밍 초보".equals(skill)) { + isElementary = true; + } else if ("홈파밍 입문".equals(skill)) { + isBeginner = true; + } + + + if (time == 2 && (isIntermediate || isMaster)) { + return "HARD"; + } else if (time == 2 && (isBeginner || isElementary)) { + return "NORMAL"; + } else if (time == 1 && isMaster) { + return "HARD"; + } else if (time == 1 && (isIntermediate || isElementary)) { + return "NORMAL"; + } else if (time == 1 && isBeginner) { + return "EASY"; + } else if (time == 0 && isMaster) { + return "HARD"; + } else if (time == 0 && isIntermediate) { + return "NORMAL"; + } else if (time == 0 && (isElementary || isBeginner)) { + return "EASY"; + } + + return "알 수 없음"; + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/util/SocialLogin.java b/src/main/java/modernfarmer/server/farmususer/user/util/SocialLogin.java new file mode 100644 index 0000000..d9199ed --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/util/SocialLogin.java @@ -0,0 +1,22 @@ +package modernfarmer.server.farmususer.user.util; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +@RequiredArgsConstructor +@Component +public class SocialLogin { + + private final WebClient webClient; + + public Mono getUserInfo(String accessToken, String apiUrl, Class responseType) { + return webClient + .get() + .uri(apiUrl) + .headers(headers -> headers.setBearerAuth(accessToken)) + .retrieve() + .bodyToMono(responseType); + } +} diff --git a/src/main/java/modernfarmer/server/farmususer/user/util/TimeCalculator.java b/src/main/java/modernfarmer/server/farmususer/user/util/TimeCalculator.java new file mode 100644 index 0000000..f0bf2f4 --- /dev/null +++ b/src/main/java/modernfarmer/server/farmususer/user/util/TimeCalculator.java @@ -0,0 +1,29 @@ +package modernfarmer.server.farmususer.user.util; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; + + +@Component +public class TimeCalculator { + + public long calFromToday(LocalDateTime date){ + + LocalDateTime currentDateTime = LocalDateTime.now(); + + // 날짜 차이 계산 + long daysDifference = ChronoUnit.DAYS.between(date.toLocalDate(), currentDateTime.toLocalDate()); + + + return daysDifference; + + } + + +}