Skip to content

Commit 86225f4

Browse files
authored
hotfix: 탈퇴 후 재가입 안되는 bug fix (#39)
- 세션 확인 시 회원 타입도 리턴하도록 변경
1 parent 0491c91 commit 86225f4

File tree

13 files changed

+141
-21
lines changed

13 files changed

+141
-21
lines changed

src/main/java/com/tnt/application/member/MemberService.java

+11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static com.tnt.common.error.model.ErrorMessage.MEMBER_CONFLICT;
44
import static com.tnt.common.error.model.ErrorMessage.MEMBER_NOT_FOUND;
5+
import static com.tnt.dto.member.MemberProjection.MemberTypeDto;
56

67
import org.springframework.stereotype.Service;
78
import org.springframework.transaction.annotation.Transactional;
@@ -10,7 +11,9 @@
1011
import com.tnt.common.error.exception.NotFoundException;
1112
import com.tnt.domain.member.Member;
1213
import com.tnt.domain.member.SocialType;
14+
import com.tnt.gateway.dto.response.CheckSessionResponse;
1315
import com.tnt.infrastructure.mysql.repository.member.MemberRepository;
16+
import com.tnt.infrastructure.mysql.repository.member.MemberSearchRepository;
1417

1518
import lombok.RequiredArgsConstructor;
1619

@@ -19,6 +22,7 @@
1922
public class MemberService {
2023

2124
private final MemberRepository memberRepository;
25+
private final MemberSearchRepository memberSearchRepository;
2226

2327
public Member getMemberWithMemberId(Long memberId) {
2428
return memberRepository.findByIdAndDeletedAtIsNull(memberId)
@@ -41,4 +45,11 @@ public void validateMemberNotExists(String socialId, SocialType socialType) {
4145
public Member saveMember(Member member) {
4246
return memberRepository.save(member);
4347
}
48+
49+
public CheckSessionResponse getMemberType(Long memberId) {
50+
MemberTypeDto memberTypeDto = memberSearchRepository.findMemberTypeByMemberId(memberId)
51+
.orElseThrow(() -> new NotFoundException(MEMBER_NOT_FOUND));
52+
53+
return new CheckSessionResponse(memberTypeDto.memberType());
54+
}
4455
}

src/main/java/com/tnt/application/member/SignUpService.java

-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import lombok.RequiredArgsConstructor;
2828

2929
@Service
30-
@Transactional(readOnly = true)
3130
@RequiredArgsConstructor
3231
public class SignUpService {
3332

src/main/java/com/tnt/application/pt/PtService.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import lombok.RequiredArgsConstructor;
3535

3636
@Service
37-
@Transactional(readOnly = true)
3837
@RequiredArgsConstructor
3938
public class PtService {
4039

@@ -69,6 +68,7 @@ public ConnectWithTrainerDto connectWithTrainer(Long memberId, ConnectWithTraine
6968
trainerMember.getProfileImageUrl(), traineeMember.getProfileImageUrl(), trainer.getId(), trainee.getId());
7069
}
7170

71+
@Transactional(readOnly = true)
7272
public ConnectWithTraineeResponse getFirstTrainerTraineeConnect(Long memberId, Long trainerId,
7373
Long traineeId) {
7474
validateIfNotConnected(trainerId, traineeId);
@@ -87,6 +87,7 @@ public ConnectWithTraineeResponse getFirstTrainerTraineeConnect(Long memberId, L
8787
trainee.getHeight(), trainee.getWeight(), ptGoal, trainee.getCautionNote());
8888
}
8989

90+
@Transactional(readOnly = true)
9091
public GetPtLessonsOnDateResponse getPtLessonsOnDate(Long memberId, LocalDate date) {
9192
Trainer trainer = trainerService.getTrainerWithMemberId(memberId);
9293

src/main/java/com/tnt/application/trainee/PtGoalService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import lombok.RequiredArgsConstructor;
1212

1313
@Service
14-
@Transactional(readOnly = true)
1514
@RequiredArgsConstructor
1615
public class PtGoalService {
1716

@@ -21,6 +20,7 @@ public List<PtGoal> getAllPtGoalsWithTraineeId(Long traineeId) {
2120
return ptGoalRepository.findAllByTraineeIdAndDeletedAtIsNull(traineeId);
2221
}
2322

23+
@Transactional
2424
public List<PtGoal> saveAllPtGoals(List<PtGoal> ptGoals) {
2525
return ptGoalRepository.saveAll(ptGoals);
2626
}

src/main/java/com/tnt/application/trainee/TraineeService.java

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import lombok.RequiredArgsConstructor;
1414

1515
@Service
16-
@Transactional(readOnly = true)
1716
@RequiredArgsConstructor
1817
public class TraineeService {
1918

src/main/java/com/tnt/application/trainer/TrainerService.java

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import lombok.RequiredArgsConstructor;
1616

1717
@Service
18-
@Transactional(readOnly = true)
1918
@RequiredArgsConstructor
2019
public class TrainerService {
2120

src/main/java/com/tnt/domain/member/Member.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package com.tnt.domain.member;
22

3-
import static com.tnt.common.error.model.ErrorMessage.*;
3+
import static com.tnt.common.error.model.ErrorMessage.MEMBER_INVALID_COLLECTION_AGREEMENT;
4+
import static com.tnt.common.error.model.ErrorMessage.MEMBER_INVALID_EMAIL;
5+
import static com.tnt.common.error.model.ErrorMessage.MEMBER_INVALID_NAME;
6+
import static com.tnt.common.error.model.ErrorMessage.MEMBER_INVALID_PROFILE_IMAGE_URL;
7+
import static com.tnt.common.error.model.ErrorMessage.MEMBER_INVALID_SERVICE_AGREEMENT;
8+
import static com.tnt.common.error.model.ErrorMessage.MEMBER_INVALID_SOCIAL_ID;
9+
import static com.tnt.common.error.model.ErrorMessage.MEMBER_NULL_ADVERTISEMENT_AGREEMENT;
410
import static io.micrometer.common.util.StringUtils.isBlank;
511
import static java.lang.Boolean.FALSE;
612
import static java.util.Objects.isNull;
@@ -41,7 +47,7 @@ public class Member extends BaseTimeEntity {
4147
@Column(name = "id", nullable = false, unique = true)
4248
private Long id;
4349

44-
@Column(name = "social_id", nullable = false, unique = true, length = SOCIAL_ID_LENGTH)
50+
@Column(name = "social_id", nullable = true, unique = true, length = SOCIAL_ID_LENGTH)
4551
private String socialId;
4652

4753
@Column(name = "fcm_token", nullable = false, length = 255)
@@ -154,6 +160,7 @@ public void updateProfileImageUrl(String profileImageUrl) {
154160
}
155161

156162
public void softDelete() {
163+
this.socialId = null;
157164
this.deletedAt = LocalDateTime.now();
158165
}
159166

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.tnt.dto.member;
2+
3+
import com.querydsl.core.annotations.QueryProjection;
4+
import com.tnt.domain.member.MemberType;
5+
6+
import lombok.AccessLevel;
7+
import lombok.NoArgsConstructor;
8+
9+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
10+
public class MemberProjection {
11+
12+
@QueryProjection
13+
public record MemberTypeDto(MemberType memberType) {
14+
15+
}
16+
}

src/main/java/com/tnt/gateway/controller/AuthenticationController.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22

33
import static org.springframework.http.HttpStatus.OK;
44

5-
import org.springframework.http.ResponseEntity;
65
import org.springframework.web.bind.annotation.GetMapping;
76
import org.springframework.web.bind.annotation.PostMapping;
87
import org.springframework.web.bind.annotation.RequestBody;
98
import org.springframework.web.bind.annotation.ResponseStatus;
109
import org.springframework.web.bind.annotation.RestController;
1110

11+
import com.tnt.application.member.MemberService;
1212
import com.tnt.dto.member.response.LogoutResponse;
1313
import com.tnt.gateway.config.AuthMember;
1414
import com.tnt.gateway.dto.request.OAuthLoginRequest;
15+
import com.tnt.gateway.dto.response.CheckSessionResponse;
1516
import com.tnt.gateway.dto.response.OAuthLoginResponse;
1617
import com.tnt.gateway.service.OAuthService;
1718

@@ -26,6 +27,7 @@
2627
public class AuthenticationController {
2728

2829
private final OAuthService oauthService;
30+
private final MemberService memberService;
2931

3032
@Operation(summary = "소셜 로그인 API")
3133
@PostMapping("/login")
@@ -44,7 +46,7 @@ public LogoutResponse logout(@AuthMember Long memberId) {
4446
@Operation(summary = "로그인 세션 유효 확인 API")
4547
@GetMapping("/check-session")
4648
@ResponseStatus(OK)
47-
public ResponseEntity<Void> checkSession() {
48-
return new ResponseEntity<>(OK);
49+
public CheckSessionResponse checkSession(@AuthMember Long memberId) {
50+
return memberService.getMemberType(memberId);
4951
}
5052
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.tnt.gateway.dto.response;
2+
3+
import com.tnt.domain.member.MemberType;
4+
5+
import io.swagger.v3.oas.annotations.media.Schema;
6+
7+
@Schema(description = "세션 확인 API 응답")
8+
public record CheckSessionResponse(
9+
@Schema(description = "회원 타입", example = "TRAINER", nullable = false)
10+
MemberType memberType
11+
) {
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.tnt.infrastructure.mysql.repository.member;
2+
3+
import static com.tnt.domain.member.QMember.member;
4+
5+
import java.util.Optional;
6+
7+
import org.springframework.stereotype.Repository;
8+
9+
import com.querydsl.jpa.impl.JPAQueryFactory;
10+
import com.tnt.dto.member.MemberProjection;
11+
import com.tnt.dto.member.QMemberProjection_MemberTypeDto;
12+
13+
import lombok.RequiredArgsConstructor;
14+
15+
@Repository
16+
@RequiredArgsConstructor
17+
public class MemberSearchRepository {
18+
19+
private final JPAQueryFactory jpaQueryFactory;
20+
21+
public Optional<MemberProjection.MemberTypeDto> findMemberTypeByMemberId(Long memberId) {
22+
return Optional.ofNullable(jpaQueryFactory
23+
.select(new QMemberProjection_MemberTypeDto(member.memberType))
24+
.from(member)
25+
.where(
26+
member.id.eq(memberId),
27+
member.deletedAt.isNull()
28+
)
29+
.fetchOne());
30+
}
31+
}

src/test/java/com/tnt/application/member/MemberServiceTest.java

+39-5
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,35 @@
1010

1111
import java.util.Optional;
1212

13+
import org.assertj.core.api.Assertions;
1314
import org.junit.jupiter.api.DisplayName;
1415
import org.junit.jupiter.api.Test;
1516
import org.junit.jupiter.api.extension.ExtendWith;
1617
import org.mockito.InjectMocks;
1718
import org.mockito.Mock;
1819
import org.mockito.junit.jupiter.MockitoExtension;
1920

20-
import com.tnt.application.s3.S3Service;
2121
import com.tnt.common.error.exception.ConflictException;
2222
import com.tnt.common.error.exception.NotFoundException;
2323
import com.tnt.domain.member.Member;
2424
import com.tnt.domain.member.SocialType;
25+
import com.tnt.dto.member.MemberProjection;
2526
import com.tnt.fixture.MemberFixture;
27+
import com.tnt.gateway.dto.response.CheckSessionResponse;
2628
import com.tnt.infrastructure.mysql.repository.member.MemberRepository;
29+
import com.tnt.infrastructure.mysql.repository.member.MemberSearchRepository;
2730

2831
@ExtendWith(MockitoExtension.class)
2932
class MemberServiceTest {
3033

31-
@Mock
32-
private S3Service s3Service;
34+
@InjectMocks
35+
private MemberService memberService;
3336

3437
@Mock
3538
private MemberRepository memberRepository;
3639

37-
@InjectMocks
38-
private MemberService memberService;
40+
@Mock
41+
private MemberSearchRepository memberSearchRepository;
3942

4043
@Test
4144
@DisplayName("memberId로 회원 조회 성공")
@@ -131,4 +134,35 @@ void save_member_success() {
131134
assertThat(savedMember).isNotNull().isEqualTo(member);
132135
verify(memberRepository).save(member);
133136
}
137+
138+
@Test
139+
@DisplayName("memberId로 회원 타입 조회 성공")
140+
void get_member_type_success() {
141+
// given
142+
Member member = MemberFixture.getTrainerMember1WithId();
143+
Long memberId = member.getId();
144+
145+
given(memberSearchRepository.findMemberTypeByMemberId(memberId)).willReturn(
146+
Optional.of(new MemberProjection.MemberTypeDto(member.getMemberType())));
147+
148+
// when
149+
CheckSessionResponse checkSessionResponse = memberService.getMemberType(memberId);
150+
151+
// then
152+
assertThat(checkSessionResponse.memberType()).isEqualTo(member.getMemberType());
153+
}
154+
155+
@Test
156+
@DisplayName("memberId로 회원 타입 조회 실패")
157+
void get_member_type_fail() {
158+
// given
159+
Member member = MemberFixture.getTrainerMember1WithId();
160+
Long memberId = member.getId();
161+
162+
given(memberSearchRepository.findMemberTypeByMemberId(memberId)).willReturn(Optional.empty());
163+
164+
// when & then
165+
Assertions.assertThatThrownBy(() -> memberService.getMemberType(memberId))
166+
.isInstanceOf(NotFoundException.class);
167+
}
134168
}

src/test/java/com/tnt/gateway/controller/AuthenticationControllerTest.java

+14-6
Original file line numberDiff line numberDiff line change
@@ -19,34 +19,42 @@
1919
import org.mockito.InjectMocks;
2020
import org.mockito.Mock;
2121
import org.mockito.junit.jupiter.MockitoExtension;
22-
import org.springframework.http.HttpStatusCode;
23-
import org.springframework.http.ResponseEntity;
2422
import org.springframework.security.core.context.SecurityContextHolder;
2523

24+
import com.tnt.application.member.MemberService;
2625
import com.tnt.common.error.exception.NotFoundException;
2726
import com.tnt.common.error.exception.OAuthException;
2827
import com.tnt.dto.member.response.LogoutResponse;
2928
import com.tnt.gateway.dto.request.OAuthLoginRequest;
29+
import com.tnt.gateway.dto.response.CheckSessionResponse;
3030
import com.tnt.gateway.dto.response.OAuthLoginResponse;
3131
import com.tnt.gateway.service.OAuthService;
3232

3333
@ExtendWith(MockitoExtension.class)
3434
class AuthenticationControllerTest {
3535

36+
@InjectMocks
37+
private AuthenticationController authenticationController;
38+
3639
@Mock
3740
private OAuthService oauthService;
3841

39-
@InjectMocks
40-
private AuthenticationController authenticationController;
42+
@Mock
43+
private MemberService memberService;
4144

4245
@Test
4346
@DisplayName("로그인 세션 유효 확인 성공")
4447
void is_session_valid_success() {
48+
// given
49+
Long memberId = 1L;
50+
51+
given(memberService.getMemberType(memberId)).willReturn(new CheckSessionResponse(TRAINER));
52+
4553
// when
46-
ResponseEntity<Void> voidResponseEntity = authenticationController.checkSession();
54+
CheckSessionResponse checkSessionResponse = authenticationController.checkSession(memberId);
4755

4856
// then
49-
assertThat(voidResponseEntity.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(200));
57+
assertThat(checkSessionResponse.memberType()).isEqualTo(TRAINER);
5058
}
5159

5260
@Nested

0 commit comments

Comments
 (0)