Skip to content
Merged

Dev #29

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6c6ba7a
feat: 이메일 전송 util 생성
LeeJeonggyo Feb 15, 2025
7c1684e
chore: 사용하지 않는 import 삭제
LeeJeonggyo Feb 15, 2025
084cdc6
FEATURE/피그마에 따른 요양 보호사 테이블 수정
karl21-02 Feb 16, 2025
80ef676
Merge branch 'dev' of https://github.com/blaybus-hackathon/backend in…
LeeJeonggyo Feb 16, 2025
1fa0007
chore: 로그인/회원가입 uri 권한 검증 제외
LeeJeonggyo Feb 16, 2025
d90af8e
feat: 토큰 유효성 검사에 따른 예외 메세지 전달
LeeJeonggyo Feb 16, 2025
f7796c7
Merge pull request #21 from blaybus-hackathon/feature/#5_JWT-filter
LeeJeonggyo Feb 16, 2025
99d4603
Merge branch 'dev' of https://github.com/blaybus-hackathon/backend in…
LeeJeonggyo Feb 16, 2025
b9684f5
FEATURE/ 피그마에 디자인 보고 다시 수정
karl21-02 Feb 16, 2025
5baa1de
Merge pull request #22 from blaybus-hackathon/feature/#8_send-email-util
karl21-02 Feb 16, 2025
b01ecd9
Merge branch 'dev' into feature/#14_working-condition
karl21-02 Feb 16, 2025
cabd001
feat: 프로필 이미지 변경 및 업로드 API
LeeJeonggyo Feb 16, 2025
7fa1836
Merge pull request #23 from blaybus-hackathon/feature/#14_working-con…
LeeJeonggyo Feb 16, 2025
0438be6
Merge branch 'dev' of https://github.com/blaybus-hackathon/backend in…
LeeJeonggyo Feb 16, 2025
9aa1cf8
Merge pull request #25 from blaybus-hackathon/feature/#7_file-upload-…
bebeaubn Feb 16, 2025
184d24b
FEATURE / 요양 보호사 검색 API
karl21-02 Feb 17, 2025
71c9bdc
FEATURE / 요양 보호사 검색 API
karl21-02 Feb 17, 2025
fd80919
Merge pull request #27 from blaybus-hackathon/feature/#24_helper-search
karl21-02 Feb 17, 2025
f98f7f3
FIX / patient 병합 에러 수정
karl21-02 Feb 17, 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ out/
### application*.yml ###
src/main/resources/application.yml
src/main/resources/application-db.yml
src/main/resources/application-jwt.yml
src/main/resources/application-jwt.yml
src/main/resources/application-mail.yml
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ dependencies {

// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-maven-plugin
implementation group: 'org.springframework.boot', name: 'spring-boot-maven-plugin', version: '3.4.2'

/* mail */
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.balybus.galaxy.domain.BaseEntity;
import com.balybus.galaxy.domain.tblCenter.TblCenter;
import com.balybus.galaxy.domain.tblImg.TblImg;
import com.balybus.galaxy.global.utils.file.ChangeProfileImg;
import com.balybus.galaxy.member.domain.TblUser;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
Expand All @@ -15,7 +17,7 @@
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class TblCenterManager extends BaseEntity {
public class TblCenterManager extends BaseEntity implements ChangeProfileImg {

@Id
@Column(name="cm_seq")
Expand All @@ -33,6 +35,11 @@ public class TblCenterManager extends BaseEntity {
@JoinColumn(name = "center_seq", nullable = false)
private TblCenter center; //센터 구분자

@OneToOne(fetch = FetchType.LAZY)
@Comment("이미지 구분자")
@JoinColumn(name = "img_seq")
private TblImg img;

@Comment(value="직책")
@Column(length = 10, nullable = false)
private String cmPosition; // 직책
Expand All @@ -41,5 +48,12 @@ public class TblCenterManager extends BaseEntity {
@Column(length = 10, nullable = false)
private String cmName; // 직원명

/* ==================================================
* UPDATE
* ================================================== */
@Override
public TblImg getImg() { return this.img; }

@Override
public void updateImg(TblImg img) { this.img = img; }
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.balybus.galaxy.domain.tblImg;

import com.balybus.galaxy.domain.tblImg.dto.ImgRequestDto;
import com.balybus.galaxy.global.exception.BadRequestException;
import com.balybus.galaxy.global.exception.ExceptionCode;
import com.balybus.galaxy.global.utils.FileUploadUtils;
import com.balybus.galaxy.global.utils.file.FileUploadUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
Expand All @@ -19,9 +17,8 @@ public class TblImgServiceImpl {
private final FileUploadUtils fileUploadUtils;

@Transactional
public List<Long> uploadImg(UserDetails userDetails, ImgRequestDto.UploadImg dto) {
public List<Long> uploadImg(MultipartFile[] photoFiles) {
List<Long> imgSeq = new ArrayList<>();
MultipartFile[] photoFiles = dto.getPhotoFiles();
if (photoFiles != null && photoFiles.length > 0) {
try {
imgSeq = fileUploadUtils.uploadFiles(photoFiles);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package com.balybus.galaxy.domain.tblImg.dto;

import com.balybus.galaxy.login.domain.type.RoleType;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
public class ImgRequestDto {
@Data
public static class UploadImg{
private MultipartFile[] photoFiles; // 첨부파일
}
@Data
public static class uploadUserImg{
private MultipartFile[] photoFiles; // 첨부파일
private Long seq; //유저 구분자(요양보호사:tblHelper, 관리자:tblCenterManager, 어르신:tblPatient)
private RoleType imgOwnerAuth; //이미지 주체자 권한(요양보호사:MEMBER, 관리자:MANAGER, 어르신:PATIENT)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
package com.balybus.galaxy.domain.tblImg.dto;

import com.balybus.galaxy.login.domain.type.RoleType;
import lombok.Builder;
import lombok.Getter;

public class ImgResponseDto {
@Getter
@Builder
public static class uploadUserImg{
private Long imgSeq; // 이미지 구분자
private Long seq; // 유저 구분자
private RoleType imgOwnerAuth; // 유저 권한
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.balybus.galaxy.global.common;

import com.balybus.galaxy.domain.tblImg.dto.ImgRequestDto;
import com.balybus.galaxy.global.exception.ErrorResponse;
import com.balybus.galaxy.member.dto.response.MemberResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/api/cmn")
public class CommonController {
private final CommonServiceImpl commonService;

@PostMapping("/upload-img")
@Operation(summary = "프로필 이미지 변경 및 업로드 API",
description = "주체(요양보호사, 관리자, 어르신)의 프로필 이미지를 업로드하고 서버에 저장하는 기능을 제공합니다. " +
"이미지 파일은 multipart/form-data로 전송해야 하며, 성공적으로 업로드되면 이미지 구분자(imgSeq)가 반환됩니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "프로필 이미지 변경 성공",
content = @Content(schema = @Schema(implementation = MemberResponse.SignInDto.class))),
@ApiResponse(responseCode = "4005", description = "이미지 등록 권한 없음",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "5000", description = "예상하지 못한 서버 에러",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "6000", description = "사용자정의에러코드:파일 업로드 실패",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "6001", description = "사용자정의에러코드:삭제 파일을 찾지 못함",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "6002", description = "사용자정의에러코드:2개 이상의 파일이 전송됨",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "6003", description = "사용자정의에러코드:이미지를 등록하려는 주체 정보 조회 불가",
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
public ResponseEntity<?> uploadUserImg(@AuthenticationPrincipal UserDetails userDetails,
ImgRequestDto.uploadUserImg dto) {
return ResponseEntity.ok().body(commonService.uploadUserImg(userDetails, dto));
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/balybus/galaxy/global/common/CommonService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.balybus.galaxy.global.common;

import com.balybus.galaxy.domain.tblImg.dto.ImgRequestDto;
import com.balybus.galaxy.domain.tblImg.dto.ImgResponseDto;
import org.springframework.security.core.userdetails.UserDetails;

public interface CommonService {
/** 이미지 파일 저장 (요양보호사, 관리자, 어르신) */
ImgResponseDto.uploadUserImg uploadUserImg(UserDetails userDetails, ImgRequestDto.uploadUserImg dto);
}
115 changes: 115 additions & 0 deletions src/main/java/com/balybus/galaxy/global/common/CommonServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.balybus.galaxy.global.common;

import com.balybus.galaxy.domain.tblCenterManager.TblCenterManagerRepository;
import com.balybus.galaxy.domain.tblImg.TblImg;
import com.balybus.galaxy.domain.tblImg.TblImgServiceImpl;
import com.balybus.galaxy.domain.tblImg.dto.ImgRequestDto;
import com.balybus.galaxy.domain.tblImg.dto.ImgResponseDto;
import com.balybus.galaxy.global.exception.BadRequestException;
import com.balybus.galaxy.global.exception.ExceptionCode;
import com.balybus.galaxy.global.utils.file.ChangeProfileImg;
import com.balybus.galaxy.global.utils.file.FileUploadUtils;
import com.balybus.galaxy.helper.repository.HelperRepository;
import com.balybus.galaxy.login.domain.type.RoleType;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class CommonServiceImpl {

private final TblImgServiceImpl imgService;

private final HelperRepository helperRepository;
private final TblCenterManagerRepository centerManagerRepository;

private final FileUploadUtils fileUploadUtils;

/**
* 프로필 이미지 변경 (요양보호사, 관리자, 어르신)
* 기존 등록된 이미지가 있는 경우, 삭제 / 새로운 이미지가 있는 경우, 등록
* @param userDetails UserDetails:토큰 추출 데이터
* @param dto ImgRequestDto.uploadUserImg
* @return ImgResponseDto.uploadUserImg
*/
@Transactional
public ImgResponseDto.uploadUserImg uploadUserImg(UserDetails userDetails, ImgRequestDto.uploadUserImg dto) {
//1. 이미지 개수 검사
MultipartFile[] photoFiles = dto.getPhotoFiles();
if(photoFiles != null && photoFiles.length > 1)
throw new BadRequestException(ExceptionCode.TOO_MUCH_FILE);

//2. 권한별 이미지 등록 가능여부 파악
boolean authValidation = false;
RoleType roleType = dto.getImgOwnerAuth();
for (GrantedAuthority authority : userDetails.getAuthorities()) {
if(RoleType.MEMBER.getCode().equals(authority.getAuthority())){
//2-1. 요양보호사:MEMBER 로그인의 경우, 요양보호사 이미지만 등록 가능
authValidation = (RoleType.MEMBER == roleType);
break;
} else if (RoleType.MANAGER.getCode().equals(authority.getAuthority())){
//2-2. 관리자:MANAGER 로그인의 경우, 관리자와 어르신 이미지만 등록 가능
authValidation = (RoleType.MANAGER == roleType || RoleType.PATIENT == roleType);
break;
}
}
// 2-3. 그 외는 권한이 없다.
if (!authValidation) throw new BadRequestException(ExceptionCode.UNAUTHORIZED);

//3. 이미지 등록 주체에 따른 사용자 정보 조회
Long seq = dto.getSeq();
Long newImgSeq = null;
if(RoleType.MEMBER == roleType) {
newImgSeq = updateUserProfileImage(helperRepository, seq, photoFiles);
} else if (RoleType.MANAGER == roleType) {
newImgSeq = updateUserProfileImage(centerManagerRepository, seq, photoFiles);
} else {
log.info("어르신(TblPatient) entity 구현되면 추가 구현 예정");
// newImgSeq = updateUserProfileImage(patientRepository, seq, photoFiles);
}
return ImgResponseDto.uploadUserImg.builder()
.imgSeq(newImgSeq)
.seq(dto.getSeq())
.imgOwnerAuth(dto.getImgOwnerAuth())
.build();
}

/**
* 프로필 이미지 변경(기존 등록된 이미지가 있는 경우, 삭제 / 새로운 이미지가 있는 경우, 등록)
* @param repository 엔티티를 조회할 JpaRepository
* @param seq 업데이트할 사용자의 ID
* @param photoFiles 새로운 프로필 이미지 파일 목록
* @param <T> 프로필 이미지를 가진 엔티티 타입
* @return 새로 등록한 이미지 파일 ID
*/
private <T extends ChangeProfileImg> Long updateUserProfileImage(
JpaRepository<T, Long> repository, Long seq, MultipartFile[] photoFiles) {
//1. 엔티티 검색
T entity = repository.findById(seq)
.orElseThrow(() -> new BadRequestException(ExceptionCode.NOT_FOUND_TARGET));

//2. 기존 이미지 삭제
if(entity.getImg() != null)
fileUploadUtils.deleteFile(entity.getImg().getId());

//3. 새로운 이미지 등록
List<Long> newImgSeqList = imgService.uploadImg(photoFiles);
entity.updateImg((newImgSeqList.size() == 1)
? TblImg.builder()
.id(newImgSeqList.get(0))
.build() : null);

//4. 새로운 이미지 구분자 값 반환
return entity.getImg().getId();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.balybus.galaxy.global.config;

import com.balybus.galaxy.global.config.jwt.JwtAuthenticationFilter;
import com.balybus.galaxy.login.infrastructure.jwt.TokenProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -37,8 +36,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.logout(AbstractHttpConfigurer::disable)
.sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/sign-up", "/api/sign-in").permitAll()
.requestMatchers("/api/sign-up", "/api/sign/up/helper", "/api/sign/in").permitAll()
// .requestMatchers("/api/**").permitAll()
.requestMatchers("/api/sign/**").permitAll()
.requestMatchers("/api/token/**").permitAll()
.requestMatchers("/swagger-resources/**", "/swagger-ui/**", "/v3/api-docs/**").permitAll()
.requestMatchers("/img/**", "/css/**", "/static/js/**", "/docs/**").permitAll()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.balybus.galaxy.global.config.jwt;

public class ExpiredTokenException extends RuntimeException {
public ExpiredTokenException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.balybus.galaxy.global.config.jwt;

public class InvalidTokenException extends RuntimeException {
public InvalidTokenException(String message) {
super(message);
}
}
Loading
Loading