-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Feature/#173 깃 액션 빌드조건 변경 (#174) * feat: 백엔드 조건 변경 #173 * feat: 프론트 조건 변경 #173 * Feature/#175 test 및 application 수정 (#176) * feat: config 폴더 업데이트 #175 * feat: application 수정 #175 * feat: test 주석 처리 #175 * feat: config submodule 업데이트 #175 * feat: application 수정 #175 * Feature/#175 test 및 application 수정 (#178) * feat: config 폴더 업데이트 #175 * feat: application 수정 #175 * feat: test 주석 처리 #175 * feat: config submodule 업데이트 #175 * feat: application 수정 #175 * feat: application test 주석처리 #175 * Feature/#182 출시이후 기능 안보이도록 수정 (#183) * RELEASE (#177) * Feature/#173 깃 액션 빌드조건 변경 (#174) * feat: 백엔드 조건 변경 #173 * feat: 프론트 조건 변경 #173 * Feature/#175 test 및 application 수정 (#176) * feat: config 폴더 업데이트 #175 * feat: application 수정 #175 * feat: test 주석 처리 #175 * feat: config submodule 업데이트 #175 * feat: application 수정 #175 * release (#179) * Feature/#173 깃 액션 빌드조건 변경 (#174) * feat: 백엔드 조건 변경 #173 * feat: 프론트 조건 변경 #173 * Feature/#175 test 및 application 수정 (#176) * feat: config 폴더 업데이트 #175 * feat: application 수정 #175 * feat: test 주석 처리 #175 * feat: config submodule 업데이트 #175 * feat: application 수정 #175 * Feature/#175 test 및 application 수정 (#178) * feat: config 폴더 업데이트 #175 * feat: application 수정 #175 * feat: test 주석 처리 #175 * feat: config submodule 업데이트 #175 * feat: application 수정 #175 * feat: application test 주석처리 #175 * Develop (#180) * Feature/#173 깃 액션 빌드조건 변경 (#174) * feat: 백엔드 조건 변경 #173 * feat: 프론트 조건 변경 #173 * Feature/#175 test 및 application 수정 (#176) * feat: config 폴더 업데이트 #175 * feat: application 수정 #175 * feat: test 주석 처리 #175 * feat: config submodule 업데이트 #175 * feat: application 수정 #175 * Feature/#175 test 및 application 수정 (#178) * feat: config 폴더 업데이트 #175 * feat: application 수정 #175 * feat: test 주석 처리 #175 * feat: config submodule 업데이트 #175 * feat: application 수정 #175 * feat: application test 주석처리 #175 * fix: mixed-content 에러 해결 * feat: 메인 페이지의 마일스톤 api 연결 및 mock 데이터 삭제 #182 * refactor: 서버 api 구조 변경 #182 * feat: test-data.sql의 데이터 수정 #182 * feat: config submodule 폴더 최신화 #182 * feat: 메인페이지의 외부 링크 변경 #182 * feat: 해커톤 개발중인 기능이라고 표시 #182 * feat: 팀 빌딩 구현 중인 기능으로 표시 #182 * feat: title 의 제목 글씨 크기 28px 로 축소 #182 * feat: 관리자 페이지로 이동할 수 있는 버튼 생성 #182 * feat: 메인 페이지의 외부 링크 명 변경 #182 * Feature/#170 관리자 관련 api 구현 (#185) * feat: 관리자 계정들의 id 자동 생성되도록 수정 #170 * feat: super admin 어노테이션 구현 #170 * feat: 관리자 계정의 어노테이션 구현 #170 * feat: 관리자 단일 등록 api 구현 #170 * feat: Admin & SuperAdmin annotation 등록 #170 * feat: config 폴더 최신화 #170 * feat: 파일을 이용한 교직원 등록 api 구현 #170 * feat: 교직원 탈퇴 api 구현 #170 * feat: 로그인 할 때 deleted 된 사용자인지 검증하는 로직 추가 #179 * feat: 이메일 및 전화번호 중복확인 api 삭제 #170 * feat: 회원가입 및 이메일 인증시 탈퇴한 회원인지 확인하는 로직 추가 #170 * feat: 로그인 관련 회원을 찾지 못할 때의 문구 수정 #170 * feat: 교직원 단일/다중 등록 시 deleted 된 회원인지 검증하는 로직 추가 #170 * refactor: 관리자 등록 및 삭제 api의 컨트롤러 명 수정 #170 * refactor: 관리자 권한 관련 컨트롤러 명 수정 #170 * feat: 관리자 등록/삭제 관련 api test 코드 작성 및 rest docs 작성 #170 * refactor: 코드리뷰 반영 - soft delete 에 해당하는 SQLRestriction 사용하기 - 조회를 뜻하는 queryService에서 commandService로 서비스명 수정 #170 * refactor: 코드리뷰 반영 - setter 삭제 #170 * Feature/#186 마일스톤 권한 설정 (#187) * refactor: jwt argument Resolver 명 변경 #186 * refactor: jwt annotation 명 수정 #186 * refactor: jwt annotation 명 수정 #186 * feat: student argument resolver 추가 #186 * feat: 마일스톤 등록 시, 해당 회원 권환 확인 #186 * feat: 학생만 마일스톤 삭제할 수 있도록 권한 설정 #186 * feat: 마일스톤 조회 권한 설정 #186 * feat: 마일스톤 점수 조회 api 불러오는 것 권한 설정 #186 * feat: 관리자의 마일스톤 권한 설정 #186 * feat: 프론트 오류 수정 및 api 에 authentication 추가 #186 * feat: api 호출 시 Authorization 붙여서 보내도록 수정 #186 * fix: page 폴더 바깥에서 next/header 사용할 수 없어서 직접 token 넣어주도록 변경 #186
- Loading branch information
Showing
46 changed files
with
1,003 additions
and
314 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
backend/src/main/java/sw_css/admin/auth/api/AdminAuthController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package sw_css.admin.auth.api; | ||
|
||
import jakarta.validation.Valid; | ||
import java.net.URI; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.validation.annotation.Validated; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestPart; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.multipart.MultipartFile; | ||
import sw_css.admin.auth.application.AdminAuthCommandService; | ||
import sw_css.admin.auth.application.dto.request.DeleteFacultyRequest; | ||
import sw_css.admin.auth.application.dto.request.RegisterFacultyRequest; | ||
import sw_css.member.domain.FacultyMember; | ||
import sw_css.utils.annotation.AdminInterface; | ||
import sw_css.utils.annotation.SuperAdminInterface; | ||
|
||
@Validated | ||
@RequestMapping("/admin/auth") | ||
@RestController | ||
@RequiredArgsConstructor | ||
public class AdminAuthController { | ||
|
||
private final AdminAuthCommandService adminAuthCommandService; | ||
|
||
@PostMapping | ||
public ResponseEntity<Void> registerFaculty( | ||
@AdminInterface FacultyMember facultyMember, | ||
@RequestBody @Valid RegisterFacultyRequest request) { | ||
Long memberId = adminAuthCommandService.registerFaculty(request); | ||
return ResponseEntity.created(URI.create("/members/" + memberId)).build(); | ||
} | ||
|
||
@PostMapping("/files") | ||
public ResponseEntity<Void> registerFaculties( | ||
@AdminInterface FacultyMember facultyMember, | ||
@RequestPart(value = "file") final MultipartFile file) { | ||
adminAuthCommandService.registerFaculties(file); | ||
return ResponseEntity.created(URI.create("/admin/faculties")).build(); | ||
} | ||
|
||
@DeleteMapping() | ||
public ResponseEntity<Void> deleteFaculty( | ||
@SuperAdminInterface FacultyMember facultyMember, | ||
@RequestBody @Valid DeleteFacultyRequest request) { | ||
adminAuthCommandService.deleteFaculty(request.member_id()); | ||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
} |
156 changes: 156 additions & 0 deletions
156
backend/src/main/java/sw_css/admin/auth/application/AdminAuthCommandService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package sw_css.admin.auth.application; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Collectors; | ||
import lombok.RequiredArgsConstructor; | ||
import org.apache.commons.io.FilenameUtils; | ||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | ||
import org.apache.poi.ss.usermodel.Row; | ||
import org.apache.poi.ss.usermodel.Sheet; | ||
import org.apache.poi.ss.usermodel.Workbook; | ||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.web.multipart.MultipartFile; | ||
import sw_css.admin.auth.application.dto.request.RegisterFacultyRequest; | ||
import sw_css.admin.auth.exception.AdminAuthException; | ||
import sw_css.admin.auth.exception.AdminAuthExceptionType; | ||
import sw_css.auth.application.AuthCheckDuplicateService; | ||
import sw_css.member.domain.FacultyMember; | ||
import sw_css.member.domain.Member; | ||
import sw_css.member.domain.embedded.EmailAddress; | ||
import sw_css.member.domain.embedded.Password; | ||
import sw_css.member.domain.embedded.RealName; | ||
import sw_css.member.domain.repository.FacultyMemberRepository; | ||
import sw_css.member.domain.repository.MemberRepository; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class AdminAuthCommandService { | ||
|
||
private final MemberRepository memberRepository; | ||
private final FacultyMemberRepository facultyMemberRepository; | ||
private final AuthCheckDuplicateService authCheckDuplicateService; | ||
|
||
@Value("${password.admin}") | ||
private String password; | ||
|
||
@Transactional | ||
public Long registerFaculty(RegisterFacultyRequest request) { | ||
validateDuplicateEmail(request.email()); | ||
|
||
final String encodedPassword = Password.encode(password); | ||
|
||
final long memberId = memberRepository.save(request.toMember(encodedPassword)).getId(); | ||
facultyMemberRepository.save(request.toFacultyMember(memberId, encodedPassword)); | ||
|
||
return memberId; | ||
} | ||
|
||
public void registerFaculties(MultipartFile file) { | ||
final String extension = FilenameUtils.getExtension(file.getOriginalFilename()); | ||
if (extension == null || !(extension.equals("xlsx") || extension.equals("xls"))) { | ||
throw new AdminAuthException(AdminAuthExceptionType.NO_MATCH_EXTENSION); | ||
} | ||
|
||
final String encodedPassword = Password.encode(password); | ||
final List<Integer> failedData = new ArrayList<>(); | ||
|
||
final Workbook workbook = generateWorkbook(file, extension); | ||
|
||
final Sheet worksheet = workbook.getSheetAt(0); | ||
for (int i = 1; i < worksheet.getPhysicalNumberOfRows(); i++) { | ||
final Row row = worksheet.getRow(i); | ||
|
||
final String email = row.getCell(0).getStringCellValue(); | ||
final String name = row.getCell(1).getStringCellValue(); | ||
|
||
if (isInvalidInput(email, name)) { | ||
failedData.add(i + 1); | ||
continue; | ||
} | ||
|
||
saveFaculty(email, name, encodedPassword); | ||
} | ||
|
||
checkFailedData(failedData); | ||
} | ||
|
||
@Transactional | ||
public void deleteFaculty(Long memberId) { | ||
FacultyMember facultyMember = facultyMemberRepository.findById(memberId) | ||
.orElseThrow(() -> new AdminAuthException(AdminAuthExceptionType.MEMBER_NOT_FOUND)); | ||
|
||
Member member = facultyMember.getMember(); | ||
|
||
checkIsMemberDeleted(member); | ||
|
||
member.setDeleted(true); | ||
memberRepository.save(member); | ||
} | ||
|
||
private Workbook generateWorkbook(final MultipartFile file, String extension) { | ||
try { | ||
if (extension.equals("xlsx")) { | ||
return new XSSFWorkbook(file.getInputStream()); | ||
} | ||
return new HSSFWorkbook(file.getInputStream()); | ||
} catch (final IOException exception) { | ||
throw new AdminAuthException(AdminAuthExceptionType.CANNOT_OPEN_FILE); | ||
} | ||
} | ||
|
||
private void saveFaculty(final String email, final String name, final String password) { | ||
Member member = new Member(email, name, password, "01000000000", false); | ||
|
||
final Member savedMember = memberRepository.save(member); | ||
|
||
FacultyMember facultyMember = new FacultyMember(null, savedMember); | ||
facultyMemberRepository.save(facultyMember); | ||
} | ||
|
||
private void validateDuplicateEmail(String email) { | ||
if (authCheckDuplicateService.isDuplicateEmail(email)) { | ||
throw new AdminAuthException(AdminAuthExceptionType.MEMBER_EMAIL_DUPLICATE); | ||
} | ||
} | ||
|
||
private boolean isDuplicateEmail(String email) { | ||
return authCheckDuplicateService.isDuplicateEmail(email); | ||
} | ||
|
||
private boolean isInvalidInput(final String email, final String name) { | ||
if (Pattern.matches(EmailAddress.EMAIL_ADDRESS_REGEX, email) && | ||
Pattern.matches(RealName.NAME_REGEX, name) && !isDuplicateEmail(email)) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
private void checkFailedData(final List<Integer> failedData) { | ||
if (failedData.isEmpty()) { | ||
return; | ||
} | ||
|
||
String ids = failedData.stream() | ||
.map(Object::toString) | ||
.collect(Collectors.joining(", ")); | ||
AdminAuthExceptionType exceptionType = AdminAuthExceptionType.FAILED_REGISTER_FACULTY; | ||
exceptionType.setErrorMessage(ids + "번째 줄의 관리자를 등록하는데 실패했습니다."); | ||
|
||
throw new AdminAuthException(exceptionType); | ||
} | ||
|
||
private void checkIsMemberDeleted(final Member member) { | ||
if (!member.isDeleted()) { | ||
return; | ||
} | ||
throw new AdminAuthException(AdminAuthExceptionType.MEMBER_NOT_FOUND); | ||
|
||
} | ||
|
||
} |
6 changes: 6 additions & 0 deletions
6
backend/src/main/java/sw_css/admin/auth/application/dto/request/DeleteFacultyRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package sw_css.admin.auth.application.dto.request; | ||
|
||
public record DeleteFacultyRequest( | ||
Long member_id | ||
) { | ||
} |
29 changes: 29 additions & 0 deletions
29
backend/src/main/java/sw_css/admin/auth/application/dto/request/RegisterFacultyRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package sw_css.admin.auth.application.dto.request; | ||
|
||
import jakarta.validation.constraints.Email; | ||
import jakarta.validation.constraints.Pattern; | ||
import sw_css.member.domain.FacultyMember; | ||
import sw_css.member.domain.Member; | ||
import sw_css.member.domain.embedded.EmailAddress; | ||
import sw_css.member.domain.embedded.RealName; | ||
|
||
public record RegisterFacultyRequest( | ||
@Email(message = "이메일 형식을 확인해주세요.") | ||
@Pattern(regexp = EmailAddress.EMAIL_ADDRESS_REGEX, message = EmailAddress.EMAIL_ADDRESS_INVALID) | ||
String email, | ||
@Pattern(regexp = RealName.NAME_REGEX, message = RealName.NAME_INVALID) | ||
String name) { | ||
|
||
public Member toMember(String password) { | ||
return new Member(email, name, password, "01000000000", false); | ||
} | ||
|
||
public Member toMember(Long memberId, String password) { | ||
return new Member(memberId, email, name, password, "01000000000", false); | ||
} | ||
|
||
public FacultyMember toFacultyMember(Long memberId, String password) { | ||
final Member member = toMember(memberId, password); | ||
return new FacultyMember(null, member); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
backend/src/main/java/sw_css/admin/auth/exception/AdminAuthException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package sw_css.admin.auth.exception; | ||
|
||
|
||
import sw_css.base.BaseException; | ||
import sw_css.base.BaseExceptionType; | ||
|
||
public class AdminAuthException extends BaseException { | ||
private final AdminAuthExceptionType adminAuthExceptionType; | ||
|
||
public AdminAuthException(final AdminAuthExceptionType exceptionType) { | ||
super(exceptionType.errorMessage()); | ||
this.adminAuthExceptionType = exceptionType; | ||
} | ||
|
||
@Override | ||
public BaseExceptionType exceptionType() { | ||
return adminAuthExceptionType; | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
backend/src/main/java/sw_css/admin/auth/exception/AdminAuthExceptionType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package sw_css.admin.auth.exception; | ||
|
||
import lombok.Setter; | ||
import org.springframework.http.HttpStatus; | ||
import sw_css.base.BaseExceptionType; | ||
|
||
public enum AdminAuthExceptionType implements BaseExceptionType { | ||
NO_MATCH_EXTENSION(HttpStatus.BAD_REQUEST, "파일 확장자가 올바르지 않습니다."), | ||
CANNOT_OPEN_FILE(HttpStatus.BAD_REQUEST, "파일을 열 수 없습니다."), | ||
FAILED_REGISTER_FACULTY(HttpStatus.BAD_REQUEST, ""), | ||
MEMBER_EMAIL_DUPLICATE(HttpStatus.CONFLICT, "이메일이 중복됩니다."), | ||
MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 회원을 찾을 수 없습니다."), | ||
; | ||
|
||
private final HttpStatus httpStatus; | ||
@Setter | ||
private String errorMessage; | ||
|
||
AdminAuthExceptionType(final HttpStatus httpStatus, final String errorMessage) { | ||
this.httpStatus = httpStatus; | ||
this.errorMessage = errorMessage; | ||
} | ||
|
||
@Override | ||
public HttpStatus httpStatus() { | ||
return httpStatus; | ||
} | ||
|
||
@Override | ||
public String errorMessage() { | ||
return errorMessage; | ||
} | ||
|
||
} |
Oops, something went wrong.