policy.js revision 759cbe36aeb56cbe1e788d90fbaa7f1a7e797f5d
/*! @license
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2012 ForgeRock AS. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*/
/*global additionalPolicies,resources */
var policyConfig = {
"policies" : [
{ "policyId" : "required",
"policyExec" : "required",
"clientValidation": true,
"policyRequirements" : ["REQUIRED"]
},
{ "policyId" : "not-empty",
"policyExec" : "notEmpty",
"clientValidation": true,
"validateOnlyIfPresent": true,
"policyRequirements" : ["REQUIRED"]
},
{
"policyId" : "max-attempts-triggers-lock-cooldown",
"policyExec" : "maxAttemptsTriggersLockCooldown",
"policyRequirements" : ["NO_MORE_THAN_X_ATTEMPTS_WITHIN_Y_MINUTES"]
},
{ "policyId" : "unique",
"policyExec" : "unique",
"policyRequirements" : ["UNIQUE"]
},
{ "policyId" : "no-internal-user-conflict",
"policyExec" : "noInternalUserConflict",
"policyRequirements" : ["UNIQUE"]
},
{
"policyId" : "valid-date",
"policyExec" : "validDate",
"clientValidation": true,
"validateOnlyIfPresent": true,
"policyRequirements": ["VALID_DATE"]
},
{
"policyId" : "valid-email-address-format",
"policyExec" : "validEmailAddressFormat",
"clientValidation": true,
"validateOnlyIfPresent": true,
"policyRequirements": ["VALID_EMAIL_ADDRESS_FORMAT"]
},
{
"policyId" : "valid-name-format",
"policyExec" : "validNameFormat",
"clientValidation": true,
"validateOnlyIfPresent": true,
"policyRequirements": ["VALID_NAME_FORMAT"]
},
{
"policyId" : "valid-phone-format",
"policyExec" : "validPhoneFormat",
"clientValidation": true,
"validateOnlyIfPresent": true,
"policyRequirements": ["VALID_PHONE_FORMAT"]
},
{ "policyId" : "at-least-X-capitals",
"policyExec" : "atLeastXCapitalLetters",
"clientValidation": true,
"validateOnlyIfPresent": true,
"policyRequirements" : ["AT_LEAST_X_CAPITAL_LETTERS"]
},
{ "policyId" : "at-least-X-numbers",
"policyExec" : "atLeastXNumbers",
"clientValidation": true,
"validateOnlyIfPresent": true,
"policyRequirements" : ["AT_LEAST_X_NUMBERS"]
},
{ "policyId" : "minimum-length",
"policyExec" : "minLength",
"clientValidation": true,
"validateOnlyIfPresent": true,
"policyRequirements" : ["MIN_LENGTH"]
},
{ "policyId" : "cannot-contain-others",
"policyExec" : "cannotContainOthers",
"clientValidation": true,
"validateOnlyIfPresent": true,
"policyRequirements" : ["CANNOT_CONTAIN_OTHERS"]
},
{ "policyId" : "cannot-contain-characters",
"policyExec" : "cannotContainCharacters",
"clientValidation": true,
"validateOnlyIfPresent": true,
"policyRequirements" : ["CANNOT_CONTAIN_CHARACTERS"]
},
{
"policyId" : "required-if-configured",
"policyExec": "requiredIfConfigured",
"policyRequirements" : ["REQUIRED"]
},
{ "policyId" : "re-auth-required",
"policyExec" : "reauthRequired",
"validateOnlyIfPresent": true,
"policyRequirements" : ["REAUTH_REQUIRED"]
}
]
},
policyImpl = (function (){
// internal-use utility function
var getSecurityContext,
checkExceptRoles = function (exceptRoles) {
if (security !== null) {
if (exceptRoles) {
role = exceptRoles[i];
if (roles) {
return true;
}
}
}
}
}
}
return false;
},
policyFunctions = {};
getSecurityContext = function(ctxt) {
return null;
} else {
}
};
return [ { "policyRequirement" : "REQUIRED" } ];
}
return [];
};
return [ {"policyRequirement": "REQUIRED"}];
}
else {
return [];
}
};
var failures = [],
failures = [{"policyRequirement": "NO_MORE_THAN_X_ATTEMPTS_WITHIN_Y_MINUTES", params: {"max":params.max,"numMinutes":params.numMinutes}}];
}
return failures;
};
var queryParams = {
"_queryId": "credential-internaluser-query",
"username": value
},
}
return [{"policyRequirement": "UNIQUE"}];
}
}
return [];
};
var queryParams = {
"_queryId": "get-by-field-value",
"field": property,
"value": value
},
{
}
return [{"policyRequirement": "UNIQUE"}];
}
}
return [];
};
return [ {"policyRequirement": "VALID_DATE"}];
} else {
return [];
}
};
var i,
join = function (arr, d) { // my own join needed since it appears params.forbiddenChars is not a proper JS array with the normal join method available
var j,list = "";
for (j in arr) {
}
};
for (i in params.forbiddenChars) {
return [ { "policyRequirement" : "CANNOT_CONTAIN_CHARACTERS", "params" : {"forbiddenChars" : join(params.forbiddenChars, ", ")} } ];
}
}
}
return [];
};
return [ {"policyRequirement": "VALID_PHONE_FORMAT"}];
} else {
return [];
}
};
var namePattern = /^([A-Za'-\u0105\u0107\u0119\u0142\u00F3\u015B\u017C\u017A\u0104\u0106\u0118\u0141\u00D3\u015A\u017B\u0179\u00C0\u00C8\u00CC\u00D2\u00D9\u00E0\u00E8\u00EC\u00F2\u00F9\u00C1\u00C9\u00CD\u00D3\u00DA\u00DD\u00E1\u00E9\u00ED\u00F3\u00FA\u00FD\u00C2\u00CA\u00CE\u00D4\u00DB\u00E2\u00EA\u00EE\u00F4\u00FB\u00C3\u00D1\u00D5\u00E3\u00F1\u00F5\u00C4\u00CB\u00CF\u00D6\u00DC\u0178\u00E4\u00EB\u00EF\u00F6\u00FC\u0178\u00A1\u00BF\u00E7\u00C7\u0152\u0153\u00DF\u00D8\u00F8\u00C5\u00E5\u00C6\u00E6\u00DE\u00FE\u00D0\u00F0\-\s])+$/;
if (typeof(value) !== "string" || !value.length || !namePattern.test(value)) {
return [ {"policyRequirement": "VALID_NAME_FORMAT"}];
} else {
return [];
}
};
policyFunctions.minLength = function(fullObject, value, params, property) {
if (typeof(value) !== "string" || !value.length || value.length < params.minLength) {
return [ { "policyRequirement" : "MIN_LENGTH", "params" : {"minLength":params.minLength} } ];
} else {
return [];
}
};
policyFunctions.atLeastXCapitalLetters = function(fullObject, value, params, property) {
var reg = /[(A-Z)]/g;
if (typeof(value) !== "string" || !value.length || value.match(reg) === null || value.match(reg).length < params.numCaps) {
return [ { "policyRequirement" : "AT_LEAST_X_CAPITAL_LETTERS", "params" : {"numCaps": params.numCaps} } ];
} else {
return [];
}
};
policyFunctions.atLeastXNumbers = function(fullObject, value, params, property) {
var reg = /\d/g;
if (typeof(value) !== "string" || !value.length || value.match(reg) === null || value.match(reg).length < params.numNums) {
return [ { "policyRequirement" : "AT_LEAST_X_NUMBERS", "params" : {"numNums": params.numNums} } ];
} else {
return [];
}
};
policyFunctions.validEmailAddressFormat = function(fullObject, value, params, property) {
var emailPattern = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
if (typeof(value) !== "string" || !value.length || !emailPattern.test(value)) {
return [ {"policyRequirement": "VALID_EMAIL_ADDRESS_FORMAT"}];
} else {
return [];
}
};
policyFunctions.cannotContainOthers = function(fullObject, value, params, property) {
var fieldArray = params.disallowedFields.split(","),
fullObject_server = {},
i;
if (typeof(openidm) !== "undefined" && typeof(request) !== "undefined" && request.id && !request.id.match('/$')) {
fullObject_server = openidm.read(request.id);
}
if (value && typeof(value) === "string" && value.length) {
for (i = 0; i < fieldArray.length; i++) {
if (typeof(fullObject[fieldArray[i]]) === "undefined" && typeof(fullObject_server[fieldArray[i]]) !== "undefined") {
fullObject[fieldArray[i]] = fullObject_server[fieldArray[i]];
}
if (typeof(fullObject[fieldArray[i]]) === "string" && value.match(fullObject[fieldArray[i]])) {
return [{"policyRequirement": "CANNOT_CONTAIN_OTHERS", params: {"disallowedFields": fieldArray[i]}}];
}
}
}
return [];
};
policyFunctions.requiredIfConfigured = function(fullObject, value, params, property) {
var currentValue = openidm.read("config/" + params.configBase),
baseKeyArray = params.baseKey.split("."),
i;
if (checkExceptRoles(params.exceptRoles)) {
return [];
}
for (i in baseKeyArray) {
currentValue = currentValue[baseKeyArray[i]];
}
if (currentValue && (!value || !value.length)) {
return [ {"policyRequirement": "REQUIRED"}];
}
else {
return [];
}
};
policyFunctions.reauthRequired = function(fullObject, value, params, propName) {
if (checkExceptRoles(params.exceptRoles)) {
return [];
}
var isHttp = request._isDirectHttp,
actionParams,response,currentObject;
if (isHttp === "true" || isHttp === true) {
if (request.id && !request.id.match('/$')) {
// only do a read if there is no id specified, in the case of new records
currentObject = openidm.read(request.id);
if (openidm.isEncrypted(currentObject[propName])) {
currentObject[propName] = openidm.decrypt(currentObject[propName]);
}
if (currentObject[propName] === fullObject[propName]) {
return [];
}
}
try {
actionParams = {
"_action": "reauthenticate"
};
response = openidm.action("authentication", actionParams);
} catch (error) {
return [ { "policyRequirement" : "REAUTH_REQUIRED" } ];
}
}
return [];
};
return policyFunctions;
}()),
policyProcessor = (function (policyConfig,policyImpl){
//Internal policy code below - do not modify this module
var getPolicy = function(policyId) {
var i;
for (i = 0; i < policyConfig.policies.length; i++) {
if (policyConfig.policies[i].policyId === policyId) {
return policyConfig.policies[i];
}
}
return null;
},
getPropertyValue = function(requestObject, propName) {
var propAddress = propName.split("/"),
tmpObject = requestObject,
i;
for (i = 0; i < propAddress.length; i++) {
tmpObject = tmpObject[propAddress[i]];
if (tmpObject === undefined || tmpObject === null) {
return tmpObject;
}
}
return tmpObject;
},
getPropertyConfig = function(resource, propName) {
var props = resource.properties,prop,i;
for (i = 0; i < props.length; i++) {
prop = props[i];
if (prop.name === propName) {
return prop;
}
}
return null;
},
resourceMatches = function(resource1, resource2) {
var rsrc1 = resource1.split("/"),
rsrc2 = resource2.split("/"),
i;
if (rsrc1.length === rsrc2.length) {
for (i = 0; i < rsrc1.length; i++) {
if (rsrc1[i] !== rsrc2[i] &&
rsrc1[i] !== "*" &&
rsrc2[i] !== "*") {
return false;
}
}
return true;
}
return false;
},
getResource = function(resources, resourceName) {
var i,resource;
if (resources !== null) {
for (i = 0; i < resources.length; i++) {
resource = resources[i];
if (resourceMatches(resource.resource, resourceName)) {
return resource;
}
}
}
return null;
},
getResourceWithPolicyRequirements = function(resource) {
var compProps = resource.properties,
i,j,x,reqs,
propPolicyReqs,
prop,policy;
// Loop through the properties for this resource
for (i = 0; i < compProps.length; i++) {
propPolicyReqs = [];
prop = compProps[i];
// loop through the policies of each property
for (j = 0; j < prop.policies.length; j++) {
policy = getPolicy(prop.policies[j].policyId);
// Check if client validation is enabled, if so add source
if ((policy.clientValidation !== undefined) && policy.clientValidation) {
prop.policies[j].policyFunction = policyImpl[policy.policyExec].toString();
}
prop.policies[j].policyRequirements = policy.policyRequirements;
reqs = policy.policyRequirements;
// loop through the requirements for each policy
for (x = 0; x < reqs.length; x++) {
}
}
}
// Add the requirements array to the property object
}
// Return all property configs for this resource
return resource;
},
getAllPolicyRequirements = function (policies) {
var reqs = [],i;
for (i in policies) {
}
return reqs;
},
var retObj = {},
policyRequirements = [],
if (policy === null) {
}
// validate this property every time unless the property has been marked as "validateOnlyIfPresent" and it isn't present
if (!(typeof(policy.validateOnlyIfPresent) !== 'undefined' && policy.validateOnlyIfPresent && typeof(propValue) === 'undefined')) {
}
failed = validationFunc.call({ "failedPolicyRequirements": policyRequirements, "allPolicyRequirements": allPolicyRequirements }, fullObject, propValue, params, propName);
}
}
}
}
}
},
var returnPolicies = [],
i,j,p,key,
}
found = false;
newPolicy = newPolicies[i];
policy = returnPolicies[j];
// update old policy with new config
returnPolicies[j] = newPolicy;
found = true;
}
}
if (!found) {
p = {};
p.params = {};
}
// add new policy
returnPolicies.push(p);
}
found = false;
}
return returnPolicies;
},
getAdditionalPolicies = function(id) {
var returnArray = [],
obj,
prop,
i,j,k;
if (index !== -1) {
} else {
}
if (props !== null) {
property = {};
}
}
}
}
}
}
}
}
return returnArray;
},
i,j,
prop;
found = false;
found = true;
} else {
}
}
}
if (!found) {
}
found = false;
}
},
processRequest = function() {
var returnObject = {},
rsrc,
i,
prop;
// Get the policy configuration for the specified resource
if (resource === null ) {
resource = {};
resource.properties = [];
}
// Update the policy configuration with any resource specific
}
if (method === "read") {
compArray = [];
}
returnObject = {};
} else {
}
} else if (method === "action") {
failedPolicyRequirements = [];
returnObject = {};
throw "No resource specified";
}
if (resource === null) {
// There is no configured policies for this resource (nothing to verify)
returnObject.result = true;
} else {
if (fullObject === undefined) {
}
// Perform the validation
if (action === "validateObject") {
// Validate
}
} else if (action === "validateProperty") {
// Validate
}
} else {
throw "Unsupported action: " + action;
}
// Set the result to true if no failedPolicyRequirements (failures), false otherwise
// Set the return failedPolicyRequirements
}
} else {
throw "Unsupported method: " + method;
}
return returnObject;
};
return {processRequest:processRequest};
}(policyConfig,policyImpl)),
var obj = {};
};
var i,j;
//Load additional policy scripts if configured
try {
eval(additionalPolicies[i]);
}
}
} catch (error) {
}
}
};
return obj;
}(policyConfig,policyImpl));
if (typeof additionalPolicies !== 'undefined') {
}