Skip to content

Commit

Permalink
MWPW-138459 XLG Entitlement support (#1649)
Browse files Browse the repository at this point in the history
Co-authored-by: aem-code-sync[bot] <43241697+aem-code-sync[bot]@users.noreply.github.com>
  • Loading branch information
chrischrischris and aem-code-sync[bot] authored Dec 15, 2023
1 parent dba63ec commit 151457b
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 181 deletions.
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"ryanluker.vscode-coverage-gutters",
"eamodio.gitlens"
"eamodio.gitlens",
"github.vscode-pull-request-github"
]
}
25 changes: 25 additions & 0 deletions libs/features/personalization/entitlements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { getConfig } from '../../utils/utils.js';

export const ENTITLEMENT_MAP = {
'9565ef55-faad-430b-b661-596ba7a036c4': 'all-apps',
'c8d50cc2-491e-48df-a1b0-1509f0ca7323': 'photoshop',
'fd30e9c7-9ae9-44db-8e70-5c652a5bb1d2': 'cc-all-apps',
};

const getEntitlements = (data) => {
const { entitlements = {} } = getConfig();
const entitlementMap = { ...entitlements, ...ENTITLEMENT_MAP };

return data.flatMap((destination) => {
const ents = destination.segments?.flatMap((segment) => {
const entMatch = entitlementMap[segment.id];
return entMatch ? [entMatch] : [];
});

return ents || [];
});
};

export default function init(data) {
return getEntitlements(data);
}
175 changes: 46 additions & 129 deletions libs/features/personalization/personalization.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,47 @@
/* eslint-disable no-console */

import {
createTag, getConfig, loadIms, loadLink, loadScript, updateConfig,
} from '../../utils/utils.js';
import { createTag, getConfig, loadLink, loadScript, updateConfig } from '../../utils/utils.js';
import { ENTITLEMENT_MAP } from './entitlements.js';

/* c8 ignore start */
export const PERSONALIZATION_TAGS = {
all: () => true,
chrome: () => navigator.userAgent.includes('Chrome') && !navigator.userAgent.includes('Mobile'),
firefox: () => navigator.userAgent.includes('Firefox') && !navigator.userAgent.includes('Mobile'),
android: () => navigator.userAgent.includes('Android'),
ios: () => /iPad|iPhone|iPod/.test(navigator.userAgent),
loggedout: () => !window.adobeIMS?.isSignedInUser(),
loggedin: () => window.adobeIMS?.isSignedInUser(),
darkmode: () => window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches,
lightmode: () => !PERSONALIZATION_TAGS.darkmode(),
};
const PERSONALIZATION_KEYS = Object.keys(PERSONALIZATION_TAGS);
/* c8 ignore stop */

const CLASS_EL_DELETE = 'p13n-deleted';
const CLASS_EL_REPLACE = 'p13n-replaced';
const LS_ENT_KEY = 'milo:entitlements';
const LS_ENT_EXPIRE_KEY = 'milo:entitlements:expire';
const COLUMN_NOT_OPERATOR = 'not';
const TARGET_EXP_PREFIX = 'target-';
const ENT_CACHE_EXPIRE = 1000 * 60 * 60 * 3; // 3 hours
const ENT_CACHE_REFRESH = 1000 * 60 * 3; // 3 minutes
const PAGE_URL = new URL(window.location.href);

export const NON_TRACKED_MANIFEST_TYPE = 'test or promo';

// Replace any non-alpha chars except comma, space, ampersand and hyphen
const RE_KEY_REPLACE = /[^a-z0-9\- _,&=]/g;

const MANIFEST_KEYS = [
'action',
'selector',
'pagefilter',
'page filter',
'page filter optional',
];

const DATA_TYPE = {
JSON: 'json',
TEXT: 'text',
};

export const appendJsonExt = (path) => (path.endsWith('.json') ? path : `${path}.json`);

export const normalizePath = (p) => {
Expand Down Expand Up @@ -62,44 +88,6 @@ export const preloadManifests = ({ targetManifests = [], persManifests = [] }) =
return manifests;
};

/* c8 ignore start */
export const PERSONALIZATION_TAGS = {
all: () => true,
chrome: () => navigator.userAgent.includes('Chrome') && !navigator.userAgent.includes('Mobile'),
firefox: () => navigator.userAgent.includes('Firefox') && !navigator.userAgent.includes('Mobile'),
android: () => navigator.userAgent.includes('Android'),
ios: () => /iPad|iPhone|iPod/.test(navigator.userAgent),
loggedout: () => !window.adobeIMS?.isSignedInUser(),
loggedin: () => window.adobeIMS?.isSignedInUser(),
darkmode: () => window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches,
lightmode: () => !PERSONALIZATION_TAGS.darkmode(),
};

export const ENTITLEMENT_TAGS = {
photoshop: (ents) => ents.photoshop_cc,
lightroom: (ents) => ents.lightroom_cc,
};
/* c8 ignore stop */

const personalizationKeys = Object.keys(PERSONALIZATION_TAGS);
const entitlementKeys = Object.keys(ENTITLEMENT_TAGS);

// Replace any non-alpha chars except comma, space, ampersand and hyphen
const RE_KEY_REPLACE = /[^a-z0-9\- _,&=]/g;

const MANIFEST_KEYS = [
'action',
'selector',
'pagefilter',
'page filter',
'page filter optional',
];

const DATA_TYPE = {
JSON: 'json',
TEXT: 'text',
};

const createFrag = (el, url, manifestId) => {
let href = url;
try {
Expand Down Expand Up @@ -316,78 +304,6 @@ function parsePlaceholders(placeholders, config, selectedVariantName = '') {
}
return config;
}

const fetchEntitlements = async () => {
const [{ default: getUserEntitlements }] = await Promise.all([
import('../../blocks/global-navigation/utilities/getUserEntitlements.js'),
loadIms(),
]);
return getUserEntitlements();
};

const setEntLocalStorage = (ents) => {
localStorage.setItem(LS_ENT_KEY, JSON.stringify(ents));
localStorage.setItem(LS_ENT_EXPIRE_KEY, Date.now());
};

const loadEntsFromLocalStorage = () => {
const ents = localStorage.getItem(LS_ENT_KEY);
const expireDate = localStorage.getItem(LS_ENT_EXPIRE_KEY);
const now = Date.now();
if (!ents || !expireDate || (now - expireDate) > ENT_CACHE_EXPIRE) return null;
if ((now - expireDate) > ENT_CACHE_REFRESH) {
// refresh entitlements in background
setTimeout(() => {
fetchEntitlements().then((newEnts) => {
setEntLocalStorage(newEnts);
});
}, 5000);
}
return JSON.parse(ents);
};

const clearEntLocalStorage = () => {
localStorage.removeItem(LS_ENT_KEY);
localStorage.removeItem(LS_ENT_EXPIRE_KEY);
};

export const getEntitlements = (() => {
let ents;
let logoutEventSet;
return (async () => {
if (window.adobeIMS && !window.adobeIMS.isSignedInUser()) {
clearEntLocalStorage();
return {};
}
if (!ents) {
ents = loadEntsFromLocalStorage();
}
if (!ents) {
ents = await fetchEntitlements();
setEntLocalStorage(ents);
}
if (!logoutEventSet) {
window.addEventListener('feds:signOut', clearEntLocalStorage);
logoutEventSet = true;
}
return ents;
});
})();

const getFlatEntitlements = async () => {
const ents = await getEntitlements();
return {
...ents.arrangement_codes,
...ents.clouds,
...ents.fulfilled_codes,
};
};

const checkForEntitlementMatch = (name, entitlements) => {
const entName = name.split('ent-')[1];
if (!entName) return false;
return entitlements[entName];
};
/* c8 ignore stop */

const checkForParamMatch = (paramStr) => {
Expand Down Expand Up @@ -427,23 +343,20 @@ async function getPersonalizationVariant(manifestPath, variantNames = [], varian
return acc;
}, { allNames: [] });

const hasEntitlementPrefix = variantInfo.allNames.some((name) => name.startsWith('ent-'));
const entitlementKeys = Object.values(ENTITLEMENT_MAP);
const hasEntitlementTag = entitlementKeys.some((tag) => variantInfo.allNames.includes(tag));

let entitlements = {};
if (hasEntitlementPrefix || hasEntitlementTag) {
entitlements = await getFlatEntitlements();
let userEntitlements = [];
if (hasEntitlementTag) {
userEntitlements = await config.entitlements();
}

const hasMatch = (name) => {
if (name === '') return true;
if (name === variantLabel?.toLowerCase()) return true;
if (name.startsWith('param-')) return checkForParamMatch(name);
if (name.startsWith('ent-')) return checkForEntitlementMatch(name, entitlements);
if (entitlementKeys.includes(name)) {
return ENTITLEMENT_TAGS[name](entitlements);
}
return personalizationKeys.includes(name) && PERSONALIZATION_TAGS[name]();
if (userEntitlements?.includes(name)) return true;
return PERSONALIZATION_KEYS.includes(name) && PERSONALIZATION_TAGS[name]();
};

const matchVariant = (name) => {
Expand Down Expand Up @@ -483,8 +396,13 @@ export async function getPersConfig(info) {
const config = parseConfig(persData);

const infoTab = manifestInfo || data?.info?.data;
config.manifestType = infoTab?.find((element) => element.key?.toLowerCase() === 'manifest-type')?.value?.toLowerCase() || 'personalization';
config.manifestOverrideName = infoTab?.find((element) => element.key?.toLowerCase() === 'manifest-override-name')?.value?.toLowerCase();
config.manifestType = infoTab
?.find((element) => element.key?.toLowerCase() === 'manifest-type')?.value?.toLowerCase()
|| 'personalization';

config.manifestOverrideName = infoTab
?.find((element) => element.key?.toLowerCase() === 'manifest-override-name')
?.value?.toLowerCase();

if (!config) {
/* c8 ignore next 3 */
Expand Down Expand Up @@ -606,7 +524,6 @@ export async function applyPers(manifests) {

if (!manifests?.length) return;

getEntitlements();
const cleanedManifests = cleanManifestList(manifests);

const override = config.mep?.override;
Expand Down
Loading

0 comments on commit 151457b

Please sign in to comment.