-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from giantim/feature/favorite
[라빈] API 테스트/문서자동화 미션 제출합니다
- Loading branch information
Showing
73 changed files
with
2,590 additions
and
465 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# 1단계 - 회원관리 기능 | ||
|
||
## 요구 사항 | ||
- 회원 정보를 관리하는 기능 구현 | ||
- 자신의 정보만 수정 가능하도록 해야하며 로그인이 선행되어야 함 | ||
- 토큰의 유효성 검사와 본인 여부를 판단하는 로직 추가 | ||
- side case에 대한 예외처리 | ||
- 인수 테스트와 단위 테스트 작성 | ||
- API 문서를 작성하고 문서화를 위한 테스트 작성 | ||
- 페이지 연동 | ||
|
||
## 기능 목록 | ||
1. 회원 가입 | ||
- [x] password / password 확인의 값이 같지 않다면 api 를 호출하지 않는다 | ||
- [x] email, name, password 를 담은 request 를 보낸다 | ||
- [x] 각 값에 대한 유효성을 서버에서 검사한다 | ||
- [x] 중복된 email 이 입력되었는지 검사한다 | ||
- [x] 정보가 유효하다면 회원을 생성한다 | ||
- [x] 실행 결과를 alert 를 이용해서 출력한다 | ||
|
||
2. 로그인 | ||
- [x] email / password 의 값을 담아서 request 를 보낸다 | ||
- [x] 각 값에 대한 유효성을 검사한다 | ||
- [x] 유효한 회원이라면 토큰을 발행해서 로그인 상태를 유지한다 | ||
|
||
3. 로그인 후 회원정보 조회 / 수정 / 삭제 | ||
- 조회 | ||
- [x] 로그인이 되어있지 않다면 로그인 화면으로 연결한다. | ||
- [x] 나의 정보를 조회 할때, 토큰을 검사해야 한다. | ||
- [x] 이메일과 이름을 표시한다. | ||
|
||
- 수정(jwt 있어야 가능하다) | ||
- [x] email 은 수정할 수 없다 | ||
- [x] name / password 만 수정 가능하다 | ||
|
||
- 탈퇴 | ||
- [x] jwt 토큰을 복호화한 email 로 member 를 찾는다 | ||
- [x] 해당 member 를 삭제하고 jwt 값을 비운다 | ||
|
||
4. 로그아웃 | ||
- [x] 클라이언트의 localStorage 의 jwt 값 비우고 메인 화면으로 이동 | ||
|
||
5. 뷰 수정 | ||
- [x] 로그인 되어있으면 로그인 -> 로그아웃 / 회원가입 노출 안함 | ||
|
||
# 2단계 - 즐겨찾기 기능 | ||
|
||
|
||
|
||
## 요구사항 | ||
|
||
- 즐겨찾기 기능을 추가(추가,삭제,조회) | ||
- 자신의 정보만 수정 가능하도록 해야하며 **로그인이 선행**되어야 함 | ||
- 토큰의 유효성 검사와 본인 여부를 판단하는 로직 추가(interceptor, argument resolver) | ||
- side case에 대한 예외처리 필수 | ||
- 인수 테스트와 단위 테스트 작성 | ||
- API 문서를 작성하고 문서화를 위한 테스트 작성 | ||
- 페이지 연동 | ||
|
||
|
||
|
||
## 기능 목록 | ||
|
||
### 1. 즐겨찾기 추가 | ||
|
||
- [x] 로그인이 선행된 상태에서 즐겨찾기를 추가할 수 있다 | ||
- [x] 즐겨찾기 버튼을 누를 때 토큰을 검사한다 | ||
- [x] 즐겨찾기 버튼을 누르면 해당 유저의 즐겨찾기 목록에 추가한다. | ||
|
||
### 2. 즐겨찾기 목록조회 / 제거 | ||
|
||
- [x] 즐겨찾기 페이지에 접속하면, 해당 유저의 즐겨찾기 목록을 출력한다. | ||
- [x] 즐겨 찾기 페이지는 로그인후 접속 가능하다. | ||
- [x] 즐겨찾기를 삭제하면, 해당 유저의 즐겨 찾기 목록에서 제거한다. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
src/main/java/wooteco/subway/domain/favorite/Favorite.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package wooteco.subway.domain.favorite; | ||
|
||
import org.springframework.data.annotation.Id; | ||
import org.springframework.data.annotation.PersistenceConstructor; | ||
import wooteco.subway.service.favorite.dto.FavoriteRequest; | ||
|
||
public class Favorite { | ||
@Id | ||
private Long id; | ||
private Long memberId; | ||
private Long departureId; | ||
private Long arrivalId; | ||
|
||
public Favorite(Long memberId, Long departureId, Long arrivalId) { | ||
this(null, memberId, departureId, arrivalId); | ||
} | ||
|
||
@PersistenceConstructor | ||
public Favorite(Long id, Long memberId, Long departureId, Long arrivalId) { | ||
this.id = id; | ||
this.memberId = memberId; | ||
this.departureId = departureId; | ||
this.arrivalId = arrivalId; | ||
} | ||
|
||
public static Favorite of(Long memberId, FavoriteRequest favoriteRequest) { | ||
return new Favorite(memberId, favoriteRequest.getDepartureId(), favoriteRequest.getArrivalId()); | ||
} | ||
|
||
public boolean isDuplicate(Favorite favorite) { | ||
return this.memberId.equals(favorite.memberId) | ||
&& this.departureId.equals(favorite.departureId) | ||
&& this.arrivalId.equals(favorite.arrivalId); | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public Long getMemberId() { | ||
return memberId; | ||
} | ||
|
||
public Long getDepartureId() { | ||
return departureId; | ||
} | ||
|
||
public Long getArrivalId() { | ||
return arrivalId; | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/wooteco/subway/domain/favorite/FavoriteRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package wooteco.subway.domain.favorite; | ||
|
||
import org.springframework.data.jdbc.repository.query.Query; | ||
import org.springframework.data.repository.CrudRepository; | ||
import org.springframework.data.repository.query.Param; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
public interface FavoriteRepository extends CrudRepository<Favorite, Long> { | ||
@Query("SELECT * FROM favorite WHERE member_id = :memberId") | ||
List<Favorite> findAllByMemberId(@Param("memberId") Long memberId); | ||
|
||
@Query("SELECT * FROM favorite " + | ||
"WHERE member_id = :memberId AND departure_id = :departureId AND arrival_id = :arrivalId") | ||
Optional<Favorite> findByMemberIdAndDepartureIdAndArrivalId(@Param("memberId") Long memberId, | ||
@Param("departureId") Long departureId, | ||
@Param("arrivalId") Long arrivalId); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
src/main/java/wooteco/subway/service/favorite/FavoriteService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package wooteco.subway.service.favorite; | ||
|
||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import wooteco.subway.domain.favorite.Favorite; | ||
import wooteco.subway.domain.favorite.FavoriteRepository; | ||
import wooteco.subway.domain.member.MemberRepository; | ||
import wooteco.subway.domain.station.StationRepository; | ||
import wooteco.subway.service.favorite.dto.FavoriteRequest; | ||
import wooteco.subway.service.favorite.dto.FavoriteResponse; | ||
import wooteco.subway.service.favorite.exception.DuplicateFavoriteException; | ||
import wooteco.subway.service.favorite.exception.NoExistFavoriteException; | ||
import wooteco.subway.service.member.exception.InvalidMemberIdException; | ||
import wooteco.subway.service.station.exception.InvalidStationNameException; | ||
|
||
import java.util.List; | ||
|
||
@Service | ||
public class FavoriteService { | ||
private final MemberRepository memberRepository; | ||
private final StationRepository stationRepository; | ||
private final FavoriteRepository favoriteRepository; | ||
|
||
public FavoriteService(MemberRepository memberRepository, StationRepository stationRepository, | ||
FavoriteRepository favoriteRepository) { | ||
this.memberRepository = memberRepository; | ||
this.stationRepository = stationRepository; | ||
this.favoriteRepository = favoriteRepository; | ||
} | ||
|
||
@Transactional | ||
public Long create(Long memberId, FavoriteRequest favoriteRequest) { | ||
memberRepository.findById(memberId).orElseThrow(InvalidMemberIdException::new); | ||
stationRepository.findById(favoriteRequest.getDepartureId()).orElseThrow(InvalidStationNameException::new); | ||
stationRepository.findById(favoriteRequest.getArrivalId()).orElseThrow(InvalidStationNameException::new); | ||
|
||
Favorite favorite = Favorite.of(memberId, favoriteRequest); | ||
|
||
if (isDuplicateFavorite(memberId, favorite)) { | ||
throw new DuplicateFavoriteException(); | ||
} | ||
|
||
return favoriteRepository.save(favorite).getId(); | ||
} | ||
|
||
private boolean isDuplicateFavorite(Long memberId, Favorite favorite) { | ||
return favoriteRepository.findAllByMemberId(memberId) | ||
.stream() | ||
.anyMatch(f -> f.isDuplicate(favorite)); | ||
} | ||
|
||
@Transactional | ||
public void delete(Long memberId, FavoriteRequest favoriteRequest) { | ||
Favorite favorite = favoriteRepository.findByMemberIdAndDepartureIdAndArrivalId(memberId, | ||
favoriteRequest.getDepartureId(), favoriteRequest.getArrivalId()) | ||
.orElseThrow(NoExistFavoriteException::new); | ||
|
||
favoriteRepository.delete(favorite); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public List<FavoriteResponse> findAll(Long memberId) { | ||
List<Favorite> favorites = favoriteRepository.findAllByMemberId(memberId); | ||
return FavoriteResponse.listOf(favorites); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
src/main/java/wooteco/subway/service/favorite/dto/FavoriteRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package wooteco.subway.service.favorite.dto; | ||
|
||
import javax.validation.constraints.NotNull; | ||
|
||
public class FavoriteRequest { | ||
@NotNull | ||
private Long departureId; | ||
@NotNull | ||
private Long arrivalId; | ||
|
||
private FavoriteRequest() { | ||
} | ||
|
||
public FavoriteRequest(Long departureId, Long arrivalId) { | ||
this.departureId = departureId; | ||
this.arrivalId = arrivalId; | ||
} | ||
|
||
public Long getDepartureId() { | ||
return departureId; | ||
} | ||
|
||
public Long getArrivalId() { | ||
return arrivalId; | ||
} | ||
} |
Oops, something went wrong.