오늘은 승인자가 실제로 승인하거나 거부하는 과정에서 사용되는 ApprovalVote를 분석했다.
승인 요청 자체와 승인자의 투표 기록은 별도로 관리한다.
ApprovalRequest
↓
ApprovalVote
├── requestId
├── approverId
├── decision
└── decidedAt
즉,
"승인이 필요한 요청"
과
"누가 그 요청에 어떤 판단을 했는가"
를 분리해서 저장한다.
ApprovalVote에는 다음과 같은 Unique Constraint가 존재한다.
@UniqueConstraint(
columnNames = {"requestId", "approverId"}
)
따라서 같은 요청에 같은 승인자가 두 번 투표하는 것을 막는다.
Service에서도 별도로 확인한다.
existsByRequestIdAndApproverId(
requestId,
approver.getId()
)
이미 투표했다면 DuplicateVoteException이 발생한다.
승인자는 단순히 시스템에 등록된 사용자라고 해서 모든 요청을 승인할 수 있는 것이 아니다.
다음 Claim을 요구한다.
stack:{stackName}:approve
예를 들어 ProdAlbStack을 승인하려면
stack:ProdAlbStack:approve
Claim이 필요하다.
따라서
배포 권한
stack:ProdAlbStack:deploy
승인 권한
stack:ProdAlbStack:approve
가 별개의 권한으로 존재한다.
이번 코드를 통해 배포 권한과 승인 권한을 분리하는 것이 보안적으로 중요하다는 것을 이해했다.
또한 애플리케이션 로직만으로 중복을 막는 것이 아니라 DB의 Unique Constraint를 함께 사용해 데이터 무결성을 보장할 수 있다는 점도 배웠다.