apps/meteor/app/custom-oauth/server/transform_helpers.js
import { isObject } from '../../../lib/utils/isObject';
export const normalizers = {
// Set 'id' to '_id' for any sources that provide it
_id(identity) {
if (identity._id && !identity.id) {
identity.id = identity._id;
}
},
// Fix for Reddit
redit(identity) {
if (identity.result) {
return identity.result;
}
},
// Fix WordPress-like identities having 'ID' instead of 'id'
wordpress(identity) {
if (identity.ID && !identity.id) {
identity.id = identity.ID;
}
},
// Fix Auth0-like identities having 'user_id' instead of 'id'
user_id(identity) {
if (identity.user_id && !identity.id) {
identity.id = identity.user_id;
}
},
characterid(identity) {
if (identity.CharacterID && !identity.id) {
identity.id = identity.CharacterID;
}
},
// Fix Dataporten having 'user.userid' instead of 'id'
dataporten(identity) {
if (identity.user && identity.user.userid && !identity.id) {
if (identity.user.userid_sec && identity.user.userid_sec[0]) {
identity.id = identity.user.userid_sec[0];
} else {
identity.id = identity.user.userid;
}
identity.email = identity.user.email;
}
},
// Fix for Xenforo [BD]API plugin for 'user.user_id; instead of 'id'
xenforo(identity) {
if (identity.user && identity.user.user_id && !identity.id) {
identity.id = identity.user.user_id;
identity.email = identity.user.user_email;
}
},
// Fix general 'phid' instead of 'id' from phabricator
phabricator(identity) {
if (identity.phid && !identity.id) {
identity.id = identity.phid;
}
},
// Fix Keycloak-like identities having 'sub' instead of 'id'
kaycloak(identity) {
if (identity.sub && !identity.id) {
identity.id = identity.sub;
}
},
// Fix OpenShift identities where id is in 'metadata' object
openshift(identity) {
if (!identity.id && identity.metadata && identity.metadata.uid) {
identity.id = identity.metadata.uid;
identity.name = identity.fullName;
}
},
// Fix general 'userid' instead of 'id' from provider
userid(identity) {
if (identity.userid && !identity.id) {
identity.id = identity.userid;
}
},
// Fix Nextcloud provider
nextcloud(identity) {
if (!identity.id && identity.ocs && identity.ocs.data && identity.ocs.data.id) {
identity.id = identity.ocs.data.id;
identity.name = identity.ocs.data.displayname;
identity.email = identity.ocs.data.email;
}
},
// Fix when authenticating from a meteor app with 'emails' field
meteor(identity) {
if (!identity.email && identity.emails && Array.isArray(identity.emails) && identity.emails.length >= 1) {
identity.email = identity.emails[0].address ? identity.emails[0].address : undefined;
}
},
};
const IDENTITY_PROPNAME_FILTER = /(\.)/g;
export const renameInvalidProperties = (input) => {
if (Array.isArray(input)) {
return input.map(renameInvalidProperties);
}
if (!isObject(input)) {
return input;
}
return Object.entries(input).reduce(
(result, [name, value]) => ({
...result,
[name.replace(IDENTITY_PROPNAME_FILTER, '_')]: renameInvalidProperties(value),
}),
{},
);
};
export const getNestedValue = (propertyPath, source) =>
propertyPath.split('.').reduce((prev, curr) => (prev ? prev[curr] : undefined), source);
// /^(.+)@/::email
const REGEXP_FROM_FORMULA = /^\/((?!\/::).*)\/::(.+)/;
export const getRegexpMatch = (formula, data) => {
const regexAndPath = REGEXP_FROM_FORMULA.exec(formula);
if (!regexAndPath) {
return getNestedValue(formula, data);
}
if (regexAndPath.length !== 3) {
throw new Error(`expected array of length 3, got ${regexAndPath.length}`);
}
const [, regexString, path] = regexAndPath;
const nestedValue = getNestedValue(path, data);
const regex = new RegExp(regexString);
const matches = regex.exec(nestedValue);
// regexp does not match nested value
if (!matches) {
return undefined;
}
// we only support regular expressions with a single capture group
const [, value] = matches;
// this could mean we return `undefined` (e.g. when capture group is empty)
return value;
};
const templateStringRegex = /{{((?:(?!}}).)+)}}/g;
export const fromTemplate = (template, data) => {
if (!templateStringRegex.test(template)) {
return getNestedValue(template, data);
}
return template.replace(templateStringRegex, (fullMatch, match) => getRegexpMatch(match, data));
};