From 37c76e0c1cf38cd5f5d53ab952c8fc807ec5a09d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=84=9D=EB=B2=94?= Date: Thu, 12 Feb 2026 00:10:46 +0900 Subject: [PATCH 1/8] =?UTF-8?q?Feat:=20=EA=B7=B8=EB=A3=B9=20=EC=97=AD?= =?UTF-8?q?=ED=95=A0=EB=B3=84=20=EA=B6=8C=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/out/entity/GroupMemberEntity.java | 29 +++--------- .../adapter/out/entity/GroupRoleEntity.java | 46 +++++++++++++++++++ .../out/entity/GroupRolePermissionEntity.java | 45 ++++++++++++++++++ .../group/domain/model/permission/.gitkeep | 0 .../model/permission/GroupMemberRole.java | 5 ++ .../model/permission/GroupPermission.java | 5 ++ 6 files changed, 108 insertions(+), 22 deletions(-) create mode 100644 src/main/java/flipnote/group/adapter/out/entity/GroupRoleEntity.java create mode 100644 src/main/java/flipnote/group/adapter/out/entity/GroupRolePermissionEntity.java delete mode 100644 src/main/java/flipnote/group/domain/model/permission/.gitkeep create mode 100644 src/main/java/flipnote/group/domain/model/permission/GroupMemberRole.java create mode 100644 src/main/java/flipnote/group/domain/model/permission/GroupPermission.java diff --git a/src/main/java/flipnote/group/adapter/out/entity/GroupMemberEntity.java b/src/main/java/flipnote/group/adapter/out/entity/GroupMemberEntity.java index 8161510..ea59dba 100644 --- a/src/main/java/flipnote/group/adapter/out/entity/GroupMemberEntity.java +++ b/src/main/java/flipnote/group/adapter/out/entity/GroupMemberEntity.java @@ -40,42 +40,27 @@ public class GroupMemberEntity extends BaseEntity { @Column(name = "user_id", nullable = false) private Long userId; - @Enumerated(EnumType.STRING) - @Column(nullable = false) - private GroupMemberRole role; + @Column(name = "group_role_id", nullable = false) + private Long groupRoleId; @Builder - private GroupMemberEntity(Long groupId, Long userId, GroupMemberRole role) { + private GroupMemberEntity(Long groupId, Long userId, Long groupRoleId) { this.groupId = groupId; this.userId = userId; - this.role = (role != null) ? role : GroupMemberRole.MEMBER; + this.groupRoleId = groupRoleId; } /** - * 오너인 경우 + * 멤버 생성 * @param groupId * @param userId * @return */ - public static GroupMemberEntity createOwner(Long groupId, Long userId) { + public static GroupMemberEntity create(Long groupId, Long userId, Long groupRoleId) { return GroupMemberEntity.builder() .groupId(groupId) .userId(userId) - .role(GroupMemberRole.OWNER) - .build(); - } - - /** - * 오너가 아닌 경우 - * @param groupId - * @param userId - * @return - */ - public static GroupMemberEntity join(Long groupId, Long userId) { - return GroupMemberEntity.builder() - .groupId(groupId) - .userId(userId) - .role(GroupMemberRole.MEMBER) + .groupRoleId(groupRoleId) .build(); } } diff --git a/src/main/java/flipnote/group/adapter/out/entity/GroupRoleEntity.java b/src/main/java/flipnote/group/adapter/out/entity/GroupRoleEntity.java new file mode 100644 index 0000000..bbb3833 --- /dev/null +++ b/src/main/java/flipnote/group/adapter/out/entity/GroupRoleEntity.java @@ -0,0 +1,46 @@ +package flipnote.group.adapter.out.entity; + +import flipnote.group.domain.model.member.GroupMemberRole; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "group_roles", + uniqueConstraints = @UniqueConstraint( + name = "uk_group_roles_group_name", + columnNames = {"group_id", "name"} + ) +) +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class GroupRoleEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "group_id", nullable = false) + private Long groupId; + + @Enumerated(EnumType.STRING) + @Column(nullable = false, length = 50) + private GroupMemberRole name; + + @Builder + private GroupRoleEntity(Long groupId, GroupMemberRole name) { + this.groupId = groupId; + this.name = name; + } +} + diff --git a/src/main/java/flipnote/group/adapter/out/entity/GroupRolePermissionEntity.java b/src/main/java/flipnote/group/adapter/out/entity/GroupRolePermissionEntity.java new file mode 100644 index 0000000..a23fe22 --- /dev/null +++ b/src/main/java/flipnote/group/adapter/out/entity/GroupRolePermissionEntity.java @@ -0,0 +1,45 @@ +package flipnote.group.adapter.out.entity; + +import flipnote.group.domain.model.member.GroupMemberRole; +import flipnote.group.domain.model.permission.GroupPermission; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "group_role_permissions", + uniqueConstraints = @UniqueConstraint( + name = "uk_grp_role_perm", + columnNames = {"group_role_id", "permission"} + ) +) +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class GroupRolePermissionEntity { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "group_role_id", nullable = false) + private Long groupRoleId; + + @Enumerated(EnumType.STRING) + @Column(nullable = false, length = 50) + private GroupPermission permission; + + @Builder + private GroupRolePermissionEntity(Long groupRoleId, GroupPermission permission) { + this.groupRoleId = groupRoleId; + this.permission = permission; + } +} diff --git a/src/main/java/flipnote/group/domain/model/permission/.gitkeep b/src/main/java/flipnote/group/domain/model/permission/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/flipnote/group/domain/model/permission/GroupMemberRole.java b/src/main/java/flipnote/group/domain/model/permission/GroupMemberRole.java new file mode 100644 index 0000000..c6c1db2 --- /dev/null +++ b/src/main/java/flipnote/group/domain/model/permission/GroupMemberRole.java @@ -0,0 +1,5 @@ +package flipnote.group.domain.model.permission; + +public enum GroupMemberRole { + OWNER, HEAD_MANAGER, MANAGER, STAFF, MEMBER +} diff --git a/src/main/java/flipnote/group/domain/model/permission/GroupPermission.java b/src/main/java/flipnote/group/domain/model/permission/GroupPermission.java new file mode 100644 index 0000000..8423970 --- /dev/null +++ b/src/main/java/flipnote/group/domain/model/permission/GroupPermission.java @@ -0,0 +1,5 @@ +package flipnote.group.domain.model.permission; + +public enum GroupPermission { + INVITE, KICK, JOIN_REQUEST_MANAGE +} From 602fa0cf9ba704a34179ce6801dd291be17dcab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=84=9D=EB=B2=94?= Date: Thu, 12 Feb 2026 00:42:45 +0900 Subject: [PATCH 2/8] =?UTF-8?q?Feat:=20=EA=B7=B8=EB=A3=B9=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=8B=9C=20=EA=B6=8C=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ssionEntity.java => PermissionEntity.java} | 12 ++- .../{GroupRoleEntity.java => RoleEntity.java} | 19 +++-- .../GroupMemberRepositoryAdapter.java | 6 +- .../GroupRoleRepositoryAdapter.java | 82 +++++++++++++++++++ .../persistence/mapper/GroupMemberMapper.java | 8 +- .../port/out/GroupMemberRepositoryPort.java | 2 +- .../port/out/GroupRoleRepositoryPort.java | 5 ++ .../service/CreateGroupService.java | 9 +- .../jpa/GroupRolePermissionRepository.java | 8 ++ .../persistence/jpa/GroupRoleRepository.java | 8 ++ 10 files changed, 138 insertions(+), 21 deletions(-) rename src/main/java/flipnote/group/adapter/out/entity/{GroupRolePermissionEntity.java => PermissionEntity.java} (78%) rename src/main/java/flipnote/group/adapter/out/entity/{GroupRoleEntity.java => RoleEntity.java} (69%) create mode 100644 src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java create mode 100644 src/main/java/flipnote/group/application/port/out/GroupRoleRepositoryPort.java create mode 100644 src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRolePermissionRepository.java create mode 100644 src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRoleRepository.java diff --git a/src/main/java/flipnote/group/adapter/out/entity/GroupRolePermissionEntity.java b/src/main/java/flipnote/group/adapter/out/entity/PermissionEntity.java similarity index 78% rename from src/main/java/flipnote/group/adapter/out/entity/GroupRolePermissionEntity.java rename to src/main/java/flipnote/group/adapter/out/entity/PermissionEntity.java index a23fe22..530cf0e 100644 --- a/src/main/java/flipnote/group/adapter/out/entity/GroupRolePermissionEntity.java +++ b/src/main/java/flipnote/group/adapter/out/entity/PermissionEntity.java @@ -1,6 +1,5 @@ package flipnote.group.adapter.out.entity; -import flipnote.group.domain.model.member.GroupMemberRole; import flipnote.group.domain.model.permission.GroupPermission; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -25,7 +24,7 @@ ) @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class GroupRolePermissionEntity { +public class PermissionEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -38,8 +37,15 @@ public class GroupRolePermissionEntity { private GroupPermission permission; @Builder - private GroupRolePermissionEntity(Long groupRoleId, GroupPermission permission) { + private PermissionEntity(Long groupRoleId, GroupPermission permission) { this.groupRoleId = groupRoleId; this.permission = permission; } + + public static PermissionEntity create(Long groupRoleId, GroupPermission permission) { + return PermissionEntity.builder() + .groupRoleId(groupRoleId) + .permission(permission) + .build(); + } } diff --git a/src/main/java/flipnote/group/adapter/out/entity/GroupRoleEntity.java b/src/main/java/flipnote/group/adapter/out/entity/RoleEntity.java similarity index 69% rename from src/main/java/flipnote/group/adapter/out/entity/GroupRoleEntity.java rename to src/main/java/flipnote/group/adapter/out/entity/RoleEntity.java index bbb3833..58bf25f 100644 --- a/src/main/java/flipnote/group/adapter/out/entity/GroupRoleEntity.java +++ b/src/main/java/flipnote/group/adapter/out/entity/RoleEntity.java @@ -19,12 +19,12 @@ @Table(name = "group_roles", uniqueConstraints = @UniqueConstraint( name = "uk_group_roles_group_name", - columnNames = {"group_id", "name"} + columnNames = {"group_id", "role"} ) ) @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class GroupRoleEntity { +public class RoleEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -34,13 +34,20 @@ public class GroupRoleEntity { private Long groupId; @Enumerated(EnumType.STRING) - @Column(nullable = false, length = 50) - private GroupMemberRole name; + @Column(nullable = false, length = 50, name = "group_role") + private GroupMemberRole role; @Builder - private GroupRoleEntity(Long groupId, GroupMemberRole name) { + private RoleEntity(Long groupId, GroupMemberRole role) { this.groupId = groupId; - this.name = name; + this.role = role; + } + + public static RoleEntity create(Long groupId, GroupMemberRole groupMemberRole) { + return RoleEntity.builder() + .groupId(groupId) + .role(groupMemberRole) + .build(); } } diff --git a/src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java b/src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java index ad903b3..3f0026f 100644 --- a/src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java +++ b/src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java @@ -15,12 +15,12 @@ public class GroupMemberRepositoryAdapter implements GroupMemberRepositoryPort { private final GroupMemberRepository groupMemberRepository; /** - * 오너일 경우 + * * @param groupId * @param userId */ @Override - public void saveOwner(Long groupId, Long userId) { - groupMemberRepository.save(GroupMemberMapper.createOwner(groupId, userId)); + public void save(Long groupId, Long userId, Long roleId) { + groupMemberRepository.save(GroupMemberMapper.create(groupId, userId, roleId)); } } diff --git a/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java b/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java new file mode 100644 index 0000000..dcda0c5 --- /dev/null +++ b/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java @@ -0,0 +1,82 @@ +package flipnote.group.adapter.out.persistence; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Repository; + +import flipnote.group.adapter.out.entity.PermissionEntity; +import flipnote.group.adapter.out.entity.RoleEntity; +import flipnote.group.application.port.out.GroupRoleRepositoryPort; +import flipnote.group.domain.model.member.GroupMemberRole; +import flipnote.group.domain.model.permission.GroupPermission; +import flipnote.group.infrastructure.persistence.jpa.GroupRolePermissionRepository; +import flipnote.group.infrastructure.persistence.jpa.GroupRoleRepository; +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class GroupRoleRepositoryAdapter implements GroupRoleRepositoryPort { + + private final GroupRoleRepository groupRoleRepository; + private final GroupRolePermissionRepository groupRolePermissionRepository; + + private static final Map> DEFAULT_PERMS_BY_ROLE = + Map.of( + GroupMemberRole.OWNER, List.of( + GroupPermission.INVITE, + GroupPermission.KICK, + GroupPermission.JOIN_REQUEST_MANAGE + ), + GroupMemberRole.HEAD_MANAGER, List.of( + GroupPermission.INVITE, + GroupPermission.KICK, + GroupPermission.JOIN_REQUEST_MANAGE + ), + GroupMemberRole.MANAGER, List.of( + GroupPermission.INVITE, + GroupPermission.KICK, + GroupPermission.JOIN_REQUEST_MANAGE + ), + GroupMemberRole.STAFF, List.of( + GroupPermission.INVITE, + GroupPermission.KICK, + GroupPermission.JOIN_REQUEST_MANAGE + ), + GroupMemberRole.MEMBER, List.of() + ); + + /** + * 그룹 생성시 역할도 추가 + * @param groupId + * @return + */ + @Override + public Long create(Long groupId) { + // 오너 역할 생성 + Map roleIdByRole = Arrays.stream(new GroupMemberRole[]{ + GroupMemberRole.OWNER, + GroupMemberRole.HEAD_MANAGER, + GroupMemberRole.MANAGER, + GroupMemberRole.STAFF, + GroupMemberRole.MEMBER + }) + .collect(java.util.stream.Collectors.toMap( + role -> role, + role -> groupRoleRepository.save(RoleEntity.create(groupId, role)).getId() + )); + + // 역할별 기본 권한 세팅 (role-permission 매핑 생성) + List perms = DEFAULT_PERMS_BY_ROLE.entrySet().stream() + .flatMap(e -> e.getValue().stream() + .map(p -> PermissionEntity.create(roleIdByRole.get(e.getKey()), p)) + ) + .toList(); + + groupRolePermissionRepository.saveAll(perms); + + // 그룹 생성자에게 OWNER roleId 리턴 (바깥에서 group_members 생성할 때 사용) + return roleIdByRole.get(GroupMemberRole.OWNER); + } +} diff --git a/src/main/java/flipnote/group/adapter/out/persistence/mapper/GroupMemberMapper.java b/src/main/java/flipnote/group/adapter/out/persistence/mapper/GroupMemberMapper.java index 5d1e4b7..4dbacc2 100644 --- a/src/main/java/flipnote/group/adapter/out/persistence/mapper/GroupMemberMapper.java +++ b/src/main/java/flipnote/group/adapter/out/persistence/mapper/GroupMemberMapper.java @@ -10,11 +10,7 @@ @Component @NoArgsConstructor(access = AccessLevel.PRIVATE) public class GroupMemberMapper { - public static GroupMemberEntity createOwner(Long groupId, Long userId) { - return GroupMemberEntity.builder() - .groupId(groupId) - .userId(userId) - .role(GroupMemberRole.OWNER) - .build(); + public static GroupMemberEntity create(Long groupId, Long userId, Long roleId) { + return GroupMemberEntity.create(groupId, userId, roleId); } } diff --git a/src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java b/src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java index 5858851..eac2ee4 100644 --- a/src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java +++ b/src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java @@ -1,5 +1,5 @@ package flipnote.group.application.port.out; public interface GroupMemberRepositoryPort { - void saveOwner(Long groupId, Long userId); + void save(Long groupId, Long userId, Long roleId); } diff --git a/src/main/java/flipnote/group/application/port/out/GroupRoleRepositoryPort.java b/src/main/java/flipnote/group/application/port/out/GroupRoleRepositoryPort.java new file mode 100644 index 0000000..6712442 --- /dev/null +++ b/src/main/java/flipnote/group/application/port/out/GroupRoleRepositoryPort.java @@ -0,0 +1,5 @@ +package flipnote.group.application.port.out; + +public interface GroupRoleRepositoryPort { + Long create(Long groupId); +} diff --git a/src/main/java/flipnote/group/application/service/CreateGroupService.java b/src/main/java/flipnote/group/application/service/CreateGroupService.java index 88bd774..89db017 100644 --- a/src/main/java/flipnote/group/application/service/CreateGroupService.java +++ b/src/main/java/flipnote/group/application/service/CreateGroupService.java @@ -9,6 +9,7 @@ import flipnote.group.application.port.in.result.CreateGroupResult; import flipnote.group.application.port.out.GroupMemberRepositoryPort; import flipnote.group.application.port.out.GroupRepositoryPort; +import flipnote.group.application.port.out.GroupRoleRepositoryPort; import flipnote.group.domain.model.group.Group; import lombok.RequiredArgsConstructor; @@ -18,6 +19,7 @@ public class CreateGroupService implements CreateGroupUseCase { private final GroupRepositoryPort groupRepository; private final GroupMemberRepositoryPort groupMemberRepository; + private final GroupRoleRepositoryPort groupRoleRepository; /** * 그룹 생성 @@ -33,9 +35,12 @@ public CreateGroupResult create(CreateGroupCommand cmd) { //그룹 도메인 -> 엔티티 변환 후 저장 Long groupId = groupRepository.saveNewGroup(domainGroup); + + //그룹 역할 생성 + Long roleId = groupRoleRepository.create(groupId); - //그룹 멤버 저장 - groupMemberRepository.saveOwner(groupId, cmd.userId()); + //생성자 오너 역할로 저장 + groupMemberRepository.save(groupId, cmd.userId(), roleId); return new CreateGroupResult(groupId); } diff --git a/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRolePermissionRepository.java b/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRolePermissionRepository.java new file mode 100644 index 0000000..c935cca --- /dev/null +++ b/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRolePermissionRepository.java @@ -0,0 +1,8 @@ +package flipnote.group.infrastructure.persistence.jpa; + +import org.springframework.data.jpa.repository.JpaRepository; + +import flipnote.group.adapter.out.entity.PermissionEntity; + +public interface GroupRolePermissionRepository extends JpaRepository { +} diff --git a/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRoleRepository.java b/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRoleRepository.java new file mode 100644 index 0000000..6d36c9e --- /dev/null +++ b/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRoleRepository.java @@ -0,0 +1,8 @@ +package flipnote.group.infrastructure.persistence.jpa; + +import org.springframework.data.jpa.repository.JpaRepository; + +import flipnote.group.adapter.out.entity.RoleEntity; + +public interface GroupRoleRepository extends JpaRepository { +} From e91d8aa32aad7c7c7f0e136230d132470f567a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=84=9D=EB=B2=94?= Date: Thu, 12 Feb 2026 01:03:03 +0900 Subject: [PATCH 3/8] =?UTF-8?q?Feat:=20=EA=B7=B8=EB=A3=B9=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=9D=B4=EB=82=98=20=EC=82=AD=EC=A0=9C=EC=8B=9C=20?= =?UTF-8?q?=EC=98=A4=EB=84=88=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=EB=A7=8C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../persistence/GroupRoleRepositoryAdapter.java | 17 +++++++++++++++++ .../port/out/GroupRoleRepositoryPort.java | 4 ++++ .../application/service/ChangeGroupService.java | 12 ++++++++++-- .../application/service/DeleteGroupService.java | 12 ++++++++++++ .../model/permission/GroupMemberRole.java | 5 ----- .../persistence/jpa/GroupMemberRepository.java | 1 + .../persistence/jpa/GroupRoleRepository.java | 2 ++ 7 files changed, 46 insertions(+), 7 deletions(-) delete mode 100644 src/main/java/flipnote/group/domain/model/permission/GroupMemberRole.java diff --git a/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java b/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java index dcda0c5..9633898 100644 --- a/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java +++ b/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java @@ -11,6 +11,7 @@ import flipnote.group.application.port.out.GroupRoleRepositoryPort; import flipnote.group.domain.model.member.GroupMemberRole; import flipnote.group.domain.model.permission.GroupPermission; +import flipnote.group.infrastructure.persistence.jpa.GroupMemberRepository; import flipnote.group.infrastructure.persistence.jpa.GroupRolePermissionRepository; import flipnote.group.infrastructure.persistence.jpa.GroupRoleRepository; import lombok.RequiredArgsConstructor; @@ -21,6 +22,7 @@ public class GroupRoleRepositoryAdapter implements GroupRoleRepositoryPort { private final GroupRoleRepository groupRoleRepository; private final GroupRolePermissionRepository groupRolePermissionRepository; + private final GroupMemberRepository groupMemberRepository; private static final Map> DEFAULT_PERMS_BY_ROLE = Map.of( @@ -79,4 +81,19 @@ public Long create(Long groupId) { // 그룹 생성자에게 OWNER roleId 리턴 (바깥에서 group_members 생성할 때 사용) return roleIdByRole.get(GroupMemberRole.OWNER); } + + /** + * 해당 유저가 그룹 내에 역할인지 확인 + * 오너 여부에서 사용 + * @param userId + * @param groupId + * @param groupMemberRole + * @return + */ + @Override + public boolean checkRole(Long userId, Long groupId, GroupMemberRole groupMemberRole) { + RoleEntity roleEntity = groupRoleRepository.findByGroupIdAndRole(groupId, groupMemberRole); + + return groupMemberRepository.existsByUserIdAndGroupRoleId(userId, roleEntity.getId()); + } } diff --git a/src/main/java/flipnote/group/application/port/out/GroupRoleRepositoryPort.java b/src/main/java/flipnote/group/application/port/out/GroupRoleRepositoryPort.java index 6712442..bb61247 100644 --- a/src/main/java/flipnote/group/application/port/out/GroupRoleRepositoryPort.java +++ b/src/main/java/flipnote/group/application/port/out/GroupRoleRepositoryPort.java @@ -1,5 +1,9 @@ package flipnote.group.application.port.out; +import flipnote.group.domain.model.member.GroupMemberRole; + public interface GroupRoleRepositoryPort { Long create(Long groupId); + + boolean checkRole(Long userId, Long groupId, GroupMemberRole groupMemberRole); } diff --git a/src/main/java/flipnote/group/application/service/ChangeGroupService.java b/src/main/java/flipnote/group/application/service/ChangeGroupService.java index d72fecb..948e34a 100644 --- a/src/main/java/flipnote/group/application/service/ChangeGroupService.java +++ b/src/main/java/flipnote/group/application/service/ChangeGroupService.java @@ -1,15 +1,15 @@ package flipnote.group.application.service; -import java.util.Optional; - import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import flipnote.group.adapter.out.entity.GroupEntity; +import flipnote.group.adapter.out.persistence.GroupRoleRepositoryAdapter; import flipnote.group.adapter.out.persistence.mapper.GroupMapper; import flipnote.group.application.port.in.ChangeGroupUseCase; import flipnote.group.application.port.in.command.ChangeGroupCommand; import flipnote.group.application.port.in.result.ChangeGroupResult; +import flipnote.group.domain.model.member.GroupMemberRole; import flipnote.group.infrastructure.persistence.jpa.GroupRepository; import lombok.RequiredArgsConstructor; @@ -18,6 +18,7 @@ public class ChangeGroupService implements ChangeGroupUseCase { private final GroupRepository jpaGroupRepository; + private final GroupRoleRepositoryAdapter groupRoleRepository; /** * 그룹 수정 @@ -32,6 +33,13 @@ public ChangeGroupResult change(ChangeGroupCommand cmd) { () -> new IllegalArgumentException("group not Exists") ); + //오너 인지 확인 + boolean isOwner = groupRoleRepository.checkRole(cmd.userId(), entity.getId(), GroupMemberRole.OWNER); + + if(!isOwner) { + throw new IllegalArgumentException("not owner"); + } + entity.change(cmd); return new ChangeGroupResult(GroupMapper.toDomain(entity)); diff --git a/src/main/java/flipnote/group/application/service/DeleteGroupService.java b/src/main/java/flipnote/group/application/service/DeleteGroupService.java index dbf6b86..78fb02f 100644 --- a/src/main/java/flipnote/group/application/service/DeleteGroupService.java +++ b/src/main/java/flipnote/group/application/service/DeleteGroupService.java @@ -5,6 +5,8 @@ import flipnote.group.application.port.in.DeleteGroupUseCase; import flipnote.group.application.port.in.command.DeleteGroupCommand; import flipnote.group.application.port.out.GroupRepositoryPort; +import flipnote.group.application.port.out.GroupRoleRepositoryPort; +import flipnote.group.domain.model.member.GroupMemberRole; import lombok.RequiredArgsConstructor; @Service @@ -12,9 +14,19 @@ public class DeleteGroupService implements DeleteGroupUseCase { private final GroupRepositoryPort groupRepository; + private final GroupRoleRepositoryPort groupRoleRepository; @Override public void deleteGroup(DeleteGroupCommand cmd) { + + //오너 인지 확인 + boolean isOwner = groupRoleRepository.checkRole(cmd.userId(), cmd.groupId(), GroupMemberRole.OWNER); + + //오너가 아닐 경우 삭제 + if(!isOwner) { + throw new IllegalArgumentException("not owner"); + } + groupRepository.delete(cmd.groupId()); } diff --git a/src/main/java/flipnote/group/domain/model/permission/GroupMemberRole.java b/src/main/java/flipnote/group/domain/model/permission/GroupMemberRole.java deleted file mode 100644 index c6c1db2..0000000 --- a/src/main/java/flipnote/group/domain/model/permission/GroupMemberRole.java +++ /dev/null @@ -1,5 +0,0 @@ -package flipnote.group.domain.model.permission; - -public enum GroupMemberRole { - OWNER, HEAD_MANAGER, MANAGER, STAFF, MEMBER -} diff --git a/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupMemberRepository.java b/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupMemberRepository.java index 4da80d7..06bdc5d 100644 --- a/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupMemberRepository.java +++ b/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupMemberRepository.java @@ -5,4 +5,5 @@ import flipnote.group.adapter.out.entity.GroupMemberEntity; public interface GroupMemberRepository extends JpaRepository { + boolean existsByUserIdAndGroupRoleId(Long userId, Long id); } diff --git a/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRoleRepository.java b/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRoleRepository.java index 6d36c9e..cc6bd33 100644 --- a/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRoleRepository.java +++ b/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupRoleRepository.java @@ -3,6 +3,8 @@ import org.springframework.data.jpa.repository.JpaRepository; import flipnote.group.adapter.out.entity.RoleEntity; +import flipnote.group.domain.model.member.GroupMemberRole; public interface GroupRoleRepository extends JpaRepository { + RoleEntity findByGroupIdAndRole(Long groupId, GroupMemberRole groupMemberRole); } From dab6a729ad5beb55b401ad8f4c8ca6c3ae63ed1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=84=9D=EB=B2=94?= Date: Thu, 12 Feb 2026 16:14:04 +0900 Subject: [PATCH 4/8] =?UTF-8?q?Fix:=20=EA=B7=B8=EB=A3=B9=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flipnote/group/domain/model/permission/GroupPermission.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/flipnote/group/domain/model/permission/GroupPermission.java b/src/main/java/flipnote/group/domain/model/permission/GroupPermission.java index 8423970..0a68e81 100644 --- a/src/main/java/flipnote/group/domain/model/permission/GroupPermission.java +++ b/src/main/java/flipnote/group/domain/model/permission/GroupPermission.java @@ -1,5 +1,5 @@ package flipnote.group.domain.model.permission; public enum GroupPermission { - INVITE, KICK, JOIN_REQUEST_MANAGE + KICK, JOIN_REQUEST_MANAGE } From 24ce2d11af0aba92b5882fb4c0f77ce0b00762b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=84=9D=EB=B2=94?= Date: Thu, 12 Feb 2026 16:19:16 +0900 Subject: [PATCH 5/8] =?UTF-8?q?Fix:=20=EA=B7=B8=EB=A3=B9=20=EC=97=AD?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/persistence/GroupRoleRepositoryAdapter.java | 9 --------- .../group/domain/model/member/GroupMemberRole.java | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java b/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java index 9633898..ca757da 100644 --- a/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java +++ b/src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java @@ -27,22 +27,14 @@ public class GroupRoleRepositoryAdapter implements GroupRoleRepositoryPort { private static final Map> DEFAULT_PERMS_BY_ROLE = Map.of( GroupMemberRole.OWNER, List.of( - GroupPermission.INVITE, GroupPermission.KICK, GroupPermission.JOIN_REQUEST_MANAGE ), GroupMemberRole.HEAD_MANAGER, List.of( - GroupPermission.INVITE, GroupPermission.KICK, GroupPermission.JOIN_REQUEST_MANAGE ), GroupMemberRole.MANAGER, List.of( - GroupPermission.INVITE, - GroupPermission.KICK, - GroupPermission.JOIN_REQUEST_MANAGE - ), - GroupMemberRole.STAFF, List.of( - GroupPermission.INVITE, GroupPermission.KICK, GroupPermission.JOIN_REQUEST_MANAGE ), @@ -61,7 +53,6 @@ public Long create(Long groupId) { GroupMemberRole.OWNER, GroupMemberRole.HEAD_MANAGER, GroupMemberRole.MANAGER, - GroupMemberRole.STAFF, GroupMemberRole.MEMBER }) .collect(java.util.stream.Collectors.toMap( diff --git a/src/main/java/flipnote/group/domain/model/member/GroupMemberRole.java b/src/main/java/flipnote/group/domain/model/member/GroupMemberRole.java index 4ca3784..e707111 100644 --- a/src/main/java/flipnote/group/domain/model/member/GroupMemberRole.java +++ b/src/main/java/flipnote/group/domain/model/member/GroupMemberRole.java @@ -1,5 +1,5 @@ package flipnote.group.domain.model.member; public enum GroupMemberRole { - OWNER, HEAD_MANAGER, MANAGER, STAFF, MEMBER + OWNER, HEAD_MANAGER, MANAGER, MEMBER } From 3dcb17e4d4935d30c078529531f378d65c4e6bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=84=9D=EB=B2=94?= Date: Fri, 13 Feb 2026 22:36:10 +0900 Subject: [PATCH 6/8] =?UTF-8?q?Chore:=20todo=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/flipnote/group/adapter/in/web/GroupController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/flipnote/group/adapter/in/web/GroupController.java b/src/main/java/flipnote/group/adapter/in/web/GroupController.java index a76b0bd..02b1987 100644 --- a/src/main/java/flipnote/group/adapter/in/web/GroupController.java +++ b/src/main/java/flipnote/group/adapter/in/web/GroupController.java @@ -143,4 +143,6 @@ public ResponseEntity deleteGroup( //todo 내가 생성한 그룹 전체 조회 + //todo 하위 권한 수정 + } From d8a5ee198528c5eaca9471210c70fcc1a416a4e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=84=9D=EB=B2=94?= Date: Fri, 13 Feb 2026 22:47:31 +0900 Subject: [PATCH 7/8] =?UTF-8?q?Chore:=20=EC=A3=BC=EC=84=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flipnote/group/application/service/DeleteGroupService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/flipnote/group/application/service/DeleteGroupService.java b/src/main/java/flipnote/group/application/service/DeleteGroupService.java index 2269488..5c6ea6e 100644 --- a/src/main/java/flipnote/group/application/service/DeleteGroupService.java +++ b/src/main/java/flipnote/group/application/service/DeleteGroupService.java @@ -24,7 +24,7 @@ public void deleteGroup(DeleteGroupCommand cmd) { //오너 인지 확인 boolean isOwner = groupRoleRepository.checkRole(cmd.userId(), cmd.groupId(), GroupMemberRole.OWNER); - //오너가 아닐 경우 삭제 + //오너가 아닐 경우 에러 발생 if(!isOwner) { throw new IllegalArgumentException("not owner"); } From fc0211276e475d3deab1e2249408fddb4e0d7916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=84=9D=EB=B2=94?= Date: Fri, 13 Feb 2026 22:47:53 +0900 Subject: [PATCH 8/8] =?UTF-8?q?Feat:=20=EA=B7=B8=EB=A3=B9=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=EC=8B=9C=20=EB=82=B4=EA=B0=80=20=EA=B0=80=EC=9E=85?= =?UTF-8?q?=ED=95=9C=20=EA=B7=B8=EB=A3=B9=EB=A7=8C=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../persistence/GroupMemberRepositoryAdapter.java | 13 ++++++++++++- .../port/out/GroupMemberRepositoryPort.java | 2 ++ .../group/application/service/FindGroupService.java | 9 +++++++++ .../persistence/jpa/GroupMemberRepository.java | 2 ++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java b/src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java index 3f0026f..3763430 100644 --- a/src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java +++ b/src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java @@ -15,7 +15,7 @@ public class GroupMemberRepositoryAdapter implements GroupMemberRepositoryPort { private final GroupMemberRepository groupMemberRepository; /** - * + * 그룹 멤버 저장 * @param groupId * @param userId */ @@ -23,4 +23,15 @@ public class GroupMemberRepositoryAdapter implements GroupMemberRepositoryPort { public void save(Long groupId, Long userId, Long roleId) { groupMemberRepository.save(GroupMemberMapper.create(groupId, userId, roleId)); } + + /** + * 유저가 그룹 내에 있는지 체크 + * @param groupId + * @param userId + * @return + */ + @Override + public boolean existsUserInGroup(Long groupId, Long userId) { + return groupMemberRepository.existsByGroupIdAndUserId(groupId, userId); + } } diff --git a/src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java b/src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java index eac2ee4..5f93ec1 100644 --- a/src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java +++ b/src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java @@ -2,4 +2,6 @@ public interface GroupMemberRepositoryPort { void save(Long groupId, Long userId, Long roleId); + + boolean existsUserInGroup(Long groupId, Long userId); } diff --git a/src/main/java/flipnote/group/application/service/FindGroupService.java b/src/main/java/flipnote/group/application/service/FindGroupService.java index 700ec9c..3e0673d 100644 --- a/src/main/java/flipnote/group/application/service/FindGroupService.java +++ b/src/main/java/flipnote/group/application/service/FindGroupService.java @@ -9,6 +9,7 @@ import flipnote.group.application.port.in.FindGroupUseCase; import flipnote.group.application.port.in.command.FindGroupCommand; import flipnote.group.application.port.in.result.FindGroupResult; +import flipnote.group.application.port.out.GroupMemberRepositoryPort; import flipnote.group.application.port.out.GroupRepositoryPort; import flipnote.group.domain.model.group.Group; import lombok.RequiredArgsConstructor; @@ -18,6 +19,7 @@ public class FindGroupService implements FindGroupUseCase { private final GroupRepositoryPort groupRepository; + private final GroupMemberRepositoryPort groupMemberRepository; /** * 하나의 그룹에 대한 정보 조회 @@ -27,6 +29,13 @@ public class FindGroupService implements FindGroupUseCase { @Override public FindGroupResult findGroup(FindGroupCommand cmd) { + // 유저가 그룹 내에 존재하는지 확인 + boolean isMember = groupMemberRepository.existsUserInGroup(cmd.groupId(), cmd.userId()); + + if(!isMember) { + throw new IllegalArgumentException("user not in Group"); + } + Group group = groupRepository.findById(cmd.groupId()); return new FindGroupResult(group); diff --git a/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupMemberRepository.java b/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupMemberRepository.java index 06bdc5d..b0294a5 100644 --- a/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupMemberRepository.java +++ b/src/main/java/flipnote/group/infrastructure/persistence/jpa/GroupMemberRepository.java @@ -6,4 +6,6 @@ public interface GroupMemberRepository extends JpaRepository { boolean existsByUserIdAndGroupRoleId(Long userId, Long id); + + boolean existsByGroupIdAndUserId(Long groupId, Long userId); }