From a16e5bed000a36be5f5c2a3f40659001208c90f2 Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Thu, 11 Aug 2022 11:15:28 +0100 Subject: [PATCH] Filter groups by leader's blocked and banned status --- Sources/XXDatabase/Models/Group+GRDB.swift | 13 ++++ Sources/XXModels/Models/Group.swift | 26 +++++++ Tests/XXDatabaseTests/Group+GRDBTests.swift | 80 +++++++++++++++++++++ 3 files changed, 119 insertions(+) diff --git a/Sources/XXDatabase/Models/Group+GRDB.swift b/Sources/XXDatabase/Models/Group+GRDB.swift index 5cd9090..42455de 100644 --- a/Sources/XXDatabase/Models/Group+GRDB.swift +++ b/Sources/XXDatabase/Models/Group+GRDB.swift @@ -58,6 +58,19 @@ extension Group: PersistableRecord, FetchableRecord { request = request.filter(authStatus.map(\.rawValue).contains(Column.authStatus)) } + if query.isLeaderBlocked != nil || query.isLeaderBanned != nil { + let leader = TableAlias(name: "leader") + request = request.joining(required: Association.leader.aliased(leader)) + + if let isLeaderBlocked = query.isLeaderBlocked { + request = request.filter(leader[Contact.Column.isBlocked] == isLeaderBlocked) + } + + if let isLeaderBanned = query.isLeaderBanned { + request = request.filter(leader[Contact.Column.isBanned] == isLeaderBanned) + } + } + switch query.sortBy { case .createdAt(desc: false): request = request.order(Column.createdAt) diff --git a/Sources/XXModels/Models/Group.swift b/Sources/XXModels/Models/Group.swift index 4ac7e79..b7f9b0d 100644 --- a/Sources/XXModels/Models/Group.swift +++ b/Sources/XXModels/Models/Group.swift @@ -99,16 +99,28 @@ extension Group { /// - authStatus: Filter groups by auth status. /// If set, only groups with any of the provided auth statuses will be fetched. /// If `nil` (default), the filter is not used. + /// - isLeaderBlocked: Filter by leader contact's `isBlocked` status. + /// If `true`, only groups with blocked leader contacts are included. + /// If `false`, only groups with non-blocked contacts are included. + /// If `nil` (default), the filter is not used. + /// - isLeaderBanned: Filter by leader contact's `isBlocked` status. + /// If `true`, only groups with blocked leader contacts are included. + /// If `false`, only groups with non-blocked contacts are included. + /// If `nil` (default), the filter is not used. /// - sortBy: Sort order (defaults to `.createdAt(desc: true)`). public init( id: Set<Group.ID>? = nil, withMessages: Bool? = nil, authStatus: Set<AuthStatus>? = nil, + isLeaderBlocked: Bool? = nil, + isLeaderBanned: Bool? = nil, sortBy: SortOrder = .createdAt(desc: true) ) { self.id = id self.withMessages = withMessages self.authStatus = authStatus + self.isLeaderBlocked = isLeaderBlocked + self.isLeaderBanned = isLeaderBanned self.sortBy = sortBy } @@ -128,6 +140,20 @@ extension Group { /// If `nil`, the filter is not used. public var authStatus: Set<AuthStatus>? + /// Filter by leader contact's `isBlocked` status + /// + /// If `true`, only groups with blocked leader contacts are included. + /// If `false`, only groups with non-blocked contacts are included. + /// If `nil`, the filter is not used. + public var isLeaderBlocked: Bool? + + /// Filter by leader contact's `isBanned` status + /// + /// If `true`, only groups with banned leader contacts are included. + /// If `false`, only groups with non-banned leader contacts are included. + /// If `nil`, the filter is not used. + public var isLeaderBanned: Bool? + /// Groups sort order public var sortBy: SortOrder } diff --git a/Tests/XXDatabaseTests/Group+GRDBTests.swift b/Tests/XXDatabaseTests/Group+GRDBTests.swift index 1a255b6..ad3786a 100644 --- a/Tests/XXDatabaseTests/Group+GRDBTests.swift +++ b/Tests/XXDatabaseTests/Group+GRDBTests.swift @@ -159,4 +159,84 @@ final class GroupGRDBTests: XCTestCase { [groupA, groupB] ) } + + func testFetchingWithBlockedLeaders() throws { + // Mock up contacts: + + let contactA = try db.saveContact(.stub("A").withBlocked(false)) + let contactB = try db.saveContact(.stub("B").withBlocked(true)) + + // Mock up groups: + + let groupA = try db.saveGroup(.stub( + "A", + leaderId: contactA.id, + createdAt: .stub(1) + )) + + let groupB = try db.saveGroup(.stub( + "B", + leaderId: contactB.id, + createdAt: .stub(2) + )) + + // Fetch groups with blocked leaders: + + XCTAssertNoDifference(try db.fetchGroups(.init(isLeaderBlocked: true)), [ + groupB, + ]) + + // Fetch groups with non-blocked leaders: + + XCTAssertNoDifference(try db.fetchGroups(.init(isLeaderBlocked: false)), [ + groupA, + ]) + + // Fetch groups regardless leader's blocked status: + + XCTAssertNoDifference(try db.fetchGroups(.init(isLeaderBlocked: nil)), [ + groupB, + groupA, + ]) + } + + func testFetchingWithBannedLeaders() throws { + // Mock up contacts: + + let contactA = try db.saveContact(.stub("A").withBanned(false)) + let contactB = try db.saveContact(.stub("B").withBanned(true)) + + // Mock up groups: + + let groupA = try db.saveGroup(.stub( + "A", + leaderId: contactA.id, + createdAt: .stub(1) + )) + + let groupB = try db.saveGroup(.stub( + "B", + leaderId: contactB.id, + createdAt: .stub(2) + )) + + // Fetch groups with banned leaders: + + XCTAssertNoDifference(try db.fetchGroups(.init(isLeaderBanned: true)), [ + groupB, + ]) + + // Fetch groups with non-banned leaders: + + XCTAssertNoDifference(try db.fetchGroups(.init(isLeaderBanned: false)), [ + groupA, + ]) + + // Fetch groups regardless leader's banned status: + + XCTAssertNoDifference(try db.fetchGroups(.init(isLeaderBanned: nil)), [ + groupB, + groupA, + ]) + } } -- GitLab