Removing ng-di on the server.
This commit is contained in:
parent
ddb2f47a9d
commit
8697d79ba5
37 changed files with 2838 additions and 2878 deletions
|
@ -1,12 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('DatabaseUtil', function (_) {
|
||||
return {
|
||||
inCondition: function (field, list) {
|
||||
return {
|
||||
query: '(' + field + ' IN (' + _.join(_.times(list.length, _.constant('?')), ', ') + '))',
|
||||
params: list
|
||||
};
|
||||
const _ = require('lodash')
|
||||
|
||||
module.exports = {
|
||||
inCondition (field, list) {
|
||||
return {
|
||||
query: '(' + field + ' IN (' + _.join(_.times(list.length, _.constant('?')), ', ') + '))',
|
||||
params: list
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('ErrorTypes', function () {
|
||||
return {
|
||||
badRequest: {code: 400},
|
||||
notFound: {code: 404},
|
||||
conflict: {code: 409},
|
||||
internalError: {code: 500}
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
badRequest: {code: 400},
|
||||
notFound: {code: 404},
|
||||
conflict: {code: 409},
|
||||
internalError: {code: 500}
|
||||
}
|
||||
|
|
|
@ -1,224 +1,229 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('Resources', function (_, Constraints, Validator, ErrorTypes, Logger) {
|
||||
function respond(res, httpCode, data, type) {
|
||||
switch (type) {
|
||||
case 'html':
|
||||
res.writeHead(httpCode, {'Content-Type': 'text/html'});
|
||||
res.end(data);
|
||||
break;
|
||||
const _ = require('lodash')
|
||||
|
||||
default:
|
||||
res.writeHead(httpCode, {'Content-Type': 'application/json'});
|
||||
res.end(JSON.stringify(data));
|
||||
break;
|
||||
}
|
||||
const Constraints = require('../../shared/validation/constraints')
|
||||
const ErrorTypes = require('../utils/errorTypes')
|
||||
const Logger = require('../logger')
|
||||
const Validator = require('../validation/validator')
|
||||
|
||||
function respond(res, httpCode, data, type) {
|
||||
switch (type) {
|
||||
case 'html':
|
||||
res.writeHead(httpCode, {'Content-Type': 'text/html'});
|
||||
res.end(data);
|
||||
break;
|
||||
|
||||
default:
|
||||
res.writeHead(httpCode, {'Content-Type': 'application/json'});
|
||||
res.end(JSON.stringify(data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function orderByClause(restParams, defaultSortField, allowedSortFields) {
|
||||
let sortField = _.includes(allowedSortFields, restParams._sortField) ? restParams._sortField : undefined;
|
||||
if (!sortField) {
|
||||
sortField = defaultSortField;
|
||||
}
|
||||
|
||||
function orderByClause(restParams, defaultSortField, allowedSortFields) {
|
||||
var sortField = _.includes(allowedSortFields, restParams._sortField) ? restParams._sortField : undefined;
|
||||
if (!sortField) {
|
||||
sortField = defaultSortField;
|
||||
}
|
||||
return {
|
||||
query: 'ORDER BY ' + sortField + ' ' + (restParams._sortDir === 'ASC' ? 'ASC' : 'DESC'),
|
||||
params: []
|
||||
};
|
||||
}
|
||||
|
||||
function limitOffsetClause(restParams) {
|
||||
const page = restParams._page;
|
||||
const perPage = restParams._perPage;
|
||||
|
||||
return {
|
||||
query: 'LIMIT ? OFFSET ?',
|
||||
params: [perPage, ((page - 1) * perPage)]
|
||||
};
|
||||
}
|
||||
|
||||
function escapeForLikePattern(str) {
|
||||
return str
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(/%/g, '\\%')
|
||||
.replace(/_/g, '\\_');
|
||||
}
|
||||
|
||||
function filterCondition(restParams, filterFields) {
|
||||
if (_.isEmpty(filterFields)) {
|
||||
return {
|
||||
query: 'ORDER BY ' + sortField + ' ' + (restParams._sortDir === 'ASC' ? 'ASC' : 'DESC'),
|
||||
query: '1 = 1',
|
||||
params: []
|
||||
};
|
||||
}
|
||||
|
||||
function limitOffsetClause(restParams) {
|
||||
var page = restParams._page;
|
||||
var perPage = restParams._perPage;
|
||||
let query = _.join(
|
||||
_.map(filterFields, function (field) {
|
||||
return 'LOWER(' + field + ') LIKE ?';
|
||||
}),
|
||||
' OR '
|
||||
);
|
||||
|
||||
return {
|
||||
query: 'LIMIT ? OFFSET ?',
|
||||
params: [perPage, ((page - 1) * perPage)]
|
||||
};
|
||||
}
|
||||
query += ' ESCAPE \'\\\'';
|
||||
|
||||
function escapeForLikePattern(str) {
|
||||
return str
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(/%/g, '\\%')
|
||||
.replace(/_/g, '\\_');
|
||||
}
|
||||
|
||||
function filterCondition(restParams, filterFields) {
|
||||
if (_.isEmpty(filterFields)) {
|
||||
return {
|
||||
query: '1 = 1',
|
||||
params: []
|
||||
};
|
||||
}
|
||||
|
||||
var query = _.join(
|
||||
_.map(filterFields, function (field) {
|
||||
return 'LOWER(' + field + ') LIKE ?';
|
||||
}),
|
||||
' OR '
|
||||
);
|
||||
|
||||
query += ' ESCAPE \'\\\'';
|
||||
|
||||
var search = '%' + (_.isString(restParams.q) ? escapeForLikePattern(_.toLower(restParams.q.trim())) : '') + '%';
|
||||
var params = _.times(filterFields.length, _.constant(search));
|
||||
|
||||
return {
|
||||
query: query,
|
||||
params: params
|
||||
};
|
||||
}
|
||||
|
||||
function getConstrainedValues(data, constraints) {
|
||||
var values = {};
|
||||
_.each(_.keys(constraints), function (key) {
|
||||
var value = data[key];
|
||||
values[key] =
|
||||
_.isUndefined(value) && !_.isUndefined(constraints[key].default) ? constraints[key].default : value;
|
||||
});
|
||||
return values;
|
||||
}
|
||||
const search = '%' + (_.isString(restParams.q) ? escapeForLikePattern(_.toLower(restParams.q.trim())) : '') + '%';
|
||||
const params = _.times(filterFields.length, _.constant(search));
|
||||
|
||||
return {
|
||||
getData: function (req) {
|
||||
return _.extend({}, req.body, req.params, req.query);
|
||||
},
|
||||
query: query,
|
||||
params: params
|
||||
};
|
||||
}
|
||||
|
||||
getValidRestParams: function(type, subtype, req, callback) {
|
||||
var constraints = Constraints.rest[type];
|
||||
if (!_.isPlainObject(constraints)) {
|
||||
Logger.tag('validation', 'rest').error('Unknown REST resource type: {}', type);
|
||||
function getConstrainedValues(data, constraints) {
|
||||
const values = {};
|
||||
_.each(_.keys(constraints), function (key) {
|
||||
const value = data[key];
|
||||
values[key] =
|
||||
_.isUndefined(value) && !_.isUndefined(constraints[key].default) ? constraints[key].default : value;
|
||||
});
|
||||
return values;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getData (req) {
|
||||
return _.extend({}, req.body, req.params, req.query);
|
||||
},
|
||||
|
||||
getValidRestParams(type, subtype, req, callback) {
|
||||
const 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});
|
||||
}
|
||||
|
||||
let filterConstraints = {};
|
||||
if (subtype) {
|
||||
filterConstraints = Constraints[subtype + 'Filters'];
|
||||
if (!_.isPlainObject(filterConstraints)) {
|
||||
Logger.tag('validation', 'rest').error('Unknown REST resource subtype: {}', subtype);
|
||||
return callback({data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
var filterConstraints = {};
|
||||
if (subtype) {
|
||||
filterConstraints = Constraints[subtype + 'Filters'];
|
||||
if (!_.isPlainObject(filterConstraints)) {
|
||||
Logger.tag('validation', 'rest').error('Unknown REST resource subtype: {}', subtype);
|
||||
return callback({data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
}
|
||||
|
||||
var data = this.getData(req);
|
||||
|
||||
var restParams = getConstrainedValues(data, constraints);
|
||||
var filterParams = getConstrainedValues(data, filterConstraints);
|
||||
|
||||
var areValidParams = Validator.forConstraints(constraints);
|
||||
var areValidFilters = Validator.forConstraints(filterConstraints);
|
||||
if (!areValidParams(restParams) || !areValidFilters(filterParams)) {
|
||||
return callback({data: 'Invalid REST parameters.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
restParams.filters = filterParams;
|
||||
|
||||
callback(null, restParams);
|
||||
},
|
||||
|
||||
filter: function (entities, allowedFilterFields, restParams) {
|
||||
var query = restParams.q;
|
||||
if (query) {
|
||||
query = _.toLower(query.trim());
|
||||
}
|
||||
|
||||
function queryMatches(entity) {
|
||||
if (!query) {
|
||||
return true;
|
||||
}
|
||||
return _.some(allowedFilterFields, function (field) {
|
||||
var value = entity[field];
|
||||
if (_.isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (!_.isString(value) || _.isEmpty(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value = _.toLower(value);
|
||||
if (field === 'mac') {
|
||||
return _.includes(value.replace(/:/g, ''), query.replace(/:/g, ''));
|
||||
}
|
||||
|
||||
return _.includes(value, query);
|
||||
});
|
||||
}
|
||||
|
||||
var filters = restParams.filters;
|
||||
|
||||
function filtersMatch(entity) {
|
||||
if (_.isEmpty(filters)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _.every(filters, function (value, key) {
|
||||
if (_.isUndefined(value)) {
|
||||
return true;
|
||||
}
|
||||
if (_.startsWith(key, 'has')) {
|
||||
var entityKey = key.substr(3, 1).toLowerCase() + key.substr(4);
|
||||
return _.isEmpty(entity[entityKey]).toString() !== value;
|
||||
}
|
||||
return entity[key] === value;
|
||||
});
|
||||
}
|
||||
|
||||
return _.filter(entities, function (entity) {
|
||||
return queryMatches(entity) && filtersMatch(entity);
|
||||
});
|
||||
},
|
||||
|
||||
sort: function (entities, allowedSortFields, restParams) {
|
||||
var sortField = _.includes(allowedSortFields, restParams._sortField) ? restParams._sortField : undefined;
|
||||
if (!sortField) {
|
||||
return entities;
|
||||
}
|
||||
|
||||
var sorted = _.sortBy(entities, [sortField]);
|
||||
|
||||
return restParams._sortDir === 'ASC' ? sorted : _.reverse(sorted);
|
||||
},
|
||||
|
||||
getPageEntities: function (entities, restParams) {
|
||||
var page = restParams._page;
|
||||
var perPage = restParams._perPage;
|
||||
|
||||
return entities.slice((page - 1) * perPage, page * perPage);
|
||||
},
|
||||
|
||||
whereCondition: filterCondition,
|
||||
|
||||
filterClause: function (restParams, defaultSortField, allowedSortFields, filterFields) {
|
||||
var orderBy = orderByClause(
|
||||
restParams,
|
||||
defaultSortField,
|
||||
allowedSortFields
|
||||
);
|
||||
var limitOffset = limitOffsetClause(restParams);
|
||||
|
||||
var filter = filterCondition(
|
||||
restParams,
|
||||
filterFields
|
||||
);
|
||||
|
||||
return {
|
||||
query: filter.query + ' ' + orderBy.query + ' ' + limitOffset.query,
|
||||
params: _.concat(filter.params, orderBy.params, limitOffset.params)
|
||||
};
|
||||
},
|
||||
|
||||
success: function (res, data) {
|
||||
respond(res, 200, data, 'json');
|
||||
},
|
||||
|
||||
successHtml: function (res, html) {
|
||||
respond(res, 200, html, 'html');
|
||||
},
|
||||
|
||||
error: function (res, err) {
|
||||
respond(res, err.type.code, err.data, 'json');
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const data = this.getData(req);
|
||||
|
||||
const restParams = getConstrainedValues(data, constraints);
|
||||
const filterParams = getConstrainedValues(data, filterConstraints);
|
||||
|
||||
const areValidParams = Validator.forConstraints(constraints);
|
||||
const areValidFilters = Validator.forConstraints(filterConstraints);
|
||||
if (!areValidParams(restParams) || !areValidFilters(filterParams)) {
|
||||
return callback({data: 'Invalid REST parameters.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
restParams.filters = filterParams;
|
||||
|
||||
callback(null, restParams);
|
||||
},
|
||||
|
||||
filter (entities, allowedFilterFields, restParams) {
|
||||
let query = restParams.q;
|
||||
if (query) {
|
||||
query = _.toLower(query.trim());
|
||||
}
|
||||
|
||||
function queryMatches(entity) {
|
||||
if (!query) {
|
||||
return true;
|
||||
}
|
||||
return _.some(allowedFilterFields, function (field) {
|
||||
let value = entity[field];
|
||||
if (_.isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (!_.isString(value) || _.isEmpty(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value = _.toLower(value);
|
||||
if (field === 'mac') {
|
||||
return _.includes(value.replace(/:/g, ''), query.replace(/:/g, ''));
|
||||
}
|
||||
|
||||
return _.includes(value, query);
|
||||
});
|
||||
}
|
||||
|
||||
const filters = restParams.filters;
|
||||
|
||||
function filtersMatch(entity) {
|
||||
if (_.isEmpty(filters)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _.every(filters, function (value, key) {
|
||||
if (_.isUndefined(value)) {
|
||||
return true;
|
||||
}
|
||||
if (_.startsWith(key, 'has')) {
|
||||
const entityKey = key.substr(3, 1).toLowerCase() + key.substr(4);
|
||||
return _.isEmpty(entity[entityKey]).toString() !== value;
|
||||
}
|
||||
return entity[key] === value;
|
||||
});
|
||||
}
|
||||
|
||||
return _.filter(entities, function (entity) {
|
||||
return queryMatches(entity) && filtersMatch(entity);
|
||||
});
|
||||
},
|
||||
|
||||
sort (entities, allowedSortFields, restParams) {
|
||||
const sortField = _.includes(allowedSortFields, restParams._sortField) ? restParams._sortField : undefined;
|
||||
if (!sortField) {
|
||||
return entities;
|
||||
}
|
||||
|
||||
const sorted = _.sortBy(entities, [sortField]);
|
||||
|
||||
return restParams._sortDir === 'ASC' ? sorted : _.reverse(sorted);
|
||||
},
|
||||
|
||||
getPageEntities (entities, restParams) {
|
||||
const page = restParams._page;
|
||||
const perPage = restParams._perPage;
|
||||
|
||||
return entities.slice((page - 1) * perPage, page * perPage);
|
||||
},
|
||||
|
||||
whereCondition: filterCondition,
|
||||
|
||||
filterClause (restParams, defaultSortField, allowedSortFields, filterFields) {
|
||||
const orderBy = orderByClause(
|
||||
restParams,
|
||||
defaultSortField,
|
||||
allowedSortFields
|
||||
);
|
||||
const limitOffset = limitOffsetClause(restParams);
|
||||
|
||||
const filter = filterCondition(
|
||||
restParams,
|
||||
filterFields
|
||||
);
|
||||
|
||||
return {
|
||||
query: filter.query + ' ' + orderBy.query + ' ' + limitOffset.query,
|
||||
params: _.concat(filter.params, orderBy.params, limitOffset.params)
|
||||
};
|
||||
},
|
||||
|
||||
success (res, data) {
|
||||
respond(res, 200, data, 'json');
|
||||
},
|
||||
|
||||
successHtml (res, html) {
|
||||
respond(res, 200, html, 'html');
|
||||
},
|
||||
|
||||
error (res, err) {
|
||||
respond(res, err.type.code, err.data, 'json');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('Strings', function (_) {
|
||||
return {
|
||||
normalizeString: function (str) {
|
||||
return _.isString(str) ? str.trim().replace(/\s+/g, ' ') : str;
|
||||
},
|
||||
const _ = require('lodash')
|
||||
|
||||
normalizeMac: function (mac) {
|
||||
// parts only contains values at odd indexes
|
||||
var parts = mac.toUpperCase().replace(/:/g, '').split(/([A-F0-9]{2})/);
|
||||
module.exports = {
|
||||
normalizeString (str) {
|
||||
return _.isString(str) ? str.trim().replace(/\s+/g, ' ') : str;
|
||||
},
|
||||
|
||||
var macParts = [];
|
||||
normalizeMac (mac) {
|
||||
// parts only contains values at odd indexes
|
||||
const parts = mac.toUpperCase().replace(/:/g, '').split(/([A-F0-9]{2})/);
|
||||
|
||||
for (var i = 1; i < parts.length; i += 2) {
|
||||
macParts.push(parts[i]);
|
||||
}
|
||||
const macParts = [];
|
||||
|
||||
return macParts.join(':');
|
||||
},
|
||||
|
||||
parseInt: function (str) {
|
||||
var parsed = _.parseInt(str, 10);
|
||||
return parsed.toString() === str ? parsed : undefined;
|
||||
for (let i = 1; i < parts.length; i += 2) {
|
||||
macParts.push(parts[i]);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return macParts.join(':');
|
||||
},
|
||||
|
||||
parseInt (str) {
|
||||
const parsed = _.parseInt(str, 10);
|
||||
return parsed.toString() === str ? parsed : undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +1,41 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('UrlBuilder', function (_, config) {
|
||||
function formUrl(route, queryParams) {
|
||||
var url = config.server.baseUrl;
|
||||
if (route || queryParams) {
|
||||
url += '/#/';
|
||||
}
|
||||
if (route) {
|
||||
url += route;
|
||||
}
|
||||
if (queryParams) {
|
||||
url += '?';
|
||||
url += _.join(
|
||||
_.map(
|
||||
queryParams,
|
||||
function (value, key) {
|
||||
return encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
||||
}
|
||||
),
|
||||
'&'
|
||||
);
|
||||
}
|
||||
return url;
|
||||
const _ = require('lodash')
|
||||
|
||||
const config = require('../config').config
|
||||
|
||||
function formUrl(route, queryParams) {
|
||||
let url = config.server.baseUrl;
|
||||
if (route || queryParams) {
|
||||
url += '/#/';
|
||||
}
|
||||
if (route) {
|
||||
url += route;
|
||||
}
|
||||
if (queryParams) {
|
||||
url += '?';
|
||||
url += _.join(
|
||||
_.map(
|
||||
queryParams,
|
||||
function (value, key) {
|
||||
return encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
||||
}
|
||||
),
|
||||
'&'
|
||||
);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
return {
|
||||
editNodeUrl: function () {
|
||||
return formUrl('update');
|
||||
},
|
||||
module.exports = {
|
||||
editNodeUrl () {
|
||||
return formUrl('update');
|
||||
},
|
||||
|
||||
monitoringConfirmUrl: function (nodeSecrets) {
|
||||
return formUrl('monitoring/confirm', { token: nodeSecrets.monitoringToken });
|
||||
},
|
||||
monitoringDisableUrl: function (nodeSecrets) {
|
||||
return formUrl('monitoring/disable', { token: nodeSecrets.monitoringToken });
|
||||
}
|
||||
};
|
||||
});
|
||||
monitoringConfirmUrl (nodeSecrets) {
|
||||
return formUrl('monitoring/confirm', { token: nodeSecrets.monitoringToken });
|
||||
},
|
||||
monitoringDisableUrl (nodeSecrets) {
|
||||
return formUrl('monitoring/disable', { token: nodeSecrets.monitoringToken });
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue