diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/config/WebConfig.java b/src/main/java/com/wakeUpTogetUp/togetUp/config/WebConfig.java index 557037ba..43bd7915 100644 --- a/src/main/java/com/wakeUpTogetUp/togetUp/config/WebConfig.java +++ b/src/main/java/com/wakeUpTogetUp/togetUp/config/WebConfig.java @@ -1,13 +1,21 @@ package com.wakeUpTogetUp.togetUp.config; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.wakeUpTogetUp.togetUp.config.interceptor.AuthenticationInterceptor; +import com.wakeUpTogetUp.togetUp.utils.JwtService; +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @EnableWebMvc +@RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { + private final JwtService jwtService; + private final ObjectMapper objectMapper; @Override public void addCorsMappings(CorsRegistry registry) { @@ -23,4 +31,17 @@ public void addCorsMappings(CorsRegistry registry) { // 해당 옵션 사용시 allowedOrigins를 * (전체)로 설정할 수 없다. .allowCredentials(true); } + + @Override + public void addInterceptors(InterceptorRegistry reg){ + reg.addInterceptor(new AuthenticationInterceptor(jwtService,objectMapper)) + .order(1) + .addPathPatterns("/app/users") + .excludePathPatterns("/app/group"); + // .addPathPatterns("/**"); //interceptor 작업이 필요한 path를 모두 추가한다. + + //.excludePathPatterns("app/accounts","/app/accounts/auth","app/videos/**"); + // 인가작업에서 제외할 API 경로를 따로 추가할수도 있으나, 일일히 따로 추가하기 어려우므로 어노테이션을 따로 만들어 해결한다. + } + } \ No newline at end of file diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/config/annotation/NoAuth.java b/src/main/java/com/wakeUpTogetUp/togetUp/config/annotation/NoAuth.java new file mode 100644 index 00000000..bb61d720 --- /dev/null +++ b/src/main/java/com/wakeUpTogetUp/togetUp/config/annotation/NoAuth.java @@ -0,0 +1,11 @@ +package com.wakeUpTogetUp.togetUp.config.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) //어노테이션 레벨을 결정짓는다. +@Target({ElementType.TYPE, ElementType.METHOD})//선언된 어노테이션이 적용될수 있는 위치를 결정. TYPE-class,interface,enum에 적용. +public @interface NoAuth { +} \ No newline at end of file diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/config/interceptor/AuthenticationInterceptor.java b/src/main/java/com/wakeUpTogetUp/togetUp/config/interceptor/AuthenticationInterceptor.java new file mode 100644 index 00000000..8ec2a979 --- /dev/null +++ b/src/main/java/com/wakeUpTogetUp/togetUp/config/interceptor/AuthenticationInterceptor.java @@ -0,0 +1,52 @@ +package com.wakeUpTogetUp.togetUp.config.interceptor; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.wakeUpTogetUp.togetUp.common.exception.BaseException; +import com.wakeUpTogetUp.togetUp.config.annotation.NoAuth; +import com.wakeUpTogetUp.togetUp.utils.JwtService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; +import java.util.Map; + +@RequiredArgsConstructor +public class AuthenticationInterceptor implements HandlerInterceptor { + private final JwtService jwtService; + private final ObjectMapper objectMapper; //자바 객체를 json으로 serialization + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + boolean check=checkAnnotation(handler, NoAuth.class); + + if(check) return true; + + try{ + int userNumByJwt = jwtService.getUserNum(); + + request.setAttribute("userId",userNumByJwt); + }catch(BaseException exception){ + String requestURI= request.getRequestURI(); + + Map map=new HashMap<>(); + map.put("requestURI","/app/accounts/auth?redirectURI="+requestURI); + //redirectURI는 로그인 절차가 끝내고 다시 시도했던 페이지로 돌아가기 위해 JSON 정보에 포함시킨다. + String json=objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(map); + response.getWriter().write(json); + + return false; + } + return true; + } + + private boolean checkAnnotation(Object handler,Class cls){ + HandlerMethod handlerMethod=(HandlerMethod) handler; + if(handlerMethod.getMethodAnnotation(cls)!=null){ //해당 어노테이션이 존재하면 true. + return true; + } + return false; + } +} diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/group/GroupController.java b/src/main/java/com/wakeUpTogetUp/togetUp/group/GroupController.java index aea206bd..7a795a81 100644 --- a/src/main/java/com/wakeUpTogetUp/togetUp/group/GroupController.java +++ b/src/main/java/com/wakeUpTogetUp/togetUp/group/GroupController.java @@ -3,6 +3,7 @@ import com.wakeUpTogetUp.togetUp.common.exception.BaseException; import com.wakeUpTogetUp.togetUp.common.dto.BaseResponse; import com.wakeUpTogetUp.togetUp.common.ResponseStatus; +import com.wakeUpTogetUp.togetUp.config.annotation.NoAuth; import com.wakeUpTogetUp.togetUp.group.dto.request.GroupReq; import com.wakeUpTogetUp.togetUp.group.dto.response.GroupRes; @@ -13,6 +14,7 @@ import javax.validation.Valid; import java.util.List; + @RestController @RequiredArgsConstructor @RequestMapping("/app/group") @@ -89,6 +91,7 @@ public BaseResponse updateGroup( * @param groupId * @return */ + @NoAuth @DeleteMapping("{groupId}") @ResponseBody public BaseResponse deleteGroup( diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/security.java b/src/main/java/com/wakeUpTogetUp/togetUp/security.java new file mode 100644 index 00000000..628a93e6 --- /dev/null +++ b/src/main/java/com/wakeUpTogetUp/togetUp/security.java @@ -0,0 +1,4 @@ +package com.wakeUpTogetUp.togetUp; + +public class security { +} diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/users/UserController.java b/src/main/java/com/wakeUpTogetUp/togetUp/users/UserController.java index 29d8f219..8339e05d 100644 --- a/src/main/java/com/wakeUpTogetUp/togetUp/users/UserController.java +++ b/src/main/java/com/wakeUpTogetUp/togetUp/users/UserController.java @@ -3,15 +3,24 @@ import com.wakeUpTogetUp.togetUp.common.exception.BaseException; import com.wakeUpTogetUp.togetUp.common.dto.BaseResponse; import com.wakeUpTogetUp.togetUp.common.ResponseStatus; +import com.wakeUpTogetUp.togetUp.config.annotation.NoAuth; +import com.wakeUpTogetUp.togetUp.group.dto.request.GroupReq; +import com.wakeUpTogetUp.togetUp.group.dto.response.GroupRes; +import com.wakeUpTogetUp.togetUp.users.dto.request.LoginReq; +import com.wakeUpTogetUp.togetUp.users.dto.request.PatchUserReq; import com.wakeUpTogetUp.togetUp.users.dto.request.UserReq; +import com.wakeUpTogetUp.togetUp.users.dto.response.UserInfoRes; import com.wakeUpTogetUp.togetUp.users.dto.response.UserRes; +import com.wakeUpTogetUp.togetUp.users.dto.response.UserTokenRes; import com.wakeUpTogetUp.togetUp.users.oauth.GetSocialOAuthRes; import com.wakeUpTogetUp.togetUp.users.oauth.OAuthService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; +import javax.validation.Valid; import java.io.IOException; +import java.util.List; @RestController @@ -22,19 +31,99 @@ public class UserController { private final UserService userService; private final OAuthService oAuthService; - + /** + * 회원가입 + * @param userReq + * @return + */ + @NoAuth @ResponseBody - @PostMapping("/new") // - public BaseResponse join(@RequestBody UserReq form) { + @PostMapping() // + public BaseResponse join(@RequestBody UserReq userReq) { try { - System.out.println("로그인"+form); - UserRes userRes=userService.createUser(form); + System.out.println("안녕"); + UserRes userRes=userService.createUser(userReq); return new BaseResponse<>(ResponseStatus.SUCCESS,userRes); } catch (BaseException exception) { return new BaseResponse<>((exception.getStatus())); } } + /** + * + * @param loginReq + * @return + */ + @NoAuth + @PostMapping("/login") + public BaseResponse login(@RequestBody LoginReq loginReq) { + String token = userService.createToken(loginReq); + return new BaseResponse<>(ResponseStatus.SUCCESS,new UserTokenRes(token, "bearer")); + } + + + /** + *유저 전체 GET + * @return + */ + @NoAuth + @ResponseBody + @GetMapping("list") + public BaseResponse> getUserAll(){ + List UserResList = userService.getUserAll(); + + return new BaseResponse<>(ResponseStatus.SUCCESS, UserResList); + } + + + /** + * 유저 한명 get + * @param userId + * @return + */ + + @ResponseBody + @GetMapping("{userId}") + public BaseResponse getUser(@PathVariable Integer userId){ + System.out.println("정보"); + UserInfoRes userInfoRes = userService.getUser(userId); + return new BaseResponse<>(ResponseStatus.SUCCESS, userInfoRes); + } + + /** + * + * @param userId + * @param patchUserReq + * @return + */ + @PatchMapping("{userId}") + @ResponseBody + public BaseResponse updateUser( + @PathVariable Integer userId, + @RequestBody PatchUserReq patchUserReq + ) { + + UserInfoRes userInfoRes = userService.editUser(userId, patchUserReq); + return new BaseResponse<>(ResponseStatus.SUCCESS, userInfoRes); + } + + /** + * 유저삭제 + * @param userId + * @return + */ + @DeleteMapping("{userId}") + @ResponseBody + public BaseResponse deleteUser( + @PathVariable @Valid Integer userId + ) { + + userService.deleteUser(userId); + + return new BaseResponse(ResponseStatus.SUCCESS); + } + + /** * 유저 소셜 로그인으로 리다이렉트 해주는 url * [GET] /accounts/auth diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/users/UserRepository.java b/src/main/java/com/wakeUpTogetUp/togetUp/users/UserRepository.java index 642a5d7f..b483a2dd 100644 --- a/src/main/java/com/wakeUpTogetUp/togetUp/users/UserRepository.java +++ b/src/main/java/com/wakeUpTogetUp/togetUp/users/UserRepository.java @@ -10,7 +10,7 @@ @Repository public interface UserRepository extends JpaRepository { int countByEmail(String email); - + User findByEmail(String email); // private final EntityManager em; // public void save(User user) { // em.persist(user); diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/users/UserService.java b/src/main/java/com/wakeUpTogetUp/togetUp/users/UserService.java index c103e351..b44a2b11 100644 --- a/src/main/java/com/wakeUpTogetUp/togetUp/users/UserService.java +++ b/src/main/java/com/wakeUpTogetUp/togetUp/users/UserService.java @@ -1,11 +1,19 @@ package com.wakeUpTogetUp.togetUp.users; +import com.nimbusds.openid.connect.sdk.claims.UserInfo; import com.wakeUpTogetUp.togetUp.common.ResponseStatus; import com.wakeUpTogetUp.togetUp.common.exception.BaseException; +import com.wakeUpTogetUp.togetUp.group.dto.response.GroupRes; +import com.wakeUpTogetUp.togetUp.group.model.Group; +import com.wakeUpTogetUp.togetUp.users.dto.request.LoginReq; +import com.wakeUpTogetUp.togetUp.users.dto.request.PatchUserReq; import com.wakeUpTogetUp.togetUp.users.dto.request.UserReq; +import com.wakeUpTogetUp.togetUp.users.dto.response.UserInfoRes; import com.wakeUpTogetUp.togetUp.users.dto.response.UserRes; import com.wakeUpTogetUp.togetUp.users.model.User; import com.wakeUpTogetUp.togetUp.utils.JwtService; +import com.wakeUpTogetUp.togetUp.utils.mappers.GroupMapper; +import com.wakeUpTogetUp.togetUp.utils.mappers.UserMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -15,8 +23,9 @@ import lombok.RequiredArgsConstructor; +import java.util.ArrayList; import java.util.List; - +import java.util.Optional; @Service @@ -36,6 +45,11 @@ public class UserService { @Value("${jwt.token.expired-time-ms}") private Long expiredTimeMs; + /** + * 회원가입 + * @param userReq + * @return + */ @Transactional public UserRes createUser(UserReq userReq){ @@ -48,21 +62,83 @@ public UserRes createUser(UserReq userReq){ user.setLoginType(LoginType.valueOf(userReq.getLoginType().toUpperCase())); //액세스 토큰과 jwtToken, 이외 정보들이 담긴 자바 객체를 다시 전송한다. User savedUser = userRepository.save(user); - String jwtToken = jwtService.generateAccessToken(savedUser.getId(), secretKey, expiredTimeMs); - UserRes userRes = new UserRes(savedUser.getId(),jwtToken); + //String jwtToken = jwtService.generateAccessToken(savedUser.getId(), secretKey, expiredTimeMs); + UserRes userRes = new UserRes(savedUser.getId());//,jwtToken); return userRes; } + /** + * 토큰 만들기 + */ + public String createToken(LoginReq loginReq) { + User user = userRepository.findByEmail(loginReq.getEmail()); + // .orElseThrow(IllegalArgumentException::new); + //비밀번호 확인 등의 유효성 검사 진행 + return jwtService.generateAccessToken(user.getId(), secretKey, expiredTimeMs);//createToken(user.getName()); + } + /** + * 모든 유저 찾기 + * @return + */ + public List getUserAll() { + + //모든 유저 가져오기 + List userList= userRepository.findAll(); + + // dto 매핑 + ArrayList userResList = new ArrayList<>(); + for(User user : userList) { + userResList.add(UserMapper.INSTANCE.toUserRes(user)); + } + return userResList; + } + public UserInfoRes getUser(Integer userId) { + //유저 한명 가져오기 + Optional user= userRepository.findById(userId); + // dto 매핑 + UserInfoRes userInfoRes = UserMapper.INSTANCE.toUserInfoRes(user.get()); - //회원 전체 조회 - public List findMembers(){ - return userRepository.findAll(); + return userInfoRes; + } + + + @Transactional + public UserInfoRes editUser(Integer userId, PatchUserReq patchUserReq){ + // 유저 수정 + Optional user = Optional.ofNullable(userRepository.findById(userId) + .orElseThrow( + () -> new BaseException(ResponseStatus.INVALID_USER_ID) + )); + user.get().setUserName(patchUserReq.getUsername()); + user.get().setStatusMessage(patchUserReq.getStatusMessage()); + //저장 + User modifiedUser =userRepository.save(user.get()); + + //반환 + UserInfoRes userInfoRes = UserMapper.INSTANCE.toUserInfoRes(modifiedUser); + + return userInfoRes; } + @Transactional + public void deleteUser(Integer userId) { + //TODO deleted칼럼을 추가? + userRepository.deleteById(userId); + + + } + + + + //회원 전체 조회 +// public List findMembers(){ +// return userRepository.findAll(); +// } + diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/request/LoginReq.java b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/request/LoginReq.java new file mode 100644 index 00000000..c3821662 --- /dev/null +++ b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/request/LoginReq.java @@ -0,0 +1,15 @@ +package com.wakeUpTogetUp.togetUp.users.dto.request; + +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Setter +@Getter +@Data +@NoArgsConstructor +public class LoginReq { + private String email; + private String password; +} diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/request/PatchUserReq.java b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/request/PatchUserReq.java new file mode 100644 index 00000000..1ec60f63 --- /dev/null +++ b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/request/PatchUserReq.java @@ -0,0 +1,18 @@ +package com.wakeUpTogetUp.togetUp.users.dto.request; + +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Setter +@Getter +@Data +@NoArgsConstructor + +public class PatchUserReq { + private String username; + // private String email; + private String statusMessage; +} +//TODO 이메일하고 비밀번호 변경은 따로? diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/request/UserReq.java b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/request/UserReq.java index 5ebec726..7e62d36b 100644 --- a/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/request/UserReq.java +++ b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/request/UserReq.java @@ -9,7 +9,7 @@ @Getter @Data @NoArgsConstructor -public class UserReq { +public class UserReq {//TODO PostUserReq로 이름 바꾸어야함 // private Integer id; private String password; private String username; diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/response/UserInfoRes.java b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/response/UserInfoRes.java new file mode 100644 index 00000000..2ef6fbad --- /dev/null +++ b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/response/UserInfoRes.java @@ -0,0 +1,21 @@ +package com.wakeUpTogetUp.togetUp.users.dto.response; + + +import com.wakeUpTogetUp.togetUp.users.LoginType; +import lombok.*; + +import java.sql.Timestamp; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserInfoRes { + private Integer id; + private String userName; + private String statusMessage; + private Timestamp createdAt; + private Timestamp updatedAt; + private LoginType loginType ; +} diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/response/UserRes.java b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/response/UserRes.java index d2f0b11a..c59ff445 100644 --- a/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/response/UserRes.java +++ b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/response/UserRes.java @@ -11,6 +11,6 @@ public class UserRes { private Integer id; - private String jwt; + //private String jwt; } \ No newline at end of file diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/response/UserTokenRes.java b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/response/UserTokenRes.java new file mode 100644 index 00000000..9fffcfc1 --- /dev/null +++ b/src/main/java/com/wakeUpTogetUp/togetUp/users/dto/response/UserTokenRes.java @@ -0,0 +1,13 @@ +package com.wakeUpTogetUp.togetUp.users.dto.response; + +import lombok.*; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserTokenRes { + private String accessToken; + private String tokenType; +} diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/utils/JwtService.java b/src/main/java/com/wakeUpTogetUp/togetUp/utils/JwtService.java index b46fde86..17e0c563 100644 --- a/src/main/java/com/wakeUpTogetUp/togetUp/utils/JwtService.java +++ b/src/main/java/com/wakeUpTogetUp/togetUp/utils/JwtService.java @@ -3,6 +3,7 @@ import com.wakeUpTogetUp.togetUp.common.ResponseStatus; import com.wakeUpTogetUp.togetUp.common.exception.BaseException; import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; @@ -70,6 +71,35 @@ public Integer getUserId(String accessToken) { } // 여기까지 + /** + * + * @return int + * @throws BaseException + */ + // TODO :getUserId 와 합치기 + public int getUserNum() throws BaseException{ + //1. JWT 추출 + String accessToken = getJwt(); + if(accessToken == null || accessToken.length() == 0){ + throw new BaseException(ResponseStatus.EMPTY_JWT); + } + + // 2. JWT parsing + Claims claims; + try{ + claims = Jwts.parserBuilder() + .setSigningKey(getSigningKey(key)) + .build() + .parseClaimsJws(accessToken) + .getBody(); + } catch (Exception ignored) { + throw new BaseException(ResponseStatus.INVALID_JWT); + } + + // 3. userId 추출 + return claims.get("userId",Integer.class); + } + public static Claims extractAllClaims(String token, String key) { return Jwts.parserBuilder() .setSigningKey(getSigningKey(key)) diff --git a/src/main/java/com/wakeUpTogetUp/togetUp/utils/mappers/UserMapper.java b/src/main/java/com/wakeUpTogetUp/togetUp/utils/mappers/UserMapper.java index 0b56e622..7f1e376f 100644 --- a/src/main/java/com/wakeUpTogetUp/togetUp/utils/mappers/UserMapper.java +++ b/src/main/java/com/wakeUpTogetUp/togetUp/utils/mappers/UserMapper.java @@ -1,5 +1,6 @@ package com.wakeUpTogetUp.togetUp.utils.mappers; +import com.wakeUpTogetUp.togetUp.users.dto.response.UserInfoRes; import com.wakeUpTogetUp.togetUp.users.dto.response.UserRes; import com.wakeUpTogetUp.togetUp.users.model.User; @@ -7,9 +8,14 @@ import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; +import java.util.Optional; + @Mapper(componentModel = "spring") public interface UserMapper { UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); UserRes toUserRes(User user); + UserInfoRes toUserInfoRes(User user); + + UserRes toUserRes(Optional user); }