Extended node management in amdin panel.
This commit is contained in:
parent
d5c69fa78f
commit
0f1a21c905
10 changed files with 152 additions and 32 deletions
server
|
@ -11,7 +11,7 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
) {
|
||||
var nodeFields = ['hostname', 'key', 'email', 'nickname', 'mac', 'coords', 'monitoring'];
|
||||
|
||||
function getValidNodeData(reqData) {
|
||||
function getNormalizedNodeData(reqData) {
|
||||
var node = {};
|
||||
_.each(nodeFields, function (field) {
|
||||
var value = Strings.normalizeString(reqData[field]);
|
||||
|
@ -30,7 +30,7 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
create: function (req, res) {
|
||||
var data = Resources.getData(req);
|
||||
|
||||
var node = getValidNodeData(data);
|
||||
var node = getNormalizedNodeData(data);
|
||||
if (!isValidNode(node)) {
|
||||
return Resources.error(res, {data: 'Invalid node data.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
var node = getValidNodeData(data);
|
||||
var node = getNormalizedNodeData(data);
|
||||
if (!isValidNode(node)) {
|
||||
return Resources.error(res, {data: 'Invalid node data.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
@ -95,14 +95,22 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
},
|
||||
|
||||
getAll: function (req, res) {
|
||||
// TODO: Paging + Sort + Filter
|
||||
|
||||
return NodeService.getAllNodes(function (err, nodes) {
|
||||
Resources.getValidRestParams('list', req, function (err, restParams) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
|
||||
return Resources.success(res, nodes);
|
||||
// TODO: Sort + Filter
|
||||
|
||||
return NodeService.getAllNodes(restParams._page, restParams._perPage, function (err, nodes, total) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
|
||||
res.set('X-Total-Count', total);
|
||||
|
||||
return Resources.success(res, nodes);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -369,11 +369,13 @@ angular.module('ffffng')
|
|||
deleteNodeFile(token, callback);
|
||||
},
|
||||
|
||||
getAllNodes: function (callback) {
|
||||
var files = findNodeFiles({});
|
||||
getAllNodes: function (page, perPage, callback) {
|
||||
var files = _.sortBy(findNodeFiles({}));
|
||||
var total = files.length;
|
||||
var pageFiles = files.slice((page - 1) * perPage, page * perPage);
|
||||
|
||||
async.mapLimit(
|
||||
files,
|
||||
pageFiles,
|
||||
MAX_PARALLEL_NODES_PARSING,
|
||||
parseNodeFile,
|
||||
function (err, nodes) {
|
||||
|
@ -382,7 +384,7 @@ angular.module('ffffng')
|
|||
return callback({data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
return callback(null, nodes);
|
||||
return callback(null, nodes, total);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('Resources', function (_) {
|
||||
angular.module('ffffng').factory('Resources', function (_, Constraints, Validator, ErrorTypes) {
|
||||
function respond(res, httpCode, data) {
|
||||
res.writeHead(httpCode, {'Content-Type': 'application/json'});
|
||||
res.end(JSON.stringify(data));
|
||||
|
@ -11,6 +11,31 @@ angular.module('ffffng').factory('Resources', function (_) {
|
|||
return _.extend({}, req.body, req.params, req.query);
|
||||
},
|
||||
|
||||
getValidRestParams: function(type, req, callback) {
|
||||
var constraints = Constraints.rest[type];
|
||||
if (!_.isPlainObject(constraints)) {
|
||||
Logger.tag('validation', 'rest').error('Unknown REST resource type: {}', type);
|
||||
return callback({data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
var data = this.getData(req);
|
||||
|
||||
var restParams = {};
|
||||
_.each(_.keys(constraints), function (key) {
|
||||
var value = data[key];
|
||||
restParams[key] = _.isUndefined(value) && !_.isUndefined(constraints[key].default)
|
||||
? constraints[key].default
|
||||
: value;
|
||||
});
|
||||
|
||||
var areValidParams = Validator.forConstraints(constraints);
|
||||
if (!areValidParams(restParams)) {
|
||||
return callback({data: 'Invalid REST parameters.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
callback(null, restParams);
|
||||
},
|
||||
|
||||
success: function (res, data) {
|
||||
respond(res, 200, data);
|
||||
},
|
||||
|
|
|
@ -17,6 +17,11 @@ angular.module('ffffng').factory('Strings', function (_) {
|
|||
}
|
||||
|
||||
return macParts.join(':');
|
||||
},
|
||||
|
||||
parseInt: function (str) {
|
||||
var parsed = _.parseInt(str, 10);
|
||||
return parsed.toString() === str ? parsed : undefined;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,24 +1,64 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('Validator', function (_) {
|
||||
var isValid = function (constraint, acceptUndefined, value) {
|
||||
if (value === undefined) {
|
||||
return acceptUndefined || constraint.optional;
|
||||
angular.module('ffffng').factory('Validator', function (_, Strings, Logger) {
|
||||
function isValidBoolean(value) {
|
||||
return _.isBoolean(value);
|
||||
}
|
||||
|
||||
function isValidNumber(constraint, value) {
|
||||
if (_.isString(value)) {
|
||||
value = Strings.parseInt(value);
|
||||
}
|
||||
|
||||
if (constraint.type === 'boolean') {
|
||||
return _.isBoolean(value);
|
||||
if (!_.isNumber(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_.isNaN(value) || !_.isFinite(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_.isNumber(constraint.min) && value < constraint.min) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_.isNumber(constraint.max) && value > constraint.max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function isValidString(constraint, value) {
|
||||
if (!_.isString(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var trimmed = value.trim();
|
||||
return (trimmed === '' && constraint.optional) || trimmed.match(constraint.regex);
|
||||
};
|
||||
}
|
||||
|
||||
var areValid = function (constraints, acceptUndefined, values) {
|
||||
function isValid(constraint, acceptUndefined, value) {
|
||||
if (value === undefined) {
|
||||
return acceptUndefined || constraint.optional;
|
||||
}
|
||||
|
||||
switch (constraint.type) {
|
||||
case 'boolean':
|
||||
return isValidBoolean(value);
|
||||
|
||||
case 'number':
|
||||
return isValidNumber(constraint, value);
|
||||
|
||||
case 'string':
|
||||
return isValidString(constraint, value);
|
||||
}
|
||||
|
||||
Logger.tag('validation').error('No validation method for constraint type: {}', constraint.type);
|
||||
return false;
|
||||
}
|
||||
|
||||
function areValid(constraints, acceptUndefined, values) {
|
||||
var fields = Object.keys(constraints);
|
||||
for (var i = 0; i < fields.length; i ++) {
|
||||
var field = fields[i];
|
||||
|
@ -27,7 +67,7 @@ angular.module('ffffng').factory('Validator', function (_) {
|
|||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
forConstraint: function (constraint, acceptUndefined) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue