Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ jobs:
AI_BASE_URL: ${{ secrets.AI_BASE_URL }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
MAIL_USERNAME: ${{ secrets.MAIL_USERNAME }}
MAIL_PASSWORD: ${{ secrets.MAIL_PASSWORD }}
run: |
mkdir -p "${{ env.BACKEND_DIR }}"
printf "%s" "${DOT_ENV}" > "${{ env.BACKEND_DIR }}/.env"
Expand All @@ -101,6 +103,8 @@ jobs:
echo "AI_BASE_URL=${AI_BASE_URL}" >> "${{ env.BACKEND_DIR }}/.env"
echo "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" >> "${{ env.BACKEND_DIR }}/.env"
echo "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" >> "${{ env.BACKEND_DIR }}/.env"
echo "MAIL_USERNAME=${MAIL_USERNAME}" >> "${{ env.BACKEND_DIR }}/.env"
echo "MAIL_PASSWORD=${MAIL_PASSWORD}" >> "${{ env.BACKEND_DIR }}/.env"

- name: Docker Buildx 설치
uses: docker/setup-buildx-action@v3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public class VideoController {
@GetMapping("/videos/upload")
@PreAuthorize("hasRole('ADMIN')")
@Operation(summary = "업로드용 URL 요청", description = "파일 업로드를 위한 Presigned URL을 발급받습니다.")
public RsData<UploadUrlGetResponse> getUploadUrl() {
PresignedUrlResponse uploadUrl = fileManager.getUploadUrl();
public RsData<UploadUrlGetResponse> getUploadUrl(@RequestParam String filename) {
PresignedUrlResponse uploadUrl = fileManager.getUploadUrl(filename);
UploadUrlGetResponse response = new UploadUrlGetResponse(uploadUrl.url().toString(), uploadUrl.expiresAt());
return new RsData<>("200", "업로드용 URL 요청완료", response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import com.back.domain.file.video.dto.service.PresignedUrlResponse;
import com.back.global.exception.ServiceException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

Expand All @@ -15,14 +16,42 @@ public class FileManager {
private final VideoService videoService;
private final S3Service s3Service;

public PresignedUrlResponse getUploadUrl() {
public PresignedUrlResponse getUploadUrl(String filename) {
String contentType = validateAndGetContentType(filename);
String ext = extractExt(filename);
String uuid = UUID.randomUUID().toString();
String objectKey = "videos/" + uuid + "." + ext;
Integer expires = 5;
URL url = s3Service.generateUploadUrl("videos/"+uuid, expires);
URL url = s3Service.generateUploadUrl(objectKey, expires, contentType);
LocalDateTime expiresAt = LocalDateTime.now().plusMinutes(expires);
return new PresignedUrlResponse(url, expiresAt);
}

private String extractExt(String filename) {
int pos = filename.lastIndexOf(".");
return filename.substring(pos + 1);
}

private String validateAndGetContentType(String filename) {
String ext = extractExt(filename).toLowerCase();
switch (ext) {
case "mp4":
return "video/mp4";
case "mov":
return "video/quicktime";
case "avi":
return "video/x-msvideo";
case "wmv":
return "video/x-ms-wmv";
case "mkv":
return "video/x-matroska";
case "webm":
return "video/webm";
default:
throw new ServiceException("400", "지원하지 않는 동영상 파일 형식입니다: " + ext);
}
}

public PresignedUrlResponse getDownloadUrl(String objectKey) {
Integer expires = 60;
URL url = s3Service.generateDownloadUrl(objectKey, expires);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ public class S3Service {
@Value("${aws.s3.bucket}")
private String bucket;

public URL generateUploadUrl(String objectKey, Integer expireMinutes) {
public URL generateUploadUrl(String objectKey, Integer expireMinutes, String contentType) {
validateRequest(objectKey);

PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucket)
.key(objectKey)
.contentType(contentType)
.build();

PresignedPutObjectRequest presignedRequest =
Expand All @@ -41,8 +42,8 @@ public URL generateUploadUrl(String objectKey, Integer expireMinutes) {
return presignedRequest.url();
}

public URL generateUploadUrl(String objectKey) {
return generateUploadUrl(objectKey, 30);
public URL generateUploadUrl(String objectKey, String contentType) {
return generateUploadUrl(objectKey, 30, contentType);
}

public URL generateDownloadUrl(String objectKey, Integer expireMinutes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.back.domain.member.member.dto.MentorSignupVerifyRequest;
import com.back.domain.member.member.dto.MentorVerificationRequest;
import com.back.domain.member.member.dto.LoginRequest;
import com.back.domain.member.member.dto.MemberMeResponse;
import com.back.domain.member.member.entity.Member;
import com.back.domain.member.member.service.MemberService;
import com.back.global.rq.Rq;
Expand Down Expand Up @@ -87,9 +88,9 @@ public RsData<Void> logout() {

@GetMapping("/me")
@Operation(summary = "사용자 정보 조회")
public RsData<Member> me() {
Member actor = memberService.getCurrentUser(rq.getActor());
return new RsData<>("200-5", "사용자 정보 조회 성공", actor);
public RsData<MemberMeResponse> me() {
MemberMeResponse response = memberService.getMemberMe(rq.getActor());
return new RsData<>("200-5", "사용자 정보 조회 성공", response);
}

@PostMapping("/refresh")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.back.domain.member.member.dto;

import com.back.domain.member.member.entity.Member;

public record MemberMeResponse(
Long memberId,
String publicId,
String email,
String name,
String nickname,
String role,
Long mentorId,
Long menteeId
) {
public static MemberMeResponse of(Member member, Long mentorId, Long menteeId) {
return new MemberMeResponse(
member.getId(),
member.getPublicId(),
member.getEmail(),
member.getName(),
member.getNickname(),
member.getRole().name(),
mentorId,
menteeId
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ public record MemberSearchResponse(
Boolean isDeleted,
LocalDateTime createdAt,
LocalDateTime modifiedAt,
String career, // 멘토인 경우에만 값이 있음 (TODO: Job 연결 후 수정 예정)
String job, // 멘토/멘티 모두: 직업명 또는 관심분야
Integer careerYears, // 멘토인 경우에만 값이 있음
String interestedField // 멘티인 경우에만 값이 있음 (TODO: Job 연결 후 수정 예정)
Long mentorId, // 멘토 ID (멘토인 경우에만 값이 있음)
Long menteeId // 멘티 ID (멘티인 경우에만 값이 있음)
) {
public static MemberSearchResponse from(Member member, Mentor mentor, Mentee mentee) {
return new MemberSearchResponse(
Expand All @@ -29,9 +30,10 @@ public static MemberSearchResponse from(Member member, Mentor mentor, Mentee men
member.getIsDeleted(),
member.getCreateDate(),
member.getModifyDate(),
mentor != null ? "TODO: Job 연결 필요" : null, // TODO: Job 연결 후 수정
mentor != null ? mentor.getJob().getName() : (mentee != null ? mentee.getJob().getName() : null),
mentor != null ? mentor.getCareerYears() : null,
mentee != null ? "TODO: Job 연결 필요" : null // TODO: Job 연결 후 수정
mentor != null ? mentor.getId() : null,
mentee != null ? mentee.getId() : null
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ public record MenteeMyPageResponse(
String email,
String name,
String nickname,
Long jobId
String job
) {
public static MenteeMyPageResponse from(Member member, Mentee mentee) {
return new MenteeMyPageResponse(
member.getId(),
member.getEmail(),
member.getName(),
member.getNickname(),
mentee.getJobId()
mentee.getJob().getName()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public record MentorMyPageResponse(
String email,
String name,
String nickname,
Long jobId,
String job,
Double rate,
Integer careerYears
) {
Expand All @@ -18,7 +18,7 @@ public static MentorMyPageResponse from(Member member, Mentor mentor) {
member.getEmail(),
member.getName(),
member.getNickname(),
mentor.getJobId(),
mentor.getJob().getName(),
mentor.getRate(),
mentor.getCareerYears()
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.back.domain.member.member.service;

import com.back.domain.job.job.entity.Job;
import com.back.domain.job.job.repository.JobRepository;
import com.back.domain.member.member.dto.*;
import com.back.domain.member.member.entity.Member;
import com.back.domain.member.member.repository.MemberRepository;
Expand All @@ -24,6 +26,7 @@ public class MemberService {
private final MentorRepository mentorRepository;
private final MenteeRepository menteeRepository;
private final PasswordEncoder passwordEncoder;
private final JobRepository jobRepository;

@Transactional
public Member joinMentee(String email, String name, String nickname, String password, String interestedField) {
Expand All @@ -44,8 +47,11 @@ public Member joinMentee(String email, String name, String nickname, String pass
Member member = new Member(email, passwordEncoder.encode(password), name, nickname, Member.Role.MENTEE);
Member savedMember = memberRepository.save(member);

// TODO: interestedField를 jobId로 매핑하는 로직 필요
Mentee mentee = new Mentee(savedMember, null);
// interestedField로 Job 찾기 또는 생성
Job job = jobRepository.findByName(interestedField)
.orElseGet(() -> jobRepository.save(new Job(interestedField, null)));

Mentee mentee = new Mentee(savedMember, job);
menteeRepository.save(mentee);

return savedMember;
Expand All @@ -70,8 +76,11 @@ public Member joinMentor(String email, String name, String nickname, String pass
Member member = new Member(email, passwordEncoder.encode(password), name, nickname, Member.Role.MENTOR);
Member savedMember = memberRepository.save(member);

// TODO: career를 jobId로 매핑하는 로직 필요
Mentor mentor = new Mentor(savedMember, null, null, careerYears);
// career로 Job 찾기 또는 생성
Job job = jobRepository.findByName(career)
.orElseGet(() -> jobRepository.save(new Job(career, null)));

Mentor mentor = new Mentor(savedMember, job, null, careerYears);
mentorRepository.save(mentor);

return savedMember;
Expand Down Expand Up @@ -146,6 +155,27 @@ public Member getCurrentUser(Member actor) {
return actor;
}

public MemberMeResponse getMemberMe(Member actor) {
if (actor == null) {
throw new ServiceException("401-1", "로그인이 필요합니다.");
}

Long mentorId = null;
Long menteeId = null;

if (actor.getRole() == Member.Role.MENTOR) {
mentorId = mentorRepository.findByMemberId(actor.getId())
.map(Mentor::getId)
.orElse(null);
} else if (actor.getRole() == Member.Role.MENTEE) {
menteeId = menteeRepository.findByMemberId(actor.getId())
.map(Mentee::getId)
.orElse(null);
}

return MemberMeResponse.of(actor, mentorId, menteeId);
}

public Member refreshAccessToken(String refreshToken) {
if (refreshToken.isBlank()) {
throw new ServiceException("401-1", "Refresh token이 없습니다.");
Expand Down Expand Up @@ -191,7 +221,17 @@ public void updateMentee(Member currentUser, MenteeUpdateRequest request) {
member.updateNickname(request.nickname());
memberRepository.save(member);

// TODO: interestedField를 jobId로 매핑하는 로직 필요 (현재는 기존 jobId 유지)
// Mentee 정보 업데이트 (interestedField)
if (request.interestedField() != null) {
Mentee mentee = menteeRepository.findByMemberId(currentUser.getId())
.orElseThrow(() -> new ServiceException("404-2", "멘티 정보를 찾을 수 없습니다."));

Job job = jobRepository.findByName(request.interestedField())
.orElseGet(() -> jobRepository.save(new Job(request.interestedField(), null)));

mentee.updateJob(job);
menteeRepository.save(mentee);
}
}

public MentorMyPageResponse getMentorMyPage(Member currentUser) {
Expand All @@ -216,11 +256,18 @@ public void updateMentor(Member currentUser, MentorUpdateRequest request) {
member.updateNickname(request.nickname());
memberRepository.save(member);

// Mentor 정보 업데이트 (경력연수)
mentor.updateCareerYears(request.careerYears());
mentorRepository.save(mentor);
// Mentor 정보 업데이트 (경력연수, career)
if (request.careerYears() != null) {
mentor.updateCareerYears(request.careerYears());
}

// TODO: career를 jobId로 매핑하는 로직 필요 (현재는 기존 jobId 유지)
if (request.career() != null) {
Job job = jobRepository.findByName(request.career())
.orElseGet(() -> jobRepository.save(new Job(request.career(), null)));
mentor.updateJob(job);
}

mentorRepository.save(mentor);
}


Expand Down Expand Up @@ -288,11 +335,25 @@ public void updateMemberByAdmin(Long memberId, String name, String nickname, Str
Mentor mentor = mentorRepository.findByMemberIdIncludingDeleted(member.getId())
.orElse(null);
if (mentor != null) {
if (careerYears != null) mentor.updateCareerYears(careerYears);
if (careerYears != null) {
mentor.updateCareerYears(careerYears);
}
if (career != null) {
Job job = jobRepository.findByName(career)
.orElseGet(() -> jobRepository.save(new Job(career, null)));
mentor.updateJob(job);
}
mentorRepository.save(mentor);
}
} else if (member.getRole() == Member.Role.MENTEE && interestedField != null) {
// TODO: interestedField 업데이트 로직 필요 (Mentee 엔티티에 업데이트 메서드가 있을 때)
Mentee mentee = menteeRepository.findByMemberIdIncludingDeleted(member.getId())
.orElse(null);
if (mentee != null) {
Job job = jobRepository.findByName(interestedField)
.orElseGet(() -> jobRepository.save(new Job(interestedField, null)));
mentee.updateJob(job);
menteeRepository.save(mentee);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
public record MenteeDto(
@Schema(description = "멘티 ID")
Long menteeId,
@Schema(description = "멘티 회원 ID")
Long menteeMemberId,
@Schema(description = "멘티 닉네임")
String nickname
) {
public static MenteeDto from(Mentee mentee) {
return new MenteeDto(
mentee.getId(),
mentee.getMember().getId(),
mentee.getMember().getNickname()
);
}
Expand Down
Loading