Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/main/java/rootbox/rootboxApp/api/user/business/UserMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import rootbox.rootboxApp.api.user.presentation.dto.JoinDto;
import rootbox.rootboxApp.global.entity.User;

import java.util.Optional;
Expand All @@ -22,4 +23,16 @@ public void init(){
public static Optional<User> toUserSecurity(String id){
return staticUserService.findById(id);
}

public static JoinDto.JoinResponseDto toJoinResponseDto(User user){

return JoinDto.JoinResponseDto.builder()
.alarmAgree(user.getGetAlarmYn() == 1)
.birthDay(user.getBirthday())
.gender(user.getSex().name())
.nickName(user.getNickname())
.locationAgree(user.getLocationServiceYn() == 1)
.build();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.transaction.annotation.Transactional;
import rootbox.rootboxApp.api.user.implementation.UserCommandAdapter;
import rootbox.rootboxApp.api.user.implementation.UserQueryAdapter;
import rootbox.rootboxApp.api.user.presentation.dto.JoinDto;
import rootbox.rootboxApp.api.user.presentation.dto.SocialLoginDto;
import rootbox.rootboxApp.global.entity.RefreshToken;
import rootbox.rootboxApp.global.entity.User;
Expand Down Expand Up @@ -62,6 +63,7 @@ public SocialLoginDto.KakaoSocialLoginResponseDto socialLogin(SocialLoginDto.Kak
.isNew(false)
.loginType(SocialType.KAKAO.name())
.refreshToken(refreshTokenByUserId.get().getRefreshToken())
.userSocialId(userBySocialId.get().getSocialLoginUid())
.build();
}else{
// 리프레시 토큰 없음 만약 만료된 리프레시 토큰이면 추후에 만료 로직 탈 것이라 존재 유무만 봄
Expand All @@ -71,6 +73,7 @@ public SocialLoginDto.KakaoSocialLoginResponseDto socialLogin(SocialLoginDto.Kak
.loginType(SocialType.KAKAO.name())
.refreshToken(userCommandAdapter.saveRefreshToken(tokenProvider.createRefreshToken(),
userBySocialId.get().getSocialLoginUid()).getRefreshToken())
.userSocialId(userBySocialId.get().getSocialLoginUid())
.build();
}
}else {
Expand All @@ -85,6 +88,7 @@ public SocialLoginDto.KakaoSocialLoginResponseDto socialLogin(SocialLoginDto.Kak
.accessToken(accessToken)
.refreshToken(userCommandAdapter.saveRefreshToken(tokenProvider.createRefreshToken(),
user.getSocialLoginUid()).getRefreshToken())
.userSocialId(user.getSocialLoginUid())
.build();
}
}
Expand All @@ -97,6 +101,17 @@ public String getKakaoToken(String code){
return kakaoOauthService.getKakaoAccessToken(code);
}

public Boolean checkNickname(String nickname) {
return userQueryAdapter.findUserByNickname(nickname).isPresent();
}

@Transactional
public JoinDto.JoinResponseDto join(JoinDto.JoinRequestDto request, User user) {
User joinedUser = userCommandAdapter.joinUser(request, user);

return UserMapper.toJoinResponseDto(joinedUser);
}

private String generateUniqueNickname() {
String name = "";
do {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.extern.slf4j.Slf4j;
import rootbox.rootboxApp.api.user.persistence.RefreshTokenRepository;
import rootbox.rootboxApp.api.user.persistence.UserRepository;
import rootbox.rootboxApp.api.user.presentation.dto.JoinDto;
import rootbox.rootboxApp.global.annotations.Adapter;
import rootbox.rootboxApp.global.entity.RefreshToken;
import rootbox.rootboxApp.global.entity.User;
Expand All @@ -18,7 +19,7 @@ public class UserCommandAdapter {

private final RefreshTokenRepository refreshTokenRepository;

public User createUser(String username, String socialUid){
public User createUser(String socialUid, String username){

User newUser = User.builder()
.socialLoginUid(socialUid)
Expand All @@ -38,4 +39,8 @@ public RefreshToken saveRefreshToken(String refreshToken, String userSocialId){
.build()
);
}

public User joinUser(JoinDto.JoinRequestDto requestDto, User user){
return user.joinUser(requestDto);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package rootbox.rootboxApp.api.user.presentation;

import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
Expand All @@ -8,8 +9,11 @@
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import rootbox.rootboxApp.api.user.business.UserService;
import rootbox.rootboxApp.api.user.presentation.dto.JoinDto;
import rootbox.rootboxApp.api.user.presentation.dto.SocialLoginDto;
import rootbox.rootboxApp.global.common.CommonResponse;
import rootbox.rootboxApp.global.entity.User;
import rootbox.rootboxApp.global.security.handler.annotation.AuthMember;

import java.io.IOException;

Expand Down Expand Up @@ -39,4 +43,20 @@ public void kakaoSocailLoginTest(HttpServletResponse response) throws IOExceptio
public CommonResponse<String> getKakaoToken(@RequestParam("code") String code){
return CommonResponse.onSuccess(userService.getKakaoToken(code));
}

@GetMapping("/auth/nickname")
public CommonResponse<JoinDto.JoinNickNameCheckResponseDto> checkNickName(@RequestParam(name = "nickname") String nickname) {
return CommonResponse.onSuccess(
JoinDto.JoinNickNameCheckResponseDto.builder().useYn(!userService.checkNickname(nickname)).build());
}

@PatchMapping("/")
public CommonResponse<JoinDto.JoinResponseDto> joinUser(@RequestBody @Valid JoinDto.JoinRequestDto requestDto, @AuthMember @Parameter(hidden = true) User user) {
return CommonResponse.onSuccess(userService.join(requestDto, user));
}

@GetMapping("/")
public String testToken(@AuthMember @Parameter(hidden = true) User user) {
return "인증! 현 로그인 사용자 닉네임 : " + user.getNickname();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package rootbox.rootboxApp.api.user.presentation.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;

import java.time.LocalDate;

public class JoinDto {

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class JoinNickNameCheckResponseDto{

private Boolean useYn;
}

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class JoinRequestDto{

@NotNull(message = "위치 기반 동의는 필수 입력 값입니다.")
Boolean locationAgree;

@NotNull(message = "알람 동의는 필수 입력 값입니다.")
Boolean alarmAgree;

@NotNull(message = "닉네임은 필수 입력 값입니다.")
@Size(min=2, max=8, message = "닉네임은 2 ~ 8글자 입니다.")
String nickName;

@NotNull(message = "생일은 필수 입력 값입니다.")
@JsonFormat(pattern = "yyyy-MM-dd") // JSON으로 받을 때 형식 지정
private LocalDate birthDay;

@NotNull(message = "성별은 필수 입력 값입니다.")
private String gender;

}


@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class JoinResponseDto{

@NotNull(message = "위치 기반 동의는 필수 입력 값입니다.")
Boolean locationAgree;

@NotNull(message = "알람 동의는 필수 입력 값입니다.")
Boolean alarmAgree;

@NotNull(message = "닉네임은 필수 입력 값입니다.")
@Size(min=2, max=8, message = "닉네임은 2 ~ 8글자 입니다.")
String nickName;

@NotNull(message = "생일은 필수 입력 값입니다.")
@JsonFormat(pattern = "yyyy-MM-dd") // JSON으로 받을 때 형식 지정
private LocalDate birthDay;

@NotNull(message = "성별은 필수 입력 값입니다.")
private String gender;


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public static class KakaoSocialLoginResponseDto {

@NotNull
String refreshToken;
@NotNull
String userSocialId;
}

@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public enum GlobalErrorCode implements BaseErrorCode{
INVALID_TOKEN(UNAUTHORIZED, "AUTH401_2", "인증 토큰이 유효하지 않습니다."),
INVALID_REFRESH_TOKEN(UNAUTHORIZED, "AUTH401_3", "리프레시 토큰이 유효하지 않습니다."),
REFRESH_TOKEN_EXPIRED(UNAUTHORIZED, "AUTH401_4", "리프레시 토큰이 만료 되었습니다."),
AUTHENTICATION_REQUIRED(UNAUTHORIZED, "AUTH401_5", "인증 정보가 유효하지 않습니다."),
AUTHENTICATION_REQUIRED(UNAUTHORIZED, "AUTH401_5", "인증 정보가 유효하지 않습니다. access Token을 담으셨는지, bearer를 붙이셨는지 확인 바랍니다."),
LOGIN_REQUIRED(UNAUTHORIZED, "AUTH401_6", "로그인이 필요한 서비스입니다."),

// AUTH + 403 Forbidden - 인증 거부
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package rootbox.rootboxApp.global.config;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import rootbox.rootboxApp.global.security.handler.annotation.resolver.AuthMemberArgumentResolver;

import java.util.List;

@Configuration
@RequiredArgsConstructor
public class GlobalWebConfig implements WebMvcConfigurer {

private final AuthMemberArgumentResolver authMemberArgumentResolver;

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

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI SpringCodeBaseAPI() {
Info info = new Info()
.title("RouteBox API")
.description("RouteBox API 명세서")
.version("1.0.0");

final String ACCESS_SCHEME_NAME = "Access Token";
final String REFRESH_SCHEME_NAME = "Refresh Token";

Components components = new Components()
.addSecuritySchemes(ACCESS_SCHEME_NAME,
new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.name("Authorization")
.in(SecurityScheme.In.HEADER))
.addSecuritySchemes(REFRESH_SCHEME_NAME,
new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.name("Refresh") // 예: 헤더 키를 다르게 설정할 수 있음
.in(SecurityScheme.In.HEADER));

return new OpenAPI()
.info(info)
.components(components)
.addServersItem(new Server().url("/"))
// 여기 두 개 모두 SecurityRequirement에 등록
.addSecurityItem(new SecurityRequirement().addList(ACCESS_SCHEME_NAME))
.addSecurityItem(new SecurityRequirement().addList(REFRESH_SCHEME_NAME));
}
}
18 changes: 18 additions & 0 deletions src/main/java/rootbox/rootboxApp/global/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lombok.NoArgsConstructor;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import rootbox.rootboxApp.api.user.presentation.dto.JoinDto;
import rootbox.rootboxApp.global.entity.common.BaseEntity;
import rootbox.rootboxApp.global.entity.enums.user.SocialType;
import rootbox.rootboxApp.global.entity.enums.user.UserRole;
Expand Down Expand Up @@ -65,4 +66,21 @@ public class User extends BaseEntity {

@OneToMany(mappedBy = "user")
private List<Inquery> inqueryList = new ArrayList<>();

public User joinUser(JoinDto.JoinRequestDto joinRequestDto){
this.nickname = joinRequestDto.getNickName();
this.birthday = joinRequestDto.getBirthDay();
this.locationServiceYn = joinRequestDto.getLocationAgree() ? 1 : 0;
this.getAlarmYn = joinRequestDto.getAlarmAgree() ? 1 : 0;
if (joinRequestDto.getGender().equals("male")){
this.sex = UserSexType.MALE;
}
else if (joinRequestDto.getGender().equals("female")){
this.sex = UserSexType.FEMALE;
}
else
this.sex = UserSexType.SECRET;

return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public class SecurityConfig {
private final JwtAuthenticationExceptionHandler jwtAuthenticationExceptionHandler =
new JwtAuthenticationExceptionHandler();

private static final String[] JWT_WHITE_LIST ={
"/users/login-tmp","/users/reissue"
private static final String[] whiteList = {
"/users/auth/nickname", "/users/auth/kakao/test", "/users/auth/kakao/code", "/users/auth/kakao", "/users/auth/health"
};

/**
Expand Down Expand Up @@ -80,7 +80,7 @@ public SecurityFilterChain JwtFilterChain(HttpSecurity http) throws Exception {
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(jwtAccessDeniedHandler))
.addFilterBefore(
new JwtAuthFilter(tokenProvider, JWT_WHITE_LIST),
new JwtAuthFilter(tokenProvider, whiteList),
UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(jwtAuthenticationExceptionHandler, JwtAuthFilter.class)
.build();
Expand Down
Loading