Added confirmation page for monitoring + a few tweaks.
This commit is contained in:
parent
1b173b79d4
commit
0bdce5debb
24 changed files with 431 additions and 72 deletions
server
|
@ -3,6 +3,7 @@
|
|||
angular.module('ffffng').factory('config', function (fs, deepExtend) {
|
||||
var defaultConfig = {
|
||||
server: {
|
||||
baseUrl: 'http://localhost:8080',
|
||||
port: 8080,
|
||||
peersPath: '/tmp/peers'
|
||||
},
|
||||
|
@ -16,7 +17,13 @@ angular.module('ffffng').factory('config', function (fs, deepExtend) {
|
|||
graphUrl: 'http://graph.musterstadt.freifunk.net/graph.html',
|
||||
mapUrl: 'http://graph.musterstadt.freifunk.net/geomap.html'
|
||||
},
|
||||
monitoring: {
|
||||
enabled: true
|
||||
},
|
||||
coordsSelector: {
|
||||
showInfo: false,
|
||||
showBorderForDebugging: false,
|
||||
localCommunityPolygon: [],
|
||||
lat: 53.565278,
|
||||
lng: 10.001389,
|
||||
defaultZoom: 10
|
||||
|
|
|
@ -13,11 +13,14 @@ require('./router');
|
|||
require('./libs');
|
||||
|
||||
require('./utils/errorTypes');
|
||||
require('./utils/resources');
|
||||
require('./utils/strings');
|
||||
|
||||
require('./resources/nodeResource');
|
||||
require('./resources/monitoringResource');
|
||||
|
||||
require('./services/nodeService');
|
||||
require('./services/monitoringService');
|
||||
|
||||
require('../shared/validation/constraints');
|
||||
require('./validation/validator');
|
||||
|
|
42
server/resources/monitoringResource.js
Normal file
42
server/resources/monitoringResource.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('MonitoringResource', function (
|
||||
Constraints,
|
||||
Validator,
|
||||
MonitoringService,
|
||||
_,
|
||||
Strings,
|
||||
Resources,
|
||||
ErrorTypes
|
||||
) {
|
||||
var isValidMac = Validator.forConstraint(Constraints.node.mac);
|
||||
var isValidToken = Validator.forConstraint(Constraints.token);
|
||||
|
||||
return {
|
||||
confirm: function (req, res) {
|
||||
var data = Resources.getData(req);
|
||||
|
||||
var mac = Strings.normalizeMac(data.mac);
|
||||
if (!isValidMac(mac)) {
|
||||
return Resources.error(res, {data: 'Invalid MAC.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
var token = Strings.normalizeString(data.token);
|
||||
if (!isValidToken(token)) {
|
||||
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
return MonitoringService.confirm(mac, token, function (err, node) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
return Resources.success(res, {
|
||||
hostname: node.hostname,
|
||||
mac: node.mac,
|
||||
email: node.email,
|
||||
monitoringConfirmed: node.monitoringConfirmed
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
|
@ -6,12 +6,9 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
NodeService,
|
||||
_,
|
||||
Strings,
|
||||
Resources,
|
||||
ErrorTypes
|
||||
) {
|
||||
function getData(req) {
|
||||
return _.extend({}, req.body, req.params);
|
||||
}
|
||||
|
||||
var nodeFields = ['hostname', 'key', 'email', 'nickname', 'mac', 'coords', 'monitoring'];
|
||||
|
||||
function getValidNodeData(reqData) {
|
||||
|
@ -26,87 +23,74 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
return node;
|
||||
}
|
||||
|
||||
function respond(res, httpCode, data) {
|
||||
res.writeHead(httpCode, {'Content-Type': 'application/json'});
|
||||
res.end(JSON.stringify(data));
|
||||
}
|
||||
|
||||
function success(res, data) {
|
||||
respond(res, 200, data);
|
||||
}
|
||||
|
||||
function error(res, err) {
|
||||
respond(res, err.type.code, err.data);
|
||||
}
|
||||
|
||||
var isValidNode = Validator.forConstraints(Constraints.node);
|
||||
var isValidToken = Validator.forConstraint(Constraints.token);
|
||||
|
||||
return {
|
||||
create: function (req, res) {
|
||||
var data = getData(req);
|
||||
var data = Resources.getData(req);
|
||||
|
||||
var node = getValidNodeData(data);
|
||||
if (!isValidNode(node)) {
|
||||
return error(res, {data: 'Invalid node data.', type: ErrorTypes.badRequest});
|
||||
return Resources.error(res, {data: 'Invalid node data.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
return NodeService.createNode(node, function (err, token, node) {
|
||||
if (err) {
|
||||
return error(res, err);
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
return success(res, {token: token, node: node});
|
||||
return Resources.success(res, {token: token, node: node});
|
||||
});
|
||||
},
|
||||
|
||||
update: function (req, res) {
|
||||
var data = getData(req);
|
||||
var data = Resources.getData(req);
|
||||
|
||||
var token = Strings.normalizeString(data.token);
|
||||
if (!isValidToken(token)) {
|
||||
return error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
var node = getValidNodeData(data);
|
||||
if (!isValidNode(node)) {
|
||||
return error(res, {data: 'Invalid node data.', type: ErrorTypes.badRequest});
|
||||
return Resources.error(res, {data: 'Invalid node data.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
return NodeService.updateNode(token, node, function (err, token, node) {
|
||||
if (err) {
|
||||
return error(res, err);
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
return success(res, {token: token, node: node});
|
||||
return Resources.success(res, {token: token, node: node});
|
||||
});
|
||||
},
|
||||
|
||||
delete: function (req, res) {
|
||||
var data = getData(req);
|
||||
var data = Resources.getData(req);
|
||||
|
||||
var token = Strings.normalizeString(data.token);
|
||||
if (!isValidToken(token)) {
|
||||
return error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
return NodeService.deleteNode(token, function (err) {
|
||||
if (err) {
|
||||
return error(res, err);
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
return success(res, {});
|
||||
return Resources.success(res, {});
|
||||
});
|
||||
},
|
||||
|
||||
get: function (req, res) {
|
||||
var token = Strings.normalizeString(getData(req).token);
|
||||
var token = Strings.normalizeString(Resources.getData(req).token);
|
||||
if (!isValidToken(token)) {
|
||||
return error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
return NodeService.getNodeData(token, function (err, node) {
|
||||
return NodeService.getNodeDataByToken(token, function (err, node) {
|
||||
if (err) {
|
||||
return error(res, err);
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
return success(res, node);
|
||||
return Resources.success(res, node);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('Router', function (app, NodeResource) {
|
||||
angular.module('ffffng').factory('Router', function (app, NodeResource, MonitoringResource) {
|
||||
return {
|
||||
init: function () {
|
||||
app.post('/api/node', NodeResource.create);
|
||||
app.put('/api/node/:token', NodeResource.update);
|
||||
app.delete('/api/node/:token', NodeResource.delete);
|
||||
app.get('/api/node/:token', NodeResource.get);
|
||||
|
||||
app.put('/api/monitoring/confirm/:mac', MonitoringResource.confirm);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
30
server/services/monitoringService.js
Normal file
30
server/services/monitoringService.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng')
|
||||
.service('MonitoringService', function (NodeService, ErrorTypes) {
|
||||
return {
|
||||
confirm: function (mac, token, callback) {
|
||||
NodeService.getNodeDataByMac(mac, function (err, node, nodeSecrets) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (!node.monitoring || !nodeSecrets.monitoringToken || nodeSecrets.monitoringToken !== token) {
|
||||
return callback({data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
if (node.monitoringConfirmed) {
|
||||
return callback(null, node);
|
||||
}
|
||||
|
||||
node.monitoringConfirmed = true;
|
||||
NodeService.internalUpdateNode(node.token, node, nodeSecrets, function (err, token, node) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, node);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
|
@ -185,6 +185,17 @@ angular.module('ffffng')
|
|||
callback(null, node, nodeSecrets);
|
||||
}
|
||||
|
||||
function getNodeDataByFilePattern(pattern, callback) {
|
||||
var files = findNodeFiles(pattern);
|
||||
|
||||
if (files.length !== 1) {
|
||||
return callback({data: 'Node not found.', type: ErrorTypes.notFound});
|
||||
}
|
||||
|
||||
var file = files[0];
|
||||
return parseNodeFile(file, callback);
|
||||
}
|
||||
|
||||
return {
|
||||
createNode: function (node, callback) {
|
||||
var token = generateToken();
|
||||
|
@ -210,7 +221,7 @@ angular.module('ffffng')
|
|||
},
|
||||
|
||||
updateNode: function (token, node, callback) {
|
||||
this.getNodeData(token, function (err, currentNode, nodeSecrets) {
|
||||
this.getNodeDataByToken(token, function (err, currentNode, nodeSecrets) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
@ -233,9 +244,9 @@ angular.module('ffffng')
|
|||
monitoringToken = generateToken();
|
||||
|
||||
} else {
|
||||
// email unchanged, keep token and confirmation state
|
||||
// email unchanged, keep token (fix if not set) and confirmation state
|
||||
monitoringConfirmed = currentNode.monitoringConfirmed;
|
||||
monitoringToken = nodeSecrets.monitoringToken;
|
||||
monitoringToken = nodeSecrets.monitoringToken || generateToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,19 +268,20 @@ angular.module('ffffng')
|
|||
});
|
||||
},
|
||||
|
||||
internalUpdateNode: function (token, node, nodeSecrets, callback) {
|
||||
writeNodeFile(true, token, node, nodeSecrets, callback);
|
||||
},
|
||||
|
||||
deleteNode: function (token, callback) {
|
||||
deleteNodeFile(token, callback);
|
||||
},
|
||||
|
||||
getNodeData: function (token, callback) {
|
||||
var files = findNodeFiles('*@*@*@' + token);
|
||||
getNodeDataByToken: function (token, callback) {
|
||||
return getNodeDataByFilePattern('*@*@*@' + token, callback);
|
||||
},
|
||||
|
||||
if (files.length !== 1) {
|
||||
return callback({data: 'Node not found.', type: ErrorTypes.notFound});
|
||||
}
|
||||
|
||||
var file = files[0];
|
||||
return parseNodeFile(file, callback);
|
||||
getNodeDataByMac: function (mac, callback) {
|
||||
return getNodeDataByFilePattern('*@' + mac + '@*@*', callback);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
22
server/utils/resources.js
Normal file
22
server/utils/resources.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('Resources', function (_) {
|
||||
function respond(res, httpCode, data) {
|
||||
res.writeHead(httpCode, {'Content-Type': 'application/json'});
|
||||
res.end(JSON.stringify(data));
|
||||
}
|
||||
|
||||
return {
|
||||
getData: function (req) {
|
||||
return _.extend({}, req.body, req.params, req.query);
|
||||
},
|
||||
|
||||
success: function (res, data) {
|
||||
respond(res, 200, data);
|
||||
},
|
||||
|
||||
error: function (res, err) {
|
||||
respond(res, err.type.code, err.data);
|
||||
}
|
||||
};
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue