mirror of https://gitee.com/bigwinds/arangodb
401 lines
14 KiB
JavaScript
401 lines
14 KiB
JavaScript
'use strict';
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / DISCLAIMER
|
|
// /
|
|
// / Copyright 2013-2014 triAGENS GmbH, Cologne, Germany
|
|
// / Copyright 2015-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 Lucas Dohmen
|
|
// / @author Alan Plum
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
const RequestContext = require('@arangodb/foxx/legacy/request_context');
|
|
const BaseMiddleware = require('@arangodb/foxx/legacy/base_middleware').BaseMiddleware;
|
|
const is = require('@arangodb/is');
|
|
const internal = require('@arangodb/foxx/legacy/internals');
|
|
const swagger = require('@arangodb/foxx/legacy/swagger');
|
|
|
|
var authControllerProps = {
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / JSF_foxx_controller_getUsers
|
|
// / @brief Get the users of this controller
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
getUsers() {
|
|
const foxxAuthentication = require('@arangodb/foxx/legacy/authentication');
|
|
return new foxxAuthentication.Users(this.applicationContext);
|
|
},
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / JSF_foxx_controller_getAuth
|
|
// / @brief Get the auth object of this controller
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
getAuth() {
|
|
return this.auth;
|
|
},
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_login
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
login(route, opts) {
|
|
var authentication = require('@arangodb/foxx/legacy/authentication');
|
|
return this.post(route, authentication.createStandardLoginHandler(this.getAuth(), this.getUsers(), opts));
|
|
},
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_logout
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
logout(route, opts) {
|
|
var authentication = require('@arangodb/foxx/legacy/authentication');
|
|
return this.post(route, authentication.createStandardLogoutHandler(this.getAuth(), opts));
|
|
},
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_register
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
register(route, opts) {
|
|
var authentication = require('@arangodb/foxx/legacy/authentication');
|
|
return this.post(
|
|
route,
|
|
authentication.createStandardRegistrationHandler(this.getAuth(), this.getUsers(), opts)
|
|
).errorResponse(authentication.UserAlreadyExistsError, 400, 'User already exists');
|
|
},
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_changePassword
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
changePassword(route, opts) {
|
|
var authentication = require('@arangodb/foxx/legacy/authentication');
|
|
return this.post(route, authentication.createStandardChangePasswordHandler(this.getUsers(), opts));
|
|
}
|
|
};
|
|
|
|
var sessionControllerProps = {
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / JSF_foxx_controller_getSessions
|
|
// / @brief Get the sessions object of this controller
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
getSessions() {
|
|
return this.sessions;
|
|
},
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief defines a route to logout/destroy the session
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
destroySession(route, opts) {
|
|
var method = opts.method;
|
|
if (typeof method === 'string') {
|
|
method = method.toLowerCase();
|
|
}
|
|
if (!method || typeof this[method] !== 'function') {
|
|
method = 'post';
|
|
}
|
|
var sessions = require('@arangodb/foxx/legacy/sessions');
|
|
return this[method](route, sessions.createDestroySessionHandler(this.getSessions(), opts));
|
|
}
|
|
};
|
|
|
|
class Controller {
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_initializer
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
constructor (context, options) {
|
|
this.currentPriority = 0;
|
|
|
|
var urlPrefix, baseMiddleware;
|
|
|
|
if (is.notExisty(context)) {
|
|
throw new Error('parameter <context> is missing');
|
|
}
|
|
|
|
this.routingInfo = {
|
|
routes: []
|
|
};
|
|
|
|
// Models for the Documentation
|
|
this.models = {};
|
|
|
|
options = options || {};
|
|
urlPrefix = options.urlPrefix || '';
|
|
|
|
if (urlPrefix === '') {
|
|
urlPrefix = context.prefix;
|
|
} else if (context.prefix !== '') {
|
|
urlPrefix = context.prefix + '/' + urlPrefix;
|
|
}
|
|
|
|
this.injected = Object.create(null);
|
|
this.injectors = Object.create(null);
|
|
this.routingInfo.urlPrefix = urlPrefix;
|
|
this.collectionPrefix = context.collectionPrefix;
|
|
|
|
this.extensions = {};
|
|
|
|
baseMiddleware = new BaseMiddleware();
|
|
|
|
this.routingInfo.middleware = [
|
|
{
|
|
url: { match: '/*' },
|
|
action: {
|
|
callback: baseMiddleware.functionRepresentation,
|
|
options: {
|
|
name: context.name,
|
|
version: context.version,
|
|
mount: context.mount,
|
|
isDevelopment: context.isDevelopment,
|
|
isProduction: context.isProduction,
|
|
prefix: context.prefix,
|
|
options: context.options
|
|
}
|
|
}
|
|
}
|
|
];
|
|
|
|
this.allRoutes = new RequestContext.Buffer();
|
|
|
|
context.foxxes.push(this);
|
|
|
|
if (is.existy(context.manifest.rootElement)) {
|
|
this.rootElement = context.manifest.rootElement;
|
|
} else {
|
|
this.rootElement = false;
|
|
}
|
|
|
|
this.applicationContext = context;
|
|
}
|
|
|
|
addInjector (name, factory) {
|
|
if (factory === undefined) {
|
|
Object.assign(this.injectors, name);
|
|
} else {
|
|
this.injectors[name] = factory;
|
|
}
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// /
|
|
// / The *handleRequest* method is the raw way to create a new route. You
|
|
// / probably wont call it directly, but it is used in the other request methods:
|
|
// /
|
|
// / When defining a route you can also define a so called 'parameterized' route
|
|
// / like */goose/:barn*. In this case you can later get the value the user
|
|
// / provided for *barn* via the *params* function (see the Request object).
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
handleRequest (method, route, callback) {
|
|
var constraints = {queryParams: {}, urlParams: {}};
|
|
var newRoute = internal.constructRoute(method, route, callback, this, constraints);
|
|
var requestContext = new RequestContext(
|
|
this.allRoutes, this.models, newRoute, route, this.rootElement, constraints, this.extensions
|
|
);
|
|
|
|
this.routingInfo.routes.push(newRoute);
|
|
|
|
if (method === 'post' || method === 'put' || method === 'patch') {
|
|
const Model = require('@arangodb/foxx/legacy').Model;
|
|
let UndocumentedBody = Model.extend({});
|
|
requestContext.bodyParam('undocumented body', {
|
|
description: 'Undocumented body param',
|
|
type: UndocumentedBody,
|
|
allowInvalid: true
|
|
});
|
|
}
|
|
|
|
return requestContext;
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_head
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
head (route, callback) {
|
|
return this.handleRequest('head', route, callback);
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_get
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
get (route, callback) {
|
|
return this.handleRequest('get', route, callback);
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_post
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
post (route, callback) {
|
|
return this.handleRequest('post', route, callback);
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_put
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
put (route, callback) {
|
|
return this.handleRequest('put', route, callback);
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_patch
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
patch (route, callback) {
|
|
return this.handleRequest('patch', route, callback);
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_delete
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
delete (route, callback) {
|
|
return this.handleRequest('delete', route, callback);
|
|
}
|
|
|
|
del (route, callback) {
|
|
return this.delete(route, callback);
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_before
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
before (path, func) {
|
|
if (is.notExisty(func)) {
|
|
func = path;
|
|
path = '/*';
|
|
}
|
|
|
|
this.routingInfo.middleware.push({
|
|
priority: this.currentPriority = this.currentPriority + 1,
|
|
url: {match: path},
|
|
action: {
|
|
callback(req, res, opts, next) {
|
|
var result = func(req, res, opts);
|
|
if (result !== false) {
|
|
next();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_after
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
after (path, func) {
|
|
if (is.notExisty(func)) {
|
|
func = path;
|
|
path = '/*';
|
|
}
|
|
|
|
this.routingInfo.middleware.push({
|
|
priority: this.currentPriority = this.currentPriority + 1,
|
|
url: {match: path},
|
|
action: {
|
|
callback(req, res, opts, next) { next(); func(req, res, opts); }
|
|
}
|
|
});
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_around
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
around (path, func) {
|
|
if (is.notExisty(func)) {
|
|
func = path;
|
|
path = '/*';
|
|
}
|
|
|
|
this.routingInfo.middleware.push({
|
|
priority: this.currentPriority = this.currentPriority + 1,
|
|
url: {match: path},
|
|
action: {
|
|
callback(req, res, opts, next) {
|
|
func(req, res, opts, next);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_activateAuthentication
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
activateAuthentication (opts) {
|
|
var authentication = require('@arangodb/foxx/legacy/authentication');
|
|
Object.assign(this, authControllerProps);
|
|
|
|
this.auth = authentication.createAuthObject(this.applicationContext, opts);
|
|
this.before('/*', authentication.createAuthenticationMiddleware(this.auth, this.applicationContext));
|
|
this.after('/*', authentication.createSessionUpdateMiddleware());
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief activate sessions with the giveon options for this controller
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
activateSessions (opts) {
|
|
var sessions = require('@arangodb/foxx/legacy/sessions');
|
|
Object.assign(this, sessionControllerProps);
|
|
|
|
this.sessions = new sessions.Sessions(opts);
|
|
sessions.decorateController(this.sessions, this);
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_apiDocumentation
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
apiDocumentation (route, opts) {
|
|
if (route.charAt(route.length - 1) !== '/') {
|
|
route += '/';
|
|
}
|
|
var mountPath = this.applicationContext.mount;
|
|
return this.get(route + '*', swagger.createSwaggerRouteHandler(mountPath, opts));
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief was docuBlock JSF_foxx_controller_extend
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
extend (extensions) {
|
|
var attr;
|
|
var extensionWrapper = function (scope, functionName) {
|
|
return function () {
|
|
this.applyChain.push({
|
|
functionName: functionName,
|
|
argumentList: arguments
|
|
});
|
|
return this;
|
|
}.bind(scope);
|
|
};
|
|
for (attr in extensions) {
|
|
if (extensions.hasOwnProperty(attr)) {
|
|
this.extensions[attr] = extensions[attr];
|
|
this.allRoutes[attr] = extensionWrapper(this.allRoutes, attr);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
exports.Controller = Controller;
|