Skip to content

Commit

Permalink
Freemium PIR: Manual Removal Links (#3466)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/72649045549333/1208619435900636/f
FE PR: https://dub.duckduckgo.com/duckduckgo/static-pages/pull/1012

**Description**: Adds a manual removal link to each Freemium PIR result
record view
  • Loading branch information
aataraxiaa authored Oct 31, 2024
1 parent 49ff187 commit b16b54c
Show file tree
Hide file tree
Showing 14 changed files with 329 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -409,10 +409,10 @@ extension InMemoryDataCache: DBPUICommunicationDelegate {
// 2. We map the brokers to the UI model
.flatMap { dataBroker -> [DBPUIDataBroker] in
var result: [DBPUIDataBroker] = []
result.append(DBPUIDataBroker(name: dataBroker.name, url: dataBroker.url, parentURL: dataBroker.parent))
result.append(DBPUIDataBroker(name: dataBroker.name, url: dataBroker.url, parentURL: dataBroker.parent, optOutUrl: dataBroker.optOutUrl))

for mirrorSite in dataBroker.mirrorSites {
result.append(DBPUIDataBroker(name: mirrorSite.name, url: mirrorSite.url, parentURL: dataBroker.parent))
result.append(DBPUIDataBroker(name: mirrorSite.name, url: mirrorSite.url, parentURL: dataBroker.parent, optOutUrl: dataBroker.optOutUrl))
}
return result
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,14 @@ struct DBPUIDataBroker: Codable, Hashable {
let url: String
let date: Double?
let parentURL: String?
let optOutUrl: String

init(name: String, url: String, date: Double? = nil, parentURL: String?) {
init(name: String, url: String, date: Double? = nil, parentURL: String?, optOutUrl: String) {
self.name = name
self.url = url
self.date = date
self.parentURL = parentURL
self.optOutUrl = optOutUrl
}

func hash(into hasher: inout Hasher) {
Expand Down Expand Up @@ -170,7 +172,8 @@ extension DBPUIDataBrokerProfileMatch {
dataBrokerName: String,
dataBrokerURL: String,
dataBrokerParentURL: String?,
parentBrokerOptOutJobData: [OptOutJobData]?) {
parentBrokerOptOutJobData: [OptOutJobData]?,
optOutUrl: String) {
let extractedProfile = optOutJobData.extractedProfile

/*
Expand Down Expand Up @@ -205,7 +208,7 @@ extension DBPUIDataBrokerProfileMatch {
extractedProfile.doesMatchExtractedProfile(parentOptOut.extractedProfile)
} ?? false

self.init(dataBroker: DBPUIDataBroker(name: dataBrokerName, url: dataBrokerURL, parentURL: dataBrokerParentURL),
self.init(dataBroker: DBPUIDataBroker(name: dataBrokerName, url: dataBrokerURL, parentURL: dataBrokerParentURL, optOutUrl: optOutUrl),
name: extractedProfile.fullName ?? "No name",
addresses: extractedProfile.addresses?.map {DBPUIUserProfileAddress(addressCityState: $0) } ?? [],
alternativeNames: extractedProfile.alternativeNames ?? [String](),
Expand All @@ -217,12 +220,13 @@ extension DBPUIDataBrokerProfileMatch {
hasMatchingRecordOnParentBroker: hasFoundParentMatch)
}

init(optOutJobData: OptOutJobData, dataBroker: DataBroker, parentBrokerOptOutJobData: [OptOutJobData]?) {
init(optOutJobData: OptOutJobData, dataBroker: DataBroker, parentBrokerOptOutJobData: [OptOutJobData]?, optOutUrl: String) {
self.init(optOutJobData: optOutJobData,
dataBrokerName: dataBroker.name,
dataBrokerURL: dataBroker.url,
dataBrokerParentURL: dataBroker.parent,
parentBrokerOptOutJobData: parentBrokerOptOutJobData)
parentBrokerOptOutJobData: parentBrokerOptOutJobData,
optOutUrl: optOutUrl)
}

/// Generates an array of `DBPUIDataBrokerProfileMatch` objects from the provided query data.
Expand Down Expand Up @@ -253,7 +257,8 @@ extension DBPUIDataBrokerProfileMatch {
// Create a profile match for the current data broker and append it to the list of profiles.
profiles.append(DBPUIDataBrokerProfileMatch(optOutJobData: optOutJobData,
dataBroker: dataBroker,
parentBrokerOptOutJobData: parentBrokerOptOutJobData))
parentBrokerOptOutJobData: parentBrokerOptOutJobData,
optOutUrl: dataBroker.optOutUrl))

// Handle mirror sites associated with the data broker.
if !dataBroker.mirrorSites.isEmpty {
Expand All @@ -264,7 +269,8 @@ extension DBPUIDataBrokerProfileMatch {
dataBrokerName: mirrorSite.name,
dataBrokerURL: mirrorSite.url,
dataBrokerParentURL: dataBroker.parent,
parentBrokerOptOutJobData: parentBrokerOptOutJobData)
parentBrokerOptOutJobData: parentBrokerOptOutJobData,
optOutUrl: dataBroker.optOutUrl)
}
return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ public struct DataBroker: Codable, Sendable {
let schedulingConfig: DataBrokerScheduleConfig
let parent: String?
let mirrorSites: [MirrorSite]
let optOutUrl: String

var isFakeBroker: Bool {
name.contains("fake") // A future improvement will be to add a property in the JSON file.
Expand All @@ -128,6 +129,7 @@ public struct DataBroker: Codable, Sendable {
case schedulingConfig
case parent
case mirrorSites
case optOutUrl
}

init(id: Int64? = nil,
Expand All @@ -137,7 +139,8 @@ public struct DataBroker: Codable, Sendable {
version: String,
schedulingConfig: DataBrokerScheduleConfig,
parent: String? = nil,
mirrorSites: [MirrorSite] = [MirrorSite]()
mirrorSites: [MirrorSite] = [MirrorSite](),
optOutUrl: String
) {
self.id = id
self.name = name
Expand All @@ -153,6 +156,7 @@ public struct DataBroker: Codable, Sendable {
self.schedulingConfig = schedulingConfig
self.parent = parent
self.mirrorSites = mirrorSites
self.optOutUrl = optOutUrl
}

public init(from decoder: Decoder) throws {
Expand All @@ -179,6 +183,8 @@ public struct DataBroker: Codable, Sendable {
mirrorSites = [MirrorSite]()
}

optOutUrl = (try? container.decode(String.self, forKey: .optOutUrl)) ?? ""

id = nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ struct MapperToModel {
version: decodedBroker.version,
schedulingConfig: decodedBroker.schedulingConfig,
parent: decodedBroker.parent,
mirrorSites: decodedBroker.mirrorSites
mirrorSites: decodedBroker.mirrorSites,
optOutUrl: decodedBroker.optOutUrl
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ struct DBPUICommunicationLayer: Subfeature {
weak var delegate: DBPUICommunicationDelegate?

private enum Constants {
static let version = 7
static let version = 8
}

internal init(webURLSettings: DataBrokerProtectionWebUIURLSettingsRepresentable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ struct MapperToUI {

let profileMatch = DBPUIDataBrokerProfileMatch(optOutJobData: optOutJob,
dataBroker: dataBroker,
parentBrokerOptOutJobData: parentBrokerOptOutJobData)
parentBrokerOptOutJobData: parentBrokerOptOutJobData,
optOutUrl: dataBroker.optOutUrl)

if extractedProfile.removedDate == nil {
inProgressOptOuts.append(profileMatch)
Expand All @@ -87,7 +88,8 @@ struct MapperToUI {
dataBrokerName: mirrorSite.name,
dataBrokerURL: mirrorSite.url,
dataBrokerParentURL: dataBroker.parent,
parentBrokerOptOutJobData: parentBrokerOptOutJobData)
parentBrokerOptOutJobData: parentBrokerOptOutJobData,
optOutUrl: dataBroker.optOutUrl)

if let extractedProfileRemovedDate = extractedProfile.removedDate,
mirrorSite.shouldWeIncludeMirrorSite(for: extractedProfileRemovedDate) {
Expand Down Expand Up @@ -135,13 +137,15 @@ struct MapperToUI {
brokers.append(DBPUIDataBroker(name: $0.dataBroker.name,
url: $0.dataBroker.url,
date: $0.scanJobData.lastRunDate!.timeIntervalSince1970,
parentURL: $0.dataBroker.parent))
parentURL: $0.dataBroker.parent,
optOutUrl: $0.dataBroker.optOutUrl))

for mirrorSite in $0.dataBroker.mirrorSites where mirrorSite.addedAt < $0.scanJobData.lastRunDate! {
brokers.append(DBPUIDataBroker(name: mirrorSite.name,
url: mirrorSite.url,
date: $0.scanJobData.lastRunDate!.timeIntervalSince1970,
parentURL: $0.dataBroker.parent))
parentURL: $0.dataBroker.parent,
optOutUrl: $0.dataBroker.optOutUrl))
}

return brokers
Expand Down Expand Up @@ -171,21 +175,24 @@ struct MapperToUI {
brokers.append(DBPUIDataBroker(name: $0.dataBroker.name,
url: $0.dataBroker.url,
date: $0.scanJobData.preferredRunDate!.timeIntervalSince1970,
parentURL: $0.dataBroker.parent))
parentURL: $0.dataBroker.parent,
optOutUrl: $0.dataBroker.optOutUrl))

for mirrorSite in $0.dataBroker.mirrorSites {
if let removedDate = mirrorSite.removedAt {
if removedDate > $0.scanJobData.preferredRunDate! {
brokers.append(DBPUIDataBroker(name: mirrorSite.name,
url: mirrorSite.url,
date: $0.scanJobData.preferredRunDate!.timeIntervalSince1970,
parentURL: $0.dataBroker.parent))
parentURL: $0.dataBroker.parent,
optOutUrl: $0.dataBroker.optOutUrl))
}
} else {
brokers.append(DBPUIDataBroker(name: mirrorSite.name,
url: mirrorSite.url,
date: $0.scanJobData.preferredRunDate!.timeIntervalSince1970,
parentURL: $0.dataBroker.parent))
parentURL: $0.dataBroker.parent,
optOutUrl: $0.dataBroker.optOutUrl))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ final class DBPUICommunicationModelTests: XCTestCase {
dataBrokerName: "doesn't matter for the test",
dataBrokerURL: "see above",
dataBrokerParentURL: "whatever",
parentBrokerOptOutJobData: nil)
parentBrokerOptOutJobData: nil,
optOutUrl: "broker.com")

// Then
XCTAssertEqual(profileMatch.foundDate, createdDate.timeIntervalSince1970)
Expand Down Expand Up @@ -77,7 +78,8 @@ final class DBPUICommunicationModelTests: XCTestCase {
dataBrokerName: "doesn't matter for the test",
dataBrokerURL: "see above",
dataBrokerParentURL: "whatever",
parentBrokerOptOutJobData: nil)
parentBrokerOptOutJobData: nil,
optOutUrl: "broker.com")

// Then
XCTAssertEqual(profileMatch.foundDate, foundEventDate.timeIntervalSince1970)
Expand Down Expand Up @@ -116,7 +118,8 @@ final class DBPUICommunicationModelTests: XCTestCase {
dataBrokerName: "doesn't matter for the test",
dataBrokerURL: "see above",
dataBrokerParentURL: "whatever",
parentBrokerOptOutJobData: nil)
parentBrokerOptOutJobData: nil,
optOutUrl: "broker.com")

// Then
XCTAssertEqual(profileMatch.foundDate, foundEventDate2.timeIntervalSince1970)
Expand Down Expand Up @@ -147,7 +150,8 @@ final class DBPUICommunicationModelTests: XCTestCase {
dataBrokerName: "doesn't matter for the test",
dataBrokerURL: "see above",
dataBrokerParentURL: "whatever",
parentBrokerOptOutJobData: [parentOptOut])
parentBrokerOptOutJobData: [parentOptOut],
optOutUrl: "broker.com")

// Then
XCTAssertTrue(profileMatch.hasMatchingRecordOnParentBroker)
Expand Down Expand Up @@ -177,7 +181,8 @@ final class DBPUICommunicationModelTests: XCTestCase {
dataBrokerParentURL: "whatever",
parentBrokerOptOutJobData: [parentOptOutNonmatching1,
parentOptOutMatching,
parentOptOutNonmatching2])
parentOptOutNonmatching2],
optOutUrl: "broker.com")

// Then
XCTAssertTrue(profileMatch.hasMatchingRecordOnParentBroker)
Expand All @@ -203,7 +208,8 @@ final class DBPUICommunicationModelTests: XCTestCase {
dataBrokerURL: "see above",
dataBrokerParentURL: "whatever",
parentBrokerOptOutJobData: [parentOptOutNonmatching1,
parentOptOutNonmatching2])
parentOptOutNonmatching2],
optOutUrl: "broker.com")

// Then
XCTAssertFalse(profileMatch.hasMatchingRecordOnParentBroker)
Expand All @@ -225,9 +231,70 @@ final class DBPUICommunicationModelTests: XCTestCase {
dataBrokerName: "doesn't matter for the test",
dataBrokerURL: "see above",
dataBrokerParentURL: "whatever",
parentBrokerOptOutJobData: [parentOptOut])
parentBrokerOptOutJobData: [parentOptOut],
optOutUrl: "broker.com")

// Then
XCTAssertTrue(profileMatch.hasMatchingRecordOnParentBroker)
}

// MARK: - `profileMatches` Broker OptOut URL & Name tests

func testProfileMatches_optOutUrlAndBrokerNameForChildBroker() {
// Given
let extractedProfile = ExtractedProfile(id: 1, name: "Sample Name", profileUrl: "profile.com")

let childBroker = BrokerProfileQueryData.mock(
dataBrokerName: "ChildBroker",
url: "child.com",
parentURL: "parent.com",
optOutUrl: "child.com/optout",
extractedProfile: extractedProfile
)

let parentBroker = BrokerProfileQueryData.mock(
dataBrokerName: "ParentBroker",
url: "parent.com",
optOutUrl: "parent.com/optout",
extractedProfile: extractedProfile
)

// When
let results = DBPUIDataBrokerProfileMatch.profileMatches(from: [childBroker, parentBroker])

// Then
XCTAssertEqual(results.count, 2)

let childProfile = results.first { $0.dataBroker.name == "ChildBroker" }
XCTAssertEqual(childProfile?.dataBroker.optOutUrl, "child.com/optout")
}

func testProfileMatches_optOutUrlAndBrokerNameForParentBroker() {
// Given
let extractedProfile = ExtractedProfile(id: 1, name: "Sample Name", profileUrl: "profile.com")

let childBroker = BrokerProfileQueryData.mock(
dataBrokerName: "ChildBroker",
url: "child.com",
parentURL: "parent.com",
optOutUrl: "parent.com/optout",
extractedProfile: extractedProfile
)

let parentBroker = BrokerProfileQueryData.mock(
dataBrokerName: "ParentBroker",
url: "parent.com",
optOutUrl: "parent.com/optout",
extractedProfile: extractedProfile
)

// When
let results = DBPUIDataBrokerProfileMatch.profileMatches(from: [childBroker, parentBroker])

// Then
XCTAssertEqual(results.count, 2)

let childProfile = results.first { $0.dataBroker.name == "ChildBroker" }
XCTAssertEqual(childProfile?.dataBroker.optOutUrl, "parent.com/optout")
}
}
Loading

0 comments on commit b16b54c

Please sign in to comment.