Skip to content
Merged

Dev #320

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
23 changes: 18 additions & 5 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,15 @@ jobs:
run: |
aws s3 cp revision.zip "s3://${{ secrets.CODEDEPLOY_S3_BUCKET }}/release/${GITHUB_SHA}.zip"

# 12) CodeDeploy 배포 트리거 (release -> traffic 순차)
- name: Create CodeDeploy deployments (sequential)
# 12) release 배포는 항상 수행
- name: Create CodeDeploy release deployment
run: |
APP_NAME="${{ secrets.CODEDEPLOY_APP_NAME }}"
BUCKET="${{ secrets.CODEDEPLOY_S3_BUCKET }}"
S3_KEY="release/${GITHUB_SHA}.zip"

# 새 시크릿이 없으면 기본 그룹명을 사용
RELEASE_GROUP="${{ secrets.CODEDEPLOY_RELEASE_DEPLOYMENT_GROUP }}"
TRAFFIC_GROUP="${{ secrets.CODEDEPLOY_TRAFFIC_DEPLOYMENT_GROUP }}"
: "${RELEASE_GROUP:=pooli-release-group}"
: "${TRAFFIC_GROUP:=pooli-traffic-group}"

echo "release group: ${RELEASE_GROUP}"
RELEASE_DEPLOY_ID=$(aws deploy create-deployment \
Expand All @@ -128,6 +125,22 @@ jobs:
echo "release deployment id: ${RELEASE_DEPLOY_ID}"
aws deploy wait deployment-successful --deployment-id "${RELEASE_DEPLOY_ID}"

# 13) 운영 토글이 켜져 있으면 traffic 배포 생략
- name: Skip CodeDeploy traffic deployment
if: ${{ vars.SKIP_TRAFFIC_DEPLOY == 'true' }}
run: echo "SKIP_TRAFFIC_DEPLOY=true, skipping traffic deployment"

# 14) 운영 토글이 꺼져 있으면 traffic 배포 수행
- name: Create CodeDeploy traffic deployment
if: ${{ vars.SKIP_TRAFFIC_DEPLOY != 'true' }}
run: |
APP_NAME="${{ secrets.CODEDEPLOY_APP_NAME }}"
BUCKET="${{ secrets.CODEDEPLOY_S3_BUCKET }}"
S3_KEY="release/${GITHUB_SHA}.zip"

TRAFFIC_GROUP="${{ secrets.CODEDEPLOY_TRAFFIC_DEPLOYMENT_GROUP }}"
: "${TRAFFIC_GROUP:=pooli-traffic-group}"

echo "traffic group: ${TRAFFIC_GROUP}"
TRAFFIC_DEPLOY_ID=$(aws deploy create-deployment \
--application-name "${APP_NAME}" \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,10 @@ public interface FamilyLineMapper {

// '특정 회선이 속한 가족 그룹'에 속한 모든 회선 식별자 조회
List<Long> findAllFamilyIdByLineId(Long lineId);

// 비공개 권한 해제 시 공개 상태를 true로 복구 (단건)
void forcePublicByLineId(Long lineId);

// 비공개 권한 해제 시 공개 상태를 true로 일괄 복구
void forcePublicByLineIds(@Param("lineIds") List<Long> lineIds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ public MemberPermissionResDto updateMemberPermission(Long familyId, Long lineId,
.isEnable(reqDto.getIsEnable())
.build());

// 비공개 권한(permission_id=2)을 비활성화하면 공개 상태를 강제로 true로 복구
if (reqDto.getPermissionId() == 2 && Boolean.FALSE.equals(reqDto.getIsEnable())) {
familyLineMapper.forcePublicByLineId(lineId);
}

return permissionLineMapper.findByFamilyIdAndLineId(familyId, lineId).stream()
.filter(p -> p.getPermissionId().equals(reqDto.getPermissionId()))
.findFirst()
Expand Down Expand Up @@ -143,6 +148,16 @@ public MemberPermissionListResDto bulkUpdateMemberPermissions(Long lineId, List<

permissionLineMapper.bulkUpsert(reqList);

// 비공개 권한(permission_id=2)을 비활성화한 회선만 추려서 공개 상태를 강제로 true로 복구
List<Long> lineIdsToRestore = reqList.stream()
.filter(r -> r.getPermissionId() == 2 && Boolean.FALSE.equals(r.getIsEnable()))
.map(MemberPermissionBulkUpsertReqDto::getLineId)
.distinct()
.toList();
if (!lineIdsToRestore.isEmpty()) {
familyLineMapper.forcePublicByLineIds(lineIdsToRestore);
}

reqList.stream()
.map(MemberPermissionBulkUpsertReqDto::getLineId)
.distinct()
Expand Down
19 changes: 19 additions & 0 deletions src/main/resources/mapper/permission/FamilyLineMapper.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,25 @@
);
</select>

<!-- 비공개 권한 해제 시 공개 상태 복구 (단건) -->
<update id="forcePublicByLineId">
UPDATE FAMILY_LINE
SET is_public = TRUE,
updated_at = NOW()
WHERE line_id = #{lineId}
</update>

<!-- 비공개 권한 해제 시 공개 상태 일괄 복구 -->
<update id="forcePublicByLineIds">
UPDATE FAMILY_LINE
SET is_public = TRUE,
updated_at = NOW()
WHERE line_id IN
<foreach collection="lineIds" item="lineId" open="(" separator="," close=")">
#{lineId}
</foreach>
</update>

<!-- 역할 변경 (OWNER <-> MEMBER) -->
<update id="updateRole">
UPDATE FAMILY_LINE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,45 @@ void updateMemberPermission_success_returnsUpdatedPermission() {
assertThat(captor.getValue().getIsEnable()).isTrue();
}

@Test
@DisplayName("단건 변경: 비공개 권한(permission_id=2)을 비활성화하면 공개 상태가 복구된다")
void updateMemberPermission_privacyPermissionDisabled_restoresVisibility() {
AuthUserDetails admin = userWithRole(99L, "ROLE_ADMIN");
MemberPermissionUpsertReqDto req = updateReq(2, false);

when(familyLineMapper.findByFamilyIdAndLineId(1L, 20L))
.thenReturn(Optional.of(familyLine(1L, 20L, FamilyRole.MEMBER)));
when(permissionMapper.findById(2)).thenReturn(Optional.of(permission(2)));
when(permissionLineMapper.findByFamilyIdAndLineId(1L, 20L))
.thenReturn(List.of(memberPermission(20L, 2, false)));

MemberPermissionResDto result =
memberPermissionService.updateMemberPermission(1L, 20L, req, admin);

assertThat(result.getLineId()).isEqualTo(20L);
assertThat(result.getPermissionId()).isEqualTo(2);
assertThat(result.getIsEnable()).isFalse();

verify(familyLineMapper).forcePublicByLineId(20L);
}

@Test
@DisplayName("단건 변경: 비공개 권한이 아닌 다른 권한을 꺼도 공개 복구가 호출되지 않는다")
void updateMemberPermission_nonPrivacyPermission_doesNotRestoreVisibility() {
AuthUserDetails admin = userWithRole(99L, "ROLE_ADMIN");
MemberPermissionUpsertReqDto req = updateReq(1, false);

when(familyLineMapper.findByFamilyIdAndLineId(1L, 20L))
.thenReturn(Optional.of(familyLine(1L, 20L, FamilyRole.MEMBER)));
when(permissionMapper.findById(1)).thenReturn(Optional.of(permission(1)));
when(permissionLineMapper.findByFamilyIdAndLineId(1L, 20L))
.thenReturn(List.of(memberPermission(20L, 1, false)));

memberPermissionService.updateMemberPermission(1L, 20L, req, admin);

verify(familyLineMapper, never()).forcePublicByLineId(anyLong());
}

@Test
@DisplayName("구성원 권한 변경 시 가족-회선 매핑이 없으면 PERMISSION-4404를 반환한다")
void updateMemberPermission_familyLineMissing_throwsFamilyLineMappingNotFound() {
Expand Down Expand Up @@ -299,6 +338,52 @@ void bulkUpdateMemberPermissions_ownerLineIdIgnored_usesSessionLineIdAndDistinct
assertThat(lineIdCaptor.getAllValues()).containsExactlyInAnyOrder(20L, 30L);
}

@Test
@DisplayName("일괄 변경: 비공개 권한(permission_id=2)을 비활성화하면 해당 회선만 공개 복구된다")
void bulkUpdateMemberPermissions_privacyPermissionDisabled_restoresVisibility() {
AuthUserDetails admin = userWithRole(50L, "ROLE_ADMIN");
List<MemberPermissionBulkUpsertReqDto> reqList = List.of(
req(20L, 2, false),
req(30L, 1, true)
);

when(familyLineMapper.findByLineId(50L)).thenReturn(Optional.of(familyLine(1L, 50L, FamilyRole.OWNER)));
when(familyLineMapper.findByFamilyIdAndLineId(1L, 20L))
.thenReturn(Optional.of(familyLine(1L, 20L, FamilyRole.MEMBER)));
when(familyLineMapper.findByFamilyIdAndLineId(1L, 30L))
.thenReturn(Optional.of(familyLine(1L, 30L, FamilyRole.MEMBER)));
when(permissionMapper.findById(anyInt()))
.thenAnswer(invocation -> Optional.of(permission(invocation.getArgument(0))));
when(permissionLineMapper.findByFamilyId(1L)).thenReturn(List.of());

memberPermissionService.bulkUpdateMemberPermissions(50L, reqList, admin);

verify(familyLineMapper).forcePublicByLineIds(List.of(20L));
}

@Test
@DisplayName("일괄 변경: 비공개 권한이 아닌 다른 권한만 변경하면 공개 복구가 호출되지 않는다")
void bulkUpdateMemberPermissions_nonPrivacyPermission_doesNotRestoreVisibility() {
AuthUserDetails admin = userWithRole(50L, "ROLE_ADMIN");
List<MemberPermissionBulkUpsertReqDto> reqList = List.of(
req(20L, 1, false),
req(30L, 1, true)
);

when(familyLineMapper.findByLineId(50L)).thenReturn(Optional.of(familyLine(1L, 50L, FamilyRole.OWNER)));
when(familyLineMapper.findByFamilyIdAndLineId(1L, 20L))
.thenReturn(Optional.of(familyLine(1L, 20L, FamilyRole.MEMBER)));
when(familyLineMapper.findByFamilyIdAndLineId(1L, 30L))
.thenReturn(Optional.of(familyLine(1L, 30L, FamilyRole.MEMBER)));
when(permissionMapper.findById(anyInt()))
.thenAnswer(invocation -> Optional.of(permission(invocation.getArgument(0))));
when(permissionLineMapper.findByFamilyId(1L)).thenReturn(List.of());

memberPermissionService.bulkUpdateMemberPermissions(50L, reqList, admin);

verify(familyLineMapper, never()).forcePublicByLineIds(anyList());
}

@Test
@DisplayName("일괄 변경 시 빈 목록이면 업데이트/알람 없이 현재 상태를 반환한다")
void bulkUpdateMemberPermissions_emptyReqList_returnsCurrentState() {
Expand Down Expand Up @@ -338,7 +423,7 @@ void bulkUpdateMemberPermissions_permissionNotFound_throwsPermissionNotFound() {
}

@Test
@DisplayName("bulk update: member line not in family returns PERMISSION-4404")
@DisplayName("일괄 변경 시 가족-회선 매핑이 없으면 PERMISSION-4404를 반환한다")
void bulkUpdateMemberPermissions_familyLineMissing_throwsFamilyLineMappingNotFound() {
AuthUserDetails admin = userWithRole(50L, "ROLE_ADMIN");
List<MemberPermissionBulkUpsertReqDto> reqList = List.of(req(20L, 1, true));
Expand All @@ -358,7 +443,7 @@ void bulkUpdateMemberPermissions_familyLineMissing_throwsFamilyLineMappingNotFou
}

@Test
@DisplayName("getMemberPermissions: non-owner user returns COMMON:4302")
@DisplayName("구성원 권한 조회 시 OWNER가 아니면 COMMON:4302를 반환한다")
void getMemberPermissions_nonOwner_throwsLineOwnershipForbidden() {
AuthUserDetails member = userWithRole(10L, "ROLE_FAMILY_MEMBER");
when(familyLineMapper.findByLineId(20L)).thenReturn(Optional.of(familyLine(1L, 20L, FamilyRole.MEMBER)));
Expand Down
Loading