Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
0144409
Update main-cd.yml
wodydl0 Feb 24, 2025
d6b15cc
Merge pull request #16 from Ring-Us/main-cd/fix/2
wodydl0 Feb 24, 2025
fc17b48
Fix/main cd/v3 (#18)
wodydl0 Feb 24, 2025
2f89d3b
RINGUS-34 feat: 멘티 프로필 등록 기능 구현 (#20)
wlgns12370 Feb 24, 2025
1938d49
RINGUS-36: feat: 멤버Id 및 파일경로 매핑 테이블 생성 (#21)
jbh010204 Feb 24, 2025
ca39adc
RINGUS-35 feat: 멘토 멘티 프로필 수정 API 개발 (#22)
wlgns12370 Feb 25, 2025
cf5d132
RINGUS-37 chore: 스웨거 접속 경로 변경 (#23)
jbh010204 Feb 25, 2025
8ca92cb
refactor: 프론트엔드 배포 도메인 CORS 허용
jbh010204 Feb 25, 2025
03685b9
chore: DB 마이그레이션을 위한 Flyway 도입 (#24)
jbh010204 Feb 27, 2025
7bffbf4
RINGUS-40 feat: 북마크 생성 및 삭제 API 구현 (#25)
jbh010204 Feb 27, 2025
6ce9e23
RINGUS-45 feat: SessionMemberId 커스텀 어노테이션 구현 (#26)
jbh010204 Feb 28, 2025
e2494db
RINGUS-44 refactor: 파일 로드 api 리팩토링 (#28)
wodydl0 Feb 28, 2025
2f78be1
fix: ci 코드 수정 (#31)
wodydl0 Feb 28, 2025
b7f9be7
feat: storage swagger docs 작성 (#32)
wodydl0 Mar 1, 2025
a69f1f1
RINGUS-48 refactor: 멘토 엔티티 세부필드 변경 (#33)
jbh010204 Mar 4, 2025
2662f85
RINGUS-49 docs: 내 프로필 상세 조회 Docs 작성 (#34)
wlgns12370 Mar 5, 2025
57cc5b7
RINGUS-52 fix: 내 멤버 조회 imgUrl 필드 추가 (#35)
wlgns12370 Mar 6, 2025
896f5b9
RINGUS-46 feat: 멘토링 제안 api (#36)
wodydl0 Mar 7, 2025
9cce0df
RINGUS-53 feat: 세션검증을 담당할 어노테이션 기능 구현 (#37)
jbh010204 Mar 10, 2025
78fe040
RINGUS-58 chore: multipart 파일크기 제한 수정 및 멘토링 flyway 스키마 추가(#38)
wodydl0 Mar 13, 2025
aa78523
RINGUS-27 feat: 멘토 프로필 목록 조회 API 구현 (#39)
wlgns12370 Mar 13, 2025
862feb0
RINGUS-57 feat: 닉네임 중복 검사 API 구현 (#40)
jbh010204 Mar 15, 2025
b9585c1
RINGUS-61 feat: 내 프로필 조회 API 구현 (#41)
wlgns12370 Mar 15, 2025
fc22c19
RINGUS-62 feat: 북마크 멘토 목록 조회 기능 추가 (#42)
jbh010204 Mar 15, 2025
1870361
RINGUS-62 fix: 로그인 아닐 떄 멘토 목록 조회 안되는 오류 수정 (#43)
jbh010204 Mar 16, 2025
f2a7563
RINGUS-63 feat: 내 멤버 조회 닉네임 필드 추가 (#44)
wlgns12370 Mar 18, 2025
ee0374d
RINGUS-60 feat: MentoringStatus ENUM 변경 및 MentorQueryDsl queryFilter …
wodydl0 Mar 21, 2025
0ba4af0
RINGUS-64 feat: 멘토링 멘티 목록 조회 (#46)
jbh010204 Mar 22, 2025
f40c94b
RINGUS-64 fix: git 스테이징 안된 파일 push (#47)
jbh010204 Mar 22, 2025
289f4f6
RINGUS-64 refactor: 닉네임 중복 검사 POST에서 GET으로 변경 (#48)
jbh010204 Mar 23, 2025
759d232
RINGUS-66 feat: 멘토 멘토링 수락 API 개발 (#49)
wlgns12370 Mar 24, 2025
7a0362b
Fix: CORS 문제 해결 (#50)
wlgns12370 Mar 24, 2025
371ff2d
RINGUS-70 rename: 변경된 이미지 응답 필드 반영 (#51)
wlgns12370 Mar 25, 2025
a51e3cf
RINGUS-70 feat: 멘토링 count 필드 추가 (#52)
wlgns12370 Mar 25, 2025
a4d33ea
Update main-cd.yml/v4
wodydl0 Mar 26, 2025
f48cf9a
Update main-cd.yml/v5 (#54)
wodydl0 Mar 26, 2025
dddbc02
RINGUS-70 feat: 멘토링 count 쿼리 구현 (#56)
wlgns12370 Mar 26, 2025
94f99c3
RINGUS-70 Fix: QueryDsl 생성자 주입 추가 (#57)
wlgns12370 Mar 26, 2025
c1444a8
Merge remote-tracking branch 'origin/main' into develop
wlgns12370 Mar 26, 2025
1e9ea53
RINGUS-65 feat: S3 객체 보안 설정 (#60)
wodydl0 Mar 31, 2025
9bf489e
RINGUS-77 feat: TimeTraceAop 적용 (#61)
wodydl0 Apr 17, 2025
e0c8648
RINGUS-74 fix: 누락된 코드 병합 (#62)
wlgns12370 May 2, 2025
e11e2a1
RINGUS-74 feat: Enum 데이터 서버에서 한국어로 번역하기 (#63)
wlgns12370 May 10, 2025
8be5c43
RINGUS-71 feat: 멘티가 신청한 멘토링 시간대 변경 기능 구현 (#59)
jbh010204 May 10, 2025
3990393
Feature/ringus 78 (#64)
wodydl0 May 10, 2025
2a90edb
RINGUS-74 Fix: Enum 데이터 변경 및 DTO 수정 (#66)
wlgns12370 May 15, 2025
dc46926
RINGUS-83 feat: 로그인 여부와 멘토, 멘티 여부 확인 기능 추가 (#65)
jbh010204 May 16, 2025
d726840
RINGUS-87 feat: 포트폴리오 업로드 (#67)
wodydl0 May 18, 2025
891642a
feat: S3 파일 업로드 수정 (#68)
wodydl0 May 18, 2025
7409136
Feature/ringus 81 : flyway schema 추가 (#69)
wodydl0 May 18, 2025
756dac0
RINGUS-74 fix: MentorDetail 필드 수정 (#70)
wlgns12370 May 19, 2025
c11757d
RINGUS-74 Fix: API 연동 오류 해결 (#71)
wlgns12370 May 20, 2025
be67c01
RINGUS-89 fix: 한글 파일 업로드 시 발생 오류 수정 (#72)
wodydl0 May 20, 2025
10ee9ce
RINGUS-84 feat: 멘토링 신청 알림 전송 시스템 구현 (#73)
wlgns12370 May 26, 2025
a407101
RINGUS-67: 비밀번호 재설정 기능 구현 (#74)
jbh010204 May 26, 2025
2ecadfb
RINGUS-67 fix: 비밀번호 재설정 기능에는 세션 체크 없음으로 변경
May 26, 2025
2a2a7ef
RINGUS-92 fix: Hotfix (#75)
jbh010204 May 26, 2025
a1d40c4
RINGUS-92 fix: 비밀번호 검증 api 세션체크 없음 변경 (#76)
jbh010204 May 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/main-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ jobs:
git clone [email protected]:Ring-Us/ring-us-server.git /home/ubuntu/ring-us-server
cd /home/ubuntu/ring-us-server
fi

cd /home/ubuntu/ring-us-server

echo "${{ secrets.ENV }}" > .env.dev

# 🛠 Gradle 빌드 권한 설정
echo "[GitHub Actions] 🔧 Fixing Gradle permissions"
sudo chown -R $USER:$USER ~/.gradle
sudo chmod -R 777 ~/.gradle

# 🛠 Gradle 빌드 권한 설정
echo "[GitHub Actions] 🔧 Fixing Gradle permissions"
Expand Down
8 changes: 4 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ services:
- redis
ports:
- ${SPRING_PORT}:${SPRING_PORT}
restart: always
restart: "always"

database:
image: mysql:8.4.4
Expand All @@ -27,7 +27,7 @@ services:
- ${DB_PORT}
ports:
- ${DB_PORT}:${DB_PORT}
restart: no
restart: "no"
volumes:
- ring-us-database:/var/lib/mysql

Expand All @@ -39,9 +39,9 @@ services:
- ${REDIS_PORT}
ports:
- ${REDIS_PORT}:${REDIS_PORT}
restart: always
restart: "always"
volumes:
- ring-us-redis:/data
volumes:
ring-us-database:
ring-us-redis:
ring-us-redis:
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public SignUpResponse signUp(SignUpRequest request, HttpSession session){

emailSessionRepository.deleteById(sessionId);

verificationService.deleteSession(sessionId);
return new SignUpResponse(member.getId());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import es.princip.ringus.domain.exception.SignUpErrorCode;
import es.princip.ringus.domain.member.MemberRepository;
import es.princip.ringus.global.exception.CustomRuntimeException;
import es.princip.ringus.presentation.auth.dto.request.GenerateCodeRequest;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpSession;
import jakarta.transaction.Transactional;
Expand All @@ -20,7 +21,6 @@
@Service
@RequiredArgsConstructor
public class EmailVerificationService {

private final EmailVerificationRepository verificationRepository;
private final EmailSessionRepository sessionRepository;
private final MemberRepository memberRepository;
Expand All @@ -35,14 +35,21 @@ public void init(){
}

@Transactional
public void generateVerificationCode(String email) {
if(memberRepository.existsByEmail(email)){
throw new CustomRuntimeException(SignUpErrorCode.DUPLICATE_EMAIL);
public void generateVerificationCode(GenerateCodeRequest request) {
if(request.isPasswordReset()) {
if (!memberRepository.existsByEmail(request.email())) {
throw new CustomRuntimeException(SignUpErrorCode.NOT_FOUND_MEMBER);
}
}
else {
if(memberRepository.existsByEmail(request.email())) {
throw new CustomRuntimeException(SignUpErrorCode.DUPLICATE_EMAIL);
}
}

EmailVerification verification = EmailVerification.of(email);
EmailVerification verification = EmailVerification.of(request.email());

emailSendService.sendMimeMessage(email, verification.getVerificationCode());
emailSendService.sendMimeMessage(request.email(), verification.getVerificationCode());

verificationRepository.save(verification);
}
Expand Down Expand Up @@ -91,6 +98,13 @@ public void verifySession(String email, HttpSession session){
throw new CustomRuntimeException(EmailErrorCode.SESSION_EMAIL_MISMATCH);
}

sessionRepository.delete(emailSession);
}

@Transactional
public void deleteSession(String email) {
if(!sessionRepository.existsById(email)) {
throw new CustomRuntimeException(EmailErrorCode.SESSION_NOT_FOUND);
}
sessionRepository.deleteById(email);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package es.princip.ringus.application.member.service;

import es.princip.ringus.application.auth.service.EmailVerificationService;
import es.princip.ringus.domain.exception.MemberErrorCode;
import es.princip.ringus.domain.exception.SignUpErrorCode;
import es.princip.ringus.domain.member.Member;
Expand All @@ -8,13 +9,16 @@
import es.princip.ringus.domain.mentee.MenteeRepository;
import es.princip.ringus.domain.mentor.Mentor;
import es.princip.ringus.domain.mentor.MentorRepository;
import es.princip.ringus.domain.mentoring.MentoringRepository;
import es.princip.ringus.domain.serviceTerm.ServiceTermAgreement;
import es.princip.ringus.global.exception.CustomRuntimeException;
import es.princip.ringus.global.util.UniversityDomainUtil;
import es.princip.ringus.presentation.auth.dto.request.SignUpRequest;
import es.princip.ringus.presentation.member.dto.MemberResponse;
import es.princip.ringus.presentation.member.dto.MenteeProfileResponse;
import es.princip.ringus.presentation.member.dto.MentorProfileResponse;
import es.princip.ringus.presentation.member.dto.PasswordUpdateRequest;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
Expand All @@ -30,8 +34,10 @@
public class MemberService {
private final MemberRepository memberRepository;
private final MentorRepository mentorRepository;
private final MenteeRepository menteeRepository;
private final MenteeRepository menteeRepository;
private final PasswordEncoder passwordEncoder;
private final MentoringRepository mentoringRepository;
private final EmailVerificationService emailVerificationService;

/**
* 회원 저장 (이메일 인증 후 회원가입 진행)
Expand Down Expand Up @@ -68,13 +74,30 @@ public MemberResponse getMember(Long memberId) {
Mentor mentor = mentorRepository.findByMemberId(memberId)
.orElseThrow(() -> new CustomRuntimeException(MemberErrorCode.MEMBER_NOT_FOUND));

MentorProfileResponse profile = MentorProfileResponse.from(mentor);
MentorProfileResponse profile = MentorProfileResponse.from(mentor, mentoringRepository.findMentoringCountBy(mentor.getId()));
return MemberResponse.of(member, profile);
}
}
return MemberResponse.of(member);
}

@Transactional
public void updatePassword(PasswordUpdateRequest request, HttpSession session) {
emailVerificationService.verifySession(request.email(), session);

Member member = memberRepository.findByEmail(request.email())
.orElseThrow(() -> new CustomRuntimeException(SignUpErrorCode.NOT_FOUND_MEMBER));

if (passwordEncoder.matches(request.newPassword(), member.getPassword())) {
throw new CustomRuntimeException(MemberErrorCode.DUPLICATE_EXISTING_PASSWORD);
}

member.updatePassword(request.newPassword(), passwordEncoder);

emailVerificationService.deleteSession(request.email());

}

public boolean isUniqueNickname(String nickname) {
return !mentorRepository.existsByNickname(nickname) && !menteeRepository.existsByNickname(nickname);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package es.princip.ringus.application.mentee.service;

import es.princip.ringus.domain.exception.MemberErrorCode;
import es.princip.ringus.domain.exception.MenteeErrorCode;
import es.princip.ringus.domain.member.Member;
import es.princip.ringus.domain.member.MemberRepository;
import es.princip.ringus.domain.mentee.Mentee;
import es.princip.ringus.domain.mentee.MenteeRepository;
import es.princip.ringus.global.exception.CustomRuntimeException;
Expand All @@ -13,11 +16,16 @@
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MyMenteeService {
private final MemberRepository memberRepository;
private final MenteeRepository menteeRepository;

public MyMenteeResponse getDetailBy(Long mentorId) {
Mentee mentee = menteeRepository.findByMemberId(mentorId)
.orElseThrow(() -> new CustomRuntimeException(MenteeErrorCode.MENTEE_NOT_FOUND));
return MyMenteeResponse.from(mentee);

Member member = memberRepository.findById(mentee.getMemberId())
.orElseThrow(() -> new CustomRuntimeException(MemberErrorCode.MEMBER_NOT_FOUND));

return MyMenteeResponse.from(member,mentee);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import es.princip.ringus.domain.member.MemberRepository;
import es.princip.ringus.domain.mentor.Mentor;
import es.princip.ringus.domain.mentor.MentorRepository;
import es.princip.ringus.domain.mentoring.MentoringRepository;
import es.princip.ringus.domain.support.CursorResponse;
import es.princip.ringus.global.exception.CustomRuntimeException;
import es.princip.ringus.presentation.mentor.dto.*;
Expand All @@ -25,6 +26,7 @@ public class MentorService {

private final MemberRepository memberRepository;
private final MentorRepository mentorRepository;
private final MentoringRepository mentoringRepository;

@Transactional
public Long register(Long memberId, MentorRequest request) {
Expand All @@ -47,7 +49,7 @@ public Long register(Long memberId, MentorRequest request) {

@Transactional
public Long edit(Long memberId, EditMentorRequest request) {
Mentor mentor = mentorRepository.findById(memberId)
Mentor mentor = mentorRepository.findByMemberId(memberId)
.orElseThrow(() -> new CustomRuntimeException(MentorErrorCode.MENTOR_PROFILE_NOT_FOUND));
mentor.edit(request);
return mentor.getId();
Expand All @@ -57,6 +59,7 @@ public CursorResponse<MentorCardResponse> getMentorBy(CursorRequest request, Pag
if(request.isBookmarked()) {
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new CustomRuntimeException(MemberErrorCode.MEMBER_NOT_FOUND));
Long menteeId = member.getId();

if (member.isNotMentee()) {
throw new CustomRuntimeException(MemberErrorCode.MEMBER_TYPE_DIFFERENT);
Expand All @@ -71,6 +74,10 @@ public CursorResponse<MentorCardResponse> getMentorBy(CursorRequest request, Pag
public MentorDetailResponse getDetailBy(Long mentorId) {
Mentor mentor = mentorRepository.findById(mentorId)
.orElseThrow(() -> new CustomRuntimeException(MentorErrorCode.MENTOR_PROFILE_NOT_FOUND));
return MentorDetailResponse.from(mentor);

return MentorDetailResponse.from(
mentor,
mentoringRepository.findMentoringCountBy(mentorId)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package es.princip.ringus.application.mentor.service;

import es.princip.ringus.domain.exception.MemberErrorCode;
import es.princip.ringus.domain.exception.MentorErrorCode;
import es.princip.ringus.domain.member.Member;
import es.princip.ringus.domain.member.MemberRepository;
import es.princip.ringus.domain.mentor.Mentor;
import es.princip.ringus.domain.mentor.MentorRepository;
import es.princip.ringus.domain.mentoring.MentoringRepository;
import es.princip.ringus.global.exception.CustomRuntimeException;
import es.princip.ringus.presentation.mentor.dto.MyMentorResponse;
import lombok.RequiredArgsConstructor;
Expand All @@ -14,10 +18,16 @@
@Transactional(readOnly = true)
public class MyMentorService {
private final MentorRepository mentorRepository;
private final MemberRepository memberRepository;
private final MentoringRepository mentoringRepository;

public MyMentorResponse getDetailBy(Long memberId) {
Mentor mentor = mentorRepository.findByMemberId(memberId)
.orElseThrow(() -> new CustomRuntimeException(MentorErrorCode.MENTOR_PROFILE_NOT_FOUND));
return MyMentorResponse.from(mentor);

Member member = memberRepository.findById(mentor.getMemberId())
.orElseThrow(() -> new CustomRuntimeException(MemberErrorCode.MEMBER_NOT_FOUND));

return MyMentorResponse.from(member, mentor, mentoringRepository.findMentoringCountBy(mentor.getId()));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package es.princip.ringus.application.mentoring;

import es.princip.ringus.application.notification.service.NotificationService;
import es.princip.ringus.domain.exception.MenteeErrorCode;
import es.princip.ringus.domain.exception.MentorErrorCode;
import es.princip.ringus.domain.exception.MentoringErrorCode;
import es.princip.ringus.domain.mentee.Mentee;
import es.princip.ringus.domain.mentee.MenteeRepository;
import es.princip.ringus.domain.mentor.Mentor;
Expand All @@ -10,8 +12,8 @@
import es.princip.ringus.domain.mentoring.MentoringRepository;
import es.princip.ringus.domain.mentoring.MentoringStatus;
import es.princip.ringus.global.exception.CustomRuntimeException;
import es.princip.ringus.presentation.mentoring.dto.CreateMentoringRequest;
import es.princip.ringus.presentation.mentoring.dto.MentoringResponse;
import es.princip.ringus.global.sender.dto.MentoringRequestMessage;
import es.princip.ringus.presentation.mentoring.dto.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -24,6 +26,7 @@ public class MentoringService {
private final MentorRepository mentorRepository;
private final MenteeRepository menteeRepository;

private final NotificationService notificationService;
/**
* 멘토링 신청 생성
*/
Expand All @@ -39,11 +42,46 @@ public MentoringResponse createMentoring(CreateMentoringRequest request, Long me
request.applyTimes(),
request.mentoringMessage(),
mentor,
mentee);
mentee
);

mentee.addMentoring(mentoring);
mentor.addMentoring(mentoring);

notificationService.notify(MentoringRequestMessage.from(mentee, mentor, mentoring));
return MentoringResponse.from(mentoringRepository.save(mentoring));
}

/**
* 멘토링 신청 취소
*/
@Transactional
public MentoringCancelResponse cancelMentoring(CancelMentoringRequest request, Long memberId) {
Mentoring mentoring = mentoringRepository.findById(request.mentoringId())
.orElseThrow(() -> new CustomRuntimeException(MentoringErrorCode.MENTORING_NOT_FOUND));

if (!mentoring.getMentee().getMemberId().equals(memberId)) {
throw new CustomRuntimeException(MentoringErrorCode.MENTORING_CANCEL_NOT_POSSIBLE);
}

mentoring.cancel();
return MentoringCancelResponse.from(mentoring);
}

/**
* 멘토링 신청 거절
*/
@Transactional
public MentoringRejectResponse rejectMentoring(RejectMentoringRequest request, Long memberId) {
Mentoring mentoring = mentoringRepository.findById(request.mentoringId())
.orElseThrow(() -> new CustomRuntimeException(MentoringErrorCode.MENTORING_NOT_FOUND));

if (!mentoring.getMentor().getMemberId().equals(memberId)) {
throw new CustomRuntimeException(MentorErrorCode.MENTOR_NOT_FOUND);
}

mentoring.reject();

return MentoringRejectResponse.from(mentoring);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package es.princip.ringus.application.notification.service;

import es.princip.ringus.domain.notification.Notification;
import es.princip.ringus.domain.notification.NotificationRepository;
import es.princip.ringus.global.factory.NotificationMessageFactory;
import es.princip.ringus.global.sender.NotificationSender;
import es.princip.ringus.global.sender.dto.MentoringRequestMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class NotificationService {

private final NotificationSender notificationSender;
private final NotificationMessageFactory notificationMessageFactory;
private final NotificationRepository notificationRepository;

public void notify(MentoringRequestMessage request) {
Notification notification = notificationMessageFactory.mentoringRequestMessage(request);
notificationRepository.save(notification);
notificationSender.send(notification);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package es.princip.ringus.domain.bookmark;

public interface BookmarkQueryDslRepository {
Boolean isBookmarked(Long memberId, Long mentorId);
}
Loading