-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] 회원 부서 관리 기능을 추가합니다. #279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
88d9aa0
a61cef2
a9fe88a
ceb4af5
d724fec
7b97540
20cbf12
85060c2
51b4b2a
39b067b
7816361
9fcb02c
a2831ce
e68879c
498ac05
4064b26
3c82782
2b519ba
846efdc
fb52fd6
abe3989
f4087e1
d4b516f
753d37e
0dba966
30a9cc3
52514e4
75495fd
850b9c4
6fbc5da
be1efc1
d875f34
2e5c68d
975f973
606abd3
965e95b
243f476
1e1b6b7
36d72dd
0833a8b
6791573
cac1d13
e6f91ea
388cec3
c084229
ad1e714
d21e24c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package com.blackcompany.eeos.auth.application.exception; | ||
|
|
||
| import com.blackcompany.eeos.common.exception.BusinessException; | ||
| import org.springframework.http.HttpStatus; | ||
|
|
||
| public class NotFoundAuthorityException extends BusinessException { | ||
|
|
||
| private static final String FAIL_CODE = "4013"; | ||
|
|
||
| public NotFoundAuthorityException() { | ||
| super(FAIL_CODE, HttpStatus.NOT_FOUND); | ||
| } | ||
|
|
||
| @Override | ||
| public String getMessage() { | ||
| return "회원의 권한을 찾을 수 없습니다."; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,45 @@ | ||
| package com.blackcompany.eeos.auth.application.model; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| public enum Role { | ||
| ROLE_ADMIN("ADMIN"), | ||
| ROLE_USER("USER"); | ||
| ROLE_ADMIN(1L, "ADMIN"), | ||
| ROLE_USER(2L, "USER"); | ||
|
|
||
| private String role; | ||
| private final Long id; | ||
| private final String role; // 시스템 내에 존재하는 role을 찾을 때, 이 문자열을 기준으로 찾습니다. | ||
|
|
||
| Role(String role) { | ||
| Role(Long id, String role) { | ||
| this.id = id; | ||
| this.role = role; | ||
| } | ||
|
|
||
| public static boolean isExist(String role) { | ||
| if (role == null || role.trim().isEmpty()) return false; | ||
| return Arrays.stream(Role.values()).anyMatch(obj -> obj.getRole().equalsIgnoreCase(role)); | ||
| } | ||
|
|
||
| public static Role findRole(String role) { | ||
| if (role == null || role.trim().isEmpty()) { | ||
| throw new IllegalArgumentException("해당 role 을 찾을 수 없습니다."); | ||
| } | ||
| return Arrays.stream(Role.values()) | ||
| .filter(obj -> obj.getRole().equalsIgnoreCase(role)) | ||
| .findFirst() | ||
| .orElseThrow(IllegalArgumentException::new); | ||
| } | ||
|
|
||
| public static Role findById(Long id) { | ||
| return Arrays.stream(Role.values()) | ||
| .filter(obj -> obj.getId().equals(id)) | ||
| .findFirst() | ||
| .orElseThrow(IllegalArgumentException::new); | ||
| } | ||
|
|
||
| public static List<Role> getAllRoles() { | ||
| return Arrays.asList(Role.values()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,14 @@ | ||
| package com.blackcompany.eeos.auth.application.repository; | ||
|
|
||
| import com.blackcompany.eeos.auth.application.model.AuthorityModel; | ||
| import com.blackcompany.eeos.auth.application.model.Role; | ||
| import java.util.Set; | ||
|
|
||
| public interface AuthorityRepository { | ||
|
|
||
| Set<AuthorityModel> findByMemberId(Long memberId); | ||
|
|
||
| AuthorityModel findByMemberIdAndRole(Long memberId, Role role); | ||
|
|
||
| Long save(AuthorityModel authorityModel); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ | |
| import jakarta.persistence.Id; | ||
| import jakarta.persistence.Index; | ||
| import jakarta.persistence.Table; | ||
| import jakarta.persistence.UniqueConstraint; | ||
| import lombok.AccessLevel; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Getter; | ||
|
|
@@ -25,7 +26,11 @@ | |
| @SuperBuilder(toBuilder = true) | ||
| @Table( | ||
| name = AuthorityEntity.NAME, | ||
| indexes = {@Index(name = "idx_member_id", columnList = AuthorityEntity.NAME + "_member_id")}) | ||
| indexes = {@Index(name = "idx_member_id", columnList = AuthorityEntity.NAME + "_member_id")}, | ||
| uniqueConstraints = | ||
| @UniqueConstraint( | ||
| name = "uk_authority_member_role", | ||
| columnNames = {AuthorityEntity.NAME + "_member_id", AuthorityEntity.NAME + "_role"})) | ||
|
Comment on lines
+29
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chain(member_id, role) 유니크 제약 추가: 스키마 정합성/마이그레이션 확인 필요 JPA 레벨에서 중복 방지에 유효합니다. 다만 운영 DB에 중복 데이터가 존재하면 마이그레이션 시 실패합니다. 배포 전 중복 정리 및 DDL 적용 스크립트 존재 여부를 확인해 주세요. 레포 내 마이그레이션에 본 제약이 포함되어 있는지 검색: 운영 DB 점검용 SQL 예시(참고): -- 중복 후보
SELECT authority_member_id, authority_role, COUNT(*)
FROM authority
GROUP BY authority_member_id, authority_role
HAVING COUNT(*) > 1;🏁 Script executed: #!/bin/bash
# 마이그레이션 파일 내 제약 이름 검색
rg -n "uk_authority_member_role" -S
# authority 테이블 관련 마이그레이션 후보도 같이 탐색
rg -nP -C2 '\bauthority\b.*(unique|constraint|index)' -SLength of output: 227 마이그레이션에 검색 결과
작업 완료 후, 마이그레이션 파일이 정상 적용되는지 재확인 부탁드립니다. 🤖 Prompt for AI Agents |
||
| @Getter | ||
| public class AuthorityEntity extends BaseEntity { | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package com.blackcompany.eeos.calendar.application.dto; | ||
|
|
||
| import com.blackcompany.eeos.common.support.dto.AbstractRequestDto; | ||
|
|
||
| public record CalendarCreateCommand(String title, String url, String type, Long startAt, Long endAt) | ||
| implements AbstractRequestDto {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| package com.blackcompany.eeos.calendar.application.dto; | ||
|
|
||
| public record CalendarQuery(Integer year, Integer month, Integer date, Integer duration) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package com.blackcompany.eeos.calendar.application.dto; | ||
|
|
||
| import com.blackcompany.eeos.calendar.application.model.CalendarModel; | ||
| import com.blackcompany.eeos.common.support.dto.AbstractResponseDto; | ||
| import com.blackcompany.eeos.common.utils.DateConverter; | ||
|
|
||
| public record CalendarResponse( | ||
| Long id, String title, String url, String type, Long startAt, Long endAt, String writer) | ||
| implements AbstractResponseDto { | ||
|
|
||
| public static CalendarResponse toResponse(CalendarModel model, String writerName) { | ||
| Long startAt = DateConverter.toMillis(model.getStartAt()); | ||
| Long endAt = DateConverter.toMillis(model.getEndAt()); | ||
| String type = model.getType().name(); | ||
|
|
||
| return new CalendarResponse( | ||
| model.getId(), model.getTitle(), model.getUrl(), type, startAt, endAt, writerName); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package com.blackcompany.eeos.calendar.application.dto; | ||
|
|
||
| import com.blackcompany.eeos.common.support.dto.AbstractResponseDto; | ||
| import java.util.List; | ||
|
|
||
| public record CalendarResponses(List<CalendarResponse> calendars) implements AbstractResponseDto {} |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,6 @@ | ||||||||||||||||||||||||||||||||||||||
| package com.blackcompany.eeos.calendar.application.dto; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import com.blackcompany.eeos.common.support.dto.AbstractRequestDto; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| public record CalendarUpdateCommand(String title, String url, String type, Long startAt, Long endAt) | ||||||||||||||||||||||||||||||||||||||
| implements AbstractRequestDto {} | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+5
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 입력 유효성 보강(필드 제약·교차 검증)과 타입 명확화가 필요합니다.
예시: +import jakarta.validation.constraints.*;
+import org.hibernate.validator.constraints.URL;
-public record CalendarUpdateCommand(String title, String url, String type, Long startAt, Long endAt)
- implements AbstractRequestDto {}
+public record CalendarUpdateCommand(
+ @NotBlank @Size(max = 100) String title,
+ @Size(max = 2048) @URL(regexp = "^(https?://).*$", message = "유효한 URL이어야 합니다") String url,
+ @NotBlank String type,
+ @NotNull Long startAt,
+ @NotNull Long endAt
+) implements AbstractRequestDto {
+ public CalendarUpdateCommand {
+ if (startAt != null && endAt != null && startAt > endAt) {
+ throw new IllegalArgumentException("startAt은 endAt보다 이후일 수 없습니다");
+ }
+ }
+}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package com.blackcompany.eeos.calendar.application.exception; | ||
|
|
||
| import com.blackcompany.eeos.common.exception.BusinessException; | ||
| import com.blackcompany.eeos.member.application.model.Department; | ||
| import org.springframework.http.HttpStatus; | ||
|
|
||
| public class DeniedCalendarTypeException extends BusinessException { | ||
|
|
||
| private static final String FAIL_CODE = "10001"; | ||
| private final Department department; | ||
|
|
||
| public DeniedCalendarTypeException(Department department) { | ||
| super(FAIL_CODE, HttpStatus.BAD_REQUEST); | ||
| this.department = department; | ||
| } | ||
|
|
||
| @Override | ||
| public String getMessage() { | ||
| return String.format("%s 부서는 해당 타입의 칼렌더를 생성할 수 없습니다.", department.name()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,18 @@ | ||||||||||||||
| package com.blackcompany.eeos.calendar.application.exception; | ||||||||||||||
|
|
||||||||||||||
| import com.blackcompany.eeos.common.exception.BusinessException; | ||||||||||||||
| import org.springframework.http.HttpStatus; | ||||||||||||||
|
|
||||||||||||||
| public class DeniedCalendarUpdateException extends BusinessException { | ||||||||||||||
|
|
||||||||||||||
| private static final String FAIL_CODE = "10002"; | ||||||||||||||
|
|
||||||||||||||
| public DeniedCalendarUpdateException() { | ||||||||||||||
| super(FAIL_CODE, HttpStatus.UNAUTHORIZED); | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+10
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 401(UNAUTHORIZED) 대신 403(FORBIDDEN) 사용 권장 인증은 되었으나 권한이 없는 상황이므로 403이 더 적합합니다. 현재 401은 인증 실패 의미로 오해될 수 있습니다. - super(FAIL_CODE, HttpStatus.UNAUTHORIZED);
+ super(FAIL_CODE, HttpStatus.FORBIDDEN);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| @Override | ||||||||||||||
| public String getMessage() { | ||||||||||||||
| return "캘린더를 수정할 권한이 없습니다."; | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package com.blackcompany.eeos.calendar.application.exception; | ||
|
|
||
| import com.blackcompany.eeos.common.exception.BusinessException; | ||
| import org.springframework.http.HttpStatus; | ||
|
|
||
| public class InvalidDateException extends BusinessException { | ||
|
|
||
| private static final String FAIL_CODE = "10003"; | ||
|
|
||
| public InvalidDateException() { | ||
| super(FAIL_CODE, HttpStatus.BAD_REQUEST); | ||
| } | ||
|
|
||
| @Override | ||
| public String getMessage() { | ||
| return "행사 시작 날짜는 행사 종료 날짜보다 이후일 수 없습니다."; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package com.blackcompany.eeos.calendar.application.exception; | ||
|
|
||
| import com.blackcompany.eeos.common.exception.BusinessException; | ||
| import lombok.Getter; | ||
| import org.springframework.http.HttpStatus; | ||
|
|
||
| @Getter | ||
| public class NotFoundCalendarTypeException extends BusinessException { | ||
|
|
||
| private static final String FAIL_CODE = "10000"; | ||
|
|
||
| public NotFoundCalendarTypeException() { | ||
| super(FAIL_CODE, HttpStatus.BAD_REQUEST); | ||
| } | ||
|
|
||
| @Override | ||
| public String getMessage() { | ||
| return "캘린더 타입이 존재하지 않습니다."; | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.