Skip to content

Commit

Permalink
Merge pull request #13113 from guardian/use-user-benefits-api
Browse files Browse the repository at this point in the history
Prepare DCR for an AB test between user benefits api & members data api
  • Loading branch information
rupertbates authored Jan 14, 2025
2 parents 5136f48 + 6dff48c commit 79aceda
Show file tree
Hide file tree
Showing 9 changed files with 294 additions and 334 deletions.
30 changes: 30 additions & 0 deletions dotcom-rendering/src/client/userFeatures/cookies/adFree.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { getCookie, removeCookie, setCookie } from '@guardian/libs';

const AD_FREE_USER_COOKIE = 'GU_AF1';

export const getAdFreeCookie = (): string | null =>
getCookie({ name: AD_FREE_USER_COOKIE });

/*
* Set the ad free cookie
*
* @param daysToLive - number of days the cookie should be valid
*/
export const setAdFreeCookie = (daysToLive = 1): void => {
const expires = new Date();
expires.setMonth(expires.getMonth() + 6);
setCookie({
name: AD_FREE_USER_COOKIE,
value: expires.getTime().toString(),
daysToLive,
});
};

export const adFreeDataIsPresent = (): boolean => {
const cookieVal = getAdFreeCookie();
if (!cookieVal) return false;
return !Number.isNaN(parseInt(cookieVal, 10));
};

export const removeAdFreeCookie = (): void =>
removeCookie({ name: AD_FREE_USER_COOKIE });
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { getCookie, removeCookie, setCookie } from '@guardian/libs';

const HIDE_SUPPORT_MESSAGING_COOKIE = 'gu_hide_support_messaging';

export const getHideSupportMessagingCookie = (): string | null =>
getCookie({ name: HIDE_SUPPORT_MESSAGING_COOKIE });

export const setHideSupportMessagingCookie = (value: boolean): void => {
setCookie({
name: HIDE_SUPPORT_MESSAGING_COOKIE,
value: String(value),
});
};

export const removeHideSupportMessagingCookie = (): void =>
removeCookie({ name: HIDE_SUPPORT_MESSAGING_COOKIE });
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { getCookie, removeCookie, setCookie } from '@guardian/libs';

const USER_FEATURES_EXPIRY_COOKIE = 'gu_user_features_expiry';

export const getUserFeaturesExpiryCookie = (): string | null =>
getCookie({ name: USER_FEATURES_EXPIRY_COOKIE });

export const setUserFeaturesExpiryCookie = (expiryTime: string): void =>
setCookie({ name: USER_FEATURES_EXPIRY_COOKIE, value: expiryTime });

export const removeUserFeaturesExpiryCookie = (): void =>
removeCookie({ name: USER_FEATURES_EXPIRY_COOKIE });

export const featuresDataIsOld = (): boolean => {
const cookie = getUserFeaturesExpiryCookie();
if (!cookie) return true;
const expiryTime = parseInt(cookie, 10);
const timeNow = new Date().getTime();
return timeNow >= expiryTime;
};
16 changes: 16 additions & 0 deletions dotcom-rendering/src/client/userFeatures/fetchJson.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const fetchJson = async (
path: string,
init: RequestInit = {},
): Promise<unknown> => {
const resp = await fetch(path, init);
if (resp.ok) {
try {
return resp.json();
} catch (ex) {
throw new Error(
`Fetch error while requesting ${path}: Invalid JSON response`,
);
}
}
throw new Error(`Fetch error while requesting ${path}: ${resp.statusText}`);
};
120 changes: 120 additions & 0 deletions dotcom-rendering/src/client/userFeatures/membersDataApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { isBoolean, isObject } from '@guardian/libs';
import type { SignedInWithCookies, SignedInWithOkta } from '../../lib/identity';
import { getOptionsHeadersWithOkta } from '../../lib/identity';
import { fetchJson } from './fetchJson';
import type { UserBenefits } from './user-features';

const dates = {
1: '01',
2: '02',
3: '03',
4: '04',
5: '05',
6: '06',
7: '07',
8: '08',
9: '09',
10: '10',
11: '11',
12: '12',
13: '13',
14: '14',
15: '15',
16: '16',
17: '17',
18: '18',
19: '19',
20: '20',
21: '21',
22: '22',
23: '23',
24: '24',
25: '25',
26: '26',
27: '27',
28: '28',
29: '29',
30: '30',
31: '31',
} as const;

const months = {
1: '01',
2: '02',
3: '03',
4: '04',
5: '05',
6: '06',
7: '07',
8: '08',
9: '09',
10: '10',
11: '11',
12: '12',
} as const;

type LocalDate =
`${number}-${(typeof months)[keyof typeof months]}-${(typeof dates)[keyof typeof dates]}`;

/**
* This type is manually kept in sync with the Membership API:
* https://github.com/guardian/members-data-api/blob/a48acdebed6a334ceb4336ece275b9cf9b3d6bb7/membership-attribute-service/app/models/Attributes.scala#L134-L151
*/
type UserFeaturesResponse = {
userId: string;
tier?: string;
recurringContributionPaymentPlan?: string;
oneOffContributionDate?: LocalDate;
membershipJoinDate?: LocalDate;
digitalSubscriptionExpiryDate?: LocalDate;
paperSubscriptionExpiryDate?: LocalDate;
guardianWeeklyExpiryDate?: LocalDate;
liveAppSubscriptionExpiryDate?: LocalDate;
alertAvailableFor?: string;
showSupportMessaging: boolean;
contentAccess: {
member: boolean;
paidMember: boolean;
recurringContributor: boolean;
digitalPack: boolean;
paperSubscriber: boolean;
guardianWeeklySubscriber: boolean;
};
};

export const syncDataFromMembersDataApi: (
signedInAuthStatus: SignedInWithOkta | SignedInWithCookies,
) => Promise<UserBenefits> = async (
signedInAuthStatus: SignedInWithOkta | SignedInWithCookies,
) => {
const response = await fetchJson(
`${
window.guardian.config.page.userAttributesApiUrl ??
'/USER_ATTRIBUTE_API_NOT_FOUND'
}/me`,
{
mode: 'cors',
...getOptionsHeadersWithOkta(signedInAuthStatus),
},
);
if (!validateResponse(response)) {
throw new Error('invalid response');
}
return {
hideSupportMessaging: !response.showSupportMessaging,
adFree: response.contentAccess.digitalPack,
};
};

const validateResponse = (
response: unknown,
): response is UserFeaturesResponse => {
return (
isObject(response) &&
isBoolean(response.showSupportMessaging) &&
isObject(response.contentAccess) &&
isBoolean(response.contentAccess.paidMember) &&
isBoolean(response.contentAccess.recurringContributor) &&
isBoolean(response.contentAccess.digitalPack)
);
};
176 changes: 0 additions & 176 deletions dotcom-rendering/src/client/userFeatures/user-features-lib.ts

This file was deleted.

Loading

0 comments on commit 79aceda

Please sign in to comment.