22
33import io .netty .handler .codec .http .HttpResponseStatus ;
44import io .vertx .core .AsyncResult ;
5+ import io .vertx .core .CompositeFuture ;
56import io .vertx .core .Future ;
67import io .vertx .core .http .Cookie ;
78import io .vertx .core .http .HttpHeaders ;
5051import org .prebid .server .privacy .gdpr .model .TcfResponse ;
5152import org .prebid .server .settings .ApplicationSettings ;
5253import org .prebid .server .settings .model .Account ;
54+ import org .prebid .server .settings .model .AccountGdprConfig ;
55+ import org .prebid .server .settings .model .AccountPrivacyConfig ;
5356import org .prebid .server .util .HttpUtil ;
5457import org .prebid .server .vertx .verticles .server .HttpEndpoint ;
5558import org .prebid .server .vertx .verticles .server .application .ApplicationResource ;
@@ -208,17 +211,23 @@ private void handleSetuidContextResult(AsyncResult<SetuidContext> setuidContextR
208211
209212 if (setuidContextResult .succeeded ()) {
210213 final SetuidContext setuidContext = setuidContextResult .result ();
211- final String bidder = setuidContext .getCookieName ();
214+ final String bidderCookieName = setuidContext .getCookieName ();
212215 final TcfContext tcfContext = setuidContext .getPrivacyContext ().getTcfContext ();
213216
214217 try {
215- validateSetuidContext (setuidContext , bidder );
218+ validateSetuidContext (setuidContext , bidderCookieName );
216219 } catch (InvalidRequestException | UnauthorizedUidsException | UnavailableForLegalReasonsException e ) {
217220 handleErrors (e , routingContext , tcfContext );
218221 return ;
219222 }
220223
221- isAllowedForHostVendorId (tcfContext )
224+ final AccountPrivacyConfig privacyConfig = setuidContext .getAccount ().getPrivacy ();
225+ final AccountGdprConfig accountGdprConfig = privacyConfig != null ? privacyConfig .getGdpr () : null ;
226+
227+ Future .all (
228+ tcfDefinerService .isAllowedForHostVendorId (tcfContext ),
229+ tcfDefinerService .resultForBidderNames (
230+ Collections .singleton (bidderCookieName ), tcfContext , accountGdprConfig ))
222231 .onComplete (hostTcfResponseResult -> respondByTcfResponse (hostTcfResponseResult , setuidContext ));
223232 } else {
224233 final Throwable error = setuidContextResult .cause ();
@@ -255,44 +264,25 @@ private void validateSetuidContext(SetuidContext setuidContext, String bidder) {
255264 }
256265 }
257266
258- /**
259- * If host vendor id is null, host allowed to setuid.
260- */
261- private Future <HostVendorTcfResponse > isAllowedForHostVendorId (TcfContext tcfContext ) {
262- final Integer gdprHostVendorId = tcfDefinerService .getGdprHostVendorId ();
263- return gdprHostVendorId == null
264- ? Future .succeededFuture (HostVendorTcfResponse .allowedVendor ())
265- : tcfDefinerService .resultForVendorIds (Collections .singleton (gdprHostVendorId ), tcfContext )
266- .map (this ::toHostVendorTcfResponse );
267- }
268-
269- private HostVendorTcfResponse toHostVendorTcfResponse (TcfResponse <Integer > tcfResponse ) {
270- return HostVendorTcfResponse .of (tcfResponse .getUserInGdprScope (), tcfResponse .getCountry (),
271- isSetuidAllowed (tcfResponse ));
272- }
273-
274- private boolean isSetuidAllowed (TcfResponse <Integer > hostTcfResponseToSetuidContext ) {
275- // allow cookie only if user is not in GDPR scope or vendor passed GDPR check
276- final boolean notInGdprScope = BooleanUtils .isFalse (hostTcfResponseToSetuidContext .getUserInGdprScope ());
277-
278- final Map <Integer , PrivacyEnforcementAction > vendorIdToAction = hostTcfResponseToSetuidContext .getActions ();
279- final PrivacyEnforcementAction hostPrivacyAction = vendorIdToAction != null
280- ? vendorIdToAction .get (tcfDefinerService .getGdprHostVendorId ())
281- : null ;
282- final boolean blockPixelSync = hostPrivacyAction == null || hostPrivacyAction .isBlockPixelSync ();
283-
284- return notInGdprScope || !blockPixelSync ;
285- }
286-
287- private void respondByTcfResponse (AsyncResult <HostVendorTcfResponse > hostTcfResponseResult ,
288- SetuidContext setuidContext ) {
267+ private void respondByTcfResponse (AsyncResult <CompositeFuture > hostTcfResponseResult , SetuidContext setuidContext ) {
289268 final String bidderCookieName = setuidContext .getCookieName ();
290269 final TcfContext tcfContext = setuidContext .getPrivacyContext ().getTcfContext ();
291270 final RoutingContext routingContext = setuidContext .getRoutingContext ();
292271
293272 if (hostTcfResponseResult .succeeded ()) {
294- final HostVendorTcfResponse hostTcfResponse = hostTcfResponseResult .result ();
295- if (hostTcfResponse .isVendorAllowed ()) {
273+ final CompositeFuture compositeFuture = hostTcfResponseResult .result ();
274+ final HostVendorTcfResponse hostVendorTcfResponse = compositeFuture .resultAt (0 );
275+ final TcfResponse <String > bidderTcfResponse = compositeFuture .resultAt (1 );
276+
277+ final Map <String , PrivacyEnforcementAction > vendorIdToAction = bidderTcfResponse .getActions ();
278+ final PrivacyEnforcementAction action = vendorIdToAction != null
279+ ? vendorIdToAction .get (bidderCookieName )
280+ : null ;
281+
282+ final boolean notInGdprScope = BooleanUtils .isFalse (bidderTcfResponse .getUserInGdprScope ());
283+ final boolean isBidderVendorAllowed = notInGdprScope || action == null || !action .isBlockPixelSync ();
284+
285+ if (hostVendorTcfResponse .isVendorAllowed () && isBidderVendorAllowed ) {
296286 respondWithCookie (setuidContext );
297287 } else {
298288 metrics .updateUserSyncTcfBlockedMetric (bidderCookieName );
@@ -308,7 +298,6 @@ private void respondByTcfResponse(AsyncResult<HostVendorTcfResponse> hostTcfResp
308298
309299 analyticsDelegator .processEvent (SetuidEvent .error (status .code ()), tcfContext );
310300 }
311-
312301 } else {
313302 final Throwable error = hostTcfResponseResult .cause ();
314303 metrics .updateUserSyncTcfBlockedMetric (bidderCookieName );
0 commit comments