-
Notifications
You must be signed in to change notification settings - Fork 13
Feat/week 4 #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feat/week 4 #33
Changes from all commits
b1dbd49
1e63d38
43cb730
299dc06
ac326f8
a24b3aa
676e68d
7b94fda
7b53c52
90ce723
3df566e
7fe66e9
5f6e179
bb8aaf7
0ba9159
6bb6db2
39a61b6
e52f1a2
b759e4b
3042d2a
b6cfd3d
60a4232
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| package com.example.devSns.authorities; | ||
|
|
||
| import com.example.devSns.entities.Users; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.security.core.GrantedAuthority; | ||
| import org.springframework.security.core.userdetails.UserDetails; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collection; | ||
|
|
||
| @RequiredArgsConstructor | ||
| public class MemberDetails implements UserDetails { | ||
| private final Users user; | ||
|
|
||
| @Override | ||
| public Collection<? extends GrantedAuthority> getAuthorities() { | ||
| Collection<GrantedAuthority> authorities = new ArrayList<>(); | ||
| authorities.add(() -> user.getRole().toString()); | ||
| return authorities; | ||
| } | ||
|
|
||
| @Override | ||
| public String getUsername() { | ||
| return user.getLoginID(); | ||
| } | ||
|
|
||
| @Override | ||
| public String getPassword() { | ||
| return null; | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package com.example.devSns.authorities; | ||
|
|
||
| import com.example.devSns.entities.Users; | ||
| import com.example.devSns.repositories.UserRepository; | ||
| import org.springframework.security.core.userdetails.UserDetails; | ||
| import org.springframework.security.core.userdetails.UserDetailsService; | ||
| import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||
| import org.springframework.stereotype.Service; | ||
|
|
||
| @Service | ||
| public class MemberDetailsService implements UserDetailsService { | ||
| private UserRepository userRepository; | ||
|
|
||
| public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | ||
| Users user = userRepository.findByLoginID(username).orElseThrow(); | ||
| MemberDetails memberDetails = new MemberDetails(user); | ||
| return memberDetails; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package com.example.devSns.authorities; | ||
|
|
||
| public enum Role { | ||
| ROLE_USER, | ||
| ROLE_ADMIN | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.example.devSns.config; | ||
|
|
||
| import com.example.devSns.util.JwtFilter; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.context.annotation.Bean; | ||
| 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.crypto.bcrypt.BCryptPasswordEncoder; | ||
| import org.springframework.security.crypto.password.PasswordEncoder; | ||
| import org.springframework.security.web.SecurityFilterChain; | ||
|
|
||
| // Interceptor 추가 가능 | ||
| @Configuration | ||
| @EnableWebSecurity | ||
| @RequiredArgsConstructor | ||
| public class WebConfig { | ||
|
|
||
| private final JwtFilter jwtFilter; | ||
|
|
||
| @Bean | ||
| public PasswordEncoder passwordEncoder() { | ||
| return new BCryptPasswordEncoder(); | ||
| } | ||
|
|
||
| @Bean | ||
| SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { | ||
| http.authorizeHttpRequests(authorizeRequests -> | ||
| authorizeRequests.requestMatchers("/sns/signup", "/sns/login").permitAll() | ||
| .anyRequest().authenticated()).csrf(csrf -> csrf.disable()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 보통 세션 기반 인증과 달리 토큰 기반 인증을 사용할 때 csrf를 비활성화 합니다! 그런데 JWT를 사용할 때 csrf를 diable하는 이유가 뭘까요? |
||
| return http.build(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| package com.example.devSns.controllers; | ||
|
|
||
| import com.example.devSns.dto.PostDTO; | ||
| import com.example.devSns.dto.PostResponse; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
| import com.example.devSns.services.PostService; | ||
| import java.util.List; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/sns") | ||
| @RequiredArgsConstructor | ||
| public class PostController { | ||
| private final PostService postService; | ||
|
|
||
| @GetMapping("/show") | ||
| public ResponseEntity<List<PostResponse>> showPosts() { | ||
| List<PostResponse> posts = postService.findAll(); | ||
| return new ResponseEntity<>(posts, HttpStatus.OK); | ||
| } | ||
|
|
||
| @GetMapping("/show/{userID}") | ||
| public ResponseEntity<List<PostResponse>> showPost(@PathVariable Long userID) { | ||
| List<PostResponse> post = postService.findByUserID(userID); | ||
| return new ResponseEntity<>(post, HttpStatus.OK); | ||
| } | ||
|
|
||
| @GetMapping("/search/{content}") | ||
| public ResponseEntity<List<PostResponse>> searchPost(@PathVariable String content) { | ||
| List<PostResponse> post = postService.findByContent(content); | ||
| return new ResponseEntity<>(post, HttpStatus.OK); | ||
| } | ||
|
|
||
| @PostMapping("/add") | ||
| public ResponseEntity<PostResponse> addPost(@RequestBody PostDTO postDTO) { | ||
| PostResponse postResponse = postService.save(postDTO); | ||
| return new ResponseEntity<>(postResponse, HttpStatus.CREATED); | ||
| } | ||
|
|
||
| @PutMapping("/{id}") | ||
| public ResponseEntity<PostResponse> updatePost(@PathVariable Long id, @RequestBody PostDTO postDTO) { | ||
| PostResponse postResponse = postService.update(id, postDTO); | ||
| return new ResponseEntity<>(postResponse, HttpStatus.OK); | ||
| } | ||
|
|
||
| @PatchMapping("/{id}/likeit") | ||
| public ResponseEntity<PostResponse> likePost(@PathVariable Long id) { | ||
| PostResponse postResponse = postService.likePost(id); | ||
| return new ResponseEntity<>(postResponse, HttpStatus.OK); | ||
| } | ||
|
|
||
| @DeleteMapping("/{id}") | ||
| public ResponseEntity<String> deletePost(@PathVariable Long id) { | ||
| postService.delete(id); | ||
| return new ResponseEntity<>("Post deleted", HttpStatus.OK); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| package com.example.devSns.controllers; | ||
|
|
||
| import com.example.devSns.dto.ReplyDTO; | ||
| import com.example.devSns.dto.ReplyResponse; | ||
| import com.example.devSns.services.ReplyService; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/sns/reply") | ||
| @RequiredArgsConstructor | ||
| public class ReplyController { | ||
| private final ReplyService replyService; | ||
|
|
||
| @GetMapping("/{postId}/replies") | ||
| public ResponseEntity<List<ReplyResponse>> getReplies(@PathVariable long postId) { | ||
| List<ReplyResponse> replies = replyService.replyGetAll(postId); | ||
| ResponseEntity<List<ReplyResponse>> responseEntity = new ResponseEntity<>(replies, HttpStatus.OK); | ||
| return responseEntity; | ||
| } | ||
|
|
||
| @PostMapping("/{postId}/add") | ||
| public ResponseEntity<ReplyResponse> writeReply(@PathVariable long postId, @RequestBody ReplyDTO reply) { | ||
| ReplyResponse replyResponse = replyService.writeReply(postId, reply); | ||
| ResponseEntity<ReplyResponse> responseEntity = new ResponseEntity<>(replyResponse, HttpStatus.OK); | ||
| return responseEntity; | ||
| } | ||
|
|
||
| @PutMapping("/{replyId}") | ||
| public ResponseEntity<ReplyResponse> updateReply(@PathVariable long replyId, @RequestBody ReplyDTO reply) { | ||
| ReplyResponse replyResponse = replyService.updateReply(replyId, reply); | ||
| ResponseEntity<ReplyResponse> responseEntity = new ResponseEntity<>(replyResponse, HttpStatus.OK); | ||
| return responseEntity; | ||
| } | ||
|
|
||
| @PatchMapping("/{id}") | ||
| public ResponseEntity<ReplyResponse> likeReply(@PathVariable long id) { | ||
| ReplyResponse replyResponse = replyService.likeReply(id); | ||
| ResponseEntity<ReplyResponse> responseEntity = new ResponseEntity<>(replyResponse, HttpStatus.OK); | ||
| return responseEntity; | ||
| } | ||
|
|
||
| @DeleteMapping("/{replyId}") | ||
| public ResponseEntity<String> deleteReply(@PathVariable long replyId) { | ||
| String deleteCheck = replyService.deleteReply(replyId); | ||
| ResponseEntity<String> responseEntity = new ResponseEntity<>(deleteCheck, HttpStatus.OK); | ||
| return responseEntity; | ||
|
Comment on lines
+50
to
+51
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. return ResponseEntity.status(HttpStatus.OK).body(response); 형식으로 한 번에 작성할 수도 있습니다! 그리고 응답의 경우 응답 속성이 하나더라도 DTO 형식으로 반환하면 통일성 관점에서 더 깔끔할 것 같아요! 필드 수정 시에도 더 유연하게 처리 가능합니다! |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package com.example.devSns.controllers; | ||
|
|
||
| import com.example.devSns.dto.JwtDTO; | ||
| import com.example.devSns.dto.LoginDTO; | ||
| import com.example.devSns.dto.UserDTO; | ||
| import com.example.devSns.services.UserService; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.http.ResponseEntity; | ||
| 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; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/sns") | ||
| @RequiredArgsConstructor | ||
| @Slf4j | ||
| public class UserController { | ||
| private final UserService userService; | ||
|
|
||
| @PostMapping("/signup") | ||
| public ResponseEntity<String> signup(@RequestBody UserDTO userInfo) { | ||
| String resp = userService.signUp(userInfo); | ||
| ResponseEntity<String> response = new ResponseEntity(resp, HttpStatus.OK); | ||
| return response; | ||
| } | ||
|
|
||
| @PostMapping("/login") | ||
| public ResponseEntity<JwtDTO> login(@RequestBody LoginDTO loginDTO) { | ||
| return new ResponseEntity<>(userService.login(loginDTO), HttpStatus.OK); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package com.example.devSns.dto; | ||
|
|
||
| import lombok.Builder; | ||
|
|
||
| @Builder | ||
| public record JwtDTO( | ||
| String token | ||
| ) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package com.example.devSns.dto; | ||
|
|
||
| public record LoginDTO ( | ||
| String loginID, | ||
| String password | ||
| ) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package com.example.devSns.dto; | ||
|
|
||
| import com.example.devSns.entities.Posts; | ||
| import com.example.devSns.entities.Users; | ||
| import jakarta.validation.constraints.NotBlank; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| public record PostDTO( | ||
| @NotBlank Long userId, | ||
| @NotBlank String username, | ||
| String content | ||
| ) { | ||
| public static Posts dtoToEntity(PostDTO postDTO, Users user) { | ||
| Posts postEntity = Posts.builder() | ||
| .users(user) | ||
| .content(postDTO.content()) | ||
| .createat(LocalDateTime.now()) | ||
| .build(); | ||
| return postEntity; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.example.devSns.dto; | ||
|
|
||
| import com.example.devSns.entities.Posts; | ||
| import lombok.*; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| @Builder | ||
| public record PostResponse( | ||
| Long id, | ||
| String username, | ||
| String content, | ||
| Integer like, | ||
| LocalDateTime createAt, | ||
| LocalDateTime updateAt | ||
| ) { | ||
| public static PostResponse entityToDto(Posts post) { | ||
| return PostResponse.builder() | ||
| .id(post.getId()) | ||
| .username(post.getUsers().getUsername()) | ||
| .content(post.getContent()) | ||
| .like(post.getLikeit()) | ||
| .createAt(post.getCreateat()) | ||
| .updateAt(post.getUpdateat()) | ||
| .build(); | ||
| } | ||
| } | ||
|
Comment on lines
+8
to
+27
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 빌더의 경우 필요한 파라미터만 유연하게 넣어서 구성할 때 이점이 있는데, 여기서는 항상 모든 필드를 채우는 형식이라서 |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package com.example.devSns.dto; | ||
|
|
||
| import com.example.devSns.entities.Posts; | ||
| import com.example.devSns.entities.Replies; | ||
| import com.example.devSns.entities.Users; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| public record ReplyDTO( | ||
| Long userID, | ||
| String comment | ||
| ) { | ||
| public static Replies dtoToEntity(Posts post, Users user, ReplyDTO replyDTO) { | ||
| return Replies.builder() | ||
| .posts(post) | ||
| .users(user) | ||
| .createAt(LocalDateTime.now()) | ||
| .reply(replyDTO.comment()) | ||
| .build(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package com.example.devSns.dto; | ||
|
|
||
| import com.example.devSns.entities.Replies; | ||
| import lombok.Builder; | ||
|
|
||
| @Builder | ||
| public record ReplyResponse( | ||
| long replyId, | ||
| String username, | ||
| String comment, | ||
| Integer like | ||
| ) { | ||
| public static ReplyResponse entityToDTO(Replies replies) { | ||
| return ReplyResponse.builder() | ||
| .replyId(replies.getId()) | ||
| .username(replies.getUsers().getUsername()) | ||
| .comment(replies.getReply()) | ||
| .like(replies.getLikeit()) | ||
| .build(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spring Security를 사용하셨네요! 모듈이 복잡한 편이라서 나중에 인증/인가 전체 흐름 관련해서 파트별로 기능을 정리해두면 좋을 것 같아요~ 해당 부분 템플릿화해두면 초기 프로젝트 진행 시 인증/인가 부분을 빠르게 처리해서 넘겨줄 수 있어서 좋습니다