From cc74628107ae1aed6f263e8d55fe23e04c3621ca Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 23 Feb 2026 14:08:23 +0900 Subject: [PATCH] =?UTF-8?q?fix(block-member):=20=EC=96=91=EB=B0=A9?= =?UTF-8?q?=ED=96=A5=20=EC=B0=A8=EB=8B=A8=20=EA=B4=80=EA=B3=84=EC=9D=98=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=C2=B7=EC=9D=91=EC=9B=90=C2=B7=EC=BD=98?= =?UTF-8?q?=ED=85=90=EC=B8=A0=20=EB=85=B8=EC=B6=9C=EC=9D=84=20=EC=B0=A8?= =?UTF-8?q?=EB=8B=A8=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...260223_차단유저댓글및크리에이터노출차단.md | 17 ++++ .../sodalive/api/live/LiveApiService.kt | 4 +- .../content/AudioContentController.kt | 2 + .../content/AudioContentRepository.kt | 60 +++++++++---- .../sodalive/content/AudioContentService.kt | 24 ++++-- .../content/category/CategoryService.kt | 3 +- .../comment/AudioContentCommentController.kt | 1 + .../comment/AudioContentCommentRepository.kt | 34 +++++++- .../comment/AudioContentCommentService.kt | 25 +++++- .../content/main/AudioContentMainService.kt | 19 +++-- .../main/banner/AudioContentBannerService.kt | 9 +- .../curation/AudioContentCurationService.kt | 9 +- .../main/tab/AudioContentMainTabRepository.kt | 24 ++++-- .../ContentMainTabTagCurationRepository.kt | 12 ++- .../content/series/ContentSeriesRepository.kt | 84 +++++++++++++++---- .../content/series/ContentSeriesService.kt | 3 +- .../sodalive/explorer/ExplorerController.kt | 2 +- .../explorer/ExplorerQueryRepository.kt | 47 ++++++++--- .../sodalive/explorer/ExplorerService.kt | 48 +++++++---- .../CreatorCommunityController.kt | 1 + .../CreatorCommunityService.kt | 38 +++++++-- .../CreatorCommunityCommentRepository.kt | 34 +++++++- .../live/recommend/LiveRecommendService.kt | 19 +++-- .../sodalive/live/room/LiveRoomRepository.kt | 36 ++++++-- .../sodalive/live/room/LiveRoomService.kt | 25 +++++- .../sodalive/member/MemberService.kt | 7 +- .../RecommendChannelQueryRepository.kt | 24 ++++-- .../sodalive/search/SearchRepository.kt | 72 ++++++++++++---- 28 files changed, 528 insertions(+), 155 deletions(-) create mode 100644 docs/20260223_차단유저댓글및크리에이터노출차단.md diff --git a/docs/20260223_차단유저댓글및크리에이터노출차단.md b/docs/20260223_차단유저댓글및크리에이터노출차단.md new file mode 100644 index 00000000..73ddb3fc --- /dev/null +++ b/docs/20260223_차단유저댓글및크리에이터노출차단.md @@ -0,0 +1,17 @@ +# 차단 유저 댓글 및 크리에이터 노출 차단 구현 + +- [x] 차단(`BlockMember`) 데이터 접근 패턴 및 기존 필터 지점 확인 +- [x] 콘텐츠 댓글 목록에서 차단한 유저 댓글 비노출 적용 +- [x] 채널 응원 목록에서 차단한 유저 댓글 비노출 적용 +- [x] 커뮤니티 댓글 목록에서 차단한 유저 댓글 비노출 적용 +- [x] 차단한 크리에이터의 콘텐츠/라이브 비노출 동작 보강 +- [x] 변경 파일 진단 및 테스트/빌드 검증 + +## 검증 기록 + +- 무엇을: 리뷰에서 지적된 단방향 차단 누락을 기준으로 콘텐츠/라이브/콘텐츠 댓글/커뮤니티 댓글/채널 응원(cheers) 노출 경로를 재점검해, 한쪽이라도 차단 관계면 조회·검색·상세 접근에서 숨겨지도록 양방향 차단 로직으로 보강했다. `/explorer/profile/{id}/cheers`의 우회 접근도 양방향 차단으로 막았다. +- 왜: 사용자 차단 정책을 일관되게 적용해 차단한 유저와 차단한 크리에이터의 활동이 조회 결과에 보이지 않도록 하기 위함이다. +- 어떻게 검증했는가: + - `lsp_diagnostics`를 수정 Kotlin 파일들에 대해 실행했으나, 현재 환경에 `.kt` LSP 서버가 설정되어 있지 않아 진단 불가를 확인했다. + - `./gradlew test` 실행 성공. + - `./gradlew build -x test` 실행 성공(ktlint/check 포함). diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/api/live/LiveApiService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/api/live/LiveApiService.kt index 1bc1c8ad..81a756d9 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/api/live/LiveApiService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/api/live/LiveApiService.kt @@ -53,6 +53,7 @@ class LiveApiService( val latestFinishedLiveList = liveService.getLatestFinishedLive(member) val replayLive = contentService.getLatestContentByTheme( + memberId = memberId, theme = listOf("다시듣기"), contentType = contentType, isFree = false, @@ -60,7 +61,8 @@ class LiveApiService( ) .filter { content -> if (memberId != null) { - !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = content.creatorId) + !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = content.creatorId) && + !blockMemberRepository.isBlocked(blockedMemberId = content.creatorId, memberId = memberId) } else { true } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentController.kt index 46fd18da..ab0464b5 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentController.kt @@ -252,6 +252,7 @@ class AudioContentController(private val service: AudioContentService) { ApiResponse.ok( service.getLatestContentByTheme( + memberId = member.id!!, theme = if (theme == null) listOf() else listOf(theme), contentType = contentType ?: ContentType.ALL, offset = pageable.offset, @@ -272,6 +273,7 @@ class AudioContentController(private val service: AudioContentService) { ) = run { ApiResponse.ok( service.getLatestContentByTheme( + memberId = member?.id, theme = listOf("다시듣기"), contentType = contentType ?: ContentType.ALL, isFree = false, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt index aa1ae861..cf2ea86c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -469,9 +469,15 @@ class AudioContentQueryRepositoryImpl( limit: Long, isFree: Boolean ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) val orderBy = when (sortType) { SortType.NEWEST -> listOf(audioContent.releaseDate.desc(), audioContent.id.desc()) @@ -562,9 +568,15 @@ class AudioContentQueryRepositoryImpl( offset: Long, limit: Long ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) val orderBy = listOf(audioContent.releaseDate.desc(), audioContent.id.desc()) @@ -630,9 +642,15 @@ class AudioContentQueryRepositoryImpl( isAdult: Boolean, contentType: ContentType ): Int { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = audioContent.isActive.isTrue .and(audioContent.duration.isNotNull) @@ -960,9 +978,15 @@ class AudioContentQueryRepositoryImpl( offset: Long, limit: Long ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = audioContentCuration.isActive.isTrue .and(audioContentCurationItem.isActive.isTrue) @@ -1337,9 +1361,15 @@ class AudioContentQueryRepositoryImpl( locale: String? ): List { val blockMemberCondition = if (memberId != null) { - blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) } else { null } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt index 89922a4a..e810c95f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt @@ -524,6 +524,10 @@ class AudioContentService( val creator = explorerQueryRepository.getMember(creatorId) ?: throw SodaException(messageKey = "content.error.user_not_found") + if (isBlockedBetweenMembers(memberId = member.id!!, creatorId = creatorId)) { + throw SodaException(messageKey = "content.error.invalid_content_retry") + } + val creatorFollowing = explorerQueryRepository.getCreatorFollowing( creatorId = creatorId, memberId = member.id!! @@ -534,12 +538,6 @@ class AudioContentService( contentId = audioContent.id!! ) - // 차단된 사용자 체크 - val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = creatorId) - if (isBlocked && !isExistsAudioContent) { - throw SodaException(formatMessage("content.error.access_restricted_by_creator", creator.nickname)) - } - val orderSequence = if (isExistsAudioContent) { limitedEditionOrderRepository.getOrderSequence( contentId = audioContent.id!!, @@ -886,6 +884,10 @@ class AudioContentService( ): GetAudioContentListItem? { val isAdult = member.auth != null && isAdultContentVisible + if (isBlockedBetweenMembers(memberId = member.id!!, creatorId = creatorId)) { + return null + } + val audioContent = repository.findLatestContentByCreatorId(creatorId, isAdult) ?: return null val commentCount = commentRepository @@ -957,6 +959,10 @@ class AudioContentService( val isAdult = member.auth != null && isAdultContentVisible val isCreator = member.id == creatorId + if (!isCreator && isBlockedBetweenMembers(memberId = member.id!!, creatorId = creatorId)) { + return GetAudioContentListResponse(totalCount = 0, items = listOf()) + } + val totalCount = repository.findTotalCountByCreatorId( creatorId = creatorId, isCreator = isCreator, @@ -1313,8 +1319,8 @@ class AudioContentService( } } - private fun formatMessage(key: String, vararg args: Any): String { - val template = messageSource.getMessage(key, langContext.lang) ?: return "" - return String.format(template, *args) + private fun isBlockedBetweenMembers(memberId: Long, creatorId: Long): Boolean { + return blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId) || + blockMemberRepository.isBlocked(blockedMemberId = creatorId, memberId = memberId) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryService.kt index f42a1293..c2908021 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryService.kt @@ -128,7 +128,8 @@ class CategoryService( @Transactional fun getCategoryList(creatorId: Long, memberId: Long): List { - val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId) + val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId) || + blockMemberRepository.isBlocked(blockedMemberId = creatorId, memberId = memberId) if (isBlocked) throw SodaException(messageKey = "category.error.invalid_access") // 기본 카테고리 목록 조회 (원본 언어 기준) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt index 9a6e56cd..1f91f63f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentController.kt @@ -98,6 +98,7 @@ class AudioContentCommentController( return ApiResponse.ok( service.getCommentReplyList( commentId = commentId, + memberId = member.id!!, timezone = timezone, pageable = pageable ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentRepository.kt index 59f23dd6..90cd4530 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentRepository.kt @@ -1,6 +1,7 @@ package kr.co.vividnext.sodalive.content.comment import com.querydsl.core.types.dsl.Expressions +import com.querydsl.jpa.JPAExpressions import com.querydsl.jpa.impl.JPAQueryFactory import kr.co.vividnext.sodalive.content.QAudioContent.audioContent import kr.co.vividnext.sodalive.content.comment.QAudioContentComment.audioContentComment @@ -9,6 +10,7 @@ import kr.co.vividnext.sodalive.fcm.PushTokenInfo import kr.co.vividnext.sodalive.fcm.QPushToken.pushToken import kr.co.vividnext.sodalive.fcm.QPushTokenInfo import kr.co.vividnext.sodalive.member.QMember.member +import kr.co.vividnext.sodalive.member.block.QBlockMember.blockMember import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository import java.time.LocalDateTime @@ -28,10 +30,11 @@ interface AudioContentCommentQueryRepository { ): List fun totalCountCommentByContentId(contentId: Long, memberId: Long, isContentCreator: Boolean): Int - fun commentReplyCountByAudioContentCommentId(commentId: Long): Int + fun commentReplyCountByAudioContentCommentId(commentId: Long, memberId: Long): Int fun getAudioContentCommentReplyList( cloudFrontHost: String, commentId: Long, + memberId: Long, timezone: String, offset: Long, limit: Int @@ -60,6 +63,8 @@ class AudioContentCommentQueryRepositoryImpl( var where = audioContentComment.audioContent.id.eq(contentId) .and(audioContentComment.isActive.isTrue) .and(audioContentComment.parent.isNull) + .and(audioContentComment.member.id.notIn(blockedMemberIdSubQuery(memberId))) + .and(audioContentComment.member.id.notIn(blockingMemberIdSubQuery(memberId))) if (!isContentCreator) { where = where.and( @@ -106,7 +111,7 @@ class AudioContentCommentQueryRepositoryImpl( .map { it.copy( nickname = it.nickname.removeDeletedNicknamePrefix(), - replyCount = commentReplyCountByAudioContentCommentId(it.id) + replyCount = commentReplyCountByAudioContentCommentId(it.id, memberId) ) } } @@ -115,6 +120,8 @@ class AudioContentCommentQueryRepositoryImpl( var where = audioContentComment.audioContent.id.eq(contentId) .and(audioContentComment.isActive.isTrue) .and(audioContentComment.parent.isNull) + .and(audioContentComment.member.id.notIn(blockedMemberIdSubQuery(memberId))) + .and(audioContentComment.member.id.notIn(blockingMemberIdSubQuery(memberId))) if (!isContentCreator) { where = where.and( @@ -133,13 +140,15 @@ class AudioContentCommentQueryRepositoryImpl( .size } - override fun commentReplyCountByAudioContentCommentId(commentId: Long): Int { + override fun commentReplyCountByAudioContentCommentId(commentId: Long, memberId: Long): Int { return queryFactory.select(audioContentComment.id) .from(audioContentComment) .where( audioContentComment.parent.isNotNull .and(audioContentComment.parent.id.eq(commentId)) .and(audioContentComment.isActive.isTrue) + .and(audioContentComment.member.id.notIn(blockedMemberIdSubQuery(memberId))) + .and(audioContentComment.member.id.notIn(blockingMemberIdSubQuery(memberId))) ) .fetch() .size @@ -148,6 +157,7 @@ class AudioContentCommentQueryRepositoryImpl( override fun getAudioContentCommentReplyList( cloudFrontHost: String, commentId: Long, + memberId: Long, timezone: String, offset: Long, limit: Int @@ -185,6 +195,8 @@ class AudioContentCommentQueryRepositoryImpl( audioContentComment.parent.isNotNull .and(audioContentComment.parent.id.eq(commentId)) .and(audioContentComment.isActive.isTrue) + .and(audioContentComment.member.id.notIn(blockedMemberIdSubQuery(memberId))) + .and(audioContentComment.member.id.notIn(blockingMemberIdSubQuery(memberId))) ) .offset(offset) .limit(limit.toLong()) @@ -244,4 +256,20 @@ class AudioContentCommentQueryRepositoryImpl( return response } + + private fun blockedMemberIdSubQuery(memberId: Long) = JPAExpressions + .select(blockMember.blockedMember.id) + .from(blockMember) + .where( + blockMember.member.id.eq(memberId) + .and(blockMember.isActive.isTrue) + ) + + private fun blockingMemberIdSubQuery(memberId: Long) = JPAExpressions + .select(blockMember.member.id) + .from(blockMember) + .where( + blockMember.blockedMember.id.eq(memberId) + .and(blockMember.isActive.isTrue) + ) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt index 401484ed..5413e497 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/comment/AudioContentCommentService.kt @@ -45,7 +45,7 @@ class AudioContentCommentService( ?: throw SodaException(messageKey = "content.error.invalid_content_retry") val creator = audioContent.member!! - val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = creator.id!!) + val isBlocked = isBlockedBetweenMembers(memberId = member.id!!, creatorId = creator.id!!) if (isBlocked) { throw SodaException(formatMessage("content.comment.error.blocked_by_creator", creator.nickname)) } @@ -136,6 +136,13 @@ class AudioContentCommentService( timezone: String, pageable: Pageable ): GetAudioContentCommentListResponse { + val audioContent = audioContentRepository.findByIdOrNull(id = audioContentId) + ?: return GetAudioContentCommentListResponse(totalCount = 0, items = listOf()) + + if (isBlockedBetweenMembers(memberId = memberId, creatorId = audioContent.member!!.id!!)) { + return GetAudioContentCommentListResponse(totalCount = 0, items = listOf()) + } + val isContentCreator = audioContentRepository.isContentCreator(audioContentId, memberId) val commentList = repository.findByContentId( cloudFrontHost = cloudFrontHost, @@ -157,17 +164,26 @@ class AudioContentCommentService( fun getCommentReplyList( commentId: Long, + memberId: Long, timezone: String, pageable: Pageable ): GetAudioContentCommentListResponse { + val parentComment = repository.findByIdOrNull(id = commentId) + ?: return GetAudioContentCommentListResponse(totalCount = 0, items = listOf()) + + if (isBlockedBetweenMembers(memberId = memberId, creatorId = parentComment.audioContent!!.member!!.id!!)) { + return GetAudioContentCommentListResponse(totalCount = 0, items = listOf()) + } + val commentList = repository.getAudioContentCommentReplyList( cloudFrontHost = cloudFrontHost, commentId = commentId, + memberId = memberId, timezone = timezone, offset = pageable.offset, limit = pageable.pageSize ) - val totalCount = repository.commentReplyCountByAudioContentCommentId(commentId) + val totalCount = repository.commentReplyCountByAudioContentCommentId(commentId, memberId) return GetAudioContentCommentListResponse(totalCount, commentList) } @@ -176,4 +192,9 @@ class AudioContentCommentService( val template = messageSource.getMessage(key, langContext.lang) ?: return "" return String.format(template, *args) } + + private fun isBlockedBetweenMembers(memberId: Long, creatorId: Long): Boolean { + return blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId) || + blockMemberRepository.isBlocked(blockedMemberId = creatorId, memberId = memberId) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt index 9317544b..6a78dfc6 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt @@ -118,7 +118,7 @@ class AudioContentMainService( offset = pageable.offset, limit = pageable.pageSize.toLong() ) - .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } + .filter { !isBlockedBetweenMembers(memberId = member.id!!, creatorId = it.creatorId) } val contentIds = contentList.map { it.contentId } val translatedContentList = if (contentIds.isNotEmpty()) { @@ -198,20 +198,17 @@ class AudioContentMainService( cloudfrontHost = imageHost, isAdult = isAdult ) - .asSequence() - .filter { !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creatorId) } - .toList() + .filter { !isBlockedBetweenMembers(memberId = memberId, creatorId = it.creatorId) } } @Transactional(readOnly = true) fun getAudioContentMainBannerList(memberId: Long, isAdult: Boolean) = repository.getAudioContentMainBannerList(isAdult = isAdult) - .asSequence() .filter { if (it.type == AudioContentBannerType.CREATOR && it.creator != null) { - !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creator!!.id!!) + !isBlockedBetweenMembers(memberId = memberId, creatorId = it.creator!!.id!!) } else if (it.type == AudioContentBannerType.SERIES && it.series != null) { - !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.series!!.member!!.id!!) + !isBlockedBetweenMembers(memberId = memberId, creatorId = it.series!!.member!!.id!!) } else { true } @@ -255,7 +252,6 @@ class AudioContentMainService( link = it.link ) } - .toList() @Transactional(readOnly = true) @Cacheable( @@ -281,9 +277,14 @@ class AudioContentMainService( contentType = contentType ) .filter { content -> - !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = content.creatorId) + !isBlockedBetweenMembers(memberId = memberId, creatorId = content.creatorId) } ) } .filter { it.contents.isNotEmpty() } + + private fun isBlockedBetweenMembers(memberId: Long, creatorId: Long): Boolean { + return blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId) || + blockMemberRepository.isBlocked(blockedMemberId = creatorId, memberId = memberId) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/banner/AudioContentBannerService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/banner/AudioContentBannerService.kt index 6226b23e..4aaaffa7 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/banner/AudioContentBannerService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/banner/AudioContentBannerService.kt @@ -17,9 +17,9 @@ class AudioContentBannerService( return repository.getAudioContentMainBannerList(tabId, isAdult) .filter { if (it.type == AudioContentBannerType.CREATOR && it.creator != null && memberId != null) { - !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creator!!.id!!) + !isBlockedBetweenMembers(memberId = memberId, creatorId = it.creator!!.id!!) } else if (it.type == AudioContentBannerType.SERIES && it.series != null && memberId != null) { - !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.series!!.member!!.id!!) + !isBlockedBetweenMembers(memberId = memberId, creatorId = it.series!!.member!!.id!!) } else { true } @@ -64,4 +64,9 @@ class AudioContentBannerService( ) } } + + private fun isBlockedBetweenMembers(memberId: Long, creatorId: Long): Boolean { + return blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId) || + blockMemberRepository.isBlocked(blockedMemberId = creatorId, memberId = memberId) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationService.kt index b21d8628..661cddd2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationService.kt @@ -43,7 +43,7 @@ class AudioContentCurationService( offset = pageable.offset, limit = pageable.pageSize.toLong() ) - .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } + .filter { !isBlockedBetweenMembers(memberId = member.id!!, creatorId = it.creatorId) } return GetCurationContentResponse( totalCount = totalCount, @@ -68,7 +68,7 @@ class AudioContentCurationService( contentType = contentType ).filter { item -> if (memberId != null) { - !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = item.creatorId) + !isBlockedBetweenMembers(memberId = memberId, creatorId = item.creatorId) } else { true } @@ -77,4 +77,9 @@ class AudioContentCurationService( } .filter { it.items.isNotEmpty() } } + + private fun isBlockedBetweenMembers(memberId: Long, creatorId: Long): Boolean { + return blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId) || + blockMemberRepository.isBlocked(blockedMemberId = creatorId, memberId = memberId) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt index 73d85898..a860c0ab 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt @@ -27,9 +27,15 @@ class AudioContentMainTabRepository( isAdult: Boolean, contentType: ContentType ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = member.isActive.isTrue .and(member.role.eq(MemberRole.CREATOR)) @@ -88,9 +94,15 @@ class AudioContentMainTabRepository( isAdult: Boolean, contentType: ContentType ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = member.isActive.isTrue .and(member.role.eq(MemberRole.CREATOR)) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt index 243a9ffd..271fd4b5 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/ContentMainTabTagCurationRepository.kt @@ -62,9 +62,15 @@ class ContentMainTabTagCurationRepository( tag: String, contentType: ContentType ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = audioContent.isActive.isTrue .and(audioContent.duration.isNotNull) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt index f9995040..f351a8f6 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt @@ -162,9 +162,15 @@ class ContentSeriesQueryRepositoryImpl( .select(blockMember.id) .from(blockMember) .where( - blockMember.member.id.eq(series.member.id), - blockMember.blockedMember.id.eq(memberId), blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(series.member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(series.member.id)) + ) + ) ) where = where.and(blockedSubquery.exists().not()) } @@ -230,9 +236,15 @@ class ContentSeriesQueryRepositoryImpl( .select(blockMember.id) .from(blockMember) .where( - blockMember.member.id.eq(series.member.id), - blockMember.blockedMember.id.eq(memberId), blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(series.member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(series.member.id)) + ) + ) ) where = where.and(blockedSubquery.exists().not()) } @@ -361,9 +373,15 @@ class ContentSeriesQueryRepositoryImpl( .select(blockMember.id) .from(blockMember) .where( - blockMember.member.id.eq(series.member.id), - blockMember.blockedMember.id.eq(memberId), blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(series.member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(series.member.id)) + ) + ) ) where = where.and(blockedSubquery.exists().not()) } @@ -419,9 +437,15 @@ class ContentSeriesQueryRepositoryImpl( .select(blockMember.id) .from(blockMember) .where( - blockMember.member.id.eq(series.member.id), - blockMember.blockedMember.id.eq(memberId), blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(series.member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(series.member.id)) + ) + ) ) where = where.and(blockedSubquery.exists().not()) } @@ -594,9 +618,15 @@ class ContentSeriesQueryRepositoryImpl( .select(blockMember.id) .from(blockMember) .where( - blockMember.member.id.eq(series.member.id), - blockMember.blockedMember.id.eq(memberId), blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(series.member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(series.member.id)) + ) + ) ) where = where.and(blockedSubquery.exists().not()) } @@ -829,9 +859,15 @@ class ContentSeriesQueryRepositoryImpl( memberId: Long, contentType: ContentType ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = seriesGenre.isActive.isTrue .and(series.isActive.isTrue) @@ -884,9 +920,15 @@ class ContentSeriesQueryRepositoryImpl( contentType: ContentType, locale: String ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = series.isActive.isTrue .and(member.isActive.isTrue) @@ -1033,9 +1075,15 @@ class ContentSeriesQueryRepositoryImpl( .select(blockMember.id) .from(blockMember) .where( - blockMember.member.id.eq(series.member.id), - blockMember.blockedMember.id.eq(memberId), blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(series.member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(series.member.id)) + ) + ) ) where = where.and(blockedSubquery.exists().not()) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt index 6cf0342c..dc2b2140 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt @@ -226,7 +226,8 @@ class ContentSeriesService( contentType = contentType ) ?: throw SodaException(messageKey = "series.error.invalid_series_retry") - val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = series.member!!.id!!) + val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = series.member!!.id!!) || + blockMemberRepository.isBlocked(blockedMemberId = series.member!!.id!!, memberId = member.id!!) if (isBlocked) { throw SodaException(messageKey = "series.error.invalid_series_retry") } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerController.kt index 46fdeae2..b634b0ab 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerController.kt @@ -133,6 +133,6 @@ class ExplorerController( pageable: Pageable ) = run { if (member == null) throw SodaException(messageKey = "common.error.bad_credentials") - ApiResponse.ok(service.getCreatorProfileCheers(creatorId, timezone, pageable)) + ApiResponse.ok(service.getCreatorProfileCheers(creatorId, timezone, member, pageable)) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerQueryRepository.kt index f6dace80..02d0fe45 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerQueryRepository.kt @@ -451,30 +451,52 @@ class ExplorerQueryRepository( .fetchFirst() ?: "" } - fun getCheersList(creatorId: Long, timezone: String, offset: Long, limit: Long): GetCheersResponse { + fun getCheersList(creatorId: Long, memberId: Long, timezone: String, offset: Long, limit: Long): GetCheersResponse { val cheersDatePattern = messageSource .getMessage("explorer.date.cheers.format", langContext.lang) ?: messageSource.getMessage("explorer.date.cheers.format", Lang.KO).orEmpty() val cheersDateFormatter = DateTimeFormatter.ofPattern(cheersDatePattern) .withLocale(langContext.lang.locale) + val blockedByMemberIdSet = queryFactory + .select(blockMember.blockedMember.id) + .from(blockMember) + .where( + blockMember.member.id.eq(memberId) + .and(blockMember.isActive.isTrue) + ) + .fetch() + .toSet() + + val blockingMemberIdSet = queryFactory + .select(blockMember.member.id) + .from(blockMember) + .where( + blockMember.blockedMember.id.eq(memberId) + .and(blockMember.isActive.isTrue) + ) + .fetch() + .toSet() + + val blockedMemberIdSet = blockedByMemberIdSet + blockingMemberIdSet + + var where = creatorCheers.creator.id.eq(creatorId) + .and(creatorCheers.isActive.isTrue) + .and(creatorCheers.parent.isNull) + + if (blockedMemberIdSet.isNotEmpty()) { + where = where.and(creatorCheers.member.id.notIn(blockedMemberIdSet)) + } + val totalCount = queryFactory .selectFrom(creatorCheers) - .where( - creatorCheers.creator.id.eq(creatorId) - .and(creatorCheers.isActive.isTrue) - .and(creatorCheers.parent.isNull) - ) + .where(where) .fetch() .count() val cheers = queryFactory .selectFrom(creatorCheers) - .where( - creatorCheers.creator.id.eq(creatorId) - .and(creatorCheers.isActive.isTrue) - .and(creatorCheers.parent.isNull) - ) + .where(where) .offset(offset) .limit(limit) .orderBy(creatorCheers.id.desc()) @@ -498,6 +520,9 @@ class ExplorerQueryRepository( languageCode = it.languageCode, date = date.format(cheersDateFormatter), replyList = it.children.asSequence() + .filterNot { cheers -> + cheers.member?.id != null && blockedMemberIdSet.contains(cheers.member!!.id!!) + } .map { cheers -> val replyDate = cheers.createdAt!! .atZone(ZoneId.of("UTC")) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerService.kt index c24b10e8..ed2c9f5f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerService.kt @@ -65,7 +65,7 @@ class ExplorerService( fun getCreatorRank(memberId: Long): GetExplorerSectionResponse { val creatorRankings = queryRepository .getCreatorRankings() - .filter { !memberService.isBlocked(blockedMemberId = memberId, memberId = it.id!!) } + .filter { !isBlockedBetweenMembers(memberId = memberId, otherMemberId = it.id!!) } .map { it.toExplorerSectionCreator(cloudFrontHost) } val currentDateTime = LocalDateTime.now() @@ -101,7 +101,7 @@ class ExplorerService( // 인기 크리에이터 val creatorRankings = queryRepository .getCreatorRankings() - .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } + .filter { !isBlockedBetweenMembers(memberId = member.id!!, otherMemberId = it.id!!) } .map { it.toExplorerSectionCreator(cloudFrontHost) } val currentDateTime = LocalDateTime.now() @@ -134,7 +134,7 @@ class ExplorerService( // 새로 시작 (newCreators) val newCreators = queryRepository .getNewCreators() - .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } + .filter { !isBlockedBetweenMembers(memberId = member.id!!, otherMemberId = it.id!!) } .map { it.toExplorerSectionCreator(cloudFrontHost) } val newCreatorsSection = GetExplorerSectionResponse( @@ -153,7 +153,7 @@ class ExplorerService( color = "39abde", creators = queryRepository .findCreatorByGender(1) - .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } + .filter { !isBlockedBetweenMembers(memberId = member.id!!, otherMemberId = it.id!!) } .map { it.toExplorerSectionCreator(cloudFrontHost) } ) @@ -164,7 +164,7 @@ class ExplorerService( color = "ffa517", creators = queryRepository .findCreatorByGender(0) - .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } + .filter { !isBlockedBetweenMembers(memberId = member.id!!, otherMemberId = it.id!!) } .map { it.toExplorerSectionCreator(cloudFrontHost) } ) @@ -187,7 +187,7 @@ class ExplorerService( return queryRepository.getSearchChannel(channel, member.id!!) .asSequence() - .filter { !memberService.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } + .filter { !isBlockedBetweenMembers(memberId = member.id!!, otherMemberId = it.id!!) } .map { GetRoomDetailUser(it, cloudFrontHost) } .toList() } @@ -203,8 +203,9 @@ class ExplorerService( ?: throw SodaException(messageKey = "member.validation.user_not_found") // 차단된 사용자 체크 - val isBlocked = memberService.isBlocked(blockedMemberId = member.id!!, memberId = creatorId) - if (isBlocked) { + val isBlockedByCreator = memberService.isBlocked(blockedMemberId = member.id!!, memberId = creatorId) + val isBlock = memberService.isBlocked(blockedMemberId = creatorId, memberId = member.id!!) + if (isBlockedByCreator || isBlock) { val messageTemplate = messageSource .getMessage("explorer.creator.blocked_access", langContext.lang) .orEmpty() @@ -240,7 +241,7 @@ class ExplorerService( } // 라이브 - val liveRoomList = if (isCreator) { + val liveRoomList = if (isCreator && !isBlock) { queryRepository.getLiveRoomList( creatorId, userMember = member, @@ -251,7 +252,7 @@ class ExplorerService( } // 오디오 콘텐츠 - val contentList = if (isCreator) { + val contentList = if (isCreator && !isBlock) { audioContentService.getAudioContentList( creatorId = creatorId, sortType = SortType.NEWEST, @@ -284,7 +285,7 @@ class ExplorerService( } // 크리에이터의 최신 오디오 콘텐츠 1개 - val latestContent = if (isCreator) { + val latestContent = if (isCreator && !isBlock) { audioContentService.getLatestCreatorAudioContent(creatorId, member, isAdultContentVisible) } else { null @@ -326,11 +327,15 @@ class ExplorerService( } // 응원 - val cheers = queryRepository.getCheersList(creatorId, timezone = timezone, offset = 0, limit = 4) + val cheers = queryRepository.getCheersList( + creatorId = creatorId, + memberId = member.id!!, + timezone = timezone, + offset = 0, + limit = 4 + ) // 차단한 크리에이터 인지 체크 - val isBlock = memberService.isBlocked(blockedMemberId = creatorId, memberId = member.id!!) - val activitySummary = if (isCreator) { // 활동요약 (라이브 횟수, 라이브 시간, 라이브 참여자, 콘텐츠 수) val liveCount = queryRepository.getLiveCount(creatorId) ?: 0 @@ -347,7 +352,7 @@ class ExplorerService( GetCreatorActivitySummary(0, 0, 0, 0) } - val seriesList = if (isCreator) { + val seriesList = if (isCreator && !isBlock) { seriesService .getSeriesList( creatorId = creatorId, @@ -516,7 +521,7 @@ class ExplorerService( val creator = queryRepository.getMember(request.creatorId) ?: throw SodaException(messageKey = "member.validation.user_not_found") - val isBlocked = memberService.isBlocked(blockedMemberId = member.id!!, memberId = request.creatorId) + val isBlocked = isBlockedBetweenMembers(memberId = member.id!!, otherMemberId = request.creatorId) if (isBlocked) { val messageTemplate = messageSource .getMessage("explorer.creator.blocked_cheers", langContext.lang) @@ -555,10 +560,16 @@ class ExplorerService( fun getCreatorProfileCheers( creatorId: Long, timezone: String, + member: Member, pageable: Pageable ): GetCheersResponse { + if (isBlockedBetweenMembers(memberId = member.id!!, otherMemberId = creatorId)) { + throw SodaException(messageKey = "common.error.invalid_request") + } + return queryRepository.getCheersList( creatorId = creatorId, + memberId = member.id!!, timezone = timezone, offset = pageable.offset, limit = pageable.pageSize.toLong() @@ -607,4 +618,9 @@ class ExplorerService( ) ) } + + private fun isBlockedBetweenMembers(memberId: Long, otherMemberId: Long): Boolean { + return memberService.isBlocked(blockedMemberId = memberId, memberId = otherMemberId) || + memberService.isBlocked(blockedMemberId = otherMemberId, memberId = memberId) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/CreatorCommunityController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/CreatorCommunityController.kt index b85e3cf3..dd60eaff 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/CreatorCommunityController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/CreatorCommunityController.kt @@ -179,6 +179,7 @@ class CreatorCommunityController(private val service: CreatorCommunityService) { ApiResponse.ok( service.getCommentReplyList( commentId = commentId, + memberId = member.id!!, timezone = timezone, offset = pageable.offset, limit = pageable.pageSize.toLong() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/CreatorCommunityService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/CreatorCommunityService.kt index cc3be756..8e827e69 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/CreatorCommunityService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/CreatorCommunityService.kt @@ -181,7 +181,7 @@ class CreatorCommunityService( limit: Long, isAdult: Boolean ): List { - if (blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId)) { + if (isBlockedBetweenMembers(memberId = memberId, creatorId = creatorId)) { return listOf() } @@ -275,7 +275,7 @@ class CreatorCommunityService( val post = repository.getCommunityPost(postId, isAdult = isAdult) ?: throw SodaException(messageKey = "creator.community.invalid_request_retry") - val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = post.creatorId) + val isBlocked = isBlockedBetweenMembers(memberId = memberId, creatorId = post.creatorId) if (isBlocked) { val messageTemplate = messageSource .getMessage("creator.community.blocked_access", langContext.lang) @@ -375,6 +375,11 @@ class CreatorCommunityService( ) { val post = repository.findByIdOrNull(id = postId) ?: throw SodaException(messageKey = "creator.community.invalid_post_retry") + + if (isBlockedBetweenMembers(memberId = member.id!!, creatorId = post.member!!.id!!)) { + throw SodaException(messageKey = "creator.community.invalid_access_retry") + } + val isExistOrdered = useCanRepository.isExistCommunityPostOrdered(postId = postId, memberId = member.id!!) if (isSecret && !isExistOrdered) { @@ -425,6 +430,11 @@ class CreatorCommunityService( offset: Long, limit: Long ): GetCommunityPostCommentListResponse { + val post = repository.findByIdOrNull(id = postId) + if (post != null && isBlockedBetweenMembers(memberId = memberId, creatorId = post.member!!.id!!)) { + return GetCommunityPostCommentListResponse(totalCount = 0, items = listOf()) + } + val commentList = commentRepository.findByPostId( id = postId, memberId = memberId, @@ -444,18 +454,28 @@ class CreatorCommunityService( fun getCommentReplyList( commentId: Long, + memberId: Long, timezone: String, offset: Long, limit: Long ): GetCommunityPostCommentListResponse { + val parentComment = commentRepository.findByIdOrNull(id = commentId) + if ( + parentComment != null && + isBlockedBetweenMembers(memberId = memberId, creatorId = parentComment.creatorCommunity!!.member!!.id!!) + ) { + return GetCommunityPostCommentListResponse(totalCount = 0, items = listOf()) + } + val commentList = commentRepository.getCommunityCommentReplyList( commentId = commentId, + memberId = memberId, timezone = timezone, offset = offset, limit = limit ) - val totalCount = commentRepository.commentReplyCountByCommentId(commentId) + val totalCount = commentRepository.commentReplyCountByCommentId(commentId, memberId) return GetCommunityPostCommentListResponse(totalCount = totalCount, items = commentList) } @@ -469,10 +489,7 @@ class CreatorCommunityService( return postList .filter { - !blockMemberRepository.isBlocked( - blockedMemberId = memberId, - memberId = it.creatorId - ) + !isBlockedBetweenMembers(memberId = memberId, creatorId = it.creatorId) } .map { val isLike = @@ -541,7 +558,7 @@ class CreatorCommunityService( val post = repository.findByIdAndActive(postId, isAdult) ?: throw SodaException(messageKey = "creator.community.invalid_request_retry") - val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = post.member!!.id!!) + val isBlocked = isBlockedBetweenMembers(memberId = memberId, creatorId = post.member!!.id!!) if (isBlocked) { val messageTemplate = messageSource .getMessage("creator.community.blocked_access", langContext.lang) @@ -616,4 +633,9 @@ class CreatorCommunityService( firstComment = firstComment ) } + + private fun isBlockedBetweenMembers(memberId: Long, creatorId: Long): Boolean { + return blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId) || + blockMemberRepository.isBlocked(blockedMemberId = creatorId, memberId = memberId) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/comment/CreatorCommunityCommentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/comment/CreatorCommunityCommentRepository.kt index f7e12fe1..4d56d68e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/comment/CreatorCommunityCommentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/creatorCommunity/comment/CreatorCommunityCommentRepository.kt @@ -1,9 +1,11 @@ package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment import com.querydsl.core.types.dsl.Expressions +import com.querydsl.jpa.JPAExpressions import com.querydsl.jpa.impl.JPAQueryFactory import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.QCreatorCommunityComment.creatorCommunityComment import kr.co.vividnext.sodalive.extensions.removeDeletedNicknamePrefix +import kr.co.vividnext.sodalive.member.block.QBlockMember.blockMember import org.springframework.beans.factory.annotation.Value import org.springframework.data.jpa.repository.JpaRepository import java.time.LocalDateTime @@ -21,7 +23,7 @@ interface CreatorCommunityCommentQueryRepository { limit: Long ): List - fun commentReplyCountByCommentId(commentId: Long): Int + fun commentReplyCountByCommentId(commentId: Long, memberId: Long): Int fun totalCountCommentByPostId( postId: Long, @@ -31,6 +33,7 @@ interface CreatorCommunityCommentQueryRepository { fun getCommunityCommentReplyList( commentId: Long, + memberId: Long, timezone: String, offset: Long, limit: Long @@ -66,6 +69,8 @@ class CreatorCommunityCommentQueryRepositoryImpl( var where = creatorCommunityComment.isActive.isTrue .and(creatorCommunityComment.creatorCommunity.id.eq(id)) .and(creatorCommunityComment.parent.isNull) + .and(creatorCommunityComment.member.id.notIn(blockedMemberIdSubQuery(memberId))) + .and(creatorCommunityComment.member.id.notIn(blockingMemberIdSubQuery(memberId))) if (!isContentCreator) { where = where.and( @@ -96,18 +101,20 @@ class CreatorCommunityCommentQueryRepositoryImpl( .map { it.copy( nickname = it.nickname.removeDeletedNicknamePrefix(), - replyCount = commentReplyCountByCommentId(it.id) + replyCount = commentReplyCountByCommentId(it.id, memberId) ) } } - override fun commentReplyCountByCommentId(commentId: Long): Int { + override fun commentReplyCountByCommentId(commentId: Long, memberId: Long): Int { return queryFactory.select(creatorCommunityComment.id) .from(creatorCommunityComment) .where( creatorCommunityComment.isActive.isTrue .and(creatorCommunityComment.parent.isNotNull) .and(creatorCommunityComment.parent.id.eq(commentId)) + .and(creatorCommunityComment.member.id.notIn(blockedMemberIdSubQuery(memberId))) + .and(creatorCommunityComment.member.id.notIn(blockingMemberIdSubQuery(memberId))) ) .fetch() .size @@ -121,6 +128,8 @@ class CreatorCommunityCommentQueryRepositoryImpl( var where = creatorCommunityComment.creatorCommunity.id.eq(postId) .and(creatorCommunityComment.isActive.isTrue) .and(creatorCommunityComment.parent.isNull) + .and(creatorCommunityComment.member.id.notIn(blockedMemberIdSubQuery(memberId))) + .and(creatorCommunityComment.member.id.notIn(blockingMemberIdSubQuery(memberId))) if (!isContentCreator) { where = where.and( @@ -138,6 +147,7 @@ class CreatorCommunityCommentQueryRepositoryImpl( override fun getCommunityCommentReplyList( commentId: Long, + memberId: Long, timezone: String, offset: Long, limit: Long @@ -172,6 +182,8 @@ class CreatorCommunityCommentQueryRepositoryImpl( creatorCommunityComment.isActive.isTrue .and(creatorCommunityComment.parent.isNotNull) .and(creatorCommunityComment.parent.id.eq(commentId)) + .and(creatorCommunityComment.member.id.notIn(blockedMemberIdSubQuery(memberId))) + .and(creatorCommunityComment.member.id.notIn(blockingMemberIdSubQuery(memberId))) ) .offset(offset) .limit(limit) @@ -181,4 +193,20 @@ class CreatorCommunityCommentQueryRepositoryImpl( it.copy(nickname = it.nickname.removeDeletedNicknamePrefix()) } } + + private fun blockedMemberIdSubQuery(memberId: Long) = JPAExpressions + .select(blockMember.blockedMember.id) + .from(blockMember) + .where( + blockMember.member.id.eq(memberId) + .and(blockMember.isActive.isTrue) + ) + + private fun blockingMemberIdSubQuery(memberId: Long) = JPAExpressions + .select(blockMember.member.id) + .from(blockMember) + .where( + blockMember.blockedMember.id.eq(memberId) + .and(blockMember.isActive.isTrue) + ) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendService.kt index 066dbda4..a68d896e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendService.kt @@ -22,7 +22,7 @@ class LiveRecommendService( return repository.getRecommendLive( isBlocked = { if (member != null) { - blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it) + isBlockedBetweenMembers(memberId = member.id!!, creatorId = it) } else { false } @@ -35,7 +35,7 @@ class LiveRecommendService( val onAirChannelList = repository.getOnAirRecommendChannelList( isBlocked = { if (member != null) { - blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it) + isBlockedBetweenMembers(memberId = member.id!!, creatorId = it) } else { false } @@ -55,7 +55,7 @@ class LiveRecommendService( limit = (20 - onAirChannelList.size).toLong(), isBlocked = { if (member != null) { - blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it) + isBlockedBetweenMembers(memberId = member.id!!, creatorId = it) } else { false } @@ -68,7 +68,7 @@ class LiveRecommendService( fun getFollowingChannelList(member: Member): List { val onAirFollowingChannelList = repository.getOnAirFollowingChannelList( memberId = member.id!!, - isBlocked = { blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it) }, + isBlocked = { isBlockedBetweenMembers(memberId = member.id!!, creatorId = it) }, isCreator = member.role == MemberRole.CREATOR, isAdult = member.auth != null ) @@ -83,7 +83,7 @@ class LiveRecommendService( memberId = member.id!!, withOutCreatorList = onAirCreatorIdList, limit = (20 - onAirCreatorIdList.size).toLong(), - isBlocked = { blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it) } + isBlocked = { isBlockedBetweenMembers(memberId = member.id!!, creatorId = it) } ) return onAirFollowingChannelList + notOnAirFollowingChannelList @@ -92,14 +92,14 @@ class LiveRecommendService( fun getFollowingAllChannelList(member: Member, pageable: Pageable): GetCreatorFollowingAllListResponse { val totalCount = repository.getCreatorFollowingAllListTotalCount( memberId = member.id!!, - isBlocked = { blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it) } + isBlocked = { isBlockedBetweenMembers(memberId = member.id!!, creatorId = it) } ) val items = repository.getCreatorFollowingAllList( memberId = member.id!!, offset = pageable.offset, limit = pageable.pageSize.toLong(), - isBlocked = { blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it) } + isBlocked = { isBlockedBetweenMembers(memberId = member.id!!, creatorId = it) } ) return GetCreatorFollowingAllListResponse( @@ -107,4 +107,9 @@ class LiveRecommendService( items = items ) } + + private fun isBlockedBetweenMembers(memberId: Long, creatorId: Long): Boolean { + return blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId) || + blockMemberRepository.isBlocked(blockedMemberId = creatorId, memberId = memberId) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt index 849a1adc..552a2360 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt @@ -121,9 +121,15 @@ class LiveRoomQueryRepositoryImpl( .leftJoin(quarterLiveRankings).on(liveRoom.id.eq(quarterLiveRankings.roomId)) if (hasMemberId) { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.blockedMember.id.eq(memberId)) - .and(blockMember.isActive.isTrue) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) select = select.leftJoin(blockMember).on(blockMemberCondition) where = where.and(blockMember.id.isNull) @@ -190,9 +196,15 @@ class LiveRoomQueryRepositoryImpl( .innerJoin(liveRoom.member, member) if (memberId != null) { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.blockedMember.id.eq(memberId)) - .and(blockMember.isActive.isTrue) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) select = select.leftJoin(blockMember).on(blockMemberCondition) where = where.and(blockMember.id.isNull) @@ -269,9 +281,15 @@ class LiveRoomQueryRepositoryImpl( .limit(10) if (memberId != null) { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.blockedMember.id.eq(memberId)) - .and(blockMember.isActive.isTrue) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) select = select.leftJoin(blockMember).on(blockMemberCondition) where = where.and(blockMember.id.isNull) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt index 600e8b9d..2b86cdd2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt @@ -500,6 +500,13 @@ class LiveRoomService( val room = repository.getLiveRoom(id = roomId) ?: throw SodaException(messageKey = "live.room.already_ended") + val creatorId = room.member!!.id!! + val isBlockedByCreator = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = creatorId) + val isBlockedByMember = blockMemberRepository.isBlocked(blockedMemberId = creatorId, memberId = member.id!!) + if (isBlockedByCreator || isBlockedByMember) { + throw SodaException(messageKey = "live.room.already_ended") + } + if (room.isAdult && member.auth == null) { throw SodaException(messageKey = "live.room.adult_verification_required") } @@ -747,6 +754,14 @@ class LiveRoomService( ) } + val isBlockedByMember = blockMemberRepository.isBlocked( + blockedMemberId = room.member!!.id!!, + memberId = member.id!! + ) + if (isBlockedByMember) { + throw SodaException(messageKey = "live.room.not_found") + } + val kickOutCount = kickOutService.getKickOutCount(roomId = room.id!!, userId = member.id!!) if (kickOutCount >= 2) { throw SodaException( @@ -910,6 +925,13 @@ class LiveRoomService( val room = repository.findByIdOrNull(roomId) ?: throw SodaException(messageKey = "live.room.info_not_found") + val creatorId = room.member!!.id!! + val isBlockedByCreator = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = creatorId) + val isBlockedByMember = blockMemberRepository.isBlocked(blockedMemberId = creatorId, memberId = member.id!!) + if (isBlockedByCreator || isBlockedByMember) { + throw SodaException(messageKey = "live.room.info_not_found") + } + val currentTimeStamp = Date().time val expireTimestamp = (currentTimeStamp + (60 * 60 * 24 * 1000)) / 1000 @@ -1427,7 +1449,8 @@ class LiveRoomService( return repository.getLatestFinishedLive() .filter { if (member?.id != null) { - !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.memberId) + !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.memberId) && + !blockMemberRepository.isBlocked(blockedMemberId = it.memberId, memberId = member.id!!) } else { true } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt index 81e5d686..8c60dc8b 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt @@ -576,12 +576,13 @@ class MemberService( } return repository.findByNicknameAndOtherCondition(nickname, member) - .asSequence() - .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) } + .filter { + !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.id!!) && + !blockMemberRepository.isBlocked(blockedMemberId = it.id!!, memberId = member.id!!) + } .map { GetRoomDetailUser(it, cloudFrontHost) } - .toList() } @Transactional diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/query/recommend/RecommendChannelQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/query/recommend/RecommendChannelQueryRepository.kt index fc99f58a..45f70335 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/query/recommend/RecommendChannelQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/query/recommend/RecommendChannelQueryRepository.kt @@ -28,9 +28,15 @@ class RecommendChannelQueryRepository( contentType: ContentType ): List { val blockMemberCondition = if (memberId != null) { - blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) } else { null } @@ -89,9 +95,15 @@ class RecommendChannelQueryRepository( locale: String? = null ): List { val blockMemberCondition = if (memberId != null) { - blockMember.member.id.eq(audioContent.member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(audioContent.member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(audioContent.member.id)) + ) + ) } else { null } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/search/SearchRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/search/SearchRepository.kt index 5920a062..dee7a1c7 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/search/SearchRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/search/SearchRepository.kt @@ -29,9 +29,15 @@ class SearchRepository( keyword: String, memberId: Long ): Int { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) return queryFactory .select(member.id) @@ -61,9 +67,15 @@ class SearchRepository( offset: Long, limit: Long ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) return queryFactory .select( @@ -102,9 +114,15 @@ class SearchRepository( isAdult: Boolean, contentType: ContentType ): Int { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = audioContent.member.isActive.isTrue .and(audioContent.member.role.eq(MemberRole.CREATOR)) @@ -161,9 +179,15 @@ class SearchRepository( offset: Long, limit: Long ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = audioContent.member.isActive.isTrue .and(audioContent.member.role.eq(MemberRole.CREATOR)) @@ -227,9 +251,15 @@ class SearchRepository( isAdult: Boolean, contentType: ContentType ): Int { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = series.isActive.isTrue .and(audioContent.isActive.isTrue) @@ -291,9 +321,15 @@ class SearchRepository( offset: Long, limit: Long ): List { - val blockMemberCondition = blockMember.member.id.eq(member.id) - .and(blockMember.isActive.isTrue) - .and(blockMember.blockedMember.id.eq(memberId)) + val blockMemberCondition = blockMember.isActive.isTrue + .and( + blockMember.member.id.eq(member.id) + .and(blockMember.blockedMember.id.eq(memberId)) + .or( + blockMember.member.id.eq(memberId) + .and(blockMember.blockedMember.id.eq(member.id)) + ) + ) var where = series.isActive.isTrue .and(audioContent.isActive.isTrue)