Skip to content

Commit a83497d

Browse files
authored
Merge pull request #46 from prgrms-web-devcourse-final-project/node/6
[FEAT]: 사용자가 가진 baseline 리스트 조회
2 parents a7e7a7f + cb25406 commit a83497d

File tree

7 files changed

+127
-5
lines changed

7 files changed

+127
-5
lines changed

back/src/main/java/com/back/domain/node/controller/BaseLineController.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@
66
*/
77
package com.back.domain.node.controller;
88

9-
import com.back.domain.node.dto.*;
9+
import com.back.domain.node.dto.PivotListDto;
10+
import com.back.domain.node.dto.TreeDto;
1011
import com.back.domain.node.dto.base.BaseLineBulkCreateRequest;
1112
import com.back.domain.node.dto.base.BaseLineBulkCreateResponse;
13+
import com.back.domain.node.dto.base.BaseLineDto;
1214
import com.back.domain.node.dto.base.BaseNodeDto;
1315
import com.back.domain.node.service.NodeService;
16+
import com.back.global.security.CustomUserDetails;
1417
import lombok.RequiredArgsConstructor;
1518
import org.springframework.http.HttpStatus;
1619
import org.springframework.http.ResponseEntity;
20+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1721
import org.springframework.web.bind.annotation.*;
1822

1923
import java.util.List;
@@ -55,4 +59,13 @@ public ResponseEntity<TreeDto> getTreeForBaseLine(@PathVariable Long baseLineId)
5559
TreeDto tree = nodeService.getTreeForBaseLine(baseLineId);
5660
return ResponseEntity.ok(tree);
5761
}
62+
63+
// 내가 만든 베이스라인 목록 조회
64+
@GetMapping("/mine")
65+
public ResponseEntity<List<BaseLineDto>> getMyBaseLines(
66+
@AuthenticationPrincipal CustomUserDetails me
67+
) {
68+
List<BaseLineDto> list = nodeService.getMyBaseLines(me.getId());
69+
return ResponseEntity.ok(list);
70+
}
5871
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.back.domain.node.dto.base;
2+
3+
/**
4+
* BaseLine 요약 DTO
5+
* - 프론트 첫 리스트용
6+
*/
7+
8+
public record BaseLineDto(Long id, String title) {}

back/src/main/java/com/back/domain/node/mapper/NodeMappers.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@
77
package com.back.domain.node.mapper;
88

99
import com.back.domain.node.dto.base.BaseLineBulkCreateRequest;
10+
import com.back.domain.node.dto.base.BaseLineDto;
1011
import com.back.domain.node.dto.base.BaseNodeCreateRequestDto;
1112
import com.back.domain.node.dto.base.BaseNodeDto;
1213
import com.back.domain.node.dto.decision.DecNodeDto;
1314
import com.back.domain.node.dto.decision.DecisionNodeCreateRequestDto;
14-
import com.back.global.mapper.Mapper;
15-
import com.back.global.mapper.TwoWayMapper;
16-
import com.back.global.mapper.MappingException;
1715
import com.back.domain.node.entity.*;
1816
import com.back.domain.user.entity.User;
17+
import com.back.global.mapper.Mapper;
18+
import com.back.global.mapper.MappingException;
19+
import com.back.global.mapper.TwoWayMapper;
1920

2021
import java.util.ArrayList;
2122
import java.util.List;
@@ -24,6 +25,16 @@ public final class NodeMappers {
2425

2526
private NodeMappers() {}
2627

28+
// BaseLine -> BaseLineDto
29+
public static final Mapper<BaseLine, BaseLineDto> BASELINE_READ = e -> {
30+
if (e == null) throw new MappingException("BaseLine is null");
31+
return new BaseLineDto(
32+
e.getId(),
33+
e.getTitle()
34+
);
35+
};
36+
37+
2738
// BaseNode -> BaseLineDto
2839
public static final Mapper<BaseNode, BaseNodeDto> BASE_READ = e -> {
2940
if (e == null) throw new MappingException("BaseNode is null");

back/src/main/java/com/back/domain/node/repository/BaseLineRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.springframework.data.jpa.repository.JpaRepository;
66
import org.springframework.stereotype.Repository;
77

8+
import java.util.List;
89
import java.util.Optional;
910

1011
/**
@@ -17,5 +18,8 @@ public interface BaseLineRepository extends JpaRepository<BaseLine, Long> {
1718
// Guest 베이스라인 1개 제한 확인용
1819
boolean existsByUser_id(Long userId);
1920

21+
22+
List<BaseLine> findByUser_IdOrderByIdDesc(Long userId);
23+
2024
boolean existsByUserAndTitle(User user, String title);
2125
}

back/src/main/java/com/back/domain/node/service/NodeQueryService.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
*/
1010
package com.back.domain.node.service;
1111

12-
import com.back.domain.node.dto.*;
12+
import com.back.domain.node.dto.TreeDto;
13+
import com.back.domain.node.dto.base.BaseLineDto;
1314
import com.back.domain.node.dto.base.BaseNodeDto;
1415
import com.back.domain.node.dto.decision.DecNodeDto;
1516
import com.back.domain.node.dto.decision.DecisionLineDetailDto;
@@ -18,6 +19,7 @@
1819
import com.back.domain.node.entity.DecisionLine;
1920
import com.back.domain.node.entity.DecisionNode;
2021
import com.back.domain.node.mapper.NodeMappers;
22+
import com.back.domain.node.repository.BaseLineRepository;
2123
import com.back.domain.node.repository.BaseNodeRepository;
2224
import com.back.domain.node.repository.DecisionLineRepository;
2325
import com.back.domain.node.repository.DecisionNodeRepository;
@@ -42,6 +44,7 @@ public class NodeQueryService {
4244
private final BaseNodeRepository baseNodeRepository;
4345
private final DecisionNodeRepository decisionNodeRepository;
4446
private final DecisionLineRepository decisionLineRepository;
47+
private final BaseLineRepository baseLineRepository;
4548
private final NodeDomainSupport support;
4649

4750
// 가장 중요한: 특정 BaseLine 전체 트리 조회
@@ -127,4 +130,11 @@ public DecisionLineDetailDto getDecisionLineDetail(Long decisionLineId) {
127130
nodeDtos
128131
);
129132
}
133+
134+
public List<BaseLineDto> getMyBaseLines(Long userId) {
135+
return baseLineRepository.findByUser_IdOrderByIdDesc(userId)
136+
.stream()
137+
.map(NodeMappers.BASELINE_READ::map)
138+
.toList();
139+
}
130140
}

back/src/main/java/com/back/domain/node/service/NodeService.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.back.domain.node.dto.*;
99
import com.back.domain.node.dto.base.BaseLineBulkCreateRequest;
1010
import com.back.domain.node.dto.base.BaseLineBulkCreateResponse;
11+
import com.back.domain.node.dto.base.BaseLineDto;
1112
import com.back.domain.node.dto.base.BaseNodeDto;
1213
import com.back.domain.node.dto.decision.*;
1314
import lombok.RequiredArgsConstructor;
@@ -74,4 +75,8 @@ public BaseNodeDto getBaseNode(Long baseNodeId) {
7475
public DecNodeDto forkFromDecision(ForkFromDecisionRequest request) {
7576
return decisionFlowService.forkFromDecision(request);
7677
}
78+
79+
public List<BaseLineDto> getMyBaseLines(Long id) {
80+
return nodeQueryService.getMyBaseLines(id);
81+
}
7782
}

back/src/test/java/com/back/domain/node/controller/BaseLineControllerTest.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@
1313
import com.back.domain.node.repository.BaseNodeRepository;
1414
import com.back.domain.user.entity.*;
1515
import com.back.domain.user.repository.UserRepository;
16+
import com.back.global.security.CustomUserDetails;
1617
import com.fasterxml.jackson.databind.JsonNode;
1718
import com.fasterxml.jackson.databind.ObjectMapper;
1819
import org.junit.jupiter.api.*;
1920
import org.springframework.beans.factory.annotation.Autowired;
2021
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
2122
import org.springframework.boot.test.context.SpringBootTest;
2223
import org.springframework.http.MediaType;
24+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
25+
import org.springframework.security.core.context.SecurityContext;
26+
import org.springframework.security.core.context.SecurityContextHolder;
2327
import org.springframework.test.context.jdbc.Sql;
2428
import org.springframework.test.context.jdbc.SqlConfig;
2529
import org.springframework.test.web.servlet.MockMvc;
@@ -481,6 +485,70 @@ private Long saveAndGetBaseLineId() throws Exception {
481485
}
482486
}
483487

488+
@Nested
489+
@DisplayName("내 베이스라인 목록(/mine)")
490+
class BaseLine_Mine {
491+
492+
@AfterEach
493+
void clearCtx() { SecurityContextHolder.clearContext(); }
494+
495+
@Test
496+
@DisplayName("성공 : /base-lines/mine — 최소 1개 라인 생성 후 목록에 id/title이 포함되어 반환된다")
497+
void success_mine_returnsList() throws Exception {
498+
var created = mockMvc.perform(post("/api/v1/base-lines/bulk")
499+
.contentType(MediaType.APPLICATION_JSON)
500+
.content(sampleLineJson(userId)))
501+
.andExpect(status().isCreated())
502+
.andReturn();
503+
504+
// ★ 인증 세팅
505+
var me = userRepository.findById(userId).orElseThrow();
506+
setAuth(new CustomUserDetails(me));
507+
508+
// when/then
509+
mockMvc.perform(get("/api/v1/base-lines/mine"))
510+
.andExpect(status().isOk())
511+
.andExpect(jsonPath("$[0].id").exists())
512+
.andExpect(jsonPath("$[0].title").exists());
513+
}
514+
515+
@Test
516+
@DisplayName("성공 : /base-lines/mine — 라인이 없는 사용자에겐 빈 배열([])을 반환한다")
517+
void success_mine_emptyForUserWithoutLines() throws Exception {
518+
// given: 라인 없는 사용자
519+
String uid = UUID.randomUUID().toString().substring(0, 8);
520+
User emptyUser = User.builder()
521+
.email("nouser_" + uid + "@test.local")
522+
.role(Role.USER)
523+
.birthdayAt(LocalDateTime.now().minusYears(20))
524+
.gender(Gender.F)
525+
.mbti(Mbti.INFP)
526+
.beliefs("NONE")
527+
.authProvider(AuthProvider.LOCAL)
528+
.nickname("nouser-" + uid)
529+
.username("nouser-" + uid)
530+
.build();
531+
userRepository.save(emptyUser);
532+
533+
// ★ 인증 세팅
534+
setAuth(new CustomUserDetails(emptyUser));
535+
536+
// when/then
537+
mockMvc.perform(get("/api/v1/base-lines/mine"))
538+
.andExpect(status().isOk())
539+
.andExpect(jsonPath("$.length()").value(0));
540+
}
541+
}
542+
543+
544+
// 가장 중요한 함수 한줄 요약: SecurityContextHolder에 인증 토큰 세팅
545+
private void setAuth(CustomUserDetails cud) {
546+
SecurityContext ctx = SecurityContextHolder.createEmptyContext();
547+
ctx.setAuthentication(new UsernamePasswordAuthenticationToken(cud, null, cud.getAuthorities()));
548+
SecurityContextHolder.setContext(ctx);
549+
}
550+
551+
484552

485553
// (자주 쓰는) 정상 입력 샘플 JSON 생성
486554
private String sampleLineJson(Long uid) {
@@ -496,4 +564,7 @@ private String sampleLineJson(Long uid) {
496564
""".formatted(uid,
497565
NodeCategory.EDUCATION, NodeCategory.CAREER, NodeCategory.CAREER, NodeCategory.ETC);
498566
}
567+
568+
569+
499570
}

0 commit comments

Comments
 (0)