1
0
Fork 0

Port Aardvark to FOTF

This commit is contained in:
Alan Plum 2016-04-06 18:25:30 +02:00
parent 5a3e42e289
commit 5d765be524
No known key found for this signature in database
GPG Key ID: 8ED72A9A323B6EFD
13 changed files with 1080 additions and 1788 deletions

View File

@ -1,14 +1,10 @@
/*jshint globalstrict: true */
/*global applicationContext*/
'use strict';
////////////////////////////////////////////////////////////////////////////////
/// @brief A Foxx.Controller to show all Foxx Applications
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2013 triagens GmbH, Cologne, Germany
/// 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.
@ -22,150 +18,117 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
/// @author Alan Plum
////////////////////////////////////////////////////////////////////////////////
"use strict";
const underscore = require('lodash');
const cluster = require('@arangodb/cluster');
const joi = require('joi');
const httperr = require('http-errors');
const contentDisposition = require('content-disposition');
const internal = require('internal');
const db = require('@arangodb').db;
const notifications = require('@arangodb/configuration').notifications;
const createRouter = require('@arangodb/foxx/router');
const NOT_FOUND = require('@arangodb').errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code;
var Foxx = require("@arangodb/foxx");
var publicController = new Foxx.Controller(applicationContext);
var controller = new Foxx.Controller(applicationContext);
var underscore = require("lodash");
var cluster = require("@arangodb/cluster");
var joi = require("joi");
var util = require("util");
var internal = require("internal");
var contentDisposition = require('content-disposition');
var notifications = require("@arangodb/configuration").notifications;
var db = require("@arangodb").db;
var foxxInstallKey = joi.string().required().description(
"The _key attribute, where the information of this Foxx-Install is stored."
);
const router = createRouter();
module.exports = router;
var foxxes = new (require("./lib/foxxes").Foxxes)();
var FoxxManager = require("@arangodb/foxx/manager");
var UnauthorizedError = require("http-errors").Unauthorized;
publicController.activateSessions({
autoCreateSession: false,
cookie: {name: "arango_sid_" + db._name()}
});
publicController.get("/whoAmI", function(req, res) {
var uid = req.session && req.session.get("uid");
var user = null;
if (uid) {
var users = Foxx.getExports("_system/users").userStorage;
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 {
user = users.get(uid).get("user");
const doc = db._users.document(req.session.uid);
user = doc.user;
} catch (e) {
if (!(e instanceof users.errors.UserNotFound)) {
if (!e.isArangoError || e.errorNum !== NOT_FOUND) {
throw e;
}
req.session.setUser(null);
req.session.uid = null;
}
} else if (internal.options()["server.disable-authentication"]) {
user = false;
}
res.json({user: user});
res.json({user});
});
publicController.destroySession("/logout", function (req, res) {
router.post('/logout', function (req, res) {
req.session.uid = null;
res.json({success: true});
});
publicController.post("/login", function (req, res) {
if (req.session) {
req.session.set({uid: null, userDate: null});
} else {
req.session = publicController.sessions.getSessionStorage().create();
router.post('/login', function (req, res) {
if (!req.session) {
req.session = module.context.sessions.new();
}
var users = Foxx.getExports("_system/users").userStorage;
var credentials = req.parameters.credentials;
var user = users.resolve(credentials.get("username"));
if (!user) throw new UnauthorizedError();
var auth = Foxx.getExports("_system/simple-auth").auth;
var valid = auth.verifyPassword(user.get("authData").simple, credentials.get("password"));
if (!valid) throw new UnauthorizedError();
req.session.setUser(user);
req.session.save();
res.json({
user: user.get("user")
});
}).bodyParam("credentials", {
type: Foxx.Model.extend({
username: joi.string().required(),
password: joi.string().required()
}),
description: "Login credentials."
});
publicController.get("/unauthorized", function() {
throw new UnauthorizedError();
});
const doc = db._users.firstExample({user: req.body.username});
const valid = module.context.auth.verify(
doc ? doc.authData.simple : null,
req.body.password
);
publicController.get("/index.html", function(req, res) {
var prefix = '/_db/' + encodeURIComponent(req.database) + applicationContext.mount;
res.status(302);
res.set("Location", prefix + "/standalone.html");
});
controller.activateSessions({
autoCreateSession: false,
cookie: {name: "arango_sid_" + db._name()}
});
controller.allRoutes
.errorResponse(UnauthorizedError, 401, "unauthorized")
.onlyIf(function (req, res) {
if (!internal.options()["server.disable-authentication"] && (!req.session || !req.session.get('uid'))) {
throw new UnauthorizedError();
if (!valid) {
throw new httperr.Unauthorized();
}
const user = doc.user;
req.session.uid = doc._key;
res.json({user});
})
.body({
username: joi.string().required(),
password: joi.string().required().allow('')
}, 'Login credentials.');
router.get('/unauthorized', function() {
throw new httperr.Unauthorized();
});
controller.apiDocumentation('/api', {
swaggerJson(req, res) {
var filename = applicationContext.fileName('api-docs.json');
res.sendFile(filename, {lastModified: true});
router.get('/index.html', function(req, res) {
res.redirect(req.makeAbsolute('standalone.html'));
});
const authRouter = createRouter();
router.use(authRouter);
authRouter.use((req, res, next) => {
if (!internal.options()['server.disable-authentication'] && !req.user) {
throw new httperr.Unauthorized();
}
next();
});
/** Is version check allowed
*
* Check if version check is allowed
*/
controller.get("shouldCheckVersion", function(req, res) {
authRouter.get('/api/*', module.context.createSwaggerHandler(
(req) => ({
appPath: req.queryParams.mount,
swaggerJson(req, res) {
res.sendFile(module.context.fileName('api-docs.json'), {lastModified: true});
}
})
));
authRouter.get('shouldCheckVersion', function(req, res) {
var versions = notifications.versions();
res.json(Boolean(versions && versions.enableVersionNotification));
})
.summary('Is version check allowed')
.description('Check if version check is allowed.');
if (!versions || versions.enableVersionNotification === false) {
res.json(false);
} else {
res.json(true);
}
});
/** Disable version check
*
* Disable the version check in web interface
*/
controller.post("disableVersionCheck", function(req, res) {
authRouter.post('disableVersionCheck', function(req, res) {
notifications.setVersions({
enableVersionNotification: false
});
res.json("ok");
});
res.json('ok');
})
.summary('Disable version check')
.description('Disable the version check in web interface');
/** Explains a query
*
* Explains a query in a more user-friendly way than the query
* _api/explain
*
*/
controller.post("/query/explain", function(req, res) {
authRouter.post('/query/explain', function(req, res) {
var explain, query = req.body().query,
bindVars = req.body().bindVars;
@ -173,39 +136,35 @@ controller.post("/query/explain", function(req, res) {
if (query.length > 0) {
try {
if (bindVars) {
explain = require("@arangodb/aql/explainer").explain({
explain = require('@arangodb/aql/explainer').explain({
query: query,
bindVars: bindVars
}, {colors: false}, false, bindVars);
}
else {
explain = require("@arangodb/aql/explainer").explain(query, {colors: false}, false);
explain = require('@arangodb/aql/explainer').explain(query, {colors: false}, false);
}
}
catch (e) {
explain = JSON.stringify(e);
} 
}
}
res.json({msg: explain});
}).summary("Explains a query")
.notes("This function gives useful query information");
})
.summary('Explains a query')
.description('Explains a query in a more user-friendly way than the query_api/explain');
/** Download stored queries
*
* Download and export all queries from the given username.
*
*/
controller.post("/query/upload/:user", function(req, res) {
var user = req.params("user");
var queries, userColl, queriesToSave;
authRouter.post('/query/upload/:user', function(req, res) {
var user = req.params('user');
var queries, doc, queriesToSave;
queries = req.body();
userColl = db._users.byExample({"user": user}).toArray()[0];
queriesToSave = userColl.userData.queries || [ ];
doc = db._users.byExample({'user': user}).toArray()[0];
queriesToSave = doc.userData.queries || [ ];
underscore.each(queries, function(newq) {
var found = false, i;
@ -216,7 +175,7 @@ controller.post("/query/upload/:user", function(req, res) {
break;
}
}
if (! found) {
if (!found) {
queriesToSave.push(newq);
}
});
@ -227,23 +186,18 @@ controller.post("/query/upload/:user", function(req, res) {
}
};
var result = db._users.update(userColl, toUpdate, true);
var result = db._users.update(doc, toUpdate, true);
res.json(result);
}).summary("Upload user queries")
.notes("This function uploads all given user queries");
})
.summary('Upload user queries')
.description('This function uploads all given user queries');
/** Download stored queries
*
* Download and export all queries from the given username.
*
*/
authRouter.get('/query/download/:user', function(req, res) {
var user = req.params('user');
var result = db._users.byExample({'user': user}).toArray()[0];
controller.get("/query/download/:user", function(req, res) {
var user = req.params("user");
var result = db._users.byExample({"user": user}).toArray()[0];
res.set("Content-Type", "application/json");
res.set("Content-Disposition", contentDisposition('queries.json'));
res.set('Content-Type', 'application/json');
res.set('Content-Disposition', contentDisposition('queries.json'));
if (result === null || result === undefined) {
res.json([]);
@ -252,20 +206,15 @@ controller.get("/query/download/:user", function(req, res) {
res.json(result.userData.queries || []);
}
}).summary("Download all user queries")
.notes("This function downloads all user queries from the given user");
})
.summary('Download stored queries')
.description('Download and export all queries from the given username.');
/** Download a query result
*
* Download and export all queries from the given username.
*
*/
controller.get("/query/result/download/:query", function(req, res) {
var query = req.params("query"),
authRouter.get('/query/result/download/:query', function(req, res) {
var query = req.params('query'),
parsedQuery;
var internal = require("internal");
var internal = require('internal');
query = internal.base64Decode(query);
try {
parsedQuery = JSON.parse(query);
@ -274,31 +223,26 @@ controller.get("/query/result/download/:query", function(req, res) {
}
var result = db._query(parsedQuery.query, parsedQuery.bindVars).toArray();
res.set("Content-Type", "application/json");
res.set("Content-Disposition", contentDisposition('results.json'));
res.set('Content-Type', 'application/json');
res.set('Content-Disposition', contentDisposition('results.json'));
res.json(result);
}).summary("Download the result of a query")
.notes("This function downloads the result of a user query.");
})
.summary('Download the result of a query')
.description('This function downloads the result of a user query.');
/** Create sample graphs
*
* Create one of the given sample graphs.
*
*/
controller.post("/graph-examples/create/:name", function(req, res) {
var name = req.params("name"), g,
examples = require("@arangodb/graph-examples/example-graph.js");
authRouter.post('/graph-examples/create/:name', function(req, res) {
var name = req.params('name'), g,
examples = require('@arangodb/graph-examples/example-graph.js');
if (name === 'knows_graph') {
g = examples.loadGraph("knows_graph");
g = examples.loadGraph('knows_graph');
}
else if (name === 'social') {
g = examples.loadGraph("social");
g = examples.loadGraph('social');
}
else if (name === 'routeplanner') {
g = examples.loadGraph("routeplanner");
g = examples.loadGraph('routeplanner');
}
if (typeof g === 'object') {
@ -308,16 +252,11 @@ controller.post("/graph-examples/create/:name", function(req, res) {
res.json({error: true});
}
}).summary("Create a sample graph")
.notes("This function executes the internal scripts to create one example graph.");
})
.summary('Create sample graphs')
.description('Create one of the given sample graphs.');
/** Store job id's in db
*
* Create a new job id entry in a specific system database with a given id.
*
*/
controller.post("/job", function(req, res) {
authRouter.post('/job', function(req, res) {
if (req.body().id && req.body().collection && req.body().type && req.body().desc) {
@ -336,34 +275,22 @@ controller.post("/job", function(req, res) {
res.json(false);
}
}).summary("Store job id of a running job")
.notes("This function stores a job id into a system collection.");
/** Delete all jobs
*
* Delete an existing job id entry in a specific system database with a given id.
*
*/
controller.del("/job/", function(req, res) {
})
.summary('Store job id of a running job')
.description('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('Delete all jobs in a specific system database with a given id.');
}).summary("Store job id of a running job")
.notes("This function stores a job id into a system collection.");
authRouter.delete('/job/:id', function(req, res) {
/** Delete a job id
*
* Delete an existing job id entry in a specific system database with a given id.
*
*/
controller.del("/job/:id", function(req, res) {
var id = req.params("id");
var id = req.params('id');
if (id) {
db._frontend.removeByExample({
@ -375,27 +302,15 @@ controller.del("/job/:id", function(req, res) {
res.json(false);
}
}).summary("Store job id of a running job")
.notes("This function stores a job id into a system collection.");
})
.summary('Delete a job id')
.description('Delete an existing job id entry in a specific system database with a given id.');
/** Return all job id's
*
* Return all job id's which are stored in a system database.
*
*/
controller.get("/job", function(req, res) {
authRouter.get('/job', function(req, res) {
var result = db._frontend.all().toArray();
res.json(result);
}).summary("Return all job ids.")
.notes("This function returns the job ids of all currently running jobs.");
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
/// Local Variables:
/// mode: outline-minor
/// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint"
/// End:
})
.summary('Return all job ids.')
.description('This function returns the job ids of all currently running jobs.');

View File

@ -1,13 +1,10 @@
/*global applicationContext*/
'use strict';
////////////////////////////////////////////////////////////////////////////////
/// @brief A Foxx.Controller to show all Foxx Applications
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2013 triagens GmbH, Cologne, Germany
/// 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.
@ -21,168 +18,145 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
/// @author Alan Plum
////////////////////////////////////////////////////////////////////////////////
(function() {
"use strict";
const _ = require('lodash');
const dd = require('dedent');
const httperr = require('http-errors');
const cluster = require('@arangodb/cluster');
const createRouter = require('@arangodb/foxx/router');
const internal = require('internal');
const plans = require('./repositories/plans.js');
// Initialize a new FoxxController called controller under the urlPrefix: "cluster".
var FoxxController = require("@arangodb/foxx").Controller,
UnauthorizedError = require("http-errors").Unauthorized,
internal = require("internal"),
controller = new FoxxController(applicationContext),
cluster = require("@arangodb/cluster"),
load = require("internal").download,
db = require("internal").db,
_ = require("lodash");
const router = createRouter();
module.exports = router;
controller.activateSessions({
autoCreateSession: false,
cookie: {name: "arango_sid_" + db._name()}
router.use((req, res, next) => {
if (!internal.options()['server.disable-authentication'] && !req.user) {
throw new httperr.Unauthorized();
}
next();
});
router.get('/amICoordinator', function(req, res) {
res.json(cluster.isCoordinator());
})
.summary('Plan and start a new cluster')
.description('This will plan a new cluster with the information given in the body');
if (cluster.isCluster()) {
// only make these functions available in cluster mode!
var Communication = require("@arangodb/cluster/agency-communication");
var comm = new Communication.Communication();
var beats = comm.sync.Heartbeats();
var diff = comm.diff.current;
var servers = comm.current.DBServers();
var dbs = comm.current.Databases();
var coords = comm.current.Coordinators();
router.get("/ClusterType", function(req, res) {
// Not yet implemented
res.json({
type: "symmetricSetup"
});
})
.summary('Get the type of the cluster')
.description(dd`
Returns a string containing the cluster type
Possible anwers:
- testSetup
- symmetricalSetup
- asymmetricalSetup
`);
router.get("/DBServers", function(req, res) {
var resList = [],
list = servers.getList(),
diffList = diff.DBServers(),
didBeat = beats.didBeat(),
serving = beats.getServing();
_.each(list, function(v, k) {
v.name = k;
resList.push(v);
if (!_.contains(didBeat, k)) {
v.status = "critical";
return;
}
if (v.role === "primary" && !_.contains(serving, k)) {
v.status = "warning";
return;
}
v.status = "ok";
});
_.each(diffList.missing, function(v) {
v.status = "missing";
resList.push(v);
});
res.json(resList);
})
.summary('Get all DBServers')
.description('Get a list of all running and expected DBServers within the cluster');
router.get("/Coordinators", function(req, res) {
var resList = [],
list = coords.getList(),
diffList = diff.Coordinators(),
didBeat = beats.didBeat();
_.each(list, function(v, k) {
v.name = k;
resList.push(v);
if (!_.contains(didBeat, k)) {
v.status = "critical";
return;
}
v.status = "ok";
});
_.each(diffList.missing, function(v) {
v.status = "missing";
resList.push(v);
});
res.json(resList);
});
controller.allRoutes
.errorResponse(UnauthorizedError, 401, "unauthorized")
.onlyIf(function (req, res) {
if (!internal.options()["server.disable-authentication"] && (!req.session || !req.session.get('uid'))) {
throw new UnauthorizedError();
router.get("/Databases", function(req, res) {
var list = dbs.getList();
res.json(_.map(list, (name) => ({name})));
});
router.get("/:dbname/Collections", function(req, res) {
var dbname = req.params("dbname"),
selected = dbs.select(dbname);
try {
res.json(_.map(
selected.getCollections(),
(name) => ({name})
));
} catch(e) {
res.json([]);
}
});
/** Plan and start a new cluster
*
* This will plan a new cluster with the information
* given in the body
*/
controller.get("/amICoordinator", function(req, res) {
res.json(cluster.isCoordinator());
router.get("/:dbname/:colname/Shards", function(req, res) {
var dbname = req.params("dbname");
var colname = req.params("colname");
var selected = dbs.select(dbname).collection(colname);
res.json(selected.getShardsByServers());
});
if (cluster.isCluster()) {
// only make these functions available in cluster mode!
var Communication = require("@arangodb/cluster/agency-communication"),
comm = new Communication.Communication(),
beats = comm.sync.Heartbeats(),
diff = comm.diff.current,
servers = comm.current.DBServers(),
dbs = comm.current.Databases(),
coords = comm.current.Coordinators();
/** Get the type of the cluster
*
* Returns a string containing the cluster type
* Possible anwers:
* - testSetup
* - symmetricalSetup
* - asymmetricalSetup
*
*/
controller.get("/ClusterType", function(req, res) {
// Not yet implemented
res.json({
type: "symmetricSetup"
});
});
/** Get all DBServers
*
* Get a list of all running and expected DBServers
* within the cluster
*/
controller.get("/DBServers", function(req, res) {
var resList = [],
list = servers.getList(),
diffList = diff.DBServers(),
didBeat = beats.didBeat(),
serving = beats.getServing();
_.each(list, function(v, k) {
v.name = k;
resList.push(v);
if (!_.contains(didBeat, k)) {
v.status = "critical";
return;
}
if (v.role === "primary" && !_.contains(serving, k)) {
v.status = "warning";
return;
}
v.status = "ok";
});
_.each(diffList.missing, function(v) {
v.status = "missing";
resList.push(v);
});
res.json(resList);
});
controller.get("/Coordinators", function(req, res) {
var resList = [],
list = coords.getList(),
diffList = diff.Coordinators(),
didBeat = beats.didBeat();
_.each(list, function(v, k) {
v.name = k;
resList.push(v);
if (!_.contains(didBeat, k)) {
v.status = "critical";
return;
}
v.status = "ok";
});
_.each(diffList.missing, function(v) {
v.status = "missing";
resList.push(v);
});
res.json(resList);
});
controller.get("/Databases", function(req, res) {
var list = dbs.getList();
res.json(_.map(list, function(d) {
return {name: d};
}));
});
controller.get("/:dbname/Collections", function(req, res) {
var dbname = req.params("dbname"),
selected = dbs.select(dbname);
try {
res.json(_.map(selected.getCollections(),
function(c) {
return {name: c};
})
);
} catch(e) {
res.json([]);
}
});
controller.get("/:dbname/:colname/Shards", function(req, res) {
var dbname = req.params("dbname"),
colname = req.params("colname"),
selected = dbs.select(dbname).collection(colname);
res.json(selected.getShardsByServers());
});
controller.get("/:dbname/:colname/Shards/:servername", function(req, res) {
var dbname = req.params("dbname"),
colname = req.params("colname"),
servername = req.params("servername"),
selected = dbs.select(dbname).collection(colname);
res.json(_.map(selected.getShardsForServer(servername),
function(c) {
return {id: c};
})
);
});
} // end isCluster()
}());
router.get("/:dbname/:colname/Shards/:servername", function(req, res) {
var dbname = req.params("dbname");
var colname = req.params("colname");
var servername = req.params("servername");
var selected = dbs.select(dbname).collection(colname);
res.json(_.map(
selected.getShardsForServer(servername),
(c) => ({id: c})
));
});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,13 +1,10 @@
/*global applicationContext*/
'use strict';
////////////////////////////////////////////////////////////////////////////////
/// @brief A Foxx.Controller to generate new FoxxApps
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2014 triagens GmbH, Cologne, Germany
/// Copyright 2010-2014 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.
@ -21,44 +18,41 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
/// @author Alan Plum
////////////////////////////////////////////////////////////////////////////////
(function() {
"use strict";
var FoxxController = require("@arangodb/foxx").Controller,
UnauthorizedError = require("http-errors").Unauthorized,
internal = require("internal"),
Configuration = require("./models/configuration").Model,
controller = new FoxxController(applicationContext),
db = require("internal").db,
FoxxManager = require("@arangodb/foxx/manager");
const joi = require('joi');
const httperr = require('http-errors');
const internal = require('internal');
const FoxxManager = require('@arangodb/foxx/manager');
const createRouter = require('@arangodb/foxx/router');
controller.activateSessions({
autoCreateSession: false,
cookie: {name: "arango_sid_" + db._name()}
});
controller.allRoutes
.errorResponse(UnauthorizedError, 401, "unauthorized")
.onlyIf(function (req, res) {
if (!internal.options()["server.disable-authentication"] && (!req.session || !req.session.get('uid'))) {
throw new UnauthorizedError();
}
});
const router = createRouter();
module.exports = router;
controller.get("/devMode", function(req, res) {
res.json(false);
});
router.use((req, res, next) => {
if (!internal.options()['server.disable-authentication'] && !req.user) {
throw new httperr.Unauthorized();
}
next();
});
controller.post("/generate", function(req, res) {
var conf = req.params("configuration");
res.json(FoxxManager.install("EMPTY", "/todo", conf));
}).bodyParam("configuration", {
description: "The configuration for the template.",
type: Configuration
});
}());
router.get('/devMode', (req, res) => res.json(false));
router.post('/generate', (req, res) => res.json(
FoxxManager.install('EMPTY', '/todo', req.body)
))
.body(joi.object({
applicationContext: joi.string().optional(),
path: joi.string().optional(),
name: joi.string().required(),
collectionNames: joi.array().required(),
authenticated: joi.boolean().required(),
author: joi.string().required(),
description: joi.string().required(),
license: joi.string().required()
}), 'The configuration for the template.');

View File

@ -1,14 +1,10 @@
/*global applicationContext */
"use strict";
'use strict';
////////////////////////////////////////////////////////////////////////////////
/// @brief A Foxx.Controller to show all Foxx Applications
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2013 triagens GmbH, Cologne, Germany
/// 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.
@ -22,407 +18,255 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
/// @author Alan Plum
////////////////////////////////////////////////////////////////////////////////
(function() {
var internal = require("internal");
var db = require("@arangodb").db;
var NotFound = require("http-errors").NotFound;
var FoxxController = require("@arangodb/foxx").Controller;
var UnauthorizedError = require("http-errors").Unauthorized;
var controller = new FoxxController(applicationContext);
var ArangoError = require("@arangodb").ArangoError;
var FoxxManager = require("@arangodb/foxx/manager");
var fmUtils = require("@arangodb/foxx/manager-utils");
var actions = require("@arangodb/actions");
var joi = require("joi");
var marked = require("marked");
var highlightAuto = require("highlight.js").highlightAuto;
var docu = require("./lib/swagger").Swagger;
var underscore = require("lodash");
var contentDisposition = require('content-disposition');
var mountPoint = {
type: joi.string().required().description(
"The mount point of the app. Has to be url-encoded."
)
};
var scriptName = {
type: joi.string().required().description(
"The name of an app's script to run."
)
};
var fs = require("fs");
var defaultThumb = require("./lib/defaultThumbnail").defaultThumb;
const fs = require('fs');
const joi = require('joi');
const marked = require('marked');
const httperr = require('http-errors');
const internal = require('internal');
const highlightAuto = require('highlight.js').highlightAuto;
const FoxxManager = require('@arangodb/foxx/manager');
const fmUtils = require('@arangodb/foxx/manager-utils');
const createRouter = require('@arangodb/foxx/router');
controller.activateSessions({
autoCreateSession: false,
cookie: {name: "arango_sid_" + db._name()}
const DEFAULT_THUMBNAIL = module.context.fileName('default-thumbnail.png');
const mountSchema = joi.string().required().description(
'The mount point of the service. Has to be url-encoded.'
);
const router = createRouter();
module.exports = router;
router.use((req, res, next) => {
if (!internal.options()['server.disable-authentication'] && !req.user) {
throw new httperr.Unauthorized();
}
next();
});
function installApp(req, res, appInfo, options) {
var mount = decodeURIComponent(req.params('mount'));
var upgrade = req.params('upgrade');
var replace = req.params('replace');
var service;
if (upgrade) {
service = FoxxManager.upgrade(appInfo, mount, options);
} else if (replace) {
service = FoxxManager.replace(appInfo, mount, options);
} else {
service = FoxxManager.install(appInfo, mount, options);
}
var config = FoxxManager.configuration(mount);
res.json({
error: false,
configuration: config,
name: service.name,
version: service.version
});
}
controller.allRoutes
.errorResponse(UnauthorizedError, 401, "unauthorized")
.onlyIf(function (req, res) {
if (!internal.options()["server.disable-authentication"] && (!req.session || !req.session.get('uid'))) {
throw new UnauthorizedError();
const installer = createRouter();
router.use(installer)
.queryParam('mount', mountSchema)
.queryParam('upgrade', joi.boolean().default(false).description(
'Trigger to upgrade the service installed at the mountpoint. Triggers setup.'
))
.queryParam('replace', joi.boolean().default(false).description(
'Trigger to replace the service installed at the mountpoint. Triggers teardown and setup.'
));
installer.put('/store', function (req, res) {
const content = JSON.parse(req.requestBody);
const name = content.name;
const version = content.version;
installApp(req, res, `${name}:${version}`);
})
.summary('Install a Foxx from the store')
.description('Downloads a Foxx from the store and installs it at the given mount.');
installer.put('/git', function (req, res) {
const content = JSON.parse(req.requestBody);
const url = content.url;
const version = content.version || 'master';
installApp(req, res, `git:${url}:${version}`);
})
.summary('Install a Foxx from Github')
.description('Install a Foxx with user/repository and version.');
installer.put('/generate', function (req, res) {
const info = JSON.parse(req.requestBody);
installApp(req, res, 'EMPTY', info);
})
.summary('Generate a new foxx')
.description('Generate a new empty foxx on the given mount point');
installer.put('/zip', function (req, res) {
const content = JSON.parse(req.requestBody);
const file = content.zipFile;
installApp(req, res, file);
})
.summary('Install a Foxx from temporary zip file')
.description('Install a Foxx from the given zip path. This path has to be created via _api/upload');
router.delete('/', function (req, res) {
var mount = decodeURIComponent(req.params('mount'));
var runTeardown = req.parameters.teardown;
var service = FoxxManager.uninstall(mount, {
teardown: runTeardown,
force: true
});
res.json({
error: false,
name: service.name,
version: service.version
});
})
.queryParam('mount', mountSchema)
.queryParam('teardown', joi.boolean().default(true))
.summary('Uninstall a Foxx')
.description('Uninstall the Foxx at the given mount-point.');
router.get('/', function (req, res) {
const foxxes = FoxxManager.listJson();
foxxes.forEach((foxx) => {
const readme = FoxxManager.readme(foxx.mount);
if (readme) {
foxx.readme = marked(readme, {
highlight: (code) => highlightAuto(code).value
});
}
});
res.json(foxxes);
})
.summary('List all Foxxes')
.description('Get a List of all running foxxes.');
controller.extend({
installer: function() {
this.queryParam("mount", mountPoint);
this.queryParam("upgrade", {type: joi.boolean().optional().description(
"Trigger to upgrade the app installed at the mountpoint. Triggers setup."
)});
this.queryParam("replace", {type: joi.boolean().optional().description(
"Trigger to replace the app installed at the mountpoint. Triggers teardown and setup."
)});
}
});
router.get('/thumbnail', function (req, res) {
var mount = decodeURIComponent(req.params('mount'));
var service = FoxxManager.lookupApp(mount);
res.sendFile(service.thumbnail || DEFAULT_THUMBNAIL);
})
.queryParam('mount', mountSchema)
.summary('Get the thumbnail of a Foxx')
.description('Request the thumbnail of the given Foxx in order to display it on the screen.');
// ------------------------------------------------------------
// SECTION install
// ------------------------------------------------------------
router.get('/config', function (req, res) {
var mount = decodeURIComponent(req.params('mount'));
res.json(FoxxManager.configuration(mount));
})
.queryParam('mount', mountSchema)
.summary('Get the configuration for a service')
.description('Used to request the configuration options for services');
var validateMount = function(req) {
var mount = req.params("mount");
// Validation
mount = decodeURIComponent(mount);
return mount;
};
router.patch('/config', function (req, res) {
var mount = decodeURIComponent(req.params('mount'));
var data = req.body;
res.json(FoxxManager.configure(mount, {configuration: data}));
})
.queryParam('mount', mountSchema)
.summary('Set the configuration for a service')
.description('Used to overwrite the configuration options for services');
var installApp = function(req, res, appInfo, options) {
var mount = validateMount(req);
var upgrade = req.params("upgrade") || false;
var replace = req.params("replace") || false;
var app;
if (upgrade) {
app = FoxxManager.upgrade(appInfo, mount, options);
} else if (replace) {
app = FoxxManager.replace(appInfo, mount, options);
} else {
app = FoxxManager.install(appInfo, mount, options);
}
var config = FoxxManager.configuration(mount);
res.json({
error: false,
configuration: config,
name: app.name,
version: app.version
});
};
router.get('/deps', function (req, res) {
var mount = decodeURIComponent(req.params('mount'));
res.json(FoxxManager.dependencies(mount));
})
.queryParam('mount', mountSchema)
.summary('Get the dependencies for a service')
.description('Used to request the dependencies options for services');
/** Install a Foxx from the store
*
* Downloads a Foxx from the store and installs it at the given mount
*/
controller.put("/store", function(req, res) {
var content = JSON.parse(req.requestBody),
name = content.name,
version = content.version;
installApp(req, res, name + ":" + version);
router.patch('/deps', function (req, res) {
var mount = decodeURIComponent(req.params('mount'));
var data = req.body;
res.json(FoxxManager.updateDeps(mount, {dependencies: data}));
})
.queryParam('mount', mountSchema)
.summary('Set the dependencies for a service')
.description('Used to overwrite the dependencies options for services');
router.post('/tests', function (req, res) {
var options = req.body;
var mount = decodeURIComponent(req.params('mount'));
res.json(FoxxManager.runTests(mount, options));
})
.queryParam('mount', mountSchema)
.summary('Run tests for a service')
.description('Used to run the tests of a service');
router.post('/scripts/:name', function (req, res) {
const mount = decodeURIComponent(req.params('mount'));
const name = req.params('name');
const argv = req.body;
try {
res.json(FoxxManager.runScript(name, mount, argv));
} catch (e) {
throw e.cause || e;
}
})
.queryParam('mount', mountSchema)
.pathParam('name', joi.string().required(), 'The name of a service\'s script to run.')
.body('argv', joi.any().default(null), 'Options to pass to the script.')
.summary('Run a script for a service')
.description('Used to trigger any script of a service');
router.patch('/setup', function (req, res) {
const mount = decodeURIComponent(req.params('mount'));
res.json(FoxxManager.runScript('setup', mount));
})
.queryParam('mount', mountSchema)
.summary('Trigger setup script for a service')
.description('Used to trigger the setup script of a service');
router.patch('/teardown', function (req, res) {
const mount = decodeURIComponent(req.params('mount'));
res.json(FoxxManager.runScript('teardown', mount));
})
.queryParam('mount', mountSchema)
.summary('Trigger teardown script for a service')
.description('Used to trigger the teardown script of a service');
router.patch('/devel', function (req, res) {
const mount = decodeURIComponent(req.params('mount'));
const activate = Boolean(req.body);
res.json(FoxxManager[activate ? 'development' : 'production'](mount));
})
.queryParam('mount', mountSchema)
.summary('Activate/Deactivate development mode for a service')
.description('Used to toggle between production and development mode');
router.get('/download/zip', function (req, res) {
var mount = decodeURIComponent(req.params('mount'));
var service = FoxxManager.lookupApp(mount);
var dir = fs.join(fs.makeAbsolute(service.root), service.path);
var zipPath = fmUtils.zipDirectory(dir);
res.download(zipPath, `${service.name}@${service.version}.zip`);
})
.queryParam('mount', mountSchema)
.summary('Download a service as zip archive')
.description('Download a foxx service packed in a zip archive');
router.get('/fishbowl', function (req, res) {
FoxxManager.update();
res.json(FoxxManager.availableJson());
})
.summary('List of all foxx services submitted to the Foxx store.')
.description('This function contacts the fishbowl and reports which services are available for install');
router.get('/docs/standalone/*', module.context.createSwaggerHandler(
(req) => ({
appPath: req.queryParams.mount
})
.installer();
));
/** Install a Foxx from Github
*
* Install a Foxx with user/repository and version
*/
controller.put("/git", function (req, res) {
var content = JSON.parse(req.requestBody),
url = content.url,
version = content.version;
installApp(req, res, "git:" + url + ":" + (version || "master"));
router.get('/docs/*', module.context.createSwaggerHandler(
(req) => ({
indexFile: 'index-alt.html',
appPath: req.queryParams.mount
})
.installer();
/** Generate a new foxx
*
* Generate a new empty foxx on the given mount point
*/
controller.put("/generate", function (req, res) {
var info = JSON.parse(req.requestBody);
installApp(req, res, "EMPTY", info);
})
.installer();
/** Install a Foxx from temporary zip file
*
* Install a Foxx from the given zip path.
* This path has to be created via _api/upload
*/
controller.put("/zip", function (req, res) {
var content = JSON.parse(req.requestBody),
file = content.zipFile;
installApp(req, res, file);
})
.installer();
/** Uninstall a Foxx
*
* Uninstall the Foxx at the given mount-point.
*/
controller.delete("/", function (req, res) {
var mount = validateMount(req);
var runTeardown = req.parameters.teardown;
var app = FoxxManager.uninstall(mount, {
teardown: runTeardown,
force: true
});
res.json({
error: false,
name: app.name,
version: app.version
});
})
.queryParam("mount", mountPoint)
.queryParam("teardown", joi.boolean().default(true));
// ------------------------------------------------------------
// SECTION information
// ------------------------------------------------------------
/** List all Foxxes
*
* Get a List of all running foxxes
*/
controller.get('/', function (req, res) {
var foxxes = FoxxManager.listJson();
foxxes.forEach(function (foxx) {
var readme = FoxxManager.readme(foxx.mount);
if (readme) {
foxx.readme = marked(readme, {
highlight(code) {
return highlightAuto(code).value;
}
});
}
});
res.json(foxxes);
});
/** Get the thumbnail of a Foxx
*
* Used to request the thumbnail of the given Foxx in order to display it on the screen.
*/
controller.get("/thumbnail", function (req, res) {
res.transformations = [ "base64decode" ];
var mount = validateMount(req);
var app = FoxxManager.lookupApp(mount);
if (app.hasOwnProperty("thumbnail") && app.thumbnail !== null) {
res.body = app.thumbnail;
} else {
res.body = defaultThumb;
}
// evil mimetype detection attempt...
var start = require("internal").base64Decode(res.body.substr(0, 8));
if (start.indexOf("PNG") !== -1) {
res.contentType = "image/png";
}
})
.queryParam("mount", mountPoint);
/** Get the configuration for an app
*
* Used to request the configuration options for apps
*/
controller.get("/config", function(req, res) {
var mount = validateMount(req);
res.json(FoxxManager.configuration(mount));
})
.queryParam("mount", mountPoint);
/** Set the configuration for an app
*
* Used to overwrite the configuration options for apps
*/
controller.patch("/config", function(req, res) {
var mount = validateMount(req);
var data = req.body();
res.json(FoxxManager.configure(mount, {configuration: data}));
})
.queryParam("mount", mountPoint);
/** Get the dependencies for an app
*
* Used to request the dependencies options for apps
*/
controller.get("/deps", function(req, res) {
var mount = validateMount(req);
res.json(FoxxManager.dependencies(mount));
})
.queryParam("mount", mountPoint);
/** Set the dependencies for an app
*
* Used to overwrite the dependencies options for apps
*/
controller.patch("/deps", function(req, res) {
var mount = validateMount(req);
var data = req.body();
res.json(FoxxManager.updateDeps(mount, {dependencies: data}));
})
.queryParam("mount", mountPoint);
/** Run tests for an app
*
* Used to run the tests of an app
*/
controller.post("/tests", function (req, res) {
var options = req.body();
var mount = validateMount(req);
res.json(FoxxManager.runTests(mount, options));
})
.queryParam("mount", mountPoint);
/** Run a script for an app
*
* Used to trigger any script of an app
*/
controller.post("/scripts/:name", function (req, res) {
var mount = validateMount(req);
var name = req.params("name");
var argv = req.params("argv");
try {
res.json(FoxxManager.runScript(name, mount, argv));
} catch (e) {
throw e.cause || e;
}
})
.queryParam("mount", mountPoint)
.pathParam("name", scriptName)
.bodyParam(
"argv",
joi.any().default(null)
.description('Options to pass to the script.')
);
/** Trigger setup script for an app
*
* Used to trigger the setup script of an app
*/
controller.patch("/setup", function(req, res) {
var mount = validateMount(req);
res.json(FoxxManager.runScript("setup", mount));
})
.queryParam("mount", mountPoint);
/** Trigger teardown script for an app
*
* Used to trigger the teardown script of an app
*/
controller.patch("/teardown", function(req, res) {
var mount = validateMount(req);
res.json(FoxxManager.runScript("teardown", mount));
})
.queryParam("mount", mountPoint);
/** Activate/Deactivate development mode for an app
*
* Used to toggle between production and development mode
*/
controller.patch("/devel", function(req, res) {
var mount = validateMount(req);
var activate = Boolean(req.body());
if (activate) {
res.json(FoxxManager.development(mount));
} else {
res.json(FoxxManager.production(mount));
}
})
.queryParam("mount", mountPoint);
/** Download an app as zip archive
*
* Download a foxx app packed in a zip archive
*/
controller.get("/download/zip", function(req, res) {
var mount = validateMount(req);
var app = FoxxManager.lookupApp(mount);
var dir = fs.join(fs.makeAbsolute(app.root), app.path);
var zipPath = fmUtils.zipDirectory(dir);
res.set("Content-Type", "application/octet-stream");
res.set("Content-Disposition", contentDisposition(`${app.name}@${app.version}.zip`));
res.body = fs.readFileSync(zipPath);
})
.queryParam("mount", mountPoint);
// ------------------------------------------------------------
// SECTION store
// ------------------------------------------------------------
/** List all Foxxes in Fishbowl
*
* Get the information for all Apps availbale in the Fishbowl and ready for download
*
*/
controller.get('/fishbowl', function (req, res) {
FoxxManager.update();
res.json(FoxxManager.availableJson());
}).summary("List of all foxx apps submitted to the fishbowl store.")
.notes("This function contacts the fishbowl and reports which apps are available for install")
.errorResponse(ArangoError, 503, "Could not connect to store.");
// ------------------------------------------------------------
// SECTION documentation
// ------------------------------------------------------------
controller.apiDocumentation('/docs/standalone', function (req, res) {
return {
appPath: req.parameters.mount
};
});
controller.apiDocumentation('/docs', function (req, res) {
return {
indexFile: 'index-alt.html',
appPath: req.parameters.mount
};
});
/** Returns the billboard URL for swagger
*
* Returns the billboard URL for the application mounted
* at the given mountpoint
*/
controller.get('/billboard', function(req, res) {
var mount = decodeURIComponent(decodeURIComponent(req.params("mount")));
var path = req.protocol + "://" + req.headers.host +
"/_db/" + encodeURIComponent(req.database) +
"/_admin/aardvark/foxxes/docu";
res.json({
swaggerVersion: "1.1",
basePath: path,
apis: [
{path: mount}
]
});
})
.queryParam("mount", mountPoint);
/** Returns the generated Swagger JSON description for one foxx
*
* This function returns the Swagger JSON API description of the foxx
* installed under the given mount point.
*/
controller.get('/docu/*', function(req, res) {
var mount = "";
underscore.each(req.suffix, function(part) {
mount += "/" + part;
});
res.json(docu(mount));
});
}());
));

View File

@ -0,0 +1,45 @@
'use strict';
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// 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 Alan Plum
////////////////////////////////////////////////////////////////////////////////
const db = require('@arangodb').db;
const sessionsMiddleware = require('@arangodb/foxx/sessions');
const cookieTransport = require('@arangodb/foxx/sessions/transports/cookie');
const collectionStorage = require('@arangodb/foxx/sessions/storages/collection');
const auth = require('@arangodb/foxx/auth');
module.context.sessions = collectionStorage('_sessions');
module.context.users = db._collection('_users');
module.context.auth = auth('sha256');
module.context.use(sessionsMiddleware({
autoCreate: false,
transport: cookieTransport(`arango_sid_${db._name()}`),
storage: module.context.sessions
}));
module.context.use(require('./aardvark'));
module.context.use('/foxxes', require('./foxxes'));
module.context.use('/cluster', require('./cluster'));
module.context.use('/statistics', require('./statistics'));
module.context.use('/templates', require('./foxxTemplates'));

File diff suppressed because one or more lines are too long

View File

@ -1,247 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief A TODO-List Foxx-Application written for ArangoDB
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2013 triagens 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 triAGENS GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
exports.Foxxes = function () {
"use strict";
// Define the Repository
var aal = require("internal").db._collection("_tmp_aal"),
foxxmanager = require("@arangodb/foxx/manager"),
_ = require("lodash"),
ArangoError = require("@arangodb").ArangoError,
fs = require("fs");
// Define the functionality to create a new foxx
this.store = function (content) {
throw {
code: 501,
message: "To be implemented."
};
};
this.thumbnail = function (mount) {
var example = aal.firstExample({
mount: mount
});
if (example === undefined || example === null) {
return defaultThumb;
}
var thumb = example.thumbnail;
if (thumb === undefined || thumb === null) {
thumb = defaultThumb;
}
return thumb;
};
this.install = function (name, mount, version, options) {
if (version) {
name = "app:" + name + ":" + version;
}
return foxxmanager.mount(name, mount, _.extend({}, options, { setup: true }));
};
// Define the functionality to uninstall an installed foxx
this.uninstall = function (key) {
// key is mountpoint
foxxmanager.teardown(key);
return foxxmanager.unmount(key);
};
// Define the functionality to deactivate an installed foxx.
this.deactivate = function (key) {
throw {
code: 501,
message: "To be implemented."
};
};
// Define the functionality to activate an installed foxx.
this.activate = function (key) {
throw {
code: 501,
message: "To be implemented."
};
};
// Define the functionality to display all foxxes
this.viewAll = function () {
var result = aal.toArray().concat(foxxmanager.developmentMounts());
result.forEach(function(r, i) {
// inject development flag
if (r._key.match(/^dev:/)) {
result[i] = _.extend({}, r);
result[i].development = true;
}
});
return result;
};
// Define the functionality to update one foxx.
this.update = function (id, content) {
throw {
code: 501,
message: "To be implemented."
};
};
this.move = function(key, app, mount, prefix) {
var success;
try {
success = foxxmanager.mount(app, mount, {collectionPrefix: prefix});
foxxmanager.unmount(key);
} catch (e) {
return {
error: true,
status: 409,
message: "Mount-Point already in use"
};
}
return success;
};
// TODO: merge with functionality js/client/modules/@arangodb/foxx/manager.js
this.repackZipFile = function (path) {
if (! fs.exists(path) || ! fs.isDirectory(path)) {
throw "'" + String(path) + "' is not a directory";
}
var tree = fs.listTree(path);
var files = [];
var i;
for (i = 0; i < tree.length; ++i) {
var filename = fs.join(path, tree[i]);
if (fs.isFile(filename)) {
files.push(tree[i]);
}
}
if (files.length === 0) {
throw "Directory '" + String(path) + "' is empty";
}
var tempFile = fs.getTempFile("downloads", false);
fs.zipFile(tempFile, path, files);
return tempFile;
};
// TODO: merge with functionality js/client/modules/@arangodb/foxx/manager.js
this.inspectUploadedFile = function (filename) {
var console = require("console");
if (! fs.isFile(filename)) {
throw "Unable to find zip file";
}
var i;
var path;
try {
path = fs.getTempFile("zip", false);
}
catch (err1) {
console.error("cannot get temp file: %s", String(err1));
throw err1;
}
try {
fs.unzipFile(filename, path, false, true);
}
catch (err2) {
console.error("cannot unzip file '%s' into directory '%s': %s", filename, path, String(err2));
throw err2;
}
// .............................................................................
// locate the manifest file
// .............................................................................
var tree = fs.listTree(path).sort(function(a,b) {
return a.length - b.length;
});
var found;
var mf = "manifest.json";
var re = /[\/\\\\]manifest\.json$/; // Windows!
for (i = 0; i < tree.length && found === undefined; ++i) {
var tf = tree[i];
if (re.test(tf) || tf === mf) {
found = tf;
break;
}
}
if (found === "undefined") {
fs.removeDirectoryRecursive(path);
throw "Cannot find manifest file in zip file";
}
var mp;
if (found === mf) {
mp = ".";
}
else {
mp = found.substr(0, found.length - mf.length - 1);
}
var manifest = JSON.parse(fs.read(fs.join(path, found)));
var absolutePath = this.repackZipFile(fs.join(path, mp));
var result = {
name : manifest.name,
version: manifest.version,
filename: absolutePath.substr(fs.getTempPath().length + 1),
configuration: manifest.configuration || {}
};
fs.removeDirectoryRecursive(path);
return result;
};
// Inspect a foxx in tmp zip file
this.inspect = function (path) {
var fullPath = fs.join(fs.getTempPath(), path);
try {
var result = this.inspectUploadedFile(fullPath);
fs.remove(fullPath);
return result;
} catch (e) {
throw new ArangoError();
}
};
};

View File

@ -1,66 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief functionality to expose API documentation for Foxx apps
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2013 triagens 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 triAGENS GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
(function() {
"use strict";
// Get details of one specific installed foxx.
exports.Swagger = function (mount) {
var foxx_manager = require("@arangodb/foxx/manager");
var result = {},
apis = [],
pathes,
regex = /(:)([^\/]*)/g,
i,
url,
api,
ops;
var routes = foxx_manager.routes(mount);
result.swaggerVersion = "1.1";
result.basePath = mount;
result.apis = apis;
result.models = routes.models;
pathes = routes.routes;
for (i in pathes) {
if (!pathes[i].internal && pathes[i].url.methods !== undefined) {
url = pathes[i].url.match;
api = {};
ops = [];
url = url.replace(regex, "{$2}");
api.path = url;
ops.push(pathes[i].docs);
api.operations = ops;
apis.push(api);
}
}
return result;
};
}());

View File

@ -2,11 +2,11 @@
"name": "aardvark",
"description": "ArangoDB Admin Web Interface",
"author": "ArangoDB GmbH",
"version": "1.0",
"version": "3.0.0",
"license": "Apache License, Version 2.0",
"isSystem": true,
"engines": {
"arangodb": "^2.8.0"
"arangodb": "^3.0.0-0 || ^3.0.0"
},
"repository": {
@ -29,13 +29,8 @@
}
],
"controllers": {
"/": "aardvark.js",
"/foxxes": "foxxes.js",
"/cluster": "cluster.js",
"/statistics": "statistics.js",
"/templates": "foxxTemplates.js"
},
"main": "index.js",
"defaultDocument": "index.html",
"files": {
"/standalone.html": {

View File

@ -1,50 +0,0 @@
/*jslint indent: 2, nomen: true, maxlen: 100 */
////////////////////////////////////////////////////////////////////////////////
/// @brief A configuration model for foxx templates
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens 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 triAGENS GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
(function() {
"use strict";
var Foxx = require("@arangodb/foxx"),
joi = require("joi"),
Configuration;
Configuration = Foxx.Model.extend({
schema: {
applicationContext: joi.string().optional(),
path: joi.string().optional(),
name: joi.string().required(),
collectionNames: joi.array().required(),
authenticated: joi.boolean().required(),
author: joi.string().required(),
description: joi.string().required(),
license: joi.string().required()
}
});
exports.Model = Configuration;
}());

View File

@ -1,12 +1,10 @@
'use strict';
////////////////////////////////////////////////////////////////////////////////
/// @brief A TODO-List Foxx-Application written for ArangoDB
///
/// @file This Document represents the repository communicating with ArangoDB
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
/// 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.
@ -20,89 +18,71 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
/// @author Alan Plum
////////////////////////////////////////////////////////////////////////////////
(function () {
"use strict";
const db = require('@arangodb').db;
const version = String(require('@arangodb/database-version').CURRENT_VERSION);
const collection = db._collection('_cluster_kickstarter_plans');
var _ = require("lodash"),
Foxx = require("@arangodb/foxx"),
version = require("@arangodb/database-version").CURRENT_VERSION + "", // do not use new String, there is bug in update
Plans;
module.exports = {
hasConfig() {
return Boolean(this.loadConfig());
},
Plans = Foxx.Repository.extend({
hasConfig: function() {
if (this.loadConfig()) {
return true;
}
return false;
},
clear() {
collection.truncate();
},
clear: function() {
this.collection.truncate();
},
loadConfig() {
return collection.any();
},
loadConfig: function() {
return this.collection.any();
},
getPlan() {
return this.loadConfig().plan;
},
getPlan: function() {
return this.loadConfig().plan;
},
getRunInfo() {
return this.loadConfig().runInfo;
},
getRunInfo: function() {
return this.loadConfig().runInfo;
},
getCredentials() {
return this.loadConfig().user;
},
getCredentials: function() {
return this.loadConfig().user;
},
updateConfig(config) {
const old = this.loadConfig();
collection.update(old._id, config);
return true;
},
updateConfig: function(config) {
var old = this.loadConfig();
this.collection.update(old._id, config);
return true;
},
saveCredentials(name, passwd) {
const config = {user: {name, passwd}};
const old = this.loadConfig();
collection.update(old._id, config);
return true;
},
saveCredentials: function(user, passwd) {
var config = {
user: {
name: user,
passwd: passwd
}
};
var old = this.loadConfig();
this.collection.update(old._id, config);
return true;
},
storeConfig(config) {
collection.truncate();
config.version = version;
collection.save(config);
return true;
},
storeConfig: function(config) {
this.collection.truncate();
config.version = version;
this.collection.save(config);
return true;
},
removeRunInfo() {
const old = this.loadConfig();
delete old.runInfo;
collection.replace(old._id, old);
return true;
},
removeRunInfo: function() {
var old = this.loadConfig();
delete old.runInfo;
this.collection.replace(old._id, old);
return true;
},
replaceRunInfo: function(newInfo) {
var old = this.loadConfig();
this.collection.update(old._id, {
runInfo: newInfo,
version: version
});
return true;
}
});
exports.Repository = Plans;
}());
replaceRunInfo(runInfo) {
const old = this.loadConfig();
collection.update(old._id, {runInfo, version});
return true;
}
};

File diff suppressed because it is too large Load Diff