Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/vendor/
.idea
4 changes: 4 additions & 0 deletions .snyk.d/import.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# BEGIN TERRAFORM MANAGED BLOCK
"orgName": "ps"
"schema": 2
# END TERRAFORM MANAGED BLOCK
12 changes: 12 additions & 0 deletions catalog-info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# BEGIN TERRAFORM MANAGED BLOCK
"apiVersion": "backstage.io/v1alpha1"
"kind": "Location"
"metadata":
"annotations":
"github.com/project-slug": "LiveRamp/iabconsent"
"github.com/team-slug": "LiveRamp/ps"
"description": "A Go implementation of the IAB Consent String Specs (v1.1 and v2)"
"name": "iabconsent"
"tags": []
"spec": {}
# END TERRAFORM MANAGED BLOCK
10 changes: 10 additions & 0 deletions gpp_parsed_consent.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ const (
UsColoradoSID
UsUtahSID
UsConnecticutSID
UsFloridaSID
UsMontanaSID
UsOregonSID
UsTexasSID
UsDelawareSID
UsIowaSID
UsNebraskaSID
UsNewHampshireSID
UsNewJerseySID
UsTennesseeSID
)

// GppHeader is the first section of a GPP Consent String.
Expand Down
46 changes: 39 additions & 7 deletions gpp_parsed_consent_fixture_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import (
)

// Test fixtures can be created here: https://iabgpp.com/

var gppParsedConsentFixtures = map[string]map[int]*iabconsent.MspaParsedConsent{
// Valid GPP w/ US National MSPA, No Subsection (is thesame as false GPC subsection.
// Valid GPP w/ V1 US National MSPA, No Subsection (is the same as false GPC subsection).
"DBABLA~BVVqAAEABCA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"]},
// Valid GPP w/ US National MSPA, Subsection of GPC False.
// Valid GPP w/ V1 US National MSPA, Subsection of GPC False.
"DBABLA~BVVqAAEABCA.QA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"]},
// Valid GPP w/ US National MSPA, Subsection of GPC True.
// Valid GPP w/ V1 US National MSPA, Subsection of GPC True.
"DBABLA~BVVqAAEABCA.YA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.YA"]},
// Valid GPP w/ V2 US National MSPA, Subsection of GPC True.
"DBABLA~CVVVVVVVVVVW.YA": {iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["CVVVVVVVVVVW.YA"]},
// Valid GPP w/ US California MSPA, Subsection of GPC False.
"DBABBg~BVoYYZoI": {iabconsent.UsCaliforniaSID: mspaConsentFixtures[iabconsent.UsCaliforniaSID]["BVoYYZoI"]},
// Valid GPP w/ US Virginia MSPA, Subsection of GPC False.
Expand All @@ -23,12 +24,12 @@ var gppParsedConsentFixtures = map[string]map[int]*iabconsent.MspaParsedConsent{
"DBABFg~BVaGGGCA": {iabconsent.UsUtahSID: mspaConsentFixtures[iabconsent.UsUtahSID]["BVaGGGCA.QA"]},
// Valid GPP w/ US Connecticut MSPA, Subsection of GPC False.
"DBABVg~BVoYYYQg": {iabconsent.UsConnecticutSID: mspaConsentFixtures[iabconsent.UsConnecticutSID]["BVoYYYQg"]},
// Valid GPP w/ US US National and Virgina MSPA, Subsection of GPC False.
// Valid GPP w/ US National and Virginia MSPA, Subsection of GPC False.
"DBACLMA~BVVqAAEABCA~BVoYYYI": {
iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"],
iabconsent.UsVirginiaSID: mspaConsentFixtures[iabconsent.UsVirginiaSID]["BVoYYYI"],
},
// Valid GPP w/ US US National, California MSPA, Virgina MSPA, Colorado MSPA, and Utah Subsection of GPC False.
// Valid GPP w/ V1 US National, California MSPA, Virgina MSPA, Colorado MSPA, and Utah Subsection of GPC False.
"DBABrGA~BVVqAAEABCA~BVoYYZoI~BVoYYYI~BVoYYQg~BVaGGGCA~BVoYYYQg": {
iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"],
iabconsent.UsCaliforniaSID: mspaConsentFixtures[iabconsent.UsCaliforniaSID]["BVoYYZoI"],
Expand All @@ -37,9 +38,40 @@ var gppParsedConsentFixtures = map[string]map[int]*iabconsent.MspaParsedConsent{
iabconsent.UsUtahSID: mspaConsentFixtures[iabconsent.UsUtahSID]["BVaGGGCA.QA"],
iabconsent.UsConnecticutSID: mspaConsentFixtures[iabconsent.UsConnecticutSID]["BVoYYYQg"],
},
// Valid GPP w/ V1 US National, California MSPA, Virginia MSPA, Colorado MSPA, Utah MSPA, Conneticut MSPA, Florida MSPA and Montana MSPA Subsection of GPC False.
"DBABrWA~BVVqAAEABCA~BVoYYZoI~BVoYYYI~BVoYYQg~BVaGGGCA~BVoYYYQg~Bqqqqqqo~Bqqqqqqo": {
iabconsent.UsNationalSID: mspaConsentFixtures[iabconsent.UsNationalSID]["BVVqAAEABCA.QA"],
iabconsent.UsCaliforniaSID: mspaConsentFixtures[iabconsent.UsCaliforniaSID]["BVoYYZoI"],
iabconsent.UsVirginiaSID: mspaConsentFixtures[iabconsent.UsVirginiaSID]["BVoYYYI"],
iabconsent.UsColoradoSID: mspaConsentFixtures[iabconsent.UsColoradoSID]["BVoYYQg"],
iabconsent.UsUtahSID: mspaConsentFixtures[iabconsent.UsUtahSID]["BVaGGGCA.QA"],
iabconsent.UsConnecticutSID: mspaConsentFixtures[iabconsent.UsConnecticutSID]["BVoYYYQg"],
iabconsent.UsFloridaSID: mspaConsentFixtures[iabconsent.UsFloridaSID]["Bqqqqqqo"],
iabconsent.UsMontanaSID: mspaConsentFixtures[iabconsent.UsMontanaSID]["Bqqqqqqo"],
},
// Valid GPP string w/ sections for EU TCF V2 and US Privacy
// Since both are not supported, Consent fixture should be blank.
"DBACNY~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA~1YNN": {},
// Valid GPP w/ US National MSPA and US Privacy, but skip US Privacy until supported.
// Valid GPP w/ V1 US National MSPA and US Privacy, but skip US Privacy until supported.
"DBABzw~1YNN~BVVqAAEABCA.QA": {7: mspaConsentFixtures[7]["BVVqAAEABCA.QA"]},
// Valid GPP w/ US Florida MSPA, Subsection of GPC False.
"DBABAw~Bqqqqqqo": {iabconsent.UsFloridaSID: mspaConsentFixtures[iabconsent.UsFloridaSID]["Bqqqqqqo"]},
// Valid GPP w/ US Montana MSPA, Subsection of GPC False.
"DBABQw~Bqqqqqqo": {iabconsent.UsMontanaSID: mspaConsentFixtures[iabconsent.UsMontanaSID]["Bqqqqqqo"]},
// Valid GPP w/ US Oregon MSPA, Subsection of GPC False.
"DBABIw~BqqqqqqqoA": {iabconsent.UsOregonSID: mspaConsentFixtures[iabconsent.UsOregonSID]["BqqqqqqqoA"]},
// Valid GPP w/ US Texas MSPA, Subsection of GPC False.
"DBABEw~BqqqqqqA": {iabconsent.UsTexasSID: mspaConsentFixtures[iabconsent.UsTexasSID]["BqqqqqqA"]},
// Valid GPP w/ US Delaware MSPA, Subsection of GPC False.
"DBABUw~BqqqqqqqoA": {iabconsent.UsDelawareSID: mspaConsentFixtures[iabconsent.UsDelawareSID]["BqqqqqqqoA"]},
// Valid GPP w/ US Iowa MSPA, Subsection of GPC False.
"DBABCw~BVVVVVVA": {iabconsent.UsIowaSID: mspaConsentFixtures[iabconsent.UsIowaSID]["BVVVVVVA"]},
// Valid GPP w/ US Nebraska MSPA, Subsection of GPC False.
"DBABSw~BmaqqqqA": {iabconsent.UsNebraskaSID: mspaConsentFixtures[iabconsent.UsNebraskaSID]["BmaqqqqA"]},
// Valid GPP w/ US New Hampshire MSPA, Subsection of GPC False.
"DBABKw~Bpmqqqqo": {iabconsent.UsNewHampshireSID: mspaConsentFixtures[iabconsent.UsNewHampshireSID]["Bpmqqqqo"]},
// Valid GPP w/ US New Jersey MSPA, Subsection of GPC False.
"DBABAYA~BlWqqqmaqA": {iabconsent.UsNewJerseySID: mspaConsentFixtures[iabconsent.UsNewJerseySID]["BlWqqqmaqA"]},
// Valid GPP w/ US Tennessee MSPA, Subsection of GPC False.
"DBABQYA~Bqqqqqo": {iabconsent.UsTennesseeSID: mspaConsentFixtures[iabconsent.UsTennesseeSID]["Bqqqqqo"]},
}
91 changes: 64 additions & 27 deletions gpp_parsed_consent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,23 +128,7 @@ func (s *MspaSuite) TestMapGppSectionToParser(c *check.C) {
}
}

func (s *MspaSuite) TestParseGppConsent(c *check.C) {
for g, e := range gppParsedConsentFixtures {
c.Log(g)

var p, err = iabconsent.ParseGppConsent(g)

c.Check(err, check.IsNil)
c.Check(p, check.HasLen, len(e))
for i, expected := range e {
parsed, found := p[i]
c.Check(found, check.Equals, true)
c.Check(parsed, check.DeepEquals, expected)
}
}
}

func (s *MspaSuite) TestParseGppErrors(c *check.C) {
func (s *MspaSuite) TestMapGppSectionToParserErrors(c *check.C) {
tcs := []struct {
desc string
gpp string
Expand Down Expand Up @@ -176,61 +160,114 @@ func (s *MspaSuite) TestParseGppErrors(c *check.C) {
}
}

func (s *MspaSuite) TestParseGppConsent(c *check.C) {
for g, e := range gppParsedConsentFixtures {
c.Log(g)

var p, err = iabconsent.ParseGppConsent(g)

c.Check(err, check.IsNil)
c.Check(p, check.HasLen, len(e))
for i, expected := range e {
parsed, found := p[i]
c.Check(found, check.Equals, true)
c.Check(parsed, check.DeepEquals, expected)
}
}
}

func (s *MspaSuite) TestParseGppConsentError(c *check.C) {
tcs := []struct {
desc string
gpp string
}{
{
desc: "Empty Subsection.",
gpp: "DBABzw~1YNN~BVVqAAEABCA.",
},
{
desc: "Empty Subsection.",
gpp: "DBABAw~Bqqqqqqo.",
},
}
for _, tc := range tcs {
c.Log(tc.desc)

var p, err = iabconsent.ParseGppConsent(tc.gpp)

// Despite an error in the underlying parsing, we quietly do not add the bad value to the map.
c.Check(err, check.IsNil)
c.Check(p, check.HasLen, 0)
}
}

func (s *GppParseSuite) TestParseGppSubSections(c *check.C) {
var tcs = []struct {
description string
subsections string
expected *iabconsent.GppSubSection
description string
subsections string
expectedSubsection *iabconsent.GppSubSection
expectedError error
}{
{
description: "GPC Type, false value",
// 01000000
subsections: "QA",
expected: &iabconsent.GppSubSection{
expectedSubsection: &iabconsent.GppSubSection{
Gpc: false,
},
},
{
description: "GPC Type, true value.",
// 01100000
subsections: "YA",
expected: &iabconsent.GppSubSection{
expectedSubsection: &iabconsent.GppSubSection{
Gpc: true,
},
},
{
description: "No GPC Type.",
// 00000000
subsections: "AA",
expected: &iabconsent.GppSubSection{
expectedSubsection: &iabconsent.GppSubSection{
Gpc: false,
},
},
{
description: "GPC True, then GPC False, should remain True.",
// 01100000.01000000
subsections: "YA.QA",
expected: &iabconsent.GppSubSection{
expectedSubsection: &iabconsent.GppSubSection{
Gpc: true,
},
},
{
description: "GPC False, then GPC True, should remain True.",
// 01000000.01100000
subsections: "QA.YA",
expected: &iabconsent.GppSubSection{
expectedSubsection: &iabconsent.GppSubSection{
Gpc: true,
},
},
{
description: "GPC Error.",
// Blank value
subsections: "",
expectedSubsection: nil,
expectedError: errors.New("parse gpp subsection type: read int: read bits (index=0, length=2): bits: index out of range"),
},
}

for _, tc := range tcs {
c.Log(tc)
// There may be >1 subsections, and func expects them as an array, so split.
subsect := strings.Split(tc.subsections, ".")
var g, err = iabconsent.ParseGppSubSections(subsect)
c.Check(err, check.IsNil)
c.Check(g, check.DeepEquals, tc.expected)
if tc.expectedError == nil {
c.Check(err, check.IsNil)
} else {
c.Check(err.Error(), check.Equals, tc.expectedError.Error())
}
c.Check(g, check.DeepEquals, tc.expectedSubsection)
}
}

Expand Down
3 changes: 3 additions & 0 deletions mspa_parsed_consent.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type MspaParsedConsent struct {
// 0 Not Applicable. The Business does not share Personal Data with Third Parties.
// 1 Yes, notice was provided
// 2 No, notice was not provided
// Note: ProcessingNotice and SharingNotice are the same
SharingNotice MspaNotice
// Notice of the Opportunity to Opt Out of the Sale of the Consumer’s Personal Data.
// 0 Not Applicable. The Business does not Sell Personal Data.
Expand All @@ -29,6 +30,7 @@ type MspaParsedConsent struct {
// 0 Not Applicable. The Business does not Process Sensitive Data.
// 1 Yes, notice was provided
// 2 No, notice was not provided
// Note: SensitiveDataOptOutNotice and SensitiveDataProcessingOptOutNotice are the same
SensitiveDataProcessingOptOutNotice MspaNotice
// Notice of the Opportunity to Limit Use or Disclosure of the Consumer’s Sensitive Data.
// 0 Not Applicable. The Business does not use or disclose Sensitive Data.
Expand Down Expand Up @@ -72,6 +74,7 @@ type MspaParsedConsent struct {
// 0 Not Applicable. The Business does not use, retain, Sell, or Share the Consumer’s Personal Data for advertising purposes that are unrelated to or incompatible with the purpose(s) for which the Consumer’s Personal Data was collected or processed.
// 1 No Consent
// 2 Consent
// Note: AdditionalDataProcessingConsent and PersonalDataConsents are the same
PersonalDataConsents MspaConsent
// Publisher or Advertiser, as applicable, is a signatory to the IAB Multistate Service Provider Agreement (MSPA), as may be amended from time to time, and declares that the transaction is a “Covered Transaction” as defined in the MSPA.
// 1 Yes
Expand Down
Loading