Skip to content

Commit

Permalink
Added SimpleTokenAuth, NoTokenRequiredAuth for token authentication, …
Browse files Browse the repository at this point in the history
…API definition change
  • Loading branch information
pierotofy committed Jun 25, 2018
1 parent 02a9a31 commit bf210e5
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 14 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -42,3 +42,4 @@ jspm_packages

.vscode

package-lock.json
3 changes: 2 additions & 1 deletion config-default.json
Expand Up @@ -15,5 +15,6 @@
"cleanupTasksAfter": 3,
"test": false,
"testSkipOrthophotos": false,
"testSkipDems": false
"testSkipDems": false,
"token": ""
}
4 changes: 3 additions & 1 deletion config.js
Expand Up @@ -36,7 +36,8 @@ Options:
--test Enable test mode. In test mode, no commands are sent to OpenDroneMap. This can be useful during development or testing (default: false)
--test_skip_orthophotos If test mode is enabled, skip orthophoto results when generating assets. (default: false)
--test_skip_dems If test mode is enabled, skip dems results when generating assets. (default: false)
--powercycle When set, the application exits immediately after powering up. Useful for testing launch and compilation issues.
--powercycle When set, the application exits immediately after powering up. Useful for testing launch and compilation issues.
--token <token> Sets a token that needs to be passed for every request. This can be used to limit access to the node only to token holders. (default: none)
Log Levels:
error | debug | info | verbose | debug | silly
`);
Expand Down Expand Up @@ -84,5 +85,6 @@ config.test = argv.test || fromConfigFile("test", false);
config.testSkipOrthophotos = argv.test_skip_orthophotos || fromConfigFile("testSkipOrthophotos", false);
config.testSkipDems = argv.test_skip_dems || fromConfigFile("testSkipDems", false);
config.powercycle = argv.powercycle || fromConfigFile("powercycle", false);
config.token = argv.token || fromConfigFile("token", "");

module.exports = config;
18 changes: 17 additions & 1 deletion docs/index.adoc
Expand Up @@ -8,7 +8,7 @@ REST API to access OpenDroneMap

=== Version information
[%hardbreaks]
_Version_ : 1.0.4
_Version_ : 1.1.0


=== Contact information
Expand Down Expand Up @@ -127,6 +127,8 @@ Cancels a task (stops its execution, or prevents it from being executed)
[options="header", cols=".^2,.^3,.^9,.^4,.^2"]
|===
|Type|Name|Description|Schema|Default
|*Query*|*token* +
_optional_|Token required for authentication (when authentication is required).|string|
|*Body*|*uuid* +
_required_|UUID of the task|string|
|===
Expand All @@ -153,6 +155,8 @@ Creates a new task and places it at the end of the processing queue
[options="header", cols=".^2,.^3,.^9,.^4,.^2"]
|===
|Type|Name|Description|Schema|Default
|*Query*|*token* +
_optional_|Token required for authentication (when authentication is required).|string|
|*FormData*|*images* +
_optional_|Images to process, plus an optional GPC file. If included, the GPC file should have .txt extension|file|
|*FormData*|*name* +
Expand Down Expand Up @@ -206,6 +210,8 @@ Removes a task and deletes all of its assets
[options="header", cols=".^2,.^3,.^9,.^4,.^2"]
|===
|Type|Name|Description|Schema|Default
|*Query*|*token* +
_optional_|Token required for authentication (when authentication is required).|string|
|*Body*|*uuid* +
_required_|UUID of the task|string|
|===
Expand All @@ -232,6 +238,8 @@ Restarts a task that was previously canceled, that had failed to process or that
[options="header", cols=".^2,.^3,.^9,.^4,.^2"]
|===
|Type|Name|Description|Schema|Default
|*Query*|*token* +
_optional_|Token required for authentication (when authentication is required).|string|
|*Body*|*options* +
_optional_|Serialized JSON string of the options to use for processing, as an array of the format: [{name: option1, value: value1}, {name: option2, value: value2}, …]. For example, [{"name":"cmvs-maxImages","value":"500"},{"name":"time","value":true}]. For a list of all options, call /options. Overrides the previous options set for this task.|string|
|*Body*|*uuid* +
Expand Down Expand Up @@ -264,6 +272,8 @@ Retrieves an asset (the output of OpenDroneMap's processing) associated with a t
_required_|Type of asset to download. Use "all.zip" for zip file containing all assets.|enum (all.zip, orthophoto.tif)|
|*Path*|*uuid* +
_required_|UUID of the task|string|
|*Query*|*token* +
_optional_|Token required for authentication (when authentication is required).|string|
|===


Expand Down Expand Up @@ -301,6 +311,10 @@ Gets information about this task, such as name, creation date, processing time,
|Type|Name|Description|Schema|Default
|*Path*|*uuid* +
_required_|UUID of the task|string|
|*Query*|*token* +
_optional_|Token required for authentication (when authentication is required).|string|
|*FormData*|*options* +
_optional_|Serialized JSON string of the options to use for processing, as an array of the format: [{name: option1, value: value1}, {name: option2, value: value2}, …]. For example, [{"name":"cmvs-maxImages","value":"500"},{"name":"time","value":true}]. For a list of all options, call /options|string|
|===


Expand Down Expand Up @@ -369,6 +383,8 @@ Retrieves the console output of the OpenDroneMap's process. Useful for monitorin
_required_|UUID of the task|string|
|*Query*|*line* +
_optional_|Optional line number that the console output should be truncated from. For example, passing a value of 100 will retrieve the console output starting from line 100. Defaults to 0 (retrieve all console output).|integer|`"0"`
|*Query*|*token* +
_optional_|Token required for authentication (when authentication is required).|string|
|===


Expand Down
2 changes: 1 addition & 1 deletion docs/swagger.json

Large diffs are not rendered by default.

71 changes: 62 additions & 9 deletions index.js
Expand Up @@ -40,6 +40,9 @@ let odmOptions = require('./libs/odmOptions');
let Directories = require('./libs/Directories');
let unzip = require('node-unzip-2');

let auth = require('./libs/auth/factory').fromConfig(config);
const authCheck = auth.getMiddleware();

// zip files
let request = require('request');

Expand Down Expand Up @@ -107,18 +110,24 @@ let server;
* description: URL of the zip file containing the images to process, plus an optional GPC file. If included, the GPC file should have .txt extension
* required: false
* type: string
* -
* -
* name: name
* in: formData
* description: An optional name to be associated with the task
* required: false
* type: string
* -
* -
* name: options
* in: formData
* description: 'Serialized JSON string of the options to use for processing, as an array of the format: [{name: option1, value: value1}, {name: option2, value: value2}, ...]. For example, [{"name":"cmvs-maxImages","value":"500"},{"name":"time","value":true}]. For a list of all options, call /options'
* required: false
* type: string
* -
* name: token
* in: query
* description: 'Token required for authentication (when authentication is required).'
* required: false
* type: string
* responses:
* 200:
* description: Success
Expand All @@ -134,7 +143,7 @@ let server;
* schema:
* $ref: '#/definitions/Error'
*/
app.post('/task/new', addRequestId, upload.array('images'), (req, res) => {
app.post('/task/new', authCheck, addRequestId, upload.array('images'), (req, res) => {

if ((!req.files || req.files.length === 0) && !req.body.zipurl) res.json({ error: "Need at least 1 file or a zip file url." });

Expand Down Expand Up @@ -270,6 +279,18 @@ let getTaskFromUuid = (req, res, next) => {
* description: UUID of the task
* required: true
* type: string
* -
* name: options
* in: formData
* description: 'Serialized JSON string of the options to use for processing, as an array of the format: [{name: option1, value: value1}, {name: option2, value: value2}, ...]. For example, [{"name":"cmvs-maxImages","value":"500"},{"name":"time","value":true}]. For a list of all options, call /options'
* required: false
* type: string
* -
* name: token
* in: query
* description: 'Token required for authentication (when authentication is required).'
* required: false
* type: string
* responses:
* 200:
* description: Task Information
Expand Down Expand Up @@ -315,7 +336,7 @@ let getTaskFromUuid = (req, res, next) => {
* schema:
* $ref: '#/definitions/Error'
*/
app.get('/task/:uuid/info', getTaskFromUuid, (req, res) => {
app.get('/task/:uuid/info', authCheck, getTaskFromUuid, (req, res) => {
res.json(req.task.getInfo());
});

Expand All @@ -338,6 +359,12 @@ app.get('/task/:uuid/info', getTaskFromUuid, (req, res) => {
* default: 0
* required: false
* type: integer
* -
* name: token
* in: query
* description: 'Token required for authentication (when authentication is required).'
* required: false
* type: string
* responses:
* 200:
* description: Console Output
Expand All @@ -348,7 +375,7 @@ app.get('/task/:uuid/info', getTaskFromUuid, (req, res) => {
* schema:
* $ref: '#/definitions/Error'
*/
app.get('/task/:uuid/output', getTaskFromUuid, (req, res) => {
app.get('/task/:uuid/output', authCheck, getTaskFromUuid, (req, res) => {
res.json(req.task.getOutput(req.query.line));
});

Expand All @@ -372,6 +399,12 @@ app.get('/task/:uuid/output', getTaskFromUuid, (req, res) => {
* enum:
* - all.zip
* - orthophoto.tif
* -
* name: token
* in: query
* description: 'Token required for authentication (when authentication is required).'
* required: false
* type: string
* responses:
* 200:
* description: Asset File
Expand All @@ -382,7 +415,7 @@ app.get('/task/:uuid/output', getTaskFromUuid, (req, res) => {
* schema:
* $ref: '#/definitions/Error'
*/
app.get('/task/:uuid/download/:asset', getTaskFromUuid, (req, res) => {
app.get('/task/:uuid/download/:asset', authCheck, getTaskFromUuid, (req, res) => {
let asset = req.params.asset !== undefined ? req.params.asset : "all.zip";
let filePath = req.task.getAssetsArchivePath(asset);
if (filePath) {
Expand Down Expand Up @@ -447,13 +480,19 @@ let successHandler = res => {
* required: true
* schema:
* type: string
* -
* name: token
* in: query
* description: 'Token required for authentication (when authentication is required).'
* required: false
* type: string
* responses:
* 200:
* description: Command Received
* schema:
* $ref: "#/definitions/Response"
*/
app.post('/task/cancel', uuidCheck, (req, res) => {
app.post('/task/cancel', authCheck, uuidCheck, (req, res) => {
taskManager.cancel(req.body.uuid, successHandler(res));
});

Expand All @@ -469,13 +508,19 @@ app.post('/task/cancel', uuidCheck, (req, res) => {
* required: true
* schema:
* type: string
* -
* name: token
* in: query
* description: 'Token required for authentication (when authentication is required).'
* required: false
* type: string
* responses:
* 200:
* description: Command Received
* schema:
* $ref: "#/definitions/Response"
*/
app.post('/task/remove', uuidCheck, (req, res) => {
app.post('/task/remove', authCheck, uuidCheck, (req, res) => {
taskManager.remove(req.body.uuid, successHandler(res));
});

Expand All @@ -498,13 +543,19 @@ app.post('/task/remove', uuidCheck, (req, res) => {
* required: false
* schema:
* type: string
* -
* name: token
* in: query
* description: 'Token required for authentication (when authentication is required).'
* required: false
* type: string
* responses:
* 200:
* description: Command Received
* schema:
* $ref: "#/definitions/Response"
*/
app.post('/task/restart', uuidCheck, (req, res, next) => {
app.post('/task/restart', authCheck, uuidCheck, (req, res, next) => {
if (req.body.options){
odmOptions.filterOptions(req.body.options, (err, options) => {
if (err) res.json({ error: err.message });
Expand Down Expand Up @@ -590,6 +641,7 @@ app.get('/info', (req, res) => {
let gracefulShutdown = done => {
async.series([
cb => taskManager.dumpTaskList(cb),
cb => auth.cleanup(cb),
cb => {
logger.info("Closing server");
server.close();
Expand All @@ -610,6 +662,7 @@ if (config.test) logger.info("Running in test mode");

let commands = [
cb => odmOptions.initialize(cb),
cb => auth.initialize(cb),
cb => { taskManager = new TaskManager(cb); },
cb => {
server = app.listen(config.port, err => {
Expand Down
23 changes: 23 additions & 0 deletions libs/auth/NoTokenRequiredAuth.js
@@ -0,0 +1,23 @@
/*
Node-OpenDroneMap Node.js App and REST API to access OpenDroneMap.
Copyright (C) 2018 Node-OpenDroneMap Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const TokenAuthBase = require('./TokenAuthBase');

module.exports = class NoTokenRequiredAuth extends TokenAuthBase{
// Always return valid
validateToken(token, cb){ cb(null, true); }
};
35 changes: 35 additions & 0 deletions libs/auth/SimpleTokenAuth.js
@@ -0,0 +1,35 @@
/*
Node-OpenDroneMap Node.js App and REST API to access OpenDroneMap.
Copyright (C) 2018 Node-OpenDroneMap Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const TokenAuthBase = require('./TokenAuthBase');

module.exports = class SimpleTokenAuth extends TokenAuthBase{
// @param token {String} token to use for authentication
constructor(token){
super(token);

this.token = token;
}

validateToken(token, cb){
if (this.token === token){
return cb(null, true);
}else{
cb(new Error("token does not match."), false);
}
}
};

0 comments on commit bf210e5

Please sign in to comment.