diff --git a/src/main/java/com/prgrms2/java/bitta/feed/controller/FeedController.java b/src/main/java/com/prgrms2/java/bitta/feed/controller/FeedController.java index b08af47..02ce963 100644 --- a/src/main/java/com/prgrms2/java/bitta/feed/controller/FeedController.java +++ b/src/main/java/com/prgrms2/java/bitta/feed/controller/FeedController.java @@ -170,6 +170,7 @@ public ResponseEntity getFeedById(@PathVariable("id") @Min(1) Long id) { ) } ) + @PostMapping(consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}) public ResponseEntity createFeed(@RequestPart(value = "feed") @Valid FeedDTO feedDto , @RequestPart(value = "files", required = false) List files) { @@ -294,7 +295,7 @@ public ResponseEntity deleteFeed(@PathVariable("id") @Min(1) Long id) { } private boolean checkPermission(Long id) { - if (AuthenticationProvider.getRoles() == Role.ADMIN) { + if (AuthenticationProvider.getRoles() == Role.ROLE_ADMIN) { return true; } diff --git a/src/main/java/com/prgrms2/java/bitta/global/config/SecurityConfig.java b/src/main/java/com/prgrms2/java/bitta/global/config/SecurityConfig.java index d7bffdf..4b6dbae 100644 --- a/src/main/java/com/prgrms2/java/bitta/global/config/SecurityConfig.java +++ b/src/main/java/com/prgrms2/java/bitta/global/config/SecurityConfig.java @@ -7,6 +7,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; @@ -27,24 +28,11 @@ public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { return httpSecurity - .httpBasic(basic -> basic.disable()) - .csrf(csrf -> csrf.disable()) + .httpBasic(AbstractHttpConfigurer::disable) + .csrf(AbstractHttpConfigurer::disable) .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth - .requestMatchers( - "api/v1/members/sign-up", - "api/v1/members/sign-in", - "api/v1/members/refresh").permitAll() - .requestMatchers( - "api/v1/members/test", - "api/v1/members/{id}", - "api/v1/feed/**", - "api/v1/apply/**", - "api/v1/job-post/**", - "api/v1/scout/**").hasRole("USER") - .requestMatchers("/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**", "/webjars/**").permitAll() - // .requestMatchers("/images/**").permitAll() / S3 연결 필요 - .anyRequest().authenticated()) + .anyRequest().permitAll()) .addFilterBefore(new TokenAuthenticationFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class) .build(); } diff --git a/src/main/java/com/prgrms2/java/bitta/member/controller/MemberController.java b/src/main/java/com/prgrms2/java/bitta/member/controller/MemberController.java index 38dc26a..30b30f2 100644 --- a/src/main/java/com/prgrms2/java/bitta/member/controller/MemberController.java +++ b/src/main/java/com/prgrms2/java/bitta/member/controller/MemberController.java @@ -110,7 +110,7 @@ public ResponseEntity read(@PathVariable("id") @Min(1) Long id) { } return ResponseEntity.ok(Map.of("message", "회원을 성공적으로 조회했습니다." - , "result", memberService.getDtoById(id))); + , "result", memberService.read(id))); } @PutMapping("/{id}") @@ -189,7 +189,7 @@ public ResponseEntity delete(@PathVariable Long id) { } private boolean checkPermission(Long id) { - if (AuthenticationProvider.getRoles() == Role.ADMIN) { + if (AuthenticationProvider.getRoles() == Role.ROLE_ADMIN) { return true; } diff --git a/src/main/java/com/prgrms2/java/bitta/member/dto/MemberRequestDto.java b/src/main/java/com/prgrms2/java/bitta/member/dto/MemberRequestDto.java index 94ca261..f1447a5 100644 --- a/src/main/java/com/prgrms2/java/bitta/member/dto/MemberRequestDto.java +++ b/src/main/java/com/prgrms2/java/bitta/member/dto/MemberRequestDto.java @@ -39,7 +39,7 @@ public static class Register { @Builder.Default @Schema(title = "회원 권한", description = "회원이 갖는 액세스 권한입니다.", example = "USER") - private Role role = Role.USER; + private Role role = Role.ROLE_USER; } @Data diff --git a/src/main/java/com/prgrms2/java/bitta/member/dto/MemberResponseDto.java b/src/main/java/com/prgrms2/java/bitta/member/dto/MemberResponseDto.java new file mode 100644 index 0000000..9cf778a --- /dev/null +++ b/src/main/java/com/prgrms2/java/bitta/member/dto/MemberResponseDto.java @@ -0,0 +1,31 @@ +package com.prgrms2.java.bitta.member.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +public class MemberResponseDto { + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + @Schema(title = "회원정보 DTO", description = "회원정보 요청에 사용하는 DTO입니다.") + public static class Information { + @Schema(title = "회원 ID (PK)", description = "조회한 회원의 기본키입니다.", example = "1") + private Long id; + + @Schema(title = "아이디", description = "조회한 회원의 아이디입니다.", example = "username") + private String username; + + @Schema(title = "닉네임", description = "조회한 회원의 별명입니다.", example = "nickname") + private String nickname; + + @Schema(title = "주소", description = "조회한 회원의 주소입니다.", example = "경기도 고양시 일산동구 중앙로 1256") + private String address; + + @Schema(title = "프로필 이미지 URL", description = "프로필 이미지의 URL 입니다.", example = "IMAGE_URL") + private String profileUrl; + } +} diff --git a/src/main/java/com/prgrms2/java/bitta/member/entity/Member.java b/src/main/java/com/prgrms2/java/bitta/member/entity/Member.java index 50deb00..49c7590 100644 --- a/src/main/java/com/prgrms2/java/bitta/member/entity/Member.java +++ b/src/main/java/com/prgrms2/java/bitta/member/entity/Member.java @@ -53,7 +53,7 @@ public class Member implements UserDetails { @Enumerated(EnumType.STRING) @Builder.Default - private Role role = Role.USER; + private Role role = Role.ROLE_USER; @Override public Collection getAuthorities() { diff --git a/src/main/java/com/prgrms2/java/bitta/member/entity/Role.java b/src/main/java/com/prgrms2/java/bitta/member/entity/Role.java index 7c03d0f..06d334e 100644 --- a/src/main/java/com/prgrms2/java/bitta/member/entity/Role.java +++ b/src/main/java/com/prgrms2/java/bitta/member/entity/Role.java @@ -2,6 +2,6 @@ public enum Role { - USER, - ADMIN + ROLE_USER, + ROLE_ADMIN } diff --git a/src/main/java/com/prgrms2/java/bitta/member/service/MemberService.java b/src/main/java/com/prgrms2/java/bitta/member/service/MemberService.java index d08e576..1a5c49b 100644 --- a/src/main/java/com/prgrms2/java/bitta/member/service/MemberService.java +++ b/src/main/java/com/prgrms2/java/bitta/member/service/MemberService.java @@ -2,18 +2,19 @@ import com.prgrms2.java.bitta.member.dto.MemberDTO; import com.prgrms2.java.bitta.member.dto.MemberRequestDto; +import com.prgrms2.java.bitta.member.dto.MemberResponseDto; import com.prgrms2.java.bitta.token.dto.TokenResponseDto; import org.springframework.web.multipart.MultipartFile; public interface MemberService { TokenResponseDto validate(MemberRequestDto.Login loginDto); + MemberResponseDto.Information read(Long id); + void insert(MemberRequestDto.Register registerDto); void insert(MemberRequestDto.Register registerDto, MultipartFile multipartFile); - MemberDTO getDtoById(Long id); - void changePassword(MemberRequestDto.ChangePassword memberDto); void update(MemberRequestDto.Modify memberDto); diff --git a/src/main/java/com/prgrms2/java/bitta/member/service/MemberServiceImpl.java b/src/main/java/com/prgrms2/java/bitta/member/service/MemberServiceImpl.java index 216eb09..b523b6e 100644 --- a/src/main/java/com/prgrms2/java/bitta/member/service/MemberServiceImpl.java +++ b/src/main/java/com/prgrms2/java/bitta/member/service/MemberServiceImpl.java @@ -1,9 +1,11 @@ package com.prgrms2.java.bitta.member.service; +import com.prgrms2.java.bitta.media.entity.Media; import com.prgrms2.java.bitta.media.exception.MediaTaskException; import com.prgrms2.java.bitta.media.service.MediaService; import com.prgrms2.java.bitta.member.dto.MemberDTO; import com.prgrms2.java.bitta.member.dto.MemberRequestDto; +import com.prgrms2.java.bitta.member.dto.MemberResponseDto; import com.prgrms2.java.bitta.member.entity.Member; import com.prgrms2.java.bitta.member.exception.MemberException; import com.prgrms2.java.bitta.member.repository.MemberRepository; @@ -79,11 +81,18 @@ public void insert(MemberRequestDto.Register registerDto, MultipartFile multipar } @Override - @Transactional(readOnly = true) - public MemberDTO getDtoById(Long id) { - return memberRepository.findById(id) - .map(this::entityToDto) + public MemberResponseDto.Information read(Long id) { + Member member = memberRepository.findById(id) .orElseThrow(MemberException.NOT_FOUND::get); + + MemberResponseDto.Information memberDto = memberMapper + .entityToDto(member); + + if (member.getMedia() != null) { + memberDto.setProfileUrl(mediaService.getMediaUrl(member.getMedia())); + } + + return memberDto; } @Override @@ -156,13 +165,15 @@ public boolean checkAuthority(Long id, String username) { } private MemberDTO entityToDto(Member member) { + Media media = member.getMedia(); + return MemberDTO.builder() .id(member.getId()) .username(member.getUsername()) .password(member.getPassword()) .nickname(member.getNickname()) .address(member.getAddress()) - .profileUrl(mediaService.getMediaUrl(member.getMedia())) + .profileUrl(media != null ? mediaService.getMediaUrl(media) : null) .build(); } diff --git a/src/main/java/com/prgrms2/java/bitta/member/util/MemberMapper.java b/src/main/java/com/prgrms2/java/bitta/member/util/MemberMapper.java index ad26e26..5bd9f75 100644 --- a/src/main/java/com/prgrms2/java/bitta/member/util/MemberMapper.java +++ b/src/main/java/com/prgrms2/java/bitta/member/util/MemberMapper.java @@ -1,6 +1,7 @@ package com.prgrms2.java.bitta.member.util; import com.prgrms2.java.bitta.member.dto.MemberRequestDto; +import com.prgrms2.java.bitta.member.dto.MemberResponseDto; import com.prgrms2.java.bitta.member.entity.Member; import org.springframework.stereotype.Component; @@ -31,4 +32,13 @@ public Member dtoToEntity(MemberRequestDto.Modify dto) { .address(dto.getAddress()) .build(); } + + public MemberResponseDto.Information entityToDto(Member member) { + return MemberResponseDto.Information.builder() + .id(member.getId()) + .username(member.getUsername()) + .nickname(member.getNickname()) + .address(member.getAddress()) + .build(); + } } diff --git a/src/main/java/com/prgrms2/java/bitta/token/controller/TokenController.java b/src/main/java/com/prgrms2/java/bitta/token/controller/TokenController.java index 6bccd93..84ab74d 100644 --- a/src/main/java/com/prgrms2/java/bitta/token/controller/TokenController.java +++ b/src/main/java/com/prgrms2/java/bitta/token/controller/TokenController.java @@ -38,9 +38,8 @@ public class TokenController { } ) @PostMapping - public ResponseEntity reissue(@RequestHeader("Authorization") String accessToken - , @RequestBody TokenRequestDto requestDto) { - TokenResponseDto tokenResponseDto = tokenProvider.reissue(accessToken, requestDto.getRefreshToken()); + public ResponseEntity reissue(@RequestBody TokenRequestDto requestDto) { + TokenResponseDto tokenResponseDto = tokenProvider.reissue(requestDto.getAccessToken(), requestDto.getRefreshToken()); return ResponseEntity.ok(Map.of("message", "토큰을 재발행했습니다." , "accessToken", tokenResponseDto.getAccessToken() diff --git a/src/main/java/com/prgrms2/java/bitta/token/dto/TokenRequestDto.java b/src/main/java/com/prgrms2/java/bitta/token/dto/TokenRequestDto.java index eb80640..e7c554d 100644 --- a/src/main/java/com/prgrms2/java/bitta/token/dto/TokenRequestDto.java +++ b/src/main/java/com/prgrms2/java/bitta/token/dto/TokenRequestDto.java @@ -12,6 +12,9 @@ @AllArgsConstructor @Schema(name = "인증 토큰 요청 DTO", description = "토큰 재발행을 요청하는데 사용하는 DTO입니다.") public class TokenRequestDto { + @Schema(name = "액세스 토큰", description = "회원 데이터를 가지는 짧은 생명주기의 토큰입니다.") + private String accessToken; + @Schema(name = "리프레시 토큰", description = "토큰 재발행에 사용하는 긴 생명주기의 토큰입니다.") private String refreshToken; } \ No newline at end of file diff --git a/src/main/java/com/prgrms2/java/bitta/token/filter/TokenAuthenticationFilter.java b/src/main/java/com/prgrms2/java/bitta/token/filter/TokenAuthenticationFilter.java index 765e024..eaea636 100644 --- a/src/main/java/com/prgrms2/java/bitta/token/filter/TokenAuthenticationFilter.java +++ b/src/main/java/com/prgrms2/java/bitta/token/filter/TokenAuthenticationFilter.java @@ -35,6 +35,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse if (tokenProvider.validate(accessToken)) { Authentication authentication = tokenProvider.getAuthentication(accessToken); SecurityContextHolder.getContext().setAuthentication(authentication); + log.info("Setting authentication for user: {}", authentication.getName()); } } catch (RuntimeException ignored) {} diff --git a/src/main/java/com/prgrms2/java/bitta/token/util/TokenProvider.java b/src/main/java/com/prgrms2/java/bitta/token/util/TokenProvider.java index 8b81116..587e477 100644 --- a/src/main/java/com/prgrms2/java/bitta/token/util/TokenProvider.java +++ b/src/main/java/com/prgrms2/java/bitta/token/util/TokenProvider.java @@ -25,8 +25,6 @@ @Component @RequiredArgsConstructor public class TokenProvider { - private final MemberProvider memberProvider; - @Value("${token.grant.type}") private String grantType; @@ -38,11 +36,11 @@ public class TokenProvider { public TokenResponseDto generate(Authentication authentication) { String username = authentication.getName(); - String authority = String.format("ROLE_%s", authentication + String authority = authentication .getAuthorities() .iterator() .next() - .getAuthority()); + .getAuthority(); long currentMilliseconds = System.currentTimeMillis(); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 01602cd..1d4952e 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,3 +11,7 @@ spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true logging.level.org.springframework.security.web=TRACE + +spring.servlet.multipart.enabled=true +spring.servlet.multipart.max-file-size=10MB +spring.servlet.multipart.max-request-size=10MB \ No newline at end of file