Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GPP in the setuid endpoint #2761

Merged
merged 23 commits into from
Jul 17, 2023
Merged

GPP in the setuid endpoint #2761

merged 23 commits into from
Jul 17, 2023

Conversation

guscarreon
Copy link
Contributor

Requires #2756

This pull request is a continuation of GPP Phase 2, more info in this document and issue #2380. Makes the /setuid endpoint handler to prioritize the GPP string values, parsed with the go-gpp library, over the GDPR param values it currently takes into account.

@guscarreon guscarreon changed the title GPP in the '/setuid' endpoint GPP in the 'setuid' endpoint May 22, 2023
@guscarreon guscarreon changed the title GPP in the 'setuid' endpoint GPP in the /setuid endpoint May 22, 2023
@bsardo bsardo assigned bsardo, hhhjort and AlexBVolcy and unassigned hhhjort May 23, 2023
@bsardo bsardo changed the title GPP in the /setuid endpoint GPP in the setuid endpoint May 24, 2023
if gdprQuerySignal == "1" && gdprConsent == "" {
return gdpr.RequestInfo{}, errors.New("gdpr_consent is required when gdpr=1")
}
if i, err := strconv.Atoi(gdprQuerySignal); err == nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the GDPR signal was not present in the GPP query params, you're looking at the legacy GDPR query params. If gdprQuerySignal was not specified, we should be defaulting gdprSignal to SignalAmbiguous as you'll see in the code you deleted below. The perms object instantiated via permsBuilder in preventSyncsGDPR will properly handle the ambiguous signal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're completely right. Made major corrections to this function in the next commit.

Comment on lines 178 to 181
if len(gppSID) > 0 && gppPrivacy.IsSIDInList(gppSID, gppConstants.SectionTCFEU2) {
gdprSignal = gdpr.SignalYes
signalSet = true
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the length of gppSID is greater than 0 but gppConstants.SectionTCFEU2 is not present in gppSID, should we be treating that as a SignalNo and not bother to consult the legacy query params? It looks like that is what we're doing in the cookie sync endpoint.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Logic was corrected

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Logic was corrected

endpoints/setuid.go Outdated Show resolved Hide resolved
endpoints/setuid.go Outdated Show resolved Hide resolved
endpoints/setuid.go Outdated Show resolved Hide resolved
AlexBVolcy
AlexBVolcy previously approved these changes Jun 7, 2023
Copy link
Contributor

@AlexBVolcy AlexBVolcy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just one minor comment

expected testOutput
}
testSuite := []struct {
sDesc string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this sDesc value used anywhere in these tests? If not, could it be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected in df562e9

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From looking at the requirements doc referenced in the description, it appears we aren't detecting or providing any debug information indicating mismatched data when the gdpr signal is set in the GPPSID and in the original location at regs.gdpr. This also appears to be true with respect to the consent strings. Was this intentionally omitted? I see that detected mismatches are meant to be reported as debug warnings, however, at first glance I'm not seeing support for debug mode on this endpoint so perhaps that's the reason we aren't handling it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline. There's no need to add debug functionality to these endpoints. The setuid and cookie sync endpoints currently support adding warnings to the response. This PR adds the appropriate warnings for the setuid endpoint. The cookie sync warnings will be added in another PR.

}

if i := gppPrivacy.IndexOfSID(gpp, gppConstants.SectionTCFEU2); i >= 0 {
gdprConsent = gpp.Sections[i].GetValue()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requirements for the cookie sync and setuid endpoints state that if the gdpr consent string is provided in the GPP container and also in the query string, we just compare and warn without copying. That would mean the query string value takes precedence. I wasn't sure if that was the intention but after looking at the same requirements for the auction endpoint I see this same compare requirement but with the following note right after it: "Prebid should prefer the string originally in user.consent". We should confirm the intended behavior. and if the logic is similar for the gdpr flag.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline. The requirements do not appear to be up to date. It was agreed upon that we should always favor the GPP values over the legacy values.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An edge case was identified that does not appear to be called out in the spec. If both GPP and the legacy location contain consent strings, we will always favor the GPP string, even if it is malformed. For now we will report the error found in the GPP string rather than falling back to the legacy location. This can always be added later. We can discuss with the committee.

}
return gdpr.SignalNo, strconv.Itoa(int(gdpr.SignalNo)), nil
func extractGDPRSignal(requestGDPR *int, gppSidStr string) (gdpr.Signal, string, error) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Could you remove this blank line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes in this file were discarded

@@ -154,6 +158,7 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
w.Header().Add("Content-Type", httputil.Pixel1x1PNG.ContentType)
w.Header().Add("Content-Length", strconv.Itoa(len(httputil.Pixel1x1PNG.Content)))
w.WriteHeader(http.StatusOK)
// signal, consent, error := parseGDPRFromGPP(query)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be deleted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

if err != nil {

if !errortypes.IsWarning(err) && err != nil {
//if err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be deleted?

// first and the 'gdpr' and 'gdpr_consent' query params second. If found in both, throws a
// warning. Can also throw a parsing or validation error
func extractGDPRInfo(query url.Values) (reqInfo gdpr.RequestInfo, err error) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Can this line be deleted?

}

// If warning, or there was no GDPR data in the GPP wrapper
//if (err != nil && isWarning) || (reqInfo.Consent == "" && reqInfo.GDPRSignal == gdpr.SignalAmbiguous) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this comment be deleted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleted


legacySignal, legacyConsent, err := parseLegacyGDPRFields(query, reqInfo.GDPRSignal, reqInfo.Consent)
isWarning := errortypes.IsWarning(err)
// If not warning, throw error
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment can be deleted since the flow of the code explains what it's doing nicely.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

AlexBVolcy
AlexBVolcy previously approved these changes Jul 1, 2023
Copy link
Contributor

@AlexBVolcy AlexBVolcy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bsardo bsardo assigned hhhjort and unassigned bsardo Jul 5, 2023
return gdpr.SignalAmbiguous, "", errors.New("the gdpr query param must be either 0 or 1. You gave " + gdprQuerySignal)
}

if i, err := strconv.Atoi(gdprQuerySignal); err == nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there are only 2 possible values, would a case statement be more efficient? This could even be combined with the above check, so if it does not match one of the two values, the default case is the above error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes perfect sense. Modified

@@ -20,7 +20,7 @@ func isFatal(err error) bool {
return !ok || s.Severity() == SeverityFatal
}

func isWarning(err error) bool {
func IsWarning(err error) bool {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is now being exported, might want to make a comment to explain that an error can only be a warning if it is a warning type from this package. There is no magic to divine that a random error is intended to only be a warning.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment here and similar one in the definition of the Warning type. Let me know if you agree with the wording

Copy link
Collaborator

@hhhjort hhhjort left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bsardo bsardo merged commit be632e0 into master Jul 17, 2023
3 checks passed
@SyntaxNode SyntaxNode deleted the gppSetuid branch October 2, 2023 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants