Skip to content

Commit eb5f665

Browse files
committed
feat: 기존 깃허브 핸들명 조회 API 추가
1 parent 3e3603f commit eb5f665

3 files changed

Lines changed: 52 additions & 0 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.gdschongik.gdsc.domain.discord.dto.response;
2+
3+
public record DiscordGithubHandleResponse(String previousGithubHandle, String currentGithubHandle) {
4+
5+
private static final int VISIBLE_LENGTH = 4;
6+
7+
public static DiscordGithubHandleResponse of(String previousGithubHandle, String currentGithubHandle) {
8+
return new DiscordGithubHandleResponse(maskHandle(previousGithubHandle), currentGithubHandle);
9+
}
10+
11+
/**
12+
* 앞 4자까지 노출하고 나머지를 '*'로 마스킹합니다. 4자 이하인 경우 최소 1자를 마스킹합니다.
13+
* 예: "johndoe" → "john***", "abc" → "ab*", "a" → "*"
14+
*/
15+
private static String maskHandle(String handle) {
16+
int visibleLength = Math.min(handle.length() - 1, VISIBLE_LENGTH);
17+
int maskLength = handle.length() - visibleLength;
18+
return handle.substring(0, visibleLength) + "*".repeat(maskLength);
19+
}
20+
}

src/main/java/com/gdschongik/gdsc/domain/member/api/OnboardingMemberController.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
package com.gdschongik.gdsc.domain.member.api;
22

3+
import static com.gdschongik.gdsc.global.common.constant.RegexConstant.*;
4+
5+
import com.gdschongik.gdsc.domain.discord.dto.response.DiscordGithubHandleResponse;
36
import com.gdschongik.gdsc.domain.member.application.OnboardingMemberService;
47
import com.gdschongik.gdsc.domain.member.dto.request.MemberInfoRequest;
58
import com.gdschongik.gdsc.domain.member.dto.response.MemberDashboardResponse;
69
import com.gdschongik.gdsc.domain.member.dto.response.MemberInfoResponse;
710
import com.gdschongik.gdsc.domain.member.dto.response.MemberUnivStatusResponse;
811
import io.swagger.v3.oas.annotations.Operation;
12+
import io.swagger.v3.oas.annotations.media.Schema;
913
import io.swagger.v3.oas.annotations.tags.Tag;
1014
import jakarta.validation.Valid;
15+
import jakarta.validation.constraints.Pattern;
1116
import lombok.RequiredArgsConstructor;
1217
import org.springframework.http.ResponseEntity;
1318
import org.springframework.web.bind.annotation.GetMapping;
1419
import org.springframework.web.bind.annotation.PostMapping;
1520
import org.springframework.web.bind.annotation.RequestBody;
1621
import org.springframework.web.bind.annotation.RequestMapping;
22+
import org.springframework.web.bind.annotation.RequestParam;
1723
import org.springframework.web.bind.annotation.RestController;
1824

1925
@Tag(name = "Member - Onboarding", description = "회원 온보딩 API입니다.")
@@ -51,4 +57,15 @@ public ResponseEntity<MemberInfoResponse> getMemberInfo() {
5157
MemberInfoResponse response = onboardingMemberService.getMemberInfo();
5258
return ResponseEntity.ok().body(response);
5359
}
60+
61+
@Operation(summary = "GitHub 핸들 조회하기", description = "학번으로 해당 사용자의 GitHub 핸들을 조회합니다.")
62+
@GetMapping("/github-handle")
63+
public ResponseEntity<DiscordGithubHandleResponse> getGithubHandle(
64+
@RequestParam("studentId")
65+
@Pattern(regexp = STUDENT_ID, message = "학번은 " + STUDENT_ID + " 형식이어야 합니다.")
66+
@Schema(description = "학번", pattern = STUDENT_ID)
67+
String studentId) {
68+
DiscordGithubHandleResponse response = onboardingMemberService.getGithubHandleByStudentId(studentId);
69+
return ResponseEntity.ok(response);
70+
}
5471
}

src/main/java/com/gdschongik/gdsc/domain/member/application/OnboardingMemberService.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static com.gdschongik.gdsc.global.exception.ErrorCode.*;
44

5+
import com.gdschongik.gdsc.domain.discord.dto.response.DiscordGithubHandleResponse;
56
import com.gdschongik.gdsc.domain.email.application.UnivEmailVerificationService;
67
import com.gdschongik.gdsc.domain.email.domain.UnivEmailVerification;
78
import com.gdschongik.gdsc.domain.email.domain.service.EmailVerificationStatusService;
@@ -18,6 +19,7 @@
1819
import com.gdschongik.gdsc.domain.recruitment.domain.RecruitmentRound;
1920
import com.gdschongik.gdsc.global.exception.CustomException;
2021
import com.gdschongik.gdsc.global.util.MemberUtil;
22+
import com.gdschongik.gdsc.infra.github.client.GithubClient;
2123
import java.util.Optional;
2224
import lombok.RequiredArgsConstructor;
2325
import lombok.extern.slf4j.Slf4j;
@@ -36,6 +38,7 @@ public class OnboardingMemberService {
3638
private final UnivEmailVerificationService univEmailVerificationService;
3739
private final MemberRepository memberRepository;
3840
private final EmailVerificationStatusService emailVerificationStatusService;
41+
private final GithubClient githubClient;
3942

4043
public MemberUnivStatusResponse checkUnivVerificationStatus() {
4144
Member currentMember = memberUtil.getCurrentMember();
@@ -69,6 +72,18 @@ public MemberDashboardResponse getDashboard() {
6972
member, univVerificationStatus, currentRecruitmentRound.orElse(null), myMembership.orElse(null));
7073
}
7174

75+
public DiscordGithubHandleResponse getGithubHandleByStudentId(String studentId) {
76+
Member currentMember = memberUtil.getCurrentMember();
77+
String currentGithubHandle = githubClient.getGithubHandle(currentMember.getOauthId());
78+
79+
String previousGithubHandle = memberRepository
80+
.findByStudentId(studentId)
81+
.map(member -> githubClient.getGithubHandle(member.getOauthId()))
82+
.orElseThrow(() -> new CustomException(MEMBER_NOT_FOUND));
83+
84+
return DiscordGithubHandleResponse.of(previousGithubHandle, currentGithubHandle);
85+
}
86+
7287
@Transactional
7388
public void attemptAdvanceToAssociate(long memberId) {
7489
Member member = memberRepository.findById(memberId).orElseThrow(() -> new CustomException(MEMBER_NOT_FOUND));

0 commit comments

Comments
 (0)