mirror of https://gitee.com/bigwinds/arangodb
347 lines
9.2 KiB
JavaScript
347 lines
9.2 KiB
JavaScript
'use strict';
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2010-2013 triAGENS GmbH, Cologne, Germany
|
|
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// @author Michael Hackstein
|
|
/// @author Alan Plum
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
const joi = require('joi');
|
|
const dd = require('dedent');
|
|
const internal = require('internal');
|
|
const db = require('@arangodb').db;
|
|
const errors = require('@arangodb').errors;
|
|
const notifications = require('@arangodb/configuration').notifications;
|
|
const examples = require('@arangodb/graph-examples/example-graph');
|
|
const createRouter = require('@arangodb/foxx/router');
|
|
|
|
const API_DOCS = require(module.context.fileName('api-docs.json'));
|
|
API_DOCS.basePath = `/_db/${encodeURIComponent(db._name())}`;
|
|
|
|
const sessions = module.context.sessions;
|
|
const auth = module.context.auth;
|
|
const router = createRouter();
|
|
module.exports = router;
|
|
|
|
|
|
router.get('/whoAmI', function(req, res) {
|
|
let user = null;
|
|
if (internal.options()['server.disable-authentication']) {
|
|
user = false;
|
|
} else if (req.session && req.session.uid) {
|
|
try {
|
|
const doc = db._users.document(req.session.uid);
|
|
user = doc.user;
|
|
} catch (e) {
|
|
if (!e.isArangoError || e.errorNum !== errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code) {
|
|
throw e;
|
|
}
|
|
sessions.setUser(req.session, null);
|
|
}
|
|
}
|
|
res.json({user});
|
|
})
|
|
.summary('Return the current user')
|
|
.description(dd`
|
|
Returns the current user or "null" if the user is not authenticated.
|
|
Returns "false" if authentication is disabled.
|
|
`);
|
|
|
|
|
|
router.post('/logout', function (req, res) {
|
|
sessions.clear(req.session);
|
|
delete req.session;
|
|
res.json({success: true});
|
|
})
|
|
.summary('Log out')
|
|
.description(dd`
|
|
Destroys the current session and revokes any authentication.
|
|
`);
|
|
|
|
|
|
router.post('/login', function (req, res) {
|
|
if (!req.session) {
|
|
req.session = sessions.new();
|
|
}
|
|
|
|
const doc = db._users.firstExample({user: req.body.username});
|
|
const valid = auth.verify(
|
|
doc ? doc.authData.simple : null,
|
|
req.body.password
|
|
);
|
|
|
|
if (!valid) {
|
|
res.throw('unauthorized');
|
|
}
|
|
|
|
sessions.setUser(req.session, doc);
|
|
sessions.save(req.session);
|
|
const user = doc.user;
|
|
res.json({user});
|
|
})
|
|
.body({
|
|
username: joi.string().required(),
|
|
password: joi.string().required().allow('')
|
|
}, 'Login credentials.')
|
|
.error('unauthorized', 'Invalid credentials.')
|
|
.summary('Log in')
|
|
.description(dd`
|
|
Authenticates the user for the active session with a username and password.
|
|
Creates a new session if none exists.
|
|
`);
|
|
|
|
|
|
const authRouter = createRouter();
|
|
router.use(authRouter);
|
|
|
|
|
|
authRouter.use((req, res, next) => {
|
|
if (!internal.options()['server.disable-authentication'] && (!req.session || !req.session.uid)) {
|
|
res.throw('unauthorized');
|
|
}
|
|
next();
|
|
});
|
|
|
|
|
|
authRouter.get('/api/*', module.context.apiDocumentation({
|
|
swaggerJson(req, res) {
|
|
res.json(API_DOCS);
|
|
}
|
|
}))
|
|
.summary('System API documentation')
|
|
.description(dd`
|
|
Mounts the system API documentation.
|
|
`);
|
|
|
|
|
|
authRouter.get('shouldCheckVersion', function(req, res) {
|
|
const versions = notifications.versions();
|
|
res.json(Boolean(versions && versions.enableVersionNotification));
|
|
})
|
|
.summary('Is version check allowed')
|
|
.description(dd`
|
|
Check if version check is allowed.
|
|
`);
|
|
|
|
|
|
authRouter.post('disableVersionCheck', function(req, res) {
|
|
notifications.setVersions({enableVersionNotification: false});
|
|
res.json('ok');
|
|
})
|
|
.summary('Disable version check')
|
|
.description(dd`
|
|
Disable the version check in web interface
|
|
`);
|
|
|
|
|
|
authRouter.post('/query/explain', function(req, res) {
|
|
const bindVars = req.body.bindVars;
|
|
const query = req.body.query;
|
|
let msg = null;
|
|
|
|
try {
|
|
if (bindVars) {
|
|
msg = require('@arangodb/aql/explainer').explain({
|
|
query: query,
|
|
bindVars: bindVars
|
|
}, {colors: false}, false, bindVars);
|
|
} else {
|
|
msg = require('@arangodb/aql/explainer').explain(query, {colors: false}, false);
|
|
}
|
|
} catch (e) {
|
|
res.throw('bad request', e.message, {cause: e});
|
|
}
|
|
|
|
res.json({msg});
|
|
})
|
|
.body(joi.object({
|
|
query: joi.string().required(),
|
|
bindVars: joi.object().optional()
|
|
}).required(), 'Query and bindVars to explain.')
|
|
.summary('Explains a query')
|
|
.description(dd`
|
|
Explains a query in a more user-friendly way than the query_api/explain
|
|
`);
|
|
|
|
|
|
authRouter.post('/query/upload/:user', function(req, res) {
|
|
let doc;
|
|
|
|
if (req.session && req.session.uid) {
|
|
try {
|
|
doc = db._users.document(req.session.uid);
|
|
} catch (e) {
|
|
if (!e.isArangoError || e.errorNum !== errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code) {
|
|
throw e;
|
|
}
|
|
}
|
|
} else {
|
|
doc = db._users.firstExample({user: req.pathParams.user});
|
|
}
|
|
|
|
if (!doc) {
|
|
res.throw('not found');
|
|
}
|
|
|
|
if (!doc.userData.queries) {
|
|
doc.userData.queries = [];
|
|
}
|
|
|
|
const existingQueries = doc.userData.queries
|
|
.map(query => query.name);
|
|
|
|
for (const query of req.body) {
|
|
if (existingQueries.indexOf(query.name) !== -1) {
|
|
existingQueries.push(query.name);
|
|
doc.userData.queries.push(query);
|
|
}
|
|
}
|
|
|
|
const meta = db._users.replace(doc, doc);
|
|
res.json(meta);
|
|
})
|
|
.pathParam('user', joi.string().required(), 'Username. Ignored if authentication is enabled.')
|
|
.body(joi.array().items(joi.object({
|
|
name: joi.string().required(),
|
|
parameter: joi.any().optional(),
|
|
value: joi.any().optional()
|
|
}).required()).required(), 'User query array to import.')
|
|
.error('not found', 'User does not exist.')
|
|
.summary('Upload user queries')
|
|
.description(dd`
|
|
This function uploads all given user queries.
|
|
`);
|
|
|
|
|
|
authRouter.get('/query/download/:user', function(req, res) {
|
|
let doc;
|
|
|
|
if (req.session && req.session.uid) {
|
|
try {
|
|
doc = db._users.document(req.session.uid);
|
|
} catch (e) {
|
|
if (!e.isArangoError || e.errorNum !== errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code) {
|
|
throw e;
|
|
}
|
|
}
|
|
} else {
|
|
doc = db._users.firstExample({user: req.pathParams.user});
|
|
}
|
|
|
|
if (!doc) {
|
|
res.throw('not found');
|
|
}
|
|
|
|
res.attachment(`queries-${db._name()}-${doc.user}.json`);
|
|
res.json(doc.userData.queries || []);
|
|
})
|
|
.pathParam('user', joi.string().required(), 'Username. Ignored if authentication is enabled.')
|
|
.error('not found', 'User does not exist.')
|
|
.summary('Download stored queries')
|
|
.description(dd`
|
|
Download and export all queries from the given username.
|
|
`);
|
|
|
|
|
|
authRouter.get('/query/result/download/:query', function(req, res) {
|
|
let query;
|
|
try {
|
|
query = internal.base64Decode(req.pathParams.query);
|
|
query = JSON.parse(query);
|
|
}
|
|
catch (e) {
|
|
res.throw('bad request', e.message, {cause: e});
|
|
}
|
|
|
|
const result = db._query(query.query, query.bindVars).toArray();
|
|
res.attachment(`results-${db._name()}.json`);
|
|
res.json(result);
|
|
})
|
|
.pathParam('query', joi.string().required(), 'Base64 encoded query.')
|
|
.error('bad request', 'The query is invalid or malformed.')
|
|
.summary('Download the result of a query')
|
|
.description(dd`
|
|
This function downloads the result of a user query.
|
|
`);
|
|
|
|
|
|
authRouter.post('/graph-examples/create/:name', function(req, res) {
|
|
const name = req.pathParams.name;
|
|
|
|
if (['knows_graph', 'social', 'routeplanner'].indexOf(name) === -1) {
|
|
res.throw('not found');
|
|
}
|
|
|
|
const g = examples.loadGraph(name);
|
|
res.json({error: !g});
|
|
})
|
|
.pathParam('name', joi.string().required(), 'Name of the example graph.')
|
|
.summary('Create example graphs')
|
|
.description(dd`
|
|
Create one of the given example graphs.
|
|
`);
|
|
|
|
|
|
authRouter.post('/job', function(req, res) {
|
|
db._frontend.save(Object.assign(req.body, {model: 'job'}));
|
|
res.json(true);
|
|
})
|
|
.body(joi.object({
|
|
id: joi.any().required(),
|
|
collection: joi.any().required(),
|
|
type: joi.any().required(),
|
|
desc: joi.any().required()
|
|
}).required())
|
|
.summary('Store job id of a running job')
|
|
.description(dd`
|
|
Create a new job id entry in a specific system database with a given id.
|
|
`);
|
|
|
|
|
|
authRouter.delete('/job', function(req, res) {
|
|
db._frontend.removeByExample({model: 'job'}, true);
|
|
res.json(true);
|
|
})
|
|
.summary('Delete all jobs')
|
|
.description(dd`
|
|
Delete all jobs in a specific system database with a given id.
|
|
`);
|
|
|
|
|
|
authRouter.delete('/job/:id', function(req, res) {
|
|
db._frontend.removeByExample({id: req.pathParams.id}, true);
|
|
res.json(true);
|
|
})
|
|
.summary('Delete a job id')
|
|
.description(dd`
|
|
Delete an existing job id entry in a specific system database with a given id.
|
|
`);
|
|
|
|
|
|
authRouter.get('/job', function(req, res) {
|
|
const result = db._frontend.all().toArray();
|
|
res.json(result);
|
|
})
|
|
.summary('Return all job ids.')
|
|
.description(dd`
|
|
This function returns the job ids of all currently running jobs.
|
|
`);
|