node-ldapjs/lib/schema/add_handler.js

116 lines
3.6 KiB
JavaScript

// Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert');
var dn = require('../dn');
var errors = require('../errors');
var logStub = require('../log_stub');
var getTransformer = require('./transform').getTransformer;
function createAddHandler(options) {
if (!options || typeof(options) !== 'object')
throw new TypeError('options (object) required');
if (!options.schema || typeof(options.schema) !== 'object')
throw new TypeError('options.schema (object) required');
var log4js = options.log4js || logStub;
var log = log4js.getLogger('SchemaAddHandler');
var schema = options.schema;
if (log.isDebugEnabled())
log.debug('Creating add schema handler with: %s',
JSON.stringify(options.schema, null, 2));
var CVErr = errors.ConstraintViolationError;
var NSAErr = errors.NoSuchAttributeError;
var OCVErr = errors.ObjectclassViolationError;
return function schemaAddHandler(req, res, next) {
var allowed = [];
var attributes = req.toObject().attributes;
var attrNames = Object.keys(attributes);
var i;
var j;
var k;
var key;
if (log.isDebugEnabled())
log.debug('%s running %j against schema', req.logId, attributes);
if (!attributes.objectclass)
return next(new OCVErr('no objectclass'));
for (i = 0; i < attributes.objectclass.length; i++) {
var oc = attributes.objectclass[i].toLowerCase();
if (!schema.objectclasses[oc])
return next(new NSAErr(oc + ' is not a known objectClass'));
// We can check required attributes right here in line. Mays we have to
// get the complete set of though. Also, to make checking much simpler,
// we just push the musts into the may list.
var must = schema.objectclasses[oc].must;
for (j = 0; j < must.length; j++) {
if (attrNames.indexOf(must[j]) === -1)
return next(new OCVErr(must[j] + ' is a required attribute'));
if (allowed.indexOf(must[j]) === -1)
allowed.push(must[j]);
}
schema.objectclasses[oc].may.forEach(function(attr) {
if (allowed.indexOf(attr) === -1)
allowed.push(attr);
});
}
// Now check that the entry's attributes are in the allowed list, and go
// ahead and transform the values as appropriate
for (i = 0; i < attrNames.length; i++) {
key = attrNames[i];
if (allowed.indexOf(key) === -1)
return next(new OCVErr(key + ' is not valid for the objectClasses ' +
attributes.objectclass.join()));
var transform = getTransformer(schema, key);
if (transform) {
for (j = 0; j < attributes[key].length; j++) {
try {
attributes[key][j] = transform(attributes[key][j]);
} catch (e) {
log.debug('%s Error parsing %s: %s', req.logId, k,
attributes[key][j],
e.stack);
return next(new CVErr(attrNames[i]));
}
}
for (j = 0; j < req.attributes.length; j++) {
if (req.attributes[j].type === key) {
req.attributes[j].vals = attributes[key];
break;
}
}
}
}
return next();
};
}
module.exports = createAddHandler;
// Now we have a modified attributes object we want to update
// "transparently" in the request.
// if (xformedValues) {
// attrNames.forEach(function(k) {
// for (var i = 0; i < req.attributes.length; i++) {
// if (req.attributes[i].type === k) {
// req.attributes[i].vals = attributes[k];
// return;
// }
// }
// });
// }