diff --git a/user-service/build.gradle b/user-service/build.gradle index b71a6b07..76cda7f2 100644 --- a/user-service/build.gradle +++ b/user-service/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'org.springframework.boot' version '3.2.3' id 'io.spring.dependency-management' version '1.1.4' + id "org.springdoc.openapi-gradle-plugin" version '1.8.0' } group = 'com.waither' @@ -76,8 +77,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' // Swagger - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.4' - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:2.0.4' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:2.1.0' } @@ -88,6 +89,17 @@ dependencyManagement { } } +openApi { + apiDocsUrl.set("http://localhost:3000") // Document URL + outputDir.set(file("$rootDir/docs")) // Build Result Path + outputFileName.set("user.json") // Build Result File Name + groupedApiMappings.set(Map.of("http://localhost:8080/user/api-docs", "user.json")) + waitTimeInSeconds.set(60) // Timeout + customBootRun { + args.add("--spring.profiles.active=dev") + } +} + tasks.named('test') { useJUnitPlatform() } diff --git a/user-service/docs/user.json b/user-service/docs/user.json new file mode 100644 index 00000000..d34cbbf2 --- /dev/null +++ b/user-service/docs/user.json @@ -0,0 +1,1160 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost:8080", + "description": "Generated server url" + } + ], + "paths": { + "/survey/submit": { + "post": { + "tags": [ + "survey-controller" + ], + "operationId": "createSurvey", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SurveyRequestDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/signup": { + "post": { + "tags": [ + "user-controller" + ], + "summary": "Sign Up", + "description": "회원가입", + "operationId": "register", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignUpRequestDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/password-check": { + "post": { + "tags": [ + "user-controller" + ], + "operationId": "passwordCheckEmail", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PasswordCheckDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/emails/verifications": { + "post": { + "tags": [ + "user-controller" + ], + "operationId": "verificationEmail", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EmailVerificationDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/update-password": { + "patch": { + "tags": [ + "user-controller" + ], + "operationId": "updatePassword", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdatePasswordDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/update-nickname": { + "patch": { + "tags": [ + "user-controller" + ], + "operationId": "updateNickname", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NicknameDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/user-weight": { + "get": { + "tags": [ + "setting-controller" + ], + "operationId": "getWeight", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseWeightDto" + } + } + } + } + } + }, + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateWeight", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WeightDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/region": { + "get": { + "tags": [ + "setting-controller" + ], + "operationId": "getRegion", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseRegionNameDto" + } + } + } + } + } + }, + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateRegion", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegionDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/region-report": { + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateRegionReport", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegionReportDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/noti/wind": { + "get": { + "tags": [ + "setting-controller" + ], + "operationId": "getWind", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseWindDto" + } + } + } + } + } + }, + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateWind", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WindDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/noti/user-alert": { + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateUserAlert", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserAlertDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/noti/snow-alert": { + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateSnowAlert", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SnowAlertDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/noti/out-alert": { + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateOutAlert", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OutAlertDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/noti/out-alert-set": { + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateOutAlertSet", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OutAlertSetDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/noti/climate-alert": { + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateClimateAlert", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ClimateAlertDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/display": { + "get": { + "tags": [ + "setting-controller" + ], + "operationId": "getDisplay", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseDisplayDto" + } + } + } + } + } + }, + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateDisplay", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DisplayDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/custom": { + "get": { + "tags": [ + "setting-controller" + ], + "operationId": "getUserCustom", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseCustomDto" + } + } + } + } + } + }, + "patch": { + "tags": [ + "setting-controller" + ], + "operationId": "updateCustom", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/setting/noti": { + "get": { + "tags": [ + "setting-controller" + ], + "operationId": "getNotification", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseNotificationDto" + } + } + } + } + } + } + }, + "/setting/mypage": { + "get": { + "tags": [ + "setting-controller" + ], + "operationId": "getUserInfo", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseUserInfoDto" + } + } + } + } + } + } + }, + "/reissue": { + "get": { + "tags": [ + "user-controller" + ], + "operationId": "reissueToken", + "parameters": [ + { + "name": "RefreshToken", + "in": "header", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseJwtDto" + } + } + } + } + } + } + }, + "/emails/temporary-password": { + "get": { + "tags": [ + "user-controller" + ], + "operationId": "submitTemporaryPassword", + "parameters": [ + { + "name": "email", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/emails/submit-authcode": { + "get": { + "tags": [ + "user-controller" + ], + "operationId": "submitAuthCode", + "parameters": [ + { + "name": "email", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + }, + "/delete": { + "delete": { + "tags": [ + "user-controller" + ], + "operationId": "deleteUser", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ApiResponseString" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "SurveyRequestDto": { + "type": "object", + "properties": { + "ans": { + "type": "integer", + "format": "int32" + }, + "time": { + "type": "string", + "format": "date-time" + } + } + }, + "ApiResponseString": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "result": { + "type": "string" + } + } + }, + "SignUpRequestDto": { + "required": [ + "email", + "password" + ], + "type": "object", + "properties": { + "email": { + "pattern": "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,6}$", + "type": "string" + }, + "password": { + "maxLength": 2147483647, + "minLength": 8, + "pattern": "^(?\u003d.*[a-z])(?\u003d.*\\d)(?\u003d.*[!@#$%^\u0026*]).{8,64}$", + "type": "string" + } + } + }, + "PasswordCheckDto": { + "type": "object", + "properties": { + "password": { + "type": "string" + } + } + }, + "EmailVerificationDto": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "authCode": { + "type": "string" + } + } + }, + "UpdatePasswordDto": { + "required": [ + "password" + ], + "type": "object", + "properties": { + "password": { + "maxLength": 2147483647, + "minLength": 8, + "pattern": "^(?\u003d.*[a-z])(?\u003d.*\\d)(?\u003d.*[!@#$%^\u0026*]).{8,64}$", + "type": "string" + } + } + }, + "NicknameDto": { + "type": "object", + "properties": { + "nickname": { + "type": "string" + } + } + }, + "WeightDto": { + "type": "object", + "properties": { + "weight": { + "type": "number", + "format": "double" + } + } + }, + "RegionDto": { + "type": "object", + "properties": { + "regionName": { + "type": "string" + }, + "longitude": { + "type": "number", + "format": "double" + }, + "latitude": { + "type": "number", + "format": "double" + } + } + }, + "RegionReportDto": { + "type": "object", + "properties": { + "regionReport": { + "type": "boolean" + } + } + }, + "WindDto": { + "type": "object", + "properties": { + "windAlert": { + "type": "boolean" + }, + "windDegree": { + "type": "integer", + "format": "int32" + } + } + }, + "UserAlertDto": { + "type": "object", + "properties": { + "userAlert": { + "type": "boolean" + } + } + }, + "SnowAlertDto": { + "type": "object", + "properties": { + "snowAlert": { + "type": "boolean" + } + } + }, + "OutAlertDto": { + "type": "object", + "properties": { + "outAlert": { + "type": "boolean" + } + } + }, + "LocalTime": { + "type": "object", + "properties": { + "hour": { + "type": "integer", + "format": "int32" + }, + "minute": { + "type": "integer", + "format": "int32" + }, + "second": { + "type": "integer", + "format": "int32" + }, + "nano": { + "type": "integer", + "format": "int32" + } + } + }, + "OutAlertSetDto": { + "type": "object", + "properties": { + "days": { + "type": "array", + "items": { + "type": "string" + } + }, + "outTime": { + "$ref": "#/components/schemas/LocalTime" + } + } + }, + "ClimateAlertDto": { + "type": "object", + "properties": { + "climateAlert": { + "type": "boolean" + } + } + }, + "DisplayDto": { + "type": "object", + "properties": { + "precipitation": { + "type": "boolean" + }, + "wind": { + "type": "boolean" + }, + "dust": { + "type": "boolean" + } + } + }, + "CustomDto": { + "type": "object", + "properties": { + "custom": { + "type": "boolean" + } + } + }, + "ApiResponseWeightDto": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/WeightDto" + } + } + }, + "ApiResponseRegionNameDto": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/RegionNameDto" + } + } + }, + "RegionNameDto": { + "type": "object", + "properties": { + "regionName": { + "type": "string" + } + } + }, + "ApiResponseNotificationDto": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/NotificationDto" + } + } + }, + "NotificationDto": { + "type": "object", + "properties": { + "outAlert": { + "type": "boolean" + }, + "days": { + "type": "array", + "items": { + "type": "string" + } + }, + "outTime": { + "$ref": "#/components/schemas/LocalTime" + }, + "climateAlert": { + "type": "boolean" + }, + "userAlert": { + "type": "boolean" + }, + "snowAlert": { + "type": "boolean" + } + } + }, + "ApiResponseWindDto": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/WindDto" + } + } + }, + "ApiResponseUserInfoDto": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/UserInfoDto" + } + } + }, + "UserInfoDto": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "nickname": { + "type": "string" + } + } + }, + "ApiResponseDisplayDto": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/DisplayDto" + } + } + }, + "ApiResponseCustomDto": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/CustomDto" + } + } + }, + "ApiResponseJwtDto": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/JwtDto" + } + } + }, + "JwtDto": { + "type": "object", + "properties": { + "accessToken": { + "type": "string" + }, + "refreshToken": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/user-service/src/main/java/com/waither/userservice/controller/SettingController.java b/user-service/src/main/java/com/waither/userservice/controller/SettingController.java index 411c7ca9..92440c9a 100644 --- a/user-service/src/main/java/com/waither/userservice/controller/SettingController.java +++ b/user-service/src/main/java/com/waither/userservice/controller/SettingController.java @@ -20,6 +20,51 @@ public class SettingController { private final SettingService settingService; private final SettingQueryService settingQueryService; + /* --------- ReadOnly (GET) <화면 별로 Response 구성> --------- */ + // 사용자 맞춤 서비스 제공 조히 + @GetMapping("/custom") + public ApiResponse getUserCustom(@AuthUser User user) { + return ApiResponse.onSuccess(settingQueryService.getUserCustom(user)); + } + + // 직장 지역 설정 조회 + @GetMapping("/region") + public ApiResponse getRegion(@AuthUser User user) { + return ApiResponse.onSuccess(settingQueryService.getRegion(user)); + } + + // 알림 설정 조회 + @GetMapping("/noti") + public ApiResponse getNotification(@AuthUser User user) { + return ApiResponse.onSuccess(settingQueryService.getNotification(user)); + } + + // 바람 세기 설정 조회 + @GetMapping("/noti/wind") + public ApiResponse getWind(@AuthUser User user) { + return ApiResponse.onSuccess(settingQueryService.getWind(user)); + } + + // 메인 화면 날씨 상세 정보 조회 + @GetMapping("/display") + public ApiResponse getDisplay(@AuthUser User user) { + return ApiResponse.onSuccess(settingQueryService.getDisplay(user)); + } + + // 사용자 가중치 설정 조회 + @GetMapping("/user-weight") + public ApiResponse getWeight(@AuthUser User user) { + return ApiResponse.onSuccess(settingQueryService.getWeight(user)); + } + + // 마이페이지 조회 + @GetMapping("/mypage") + public ApiResponse getUserInfo(@AuthUser User user) { + return ApiResponse.onSuccess(settingQueryService.getUserInfo(user)); + } + + /* --------- Update (Patch) --------- */ + // 사용자 맞춤 서비스 제공 @PatchMapping("/custom") public ApiResponse updateCustom(@AuthUser User user, @RequestBody SettingReqDto.CustomDto customDto) { @@ -98,40 +143,11 @@ public ApiResponse updateRegionReport(@AuthUser User user, @RequestBody return ApiResponse.onSuccess("직장 지역 레포트 알림 설정이 " + regionReportDto.regionReport() + "로 바뀌었습니다."); } - // ReadOnly (GET) - @GetMapping("/custom") - public ApiResponse getUserCustom(@AuthUser User user) { - return ApiResponse.onSuccess(settingQueryService.getUserCustom(user)); - } - - @GetMapping("/region") - public ApiResponse getRegion(@AuthUser User user) { - return ApiResponse.onSuccess(settingQueryService.getRegion(user)); - } - - @GetMapping("/noti") - public ApiResponse getNotification(@AuthUser User user) { - return ApiResponse.onSuccess(settingQueryService.getNotification(user)); - } - - @GetMapping("/noti/wind") - public ApiResponse getWind(@AuthUser User user) { - return ApiResponse.onSuccess(settingQueryService.getWind(user)); - } - - @GetMapping("/display") - public ApiResponse getDisplay(@AuthUser User user) { - return ApiResponse.onSuccess(settingQueryService.getDisplay(user)); - } - - @GetMapping("/user-weight") - public ApiResponse getWeight(@AuthUser User user) { - return ApiResponse.onSuccess(settingQueryService.getWeight(user)); - } - - @GetMapping("/mypage") - public ApiResponse getUserInfo(@AuthUser User user) { - return ApiResponse.onSuccess(settingQueryService.getUserInfo(user)); + // 사용자 가중치 설정 + @PatchMapping("/user-weight") + public ApiResponse updateWeight(@AuthUser User user, @RequestBody SettingReqDto.WeightDto weightDto) { + settingService.updateWeight(user, weightDto); + return ApiResponse.onSuccess("사용자 가중치가 " + weightDto.weight() + "로 바뀌었습니다."); } } diff --git a/user-service/src/main/java/com/waither/userservice/controller/AccountsController.java b/user-service/src/main/java/com/waither/userservice/controller/UserController.java similarity index 67% rename from user-service/src/main/java/com/waither/userservice/controller/AccountsController.java rename to user-service/src/main/java/com/waither/userservice/controller/UserController.java index 023e0395..cca7fa1b 100644 --- a/user-service/src/main/java/com/waither/userservice/controller/AccountsController.java +++ b/user-service/src/main/java/com/waither/userservice/controller/UserController.java @@ -1,11 +1,12 @@ package com.waither.userservice.controller; -import com.waither.userservice.dto.request.AccountReqDto; +import com.waither.userservice.dto.request.UserReqDto; import com.waither.userservice.entity.User; import com.waither.userservice.global.annotation.AuthUser; import com.waither.userservice.jwt.dto.JwtDto; -import com.waither.userservice.service.AccountsService; +import com.waither.userservice.service.UserService; import com.waither.userservice.global.response.ApiResponse; +import io.swagger.v3.oas.annotations.Operation; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -17,14 +18,15 @@ @RequiredArgsConstructor @RestController @RequestMapping(value = "/") -public class AccountsController { +public class UserController { - private final AccountsService accountsService; + private final UserService userService; // 회원가입 + @Operation(summary = "Sign Up", description = "회원가입") @PostMapping("/signup") - public ResponseEntity> register(@Valid @RequestBody AccountReqDto.RegisterRequestDto requestDto) { - accountsService.signup(requestDto); + public ResponseEntity> register(@Valid @RequestBody UserReqDto.SignUpRequestDto requestDto) { + userService.signup(requestDto); // SignUp 때만 201 Created 사용 return ResponseEntity .status(HttpStatus.CREATED) @@ -36,55 +38,54 @@ public ResponseEntity> register(@Valid @RequestBody AccountR // Jwt 토큰 재발급 @GetMapping("/reissue") public ApiResponse reissueToken(@RequestHeader("RefreshToken") String refreshToken) { - JwtDto jwtDto = accountsService.reissueToken(refreshToken); + JwtDto jwtDto = userService.reissueToken(refreshToken); return ApiResponse.onSuccess(jwtDto); - } // 이메일에 인증번호 보내기 @GetMapping("/emails/submit-authcode") public ApiResponse submitAuthCode(@RequestBody String email) { - accountsService.sendAuthCodeToEmail(email); + userService.sendAuthCodeToEmail(email); return ApiResponse.onSuccess("인증번호 전송에 성공했습니다."); } // 이메일 인증하기 @PostMapping("/emails/verifications") - public ApiResponse verificationEmail(@RequestBody AccountReqDto.EmailVerificationDto verificationDto) { - accountsService.verifyCode(verificationDto.email(), verificationDto.authCode()); + public ApiResponse verificationEmail(@RequestBody UserReqDto.EmailVerificationDto verificationDto) { + userService.verifyCode(verificationDto.email(), verificationDto.authCode()); return ApiResponse.onSuccess("이메일 인증에 성공했습니다."); } // 임시 비밀번호 발급 @GetMapping("/emails/temporary-password") public ApiResponse submitTemporaryPassword(@RequestParam String email) { - accountsService.checkUserExists(email); - String tempPassword = accountsService.sendTempPassword(email); - accountsService.changeToTempPassword(email, tempPassword); + userService.checkUserExists(email); + String tempPassword = userService.sendTempPassword(email); + userService.changeToTempPassword(email, tempPassword); return ApiResponse.onSuccess("인증번호 전송에 성공했습니다."); } // 닉네임 변경 @PatchMapping("/update-nickname") public ApiResponse updateNickname(@AuthUser User user, - @RequestBody AccountReqDto.NicknameDto nicknameDto) { - accountsService.updateNickname(user, nicknameDto.nickname()); + @RequestBody UserReqDto.NicknameDto nicknameDto) { + userService.updateNickname(user, nicknameDto.nickname()); return ApiResponse.onSuccess("닉네임이 " + nicknameDto.nickname() + "로 바뀌었습니다."); } // 비밀번호 확인 @PostMapping("/password-check") public ApiResponse passwordCheckEmail(@AuthUser User user, - @RequestBody AccountReqDto.PasswordCheckDto passwordCheckDto) { - accountsService.checkPassword(user, passwordCheckDto.password()); + @RequestBody UserReqDto.PasswordCheckDto passwordCheckDto) { + userService.checkPassword(user, passwordCheckDto.password()); return ApiResponse.onSuccess("비밀번호가 확인되었습니다."); } // 비밀번호 변경 @PatchMapping("/update-password") public ApiResponse updatePassword(@AuthUser User user, - @Valid @RequestBody AccountReqDto.UpdatePasswordDto updatePasswordDto) { - accountsService.updatePassword(user, updatePasswordDto.password()); + @Valid @RequestBody UserReqDto.UpdatePasswordDto updatePasswordDto) { + userService.updatePassword(user, updatePasswordDto.password()); return ApiResponse.onSuccess("비밀번호가 변경되었습니다."); } @@ -92,7 +93,7 @@ public ApiResponse updatePassword(@AuthUser User user, // Todo : soft delete로 변경 고려 @DeleteMapping("/delete") public ApiResponse deleteUser(@AuthUser User user) { - accountsService.deleteUser(user); + userService.deleteUser(user); return ApiResponse.onSuccess(user.getEmail() + "님의 계정이 성공적으로 탈퇴되었습니다."); } } diff --git a/user-service/src/main/java/com/waither/userservice/dto/converter/AccountConverter.java b/user-service/src/main/java/com/waither/userservice/dto/converter/UserConverter.java similarity index 71% rename from user-service/src/main/java/com/waither/userservice/dto/converter/AccountConverter.java rename to user-service/src/main/java/com/waither/userservice/dto/converter/UserConverter.java index 9cbef719..086f770f 100644 --- a/user-service/src/main/java/com/waither/userservice/dto/converter/AccountConverter.java +++ b/user-service/src/main/java/com/waither/userservice/dto/converter/UserConverter.java @@ -1,12 +1,12 @@ package com.waither.userservice.dto.converter; -import com.waither.userservice.dto.request.AccountReqDto; +import com.waither.userservice.dto.request.UserReqDto; import com.waither.userservice.entity.User; import com.waither.userservice.entity.type.UserStatus; -public class AccountConverter { +public class UserConverter { - public static User toUser(AccountReqDto.RegisterRequestDto requestDto, String encodedPw) { + public static User toUser(UserReqDto.SignUpRequestDto requestDto, String encodedPw) { return User.builder() .email(requestDto.email()) .password(encodedPw) diff --git a/user-service/src/main/java/com/waither/userservice/dto/request/SettingReqDto.java b/user-service/src/main/java/com/waither/userservice/dto/request/SettingReqDto.java index 590de9cf..04a1f1fc 100644 --- a/user-service/src/main/java/com/waither/userservice/dto/request/SettingReqDto.java +++ b/user-service/src/main/java/com/waither/userservice/dto/request/SettingReqDto.java @@ -52,4 +52,8 @@ public record RegionReportDto( boolean regionReport ) { } + public record WeightDto( + Double weight + ) { } + } diff --git a/user-service/src/main/java/com/waither/userservice/dto/request/AccountReqDto.java b/user-service/src/main/java/com/waither/userservice/dto/request/UserReqDto.java similarity index 93% rename from user-service/src/main/java/com/waither/userservice/dto/request/AccountReqDto.java rename to user-service/src/main/java/com/waither/userservice/dto/request/UserReqDto.java index 6c44a428..6e0bfe64 100644 --- a/user-service/src/main/java/com/waither/userservice/dto/request/AccountReqDto.java +++ b/user-service/src/main/java/com/waither/userservice/dto/request/UserReqDto.java @@ -1,12 +1,10 @@ package com.waither.userservice.dto.request; -import com.waither.userservice.entity.User; -import com.waither.userservice.entity.type.UserStatus; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; -public class AccountReqDto { +public class UserReqDto { public record LoginRequestDto( @NotBlank(message = "[ERROR] 이메일 입력은 필수입니다.") @Pattern(regexp = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,6}$", message = "[ERROR] 이메일 형식에 맞지 않습니다.") @@ -19,7 +17,7 @@ public record LoginRequestDto( ) { } // 로그인과 같은 형식이지만, 확장성(회원가입 할 떄 추가 정보를 받을 수도 있음)을 위해 나누어 놓았습니다. - public record RegisterRequestDto( + public record SignUpRequestDto( @NotBlank(message = "[ERROR] 이메일 입력은 필수입니다.") @Pattern(regexp = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,6}$", message = "[ERROR] 이메일 형식에 맞지 않습니다.") String email, diff --git a/user-service/src/main/java/com/waither/userservice/dto/response/AccountResDto.java b/user-service/src/main/java/com/waither/userservice/dto/response/UserResDto.java similarity index 63% rename from user-service/src/main/java/com/waither/userservice/dto/response/AccountResDto.java rename to user-service/src/main/java/com/waither/userservice/dto/response/UserResDto.java index 774f4d9f..e957011f 100644 --- a/user-service/src/main/java/com/waither/userservice/dto/response/AccountResDto.java +++ b/user-service/src/main/java/com/waither/userservice/dto/response/UserResDto.java @@ -1,5 +1,5 @@ package com.waither.userservice.dto.response; -public class AccountResDto { +public class UserResDto { } diff --git a/user-service/src/main/java/com/waither/userservice/jwt/filter/JwtAuthenticationFilter.java b/user-service/src/main/java/com/waither/userservice/jwt/filter/JwtAuthenticationFilter.java index b5455169..5527a2e9 100644 --- a/user-service/src/main/java/com/waither/userservice/jwt/filter/JwtAuthenticationFilter.java +++ b/user-service/src/main/java/com/waither/userservice/jwt/filter/JwtAuthenticationFilter.java @@ -1,7 +1,7 @@ package com.waither.userservice.jwt.filter; import com.fasterxml.jackson.databind.ObjectMapper; -import com.waither.userservice.dto.request.AccountReqDto; +import com.waither.userservice.dto.request.UserReqDto; import com.waither.userservice.global.response.ApiResponse; import com.waither.userservice.jwt.dto.JwtDto; import com.waither.userservice.jwt.util.HttpResponseUtil; @@ -36,9 +36,9 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ // request에 있는 username과 password를 파싱해서 자바 Object로 받기 ObjectMapper om = new ObjectMapper(); - AccountReqDto.LoginRequestDto loginRequestDto; + UserReqDto.LoginRequestDto loginRequestDto; try { - loginRequestDto = om.readValue(request.getInputStream(), AccountReqDto.LoginRequestDto.class); + loginRequestDto = om.readValue(request.getInputStream(), UserReqDto.LoginRequestDto.class); } catch (IOException e) { throw new AuthenticationServiceException("Error of request body."); } diff --git a/user-service/src/main/java/com/waither/userservice/service/SettingService.java b/user-service/src/main/java/com/waither/userservice/service/SettingService.java index 5bc3a758..eb025e4f 100644 --- a/user-service/src/main/java/com/waither/userservice/service/SettingService.java +++ b/user-service/src/main/java/com/waither/userservice/service/SettingService.java @@ -117,4 +117,10 @@ private void updateDays(Setting setting, List days) { settingRepository.save(setting); } + public void updateWeight(User user, SettingReqDto.WeightDto weightDto) { + Setting setting = user.getSetting(); + setting.setWeight(weightDto.weight()); + settingRepository.save(setting); + } + } diff --git a/user-service/src/main/java/com/waither/userservice/service/AccountsService.java b/user-service/src/main/java/com/waither/userservice/service/UserService.java similarity index 96% rename from user-service/src/main/java/com/waither/userservice/service/AccountsService.java rename to user-service/src/main/java/com/waither/userservice/service/UserService.java index ff385b33..9a019fe1 100644 --- a/user-service/src/main/java/com/waither/userservice/service/AccountsService.java +++ b/user-service/src/main/java/com/waither/userservice/service/UserService.java @@ -1,7 +1,7 @@ package com.waither.userservice.service; -import com.waither.userservice.dto.converter.AccountConverter; -import com.waither.userservice.dto.request.AccountReqDto; +import com.waither.userservice.dto.converter.UserConverter; +import com.waither.userservice.dto.request.UserReqDto; import com.waither.userservice.entity.Region; import com.waither.userservice.entity.Setting; import com.waither.userservice.entity.User; @@ -30,7 +30,7 @@ @RequiredArgsConstructor @Transactional @Service -public class AccountsService { +public class UserService { private final UserRepository userRepository; private final SettingRepository settingRepository; @@ -46,13 +46,13 @@ public class AccountsService { private long authCodeExpirationMillis; // 회원가입 - public void signup(AccountReqDto.RegisterRequestDto requestDto) { + public void signup(UserReqDto.SignUpRequestDto requestDto) { // if (!verifiedAccounts(requestDto.email())) { // throw new CustomException(ErrorCode.INVALID_Account); // } // 비밀번호 인코딩 String encodedPw = passwordEncoder.encode(requestDto.password()); - User newUser = AccountConverter.toUser(requestDto, encodedPw); + User newUser = UserConverter.toUser(requestDto, encodedPw); // Setting을 기본값으로 설정 Setting defaultSetting = Setting.builder() diff --git a/user-service/src/main/resources/bootstrap.yml b/user-service/src/main/resources/bootstrap.yml index 2a00e97f..5a46d2f0 100644 --- a/user-service/src/main/resources/bootstrap.yml +++ b/user-service/src/main/resources/bootstrap.yml @@ -9,7 +9,7 @@ spring: cloud: config: uri: http://localhost:8888 - name: database-user,redis, jwt, smtp + name: database-user,redis, jwt, smtp, apiDocs-user kafka: bootstrap-servers: "localhost:9092" consumer: