Skip to content

Commit

Permalink
Merge pull request #15 from kookmin-sw/BE_Feature/#13-club
Browse files Browse the repository at this point in the history
모임 관련 API와 예외처리
  • Loading branch information
wjdwlghks authored Apr 18, 2024
2 parents 9ca0ffc + 0e5ec17 commit 02cbcdc
Show file tree
Hide file tree
Showing 29 changed files with 555 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.UUID;

@AllArgsConstructor
public class PrincipalDetails implements UserDetails {
Expand All @@ -27,6 +28,8 @@ public String getUsername() {
return member.getEmail();
}

public String getUserId() {return member.getId().toString(); }

@Override
public boolean isAccountNonExpired() {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = jwtProvider.resolveToken(request);
try {
String email = jwtProvider.validateTokenAndGetEmail(token);
Authentication authentication = jwtProvider.createAuthentication(email);
String id = jwtProvider.validateTokenAndGetId(token);
Authentication authentication = jwtProvider.createAuthentication(id);
log.info(authentication.getName());
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (Exception e) {
log.warn(e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.UUID;

@Slf4j
@Component
Expand All @@ -39,9 +40,9 @@ private void init() {
key = Keys.hmacShaKeyFor(secret.getBytes());
}

public String generate(String email) {
public String generate(String id) {
Claims claims = Jwts.claims();
claims.put("email", email);
claims.put("id", id);
return generateToken(claims);
}

Expand Down Expand Up @@ -74,17 +75,17 @@ public String resolveToken(HttpServletRequest request) {
return null;
}

public String validateTokenAndGetEmail(String token) {
public String validateTokenAndGetId(String token) {
return Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody()
.get("email", String.class);
.get("id", String.class);
}

public Authentication createAuthentication(String email) {
UserDetails userDetails = principalDetailService.loadUserByUsername(email);
public Authentication createAuthentication(String id) {
UserDetails userDetails = principalDetailService.loadUserByUsername(id);
return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ public TokenResponse login(String email) {
}

private String generateToken(Member member) {
return jwtProvider.generate(member.getEmail());
return jwtProvider.generate(member.getId().toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.UUID;

@Service
@RequiredArgsConstructor
public class PrincipalDetailService implements UserDetailsService {
private final MemberRepository memberRepository;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Member member = memberRepository.findMemberByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("이메일이 존재하지 않습니다."));
public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
Member member = memberRepository.findMemberById(UUID.fromString(id))
.orElseThrow(() -> new UsernameNotFoundException("해당 멤버가 존재하지 않습니다."));
return new PrincipalDetails(member);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.project.capstone.club.controller;

import com.project.capstone.auth.domain.PrincipalDetails;
import com.project.capstone.club.controller.dto.ClubCreateRequest;
import com.project.capstone.club.controller.dto.ClubResponse;
import com.project.capstone.club.service.ClubService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

@RestController
@RequiredArgsConstructor
@RequestMapping("/club")
@Slf4j
public class ClubController {
private final ClubService clubService;
// 모임 불러오기
@GetMapping("/search/{id}")
public ResponseEntity<?> getClub(@PathVariable Long id) {
ClubResponse clubResponse = clubService.getClub(id);
return ResponseEntity.ok().body(clubResponse);
}

// 모임 주제별 검색
@GetMapping("/search/topic")
public ResponseEntity<List<ClubResponse>> searchByTopic(@RequestParam String topic) {
List<ClubResponse> clubResponseList = clubService.searchByTopic(topic);
return ResponseEntity.ok().body(clubResponseList);
}
// 모임 이름으로 검색
@GetMapping("/search/name")
public ResponseEntity<?> searchByName(@RequestParam String name) {
List<ClubResponse> clubResponseList = clubService.searchByName(name);
return ResponseEntity.ok().body(clubResponseList);
}
// 모임 생성하기
@PostMapping("/create")
public ResponseEntity<?> createClub(@RequestBody ClubCreateRequest request, @AuthenticationPrincipal PrincipalDetails details) {
clubService.createClub(request, details.getUserId());
return ResponseEntity.ok().body("모임 생성 완료");
}
// 모임 가입하기
@GetMapping("/join")
public ResponseEntity<?> join(@AuthenticationPrincipal PrincipalDetails details, @RequestParam Long clubId) {
clubService.join(details.getUserId(), clubId);
return ResponseEntity.ok().body("모임 가입 완료");
}
// 모임 탈퇴하기
@GetMapping("/out")
public ResponseEntity<?> out(@AuthenticationPrincipal PrincipalDetails details, @RequestParam Long clubId) {
clubService.out(details.getUserId(), clubId);
return ResponseEntity.ok().body("모임 탈퇴 완료");
}
// 모임장 위임하기
@PutMapping("/delegate")
public ResponseEntity<?> delegateManager(@AuthenticationPrincipal PrincipalDetails details,
@RequestParam UUID memberId, @RequestParam Long clubId) {
clubService.delegateManager(details, memberId, clubId);
return ResponseEntity.ok().body("위임 완료");
}
// 멤버 추방하기
@GetMapping("/expel")
public ResponseEntity<?> expelMember(@AuthenticationPrincipal PrincipalDetails details,
@RequestParam UUID memberId, @RequestParam Long clubId) {
clubService.expelMember(details, memberId, clubId);
return ResponseEntity.ok().body("추방 완료");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.project.capstone.club.controller.dto;

import com.project.capstone.club.domain.PublicStatus;

public record ClubCreateRequest(
String topic,
String name,
int maximum,
PublicStatus publicStatus,
Integer password
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.project.capstone.club.controller.dto;

import com.project.capstone.club.domain.Club;
import com.project.capstone.club.domain.PublicStatus;

import java.time.LocalDateTime;

public record ClubResponse (
Long id,
Long bookId,
String topic,
String name,
LocalDateTime createdAt,
int maximum,
PublicStatus publicstatus
) {
public ClubResponse(Club club) {
this(club.getId(), club.getBook() == null ? null : club.getBook().getId(), club.getTopic(), club.getName(), club.getCreatedAt(), club.getMaximum(), club.getPublicStatus());
}
}
12 changes: 8 additions & 4 deletions backend/src/main/java/com/project/capstone/club/domain/Club.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.project.capstone.club.domain;

import com.project.capstone.book.domain.Book;
import com.project.capstone.common.domain.MemberClub;
import com.project.capstone.memberclub.domain.MemberClub;
import com.project.capstone.content.domain.Content;
import com.project.capstone.member.domain.Member;
import com.project.capstone.post.domain.Post;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
Expand All @@ -16,6 +15,7 @@
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Entity
@EntityListeners(AuditingEntityListener.class)
Expand All @@ -27,14 +27,17 @@ public class Club {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "manager_id", columnDefinition = "BINARY(16)")
private UUID managerId;
private String topic;
private String name;
@Column(name = "created_at")
@CreatedDate
private LocalDateTime createdAt;
private int maximum;
@Column(name = "is_public")
private boolean isPublic;
@Enumerated(EnumType.STRING)
@Column(name = "public_status")
private PublicStatus publicStatus;
private Integer password;

@OneToMany(mappedBy = "club")
Expand All @@ -48,4 +51,5 @@ public class Club {

@ManyToOne
private Book book;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.project.capstone.club.domain;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

public interface ClubRepository extends JpaRepository<Club, Long> {
List<Club> findClubsByTopic(String topic);
List<Club> findClubsByNameContaining(String name);
Optional<Club> findClubById(Long id);
@Modifying(clearAutomatically = true)
@Query("update Club c set c.managerId = :id")
void updateManager(UUID id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.project.capstone.club.domain;

import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum PublicStatus {
PUBLIC("공개"),
PRIVATE("비공개");

private final String description;


@JsonCreator
public static PublicStatus from(String status) {
for (PublicStatus publicStatus : PublicStatus.values()) {
if (publicStatus.getDescription().equals(status)) {
return publicStatus;
}
}
throw new RuntimeException("잘못된 공개 여부입니다.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.project.capstone.club.exception;

import com.project.capstone.common.exception.BaseException;
import com.project.capstone.common.exception.ExceptionType;

public class ClubException extends BaseException {
public ClubException(ExceptionType exceptionType) {
super(exceptionType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.project.capstone.club.exception;

import com.project.capstone.common.exception.ExceptionType;

import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;


import static org.springframework.http.HttpStatus.*;

@AllArgsConstructor
public enum ClubExceptionType implements ExceptionType {

CLUB_NOT_FOUND(NOT_FOUND, 101, "해당 모임을 찾을 수 없습니다."),
EXIT_WITHOUT_DELEGATION(BAD_REQUEST, 102, "모임장은 위임 후 모임을 나갈 수 있습니다."),
UNAUTHORIZED_ACTION(UNAUTHORIZED, 103, "모임장만 할 수 있는 기능입니다.")
;

private final HttpStatus status;
private final int exceptionCode;
private final String message;
@Override
public HttpStatus httpStatus() {
return status;
}

@Override
public int exceptionCode() {
return exceptionCode;
}

@Override
public String message() {
return message;
}
}
Loading

0 comments on commit 02cbcdc

Please sign in to comment.