this method create the top level rest api in AWS apigateway
481860
def deploy_api(self, ret):
        '''
        
        '''
        if self.restApiId:
            res = self._cleanup_api()
            if not res.get('deleted'):
                ret['comment'] = 'Failed to cleanup restAreId {0}'.format(self.restApiId)
                ret['abort'] = True
                ret['result'] = False
                return ret
            return ret

        response = __salt__['boto_apigateway.create_api'](name=self.rest_api_name,
                                                          description=_Swagger.AWS_API_DESCRIPTION,
                                                          **self._common_aws_args)

        if not response.get('created'):
            ret['result'] = False
            ret['abort'] = True
            if 'error' in response:
                ret['comment'] = 'Failed to create rest api: {0}.'.format(response['error']['message'])
            return ret

        self.restApiId = response.get('restapi', {}).get('id')

        return _log_changes(ret, 'deploy_api', response.get('restapi'))
613098
function createEndpointFromObject(path, query, body) {
  // OPTIONS gives server permission to use CORS
  server.createRoute({
    request: {
        url: path,
        query: query || {},
        method: 'options',
    },
    response: {
        code: 200,
        delay: config.latency,
        body: {},
        headers: {
          'Access-Control-Allow-Origin': config.allowOrigin,
          // allow several methods since some endpoints are writable
          'Access-Control-Allow-Methods': 'GET, PUT, POST',
          'Access-Control-Allow-Credentials': 'true'
        }
    }
  });
  return server.get(path)
               .query(query)
               .responseHeaders({
                 'Access-Control-Allow-Origin': config.allowOrigin,
                 'Access-Control-Allow-Methods': 'GET, PUT, POST',
                 'Access-Control-Allow-Credentials': 'true'
               })
               .body(body)
               .delay(config.latency);
}
1314903
def _cleanup_api(self):
        '''
        
        '''
        resources = __salt__['boto_apigateway.describe_api_resources'](restApiId=self.restApiId,
                                                                       **self._common_aws_args)
        if resources.get('resources'):
            res = resources.get('resources')[1:]
            res.reverse()
            for resource in res:
                delres = __salt__['boto_apigateway.delete_api_resources'](restApiId=self.restApiId,
                                                                          path=resource.get('path'),
                                                                          **self._common_aws_args)
                if not delres.get('deleted'):
                    return delres

        models = __salt__['boto_apigateway.describe_api_models'](restApiId=self.restApiId, **self._common_aws_args)
        if models.get('models'):
            for model in models.get('models'):
                delres = __salt__['boto_apigateway.delete_api_model'](restApiId=self.restApiId,
                                                                      modelName=model.get('name'),
                                                                      **self._common_aws_args)
                if not delres.get('deleted'):
                    return delres

        return {'deleted': True}
662273
function() {
      if( StackMob['useRelativePathForAjax'] ){
        // Build "relative path" (also used for OAuth signing)
        return StackMob.apiDomain ? StackMob.apiDomain : (this.getHostname() + (this.getPort() ? ':' + this.getPort() : '')) + '/';
      } else {
        // Use absolute path and operate through CORS
        return StackMob.apiDomain ? StackMob.apiDomain : (StackMob['API_SERVER'] + '/');
      }
    }
191826
def create(self):
        

        self._app = Flask(__name__,
                          static_url_path="",  # Mount static files at root '/'
                          static_folder=self.static_dir  # Serve static files from this directory
                          )

        for api_gateway_route in self.routing_list:
            path = PathConverter.convert_path_to_flask(api_gateway_route.path)
            for route_key in self._generate_route_keys(api_gateway_route.methods,
                                                       path):
                self._dict_of_routes[route_key] = api_gateway_route

            self._app.add_url_rule(path,
                                   endpoint=path,
                                   view_func=self._request_handler,
                                   methods=api_gateway_route.methods,
                                   provide_automatic_options=False)

        self._construct_error_handling()
527771
def _set_current_deployment(self, stage_desc_json, stage_variables):
        '''
        
        '''
        stage = __salt__['boto_apigateway.describe_api_stage'](restApiId=self.restApiId,
                                                               stageName=self._stage_name,
                                                               **self._common_aws_args).get('stage')
        if not stage:
            stage = __salt__['boto_apigateway.create_api_stage'](restApiId=self.restApiId,
                                                                 stageName=self._stage_name,
                                                                 deploymentId=self._deploymentId,
                                                                 description=stage_desc_json,
                                                                 variables=stage_variables,
                                                                 **self._common_aws_args)
            if not stage.get('stage'):
                return {'set': False, 'error': stage.get('error')}
        else:
            # overwrite the stage variables
            overwrite = __salt__['boto_apigateway.overwrite_api_stage_variables'](restApiId=self.restApiId,
                                                                                  stageName=self._stage_name,
                                                                                  variables=stage_variables,
                                                                                  **self._common_aws_args)
            if not overwrite.get('stage'):
                return {'set': False, 'error': overwrite.get('error')}

        return __salt__['boto_apigateway.activate_api_deployment'](restApiId=self.restApiId,
                                                                   stageName=self._stage_name,
                                                                   deploymentId=self._deploymentId,
                                                                   **self._common_aws_args)
24975
def create_api_deployment(self):
        """"""
        try:
            self.client.create_deployment(restApiId=self.api_id, stageName=self.env)
            self.log.info('Created a deployment resource.')
        except botocore.exceptions.ClientError as error:
            error_code = error.response['Error']['Code']
            if error_code == 'TooManyRequestsException':
                self.log.debug('Retrying. We have hit api limit.')
            else:
                self.log.debug('Retrying. We received %s.', error_code)
1275914
private static String getGateway(DiscordApiImpl api) {
        gatewayReadLock.lock();
        if (gateway == null) {
            gatewayReadLock.unlock();
            gatewayWriteLock.lock();
            try {
                if (gateway == null) {
                    gateway = new RestRequest<String>(api, RestMethod.GET, RestEndpoint.GATEWAY)
                            .includeAuthorizationHeader(false)
                            .execute(result -> result.getJsonBody().get("url").asText())
                            .join();
                }
                gatewayReadLock.lock();
            } finally {
                gatewayWriteLock.unlock();
            }
        }

        try {
            return gateway;
        } finally {
            gatewayReadLock.unlock();
        }
    }
186714
def get_api_id(self):
        
        logger.debug('Connecting to AWS apigateway API')
        conn = client('apigateway')
        apis = conn.get_rest_apis()
        api_id = None
        for api in apis['items']:
            if api['name'] == self.config.func_name:
                api_id = api['id']
                logger.debug('Found API id: %s', api_id)
                break
        if api_id is None:
            raise Exception('Unable to find ReST API named %s' %
                            self.config.func_name)
        return api_id
999267
protected function createREST($first, $last = null, $api_url = self::API_URL)
    {
        if ($first instanceof OAuthToken) {
            $rest = new REST(array(
                'server' => $api_url,
                'debug_mode' => $this->debug_mode
            ));
            $auth = $first->getTokenType() . ' ' . $first->getAccessToken();
            $rest->setHeader('Authorization', $auth);

            return $rest;
        }

        return new REST(array(
            'server' => $api_url,
            'user'   => $first,
            'pass'   => $last,
            'debug_mode' => $this->debug_mode
        ));
    }
1018654
function createIntegration(callback) {
      setTimeout(function throttle() {
        let uri = `arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${arn}/invocations`
        // console.log(api)
        gateway.createIntegration({
          ApiId: api.ApiId,
          IntegrationMethod: 'POST',
          IntegrationType: 'AWS_PROXY',
          IntegrationUri: uri
        }, callback)
      }, 1000)
    }
1038223
def get_create_api(self, resource):
        

        create_api = {
            'path': '/%s/' % resource.get_api_name(),
            'description': 'Operations on %s' % resource.model.__name__,
            'operations': [
                {
                    'httpMethod': 'POST',
                    'nickname': 'create%ss' % resource.model
                    .__name__,
                    'summary': 'Create %ss' % resource.model.__name__,
                    'parameters': [{
                        'description': '%s object' % (resource.model.__name__),
                        'paramType': 'body',
                        'required': True,
                        'allowMultiple': False,
                        'dataType': resource.model.__name__
                    }]
                }
            ]
        }

        return create_api
362444
function createAPI(app, mountPath, middlewareOpts) {
    var router = express.Router(),
        apiDocumentationMountPoint = '/developer/api',
        logger = middlewareOpts.logger.fork('api'),
        gmeAuth = middlewareOpts.gmeAuth,
        metadataStorage = gmeAuth.metadataStorage,
        authorizer = gmeAuth.authorizer,
        safeStorage = middlewareOpts.safeStorage,
        ensureAuthenticated = middlewareOpts.ensureAuthenticated,
        gmeConfig = middlewareOpts.gmeConfig,
        getUserId = middlewareOpts.getUserId,
        STORAGE_CONSTANTS = CONSTANTS.STORAGE,
        CORE_CONSTANTS = CONSTANTS.CORE,
        versionedAPIPath = mountPath + '/v1',
        latestAPIPath = mountPath,
        registerEndPoint = typeof gmeConfig.authentication.allowUserRegistration === 'string' ?
            require(gmeConfig.authentication.allowUserRegistration)(middlewareOpts) :
            require('./defaultRegisterEndPoint')(middlewareOpts),
        seedToBlobHash = {},
        paths;

    app.get(apiDocumentationMountPoint, function (req, res) {
        res.sendFile(path.join(__dirname, '..', '..', '..', 'docs', 'REST', 'index.html'));
    });

    function getFullUrl(req, name) {
        return req.protocol + '://' + req.headers.host + middlewareOpts.getMountedPath(req) + req.baseUrl + name;
    }

    function getNewJWToken(userId, callback) {
        var deferred = Q.defer();

        if (gmeConfig.authentication.enable === true) {
            gmeAuth.generateJWTokenForAuthenticatedUser(userId)
                .then(deferred.resolve)
                .catch(deferred.reject);
        } else {
            deferred.resolve();
        }

        return deferred.promise.nodeify(callback);
    }

    function exportProject(req, res) {
        var userId = getUserId(req),
            projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                req.params.projectName),
            workerParameters = {

                command: CONSTANTS.SERVER_WORKER_REQUESTS.EXPORT_PROJECT_TO_FILE,
                projectId: projectId,
                branchName: req.params.branchId || null,
                commitHash: req.params.commitHash ? StorageUtil.getHashTaggedHash(req.params.commitHash) : null,
                tagName: req.params.tagId || null,
                withAssets: true
            };

        getNewJWToken(userId)
            .then(function (token) {
                workerParameters.webgmeToken = token;
                return Q.ninvoke(middlewareOpts.workerManager, 'request', workerParameters);
            })
            .then(function (result) {
                res.redirect(result.downloadUrl);
                return;
            })
            .catch(function (err) {
                logger.error('Cannot handle export request', err);
                res.status(403).send('Cannot process request: ' + err);
            });
    }

    function exportModel(req, res) {
        var userId = getUserId(req),
            projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                req.params.projectName),
            workerParameters = {
                command: CONSTANTS.SERVER_WORKER_REQUESTS.EXPORT_SELECTION_TO_FILE,
                projectId: projectId,
                branchName: req.params.branchId || null,
                commitHash: req.params.commitHash ? StorageUtil.getHashTaggedHash(req.params.commitHash) : null,
                tagName: req.params.tagId || null,
                paths: ['/' + req.params[0]],
                withAssets: true
            };

        getNewJWToken(userId)
            .then(function (token) {
                workerParameters.webgmeToken = token;

                return Q.ninvoke(middlewareOpts.workerManager, 'request', workerParameters);
            })
            .then(function (result) {
                res.redirect(result.downloadUrl);
                return;
            })
            .catch(function (err) {
                logger.error('Cannot handle export request', err);
                res.status(403).send('Cannot process request: ' + err);
            });
    }

    // ensure authenticated can be used only after this rule
    router.use('*', function (req, res, next) {
        // TODO: set all headers, check rate limit, etc.
        res.setHeader('X-WebGME-Media-Type', 'webgme.v1');
        next();
    });

    router.post('/register', registerEndPoint);

    // modifications are allowed only if the user is authenticated
    // all get rules by default do NOT require authentication, if the get rule has to be protected add inline
    // the ensureAuthenticated function middleware
    router.post('*', ensureAuthenticated);
    router.put('*', ensureAuthenticated);
    router.patch('*', ensureAuthenticated);
    router.delete('*', ensureAuthenticated);

    router.get('/', function (req, res/*, next*/) {
        res.json({
            current_user_url: getFullUrl(req, '/user'),
            organization_url: getFullUrl(req, '/orgs/{org}'),
            project_url: getFullUrl(req, '/projects/{owner}/{project}'),
            user_url: getFullUrl(req, '/users/{user}'),
            api_documentation_url: req.protocol + '://' + req.headers.host + apiDocumentationMountPoint,
            source_code_documentation_url: req.protocol + '://' + req.headers.host + '/docs/source/index.html'
        });
    });

    function putUser(receivedData, req, res, next) {
        var userId = getUserId(req);

        gmeAuth.getUser(userId)
            .then(function (data) {

                if (!data.siteAdmin) {
                    res.status(403);
                    throw new Error('site admin role is required for this operation');
                }

                gmeAuth.addUser(receivedData.userId,
                    receivedData.email,
                    receivedData.password,
                    receivedData.canCreate === 'true' || receivedData.canCreate === true,
                    {overwrite: receivedData.overwrite})
                    .then(function (newData) {
                        res.json(newData);
                    })
                    .catch(function (err) {
                        res.status(400);
                        next(err);
                    });
            })
            .catch(next);
    }

    function ensureSameUserOrSiteAdmin(req, res) {
        var userId = getUserId(req);

        return gmeAuth.getUser(userId)
            .then(function (userData) {
                if (userData.siteAdmin || userId === req.params.username) {
                    return userData;
                } else {
                    res.status(403);
                    throw new Error('site admin role is required for this operation');
                }
            });
    }

    /**
     * @param req
     * @param res
     * @param callback
     * @returns {*}
     */
    function getUserEntry(req, res, callback) {
        var deferred = Q.defer(),
            userId = getUserId(req),
            query = {disabled: undefined};

        gmeAuth.getUser(userId, query)
            .then(function (userData) {
                if (userData.disabled === true) {
                    res.clearCookie(gmeConfig.authentication.jwt.cookieId);
                    res.status(401);
                    deferred.reject(new Error('user has been disabled [' + userId + ']'));
                } else {
                    deferred.resolve(userData);
                }
            })
            .catch(deferred.reject);

        return deferred.promise.nodeify(callback);
    }

    function filterUsersOrOrgs(userData, projects, usersOrOrgs) {
        var result = [],
            readableProjects = {},
            filteredData,
            i;

        function getFilteredData(data) {
            var filteredProjects = {};
            data = usersOrOrgs[i];

            if (userData._id === data._id) {
                return userData;
            } else if (userData.siteAdmin === true) {
                return data;
            } else {
                if (data.type === 'Organization') {
                    if (userData._id === gmeConfig.authentication.guestAccount &&
                        data.users.indexOf(userData._id) === -1) {
                        // The guest can only view organization where he/she is a member.
                        return;
                    }
                } else {
                    // Clear out user-data.
                    data.settings = {};
                    data.data = {};
                    data.email = '';
                    data.siteAdmin = false;
                    data.canCreate = false;
                }

                // We only return project info for projects the requesting user has access to.
                Object.keys(data.projects).forEach(function (projectId) {
                    if (readableProjects[projectId]) {
                        filteredProjects[projectId] = data.projects[projectId];
                    }
                });

                data.projects = filteredProjects;

                return data;
            }
        }

        projects.forEach(function (pData) {
            readableProjects[pData._id] = true;
        });

        for (i = 0; i < usersOrOrgs.length; i += 1) {
            filteredData = getFilteredData(usersOrOrgs[i]);
            if (filteredData) {
                result.push(filteredData);
            }
        }

        return result;
    }

    // AUTHENTICATED
    router.get('/user', ensureAuthenticated, function (req, res, next) {
        getUserEntry(req, res)
            .then(function (data) {
                res.json(data);
            })
            .catch(next);
    });

    // Example: curl -i -H "Content-Type: application/json" -X PATCH
    //  -d "{\"email\":\"asdf@alkfm.com\",\"canCreate\":false}" http://demo:demo@127.0.0.1:8888/api/v1/user
    router.patch('/user', function (req, res, next) {
        var userId = getUserId(req);

        gmeAuth.getUser(userId)
            .then(function (userData) {
                var receivedData = req.body;

                if (userData.siteAdmin !== true &&
                    (receivedData.hasOwnProperty('siteAdmin') || receivedData.hasOwnProperty('canCreate'))) {
                    res.status(403);
                    throw new Error('setting siteAdmin and/or canCreate property requires site admin role');
                }

                return gmeAuth.updateUser(userId, receivedData);
            })
            .then(function (newData) {
                res.json(newData);
            })
            .catch(next);
    });

    router.delete('/user', function (req, res, next) {
        var userId = getUserId(req);

        gmeAuth.deleteUser(userId, false)
            .then(function () {
                res.sendStatus(204);
            })
            .catch(next);
    });

    router.get('/user/data', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req);

        gmeAuth.getUser(userId)
            .then(function (userData) {
                res.json(userData.data);
            })
            .catch(next);
    });

    router.put('/user/data', function (req, res, next) {
        var userId = getUserId(req);

        gmeAuth.updateUserDataField(userId, req.body, true)
            .then(function (data) {
                res.json(data);
            })
            .catch(next);
    });

    router.patch('/user/data', function (req, res, next) {
        var userId = getUserId(req);

        gmeAuth.updateUserDataField(userId, req.body)
            .then(function (data) {
                res.json(data);
            })
            .catch(next);
    });

    router.delete('/user/data', function (req, res, next) {
        var userId = getUserId(req);

        gmeAuth.updateUserDataField(userId, {}, true)
            .then(function (/*data*/) {
                res.sendStatus(204);
            })
            .catch(next);
    });

    router.get('/user/token', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req);

        if (gmeConfig.authentication.enable === false) {
            res.status(404);
            res.json({
                message: 'Authentication is turned off',
            });
            return;
        }

        if (req.userData.token && req.userData.newToken === true) {
            res.status(200);
            res.json({
                webgmeToken: req.userData.token
            });
        } else {
            getNewJWToken(userId)
                .then(function (token) {
                    res.status(200);
                    res.json({webgmeToken: token});
                })
                .catch(function (err) {
                    next(err);
                });
        }
    });

    router.get('/componentSettings', ensureAuthenticated, function (req, res, next) {
        webgmeUtils.getComponentsJson(logger)
            .then(function (componentsJson) {
                res.json(componentsJson);
            })
            .catch(next);
    });

    router.get('/componentSettings/:componentId', ensureAuthenticated, function (req, res, next) {
        webgmeUtils.getComponentsJson(logger)
            .then(function (componentsJson) {
                res.json(componentsJson[req.params.componentId] || {});
            })
            .catch(next);
    });

    router.get('/user/settings', ensureAuthenticated, function (req, res, next) {
        getUserEntry(req, res)
            .then(function (userData) {
                res.json(userData.settings || {});
            })
            .catch(next);
    });

    router.put('/user/settings', function (req, res, next) {
        getUserEntry(req, res)
            .then(function (userData) {
                return gmeAuth.updateUserSettings(userData._id, req.body, true);
            })
            .then(function (settings) {
                res.json(settings);
            })
            .catch(next);
    });

    router.patch('/user/settings', function (req, res, next) {
        getUserEntry(req, res)
            .then(function (userData) {
                return gmeAuth.updateUserSettings(userData._id, req.body);
            })
            .then(function (settings) {
                res.json(settings);
            })
            .catch(next);
    });

    router.delete('/user/settings', function (req, res, next) {
        getUserEntry(req, res)
            .then(function (userData) {
                return gmeAuth.updateUserSettings(userData._id, {}, true);
            })
            .then(function (/*settings*/) {
                res.sendStatus(204);
            })
            .catch(next);
    });

    router.get('/user/settings/:componentId', ensureAuthenticated, function (req, res, next) {
        getUserEntry(req, res)
            .then(function (userData) {
                res.json(userData.settings[req.params.componentId] || {});
            })
            .catch(next);
    });

    router.put('/user/settings/:componentId', function (req, res, next) {
        getUserEntry(req, res)
            .then(function (userData) {
                return gmeAuth.updateUserComponentSettings(userData._id, req.params.componentId, req.body, true);
            })
            .then(function (settings) {
                res.json(settings);
            })
            .catch(next);
    });

    router.patch('/user/settings/:componentId', function (req, res, next) {
        getUserEntry(req, res)
            .then(function (userData) {
                return gmeAuth.updateUserComponentSettings(userData._id, req.params.componentId, req.body);
            })
            .then(function (settings) {
                res.json(settings);
            })
            .catch(next);
    });

    router.delete('/user/settings/:componentId', function (req, res, next) {
        getUserEntry(req, res)
            .then(function (userData) {
                return gmeAuth.updateUserComponentSettings(userData._id, req.params.componentId, {}, true);
            })
            .then(function (/*settings*/) {
                res.sendStatus(204);
            })
            .catch(next);
    });

    router.get('/users', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            userData,
            query,
            projection;

        if (req.query.displayName) {
            gmeAuth.listUsers({displayName: {$type: 2}}, {displayName: 1})
                .then(function (result) {
                    res.json(result);
                })
                .catch(next);
        } else {
            gmeAuth.getUser(userId)
                .then(function (userData_) {
                    var doGetProjects = userId !== gmeConfig.authentication.guestAccount && !userData_.siteAdmin;
                    userData = userData_;

                    if (req.query.includeDisabled && userData.siteAdmin) {
                        query = {disabled: undefined};
                    }

                    if (userId === gmeConfig.authentication.guestAccount) {
                        query = {_id: userId};
                    } else if (!userData.siteAdmin) {
                        projection = {
                            data: 0,
                            settings: 0,
                            email: 0,
                            password: 0
                        };
                    }

                    return Q.all([
                        doGetProjects ? safeStorage.getProjects({username: userId}) : Q.resolve([]),
                        gmeAuth.listUsers(query, projection)
                    ]);
                })
                .then(function (results) {
                    res.json(filterUsersOrOrgs(userData, results[0], results[1]));
                })
                .catch(next);
        }
    });

    router.put('/users', function (req, res, next) {

        //"userId: "newUser"
        //"email": "user@example.com",
        //"password": "pass",
        //"canCreate": null,

        putUser(req.body, req, res, next);
    });

    router.get('/users/:username', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req);

        gmeAuth.getUser(userId)
            .then(function (userData) {
                if (userId === req.params.username) {
                    return Q.resolve(userData);
                } else if (userId === gmeConfig.authentication.guestAccount) {
                    res.status(404);
                    return Q.reject(new Error('no such user'));
                } else {
                    return Q.all([
                        userData.siteAdmin ? [] : safeStorage.getProjects({username: userId}),
                        gmeAuth.getUser(req.params.username)
                    ])
                        .then(function (results) {
                            return filterUsersOrOrgs(userData, results[0], [results[1]])[0];
                        });
                }
            })
            .then(function (data) {
                res.json(data);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.put('/users/:username', function (req, res, next) {
        var receivedData = {
            userId: req.params.username,
            email: req.body.email,
            password: req.body.password,
            canCreate: req.body.canCreate || false,
            data: req.body.data || {},
            overwrite: req.body.overwrite
        };

        putUser(receivedData, req, res, next);
    });

    router.patch('/users/:username', function (req, res, next) {
        // body params
        //"email": "user@example.com",
        //"password": "pass",
        //"canCreate": null,
        //"siteAdmin": false,
        //"disabled": false, // Only applicable if false -> will re-enable user
        //"data": {}
        ensureSameUserOrSiteAdmin(req, res)
            .then(function (userData) {
                if (userData.siteAdmin !== true &&
                    (req.body.hasOwnProperty('siteAdmin') || req.body.hasOwnProperty('canCreate'))) {
                    res.status(403);
                    throw new Error('setting siteAdmin and/or canCreate property requires site admin role');
                }

                if (req.body.hasOwnProperty('disabled') && req.body.disabled === false) {
                    if (userData.siteAdmin === true) {
                        return gmeAuth.reEnableUser(req.params.username);
                    } else {
                        res.status(403);
                        throw new Error('re-enabling users requires site admin role');
                    }
                } else {
                    return gmeAuth.updateUser(req.params.username, req.body);
                }
            })
            .then(function (userData) {
                res.json(userData);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    //TODO: why is this 400 and not 404?
                    res.status(400);
                }

                next(err);
            });
    });

    router.delete('/users/:username', function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function (userData) {
                var force = req.query.force && userData.siteAdmin === true;
                return gmeAuth.deleteUser(req.params.username, force);
            })
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user') > -1) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.get('/users/:username/data', ensureAuthenticated, function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.getUser(req.params.username);
            })
            .then(function (userData) {
                res.json(userData.data);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.put('/users/:username/data', function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.updateUserDataField(req.params.username, req.body, true);
            })
            .then(function (data) {
                res.json(data);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.patch('/users/:username/data', function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.updateUserDataField(req.params.username, req.body);
            })
            .then(function (data) {
                res.json(data);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.delete('/users/:username/data', function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.updateUserDataField(req.params.username, {}, true);
            })
            .then(function (/*userData*/) {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.get('/users/:username/settings', ensureAuthenticated, function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.getUser(req.params.username);
            })
            .then(function (userData) {
                res.json(userData.settings);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.put('/users/:username/settings', function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.updateUserSettings(req.params.username, req.body, true);
            })
            .then(function (settings) {
                res.json(settings);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.patch('/users/:username/settings', function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.updateUserSettings(req.params.username, req.body);
            })
            .then(function (settings) {
                res.json(settings);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.delete('/users/:username/settings', function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.updateUserSettings(req.params.username, {}, true);
            })
            .then(function (/*settings*/) {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.get('/users/:username/settings/:componentId', ensureAuthenticated, function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.getUser(req.params.username);
            })
            .then(function (userData) {
                res.json(userData.settings[req.params.componentId] || {});
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.put('/users/:username/settings/:componentId', function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.updateUserComponentSettings(req.params.username, req.params.componentId, req.body, true);
            })
            .then(function (settings) {
                res.json(settings);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.patch('/users/:username/settings/:componentId', function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.updateUserComponentSettings(req.params.username, req.params.componentId, req.body);
            })
            .then(function (settings) {
                res.json(settings);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.delete('/users/:username/settings/:componentId', function (req, res, next) {
        ensureSameUserOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.updateUserComponentSettings(req.params.username, req.params.componentId, {}, true);
            })
            .then(function (/*settings*/) {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user [' + req.params.username) === 0) {
                    res.status(404);
                }

                next(err);
            });
    });

    //ORGANIZATIONS
    function ensureOrgOrSiteAdmin(req, res) {
        var userId = getUserId(req),
            userData;

        return gmeAuth.getUser(userId)
            .then(function (data) {
                userData = data;
                return gmeAuth.getAdminsInOrganization(req.params.orgId);
            })
            .then(function (admins) {
                if (!userData.siteAdmin && admins.indexOf(userId) === -1) {
                    res.status(403);
                    throw new Error('site admin role or organization admin is required for this operation');
                }

                return userData;
            });
    }

    router.get('/orgs', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            userData,
            query;

        gmeAuth.getUser(userId)
            .then(function (userData_) {
                userData = userData_;
                if (req.query.includeDisabled && userData.siteAdmin) {
                    query = {disabled: undefined};
                }

                return Q.all([
                    safeStorage.getProjects({username: userId}),
                    gmeAuth.listOrganizations(query)
                ]);
            })
            .then(function (results) {
                res.json(filterUsersOrOrgs(userData, results[0], results[1]));
            })
            .catch(next);
    });

    router.put('/orgs/:orgId', function (req, res, next) {

        var userId = getUserId(req);

        gmeAuth.getUser(userId)
            .then(function (data) {
                if (!(data.siteAdmin || data.canCreate)) {
                    res.status(403);
                    throw new Error('site admin role or can create is required for this operation');
                }

                return gmeAuth.addOrganization(req.params.orgId, req.body.info);
            })
            .then(function () {
                return gmeAuth.setAdminForUserInOrganization(userId, req.params.orgId, true);
            })
            .then(function () {
                return gmeAuth.addUserToOrganization(userId, req.params.orgId);
            })
            .then(function () {
                return gmeAuth.getOrganization(req.params.orgId);
            })
            .then(function (orgData) {
                res.json(orgData);
            })
            .catch(function (err) {
                if (err.message.indexOf('user or org already exists') > -1) {
                    res.status(400);
                }

                next(err);
            });
    });

    router.get('/orgs/:orgId', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req);

        gmeAuth.getUser(userId)
            .then(function (userData) {

                return Q.all([
                    userData.siteAdmin ? [] : safeStorage.getProjects({username: userId}),
                    gmeAuth.getOrganization(req.params.orgId)
                ])
                    .then(function (results) {
                        return filterUsersOrOrgs(userData, results[0], [results[1]])[0];
                    });
            })
            .then(function (orgData) {
                if (!orgData) {
                    // This is the case where the guest is not a member.
                    throw new Error('no such organization [');
                }

                res.json(orgData);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such organization [') > -1) {
                    res.status(404);
                }
                next(err);
            });
    });

    router.patch('/orgs/:orgId', function (req, res, next) {
        // body params
        //"info": {}
        //"disabled": false, // Only applicable if false -> will re-enable org
        function updateOrg() {
            var userId;
            if (req.body.hasOwnProperty('disabled') && req.body.disabled === false) {
                userId = getUserId(req);
                return gmeAuth.getUser(userId)
                    .then(function (userData) {
                        if (userData.siteAdmin === true) {
                            return gmeAuth.reEnableOrganization(req.params.orgId);
                        } else {
                            res.status(403);
                            throw new Error('re-enabling organizations requires site admin role');
                        }
                    });
            } else {
                return ensureOrgOrSiteAdmin(req, res)
                    .then(function () {
                        return gmeAuth.updateOrganizationInfo(req.params.orgId, req.body.info);
                    });
            }
        }

        updateOrg()
            .then(function (orgData) {
                res.json(orgData);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such organization [' + req.params.orgId) === 0 ||
                    err.message.indexOf('info is not an object') > -1) {
                    res.status(400);
                }

                next(err);
            });
    });

    router.delete('/orgs/:orgId', function (req, res, next) {
        function deleteOrg() {
            var userId;
            if (req.query.force) {
                userId = getUserId(req);
                return gmeAuth.getUser(userId)
                    .then(function (userData) {
                        if (userData.siteAdmin === true) {
                            return gmeAuth.removeOrganizationByOrgId(req.params.orgId, true);
                        } else {
                            res.status(403);
                            throw new Error('force deletion requires site admin role');
                        }
                    });
            } else {
                return ensureOrgOrSiteAdmin(req, res)
                    .then(function () {
                        return gmeAuth.removeOrganizationByOrgId(req.params.orgId, req.body.info);
                    });
            }
        }

        deleteOrg(req, res)
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such organization [') > -1) {
                    res.status(404);
                }
                next(err);
            });
    });

    router.put('/orgs/:orgId/users/:username', function (req, res, next) {
        ensureOrgOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.addUserToOrganization(req.params.username, req.params.orgId);
            })
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such organization [') > -1 ||
                    err.message.indexOf('no such user [') > -1) {
                    res.status(404);
                }
                next(err);
            });
    });

    router.delete('/orgs/:orgId/users/:username', function (req, res, next) {
        ensureOrgOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.removeUserFromOrganization(req.params.username, req.params.orgId);
            })
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such organization [') > -1) {
                    res.status(404);
                }
                next(err);
            });
    });

    router.put('/orgs/:orgId/admins/:username', function (req, res, next) {
        ensureOrgOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.setAdminForUserInOrganization(req.params.username, req.params.orgId, true);
            })
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such organization [') > -1 ||
                    err.message.indexOf('no such user [') > -1) {
                    res.status(404);
                }
                next(err);
            });
    });

    router.delete('/orgs/:orgId/admins/:username', function (req, res, next) {
        ensureOrgOrSiteAdmin(req, res)
            .then(function () {
                return gmeAuth.setAdminForUserInOrganization(req.params.username, req.params.orgId, false);
            })
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such organization [') > -1 ||
                    err.message.indexOf('no such user [') > -1) {
                    res.status(404);
                }
                next(err);
            });
    });

    // PROJECTS

    function loadNodePathByCommitHash(userId, projectId, commitHash, path) {
        var getCommitParams = {
            username: userId,
            projectId: projectId,
            number: 1,
            before: commitHash
        };

        return safeStorage.getCommits(getCommitParams)
            .then(function (commits) {
                var loadPathsParams = {
                    projectId: projectId,
                    username: userId,
                    pathsInfo: [
                        {
                            parentHash: commits[0].root,
                            path: path
                        }
                    ],
                    excludeParents: true
                };

                return safeStorage.loadPaths(loadPathsParams);
            })
            .then(function (dataObjects) {
                var hashes = Object.keys(dataObjects),
                    dataObj,
                    newOvr,
                    relid,
                    hash,
                    ovrPath;

                if (hashes.length === 1) {
                    return dataObjects[hashes[0]];
                } else if (hashes.length === 0) {
                    throw new Error('Path does not exist ' + path);
                } else {
                    // There are multiple hashes -> the overlay is shared so build up the complete object
                    for (hash in dataObjects) {
                        if (dataObjects[hash].type !== STORAGE_CONSTANTS.OVERLAY_SHARD_TYPE) {
                            dataObj = dataObjects[hash];
                            break;
                        }
                    }

                    if (!dataObj) {
                        throw new Error('loadPaths did not return with a dataObj hash, only shards');
                    } else if (!dataObj.ovr || Object.keys(dataObj.ovr) === 0) {
                        throw new Error('loadPaths returned with multiple objects but missing or empty ovr..');
                    }

                    newOvr = {};
                    for (relid in dataObj.ovr) {
                        if (relid !== CORE_CONSTANTS.OVERLAY_SHARD_INDICATOR) {
                            hash = dataObj.ovr[relid];
                            if (dataObjects[hash] && dataObjects[hash].type === STORAGE_CONSTANTS.OVERLAY_SHARD_TYPE) {
                                for (ovrPath in dataObjects[hash].items) {
                                    newOvr[ovrPath] = dataObjects[hash].items[ovrPath];
                                }
                            } else {
                                logger.error('Did not find shard for overlay', hash);
                            }
                        }
                    }

                    dataObj.ovr = newOvr;

                    return dataObj;
                }
            });
    }

    function canUserAuthorizeProject(req) {
        var userId = getUserId(req);

        return gmeAuth.getUser(userId)
            .then(function (userData) {
                // Make sure user is authorized (owner, admin in owner Org or siteAdmin).
                if (userId === req.params.ownerId || userData.siteAdmin === true) {
                    return true;
                } else {
                    return gmeAuth.getOrganization(req.params.ownerId)
                        .then(function (orgData) {
                            if (orgData.admins.indexOf(userId) > -1) {
                                return true;
                            }

                            return false;
                        })
                        .catch(function (err) {
                            logger.debug(err);
                            return false;
                        });
                }
            });
    }

    router.get('/projects', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req);
        safeStorage.getProjects({username: userId, info: true})
            .then(function (result) {
                res.json(result);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.get('/projects/:ownerId/:projectName', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName),
            data = {
                username: userId,
                projectId: projectId
            },
            branches;

        safeStorage.getBranches(data)
            .then(function (branches_) {
                branches = branches_;
                return metadataStorage.getProject(projectId);
            })
            .then(function (projectData) {
                projectData.branches = branches;
                res.json(projectData);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.patch('/projects/:ownerId/:projectName', function (req, res, next) {
        var userId = getUserId(req),
            projectAuthParams = {
                entityType: authorizer.ENTITY_TYPES.PROJECT
            },
            projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName);

        authorizer.getAccessRights(userId, projectId, projectAuthParams)
            .then(function (projectAccess) {
                if (projectAccess && projectAccess.write) {
                    return;
                } else {
                    res.status(403);
                    throw new Error('Not authorized to modify project');
                }
            })
            .then(function () {
                return metadataStorage.updateProjectInfo(projectId, req.body);
            })
            .then(function (projectData) {
                res.json(projectData);
            })
            .catch(function (err) {
                next(err);
            });
    });
    /**
     * Creating project by seed
     *
     * @param {string} req.body.type - sets if the seed is coming from file (==='file') source or from some
     *  existing project(==='db').
     * @param {string} req.body.seedName - the name or rather id of the seed
     *          db - projectId
     *          seed - name of the seed-file (no extension - matches json file)
     * @param {string} [req.body.seedBranch='master'] - for 'db' optional branch name to seed from.
     * @param {string} [req.body.seedCommit] - for 'db' optional commit-hash to seed from
     * (if given seedBranch is not used).
     * @param {string} [req.body.kind] - If not given:
     *                  1) type is seed - will use kind stored in seed else name of seed.
     *                  2) type is db - will use kind stored project info.
     * @example {type:'file', seedName:'EmptyProject'}
     * @example {type:'db', seedName:'guest+aFSMProject', seedBranch:'release', kind: 'FiniteStateMachine'}
     */
    router.put('/projects/:ownerId/:projectName', function (req, res, next) {
        var userId = getUserId(req),
            command = req.body;

        command.command = 'seedProject';
        command.userId = userId;
        command.ownerId = req.params.ownerId;
        command.projectName = req.params.projectName;

        getNewJWToken(userId)
            .then(function (token) {
                command.webgmeToken = token;
                return Q.nfcall(middlewareOpts.workerManager.request, command);
            })
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                next(new Error(err));
            }); //TODO do we need special error handling???
    });

    router.delete('/projects/:ownerId/:projectName', function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName)
            };

        safeStorage.deleteProject(data)
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.put('/projects/:ownerId/:projectName/authorize/:userOrOrgId/:rights', function (req, res, next) {
        var projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName),
            projectAuthParams = {
                entityType: authorizer.ENTITY_TYPES.PROJECT
            };

        canUserAuthorizeProject(req)
            .then(function (isAuthorized) {
                if (isAuthorized === false) {
                    res.status(403);
                    throw new Error('Not allowed to authorize users/organizations for project');
                }
                // ensure project exists
                return metadataStorage.getProject(projectId);
            })
            .then(function (/*projectData*/) {
                var rights = {
                    read: req.params.rights.indexOf('r') !== -1,
                    write: req.params.rights.indexOf('w') !== -1,
                    delete: req.params.rights.indexOf('d') !== -1
                };

                return authorizer.setAccessRights(req.params.userOrOrgId, projectId, rights, projectAuthParams);
            })
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user or org') > -1 || err.message.indexOf('no such project') > -1) {
                    res.status(404);
                }
                next(err);
            });
    });

    router.delete('/projects/:ownerId/:projectName/authorize/:userOrOrgId', function (req, res, next) {
        var projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName),
            projectAuthParams = {
                entityType: authorizer.ENTITY_TYPES.PROJECT
            };

        canUserAuthorizeProject(req)
            .then(function (isAuthorized) {
                if (isAuthorized === false) {
                    res.status(403);
                    throw new Error('Not allowed to authorize users/organizations for project');
                }
                // ensure project exists
                return metadataStorage.getProject(projectId);
            })
            .then(function (/*projectData*/) {
                return authorizer.setAccessRights(req.params.userOrOrgId, projectId,
                    {read: false, write: false, delete: false}, projectAuthParams);
            })
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such user or org') > -1 || err.message.indexOf('no such project') > -1) {
                    res.status(404);
                }
                next(err);
            });
    });

    router.post('/projects/:ownerId/:projectName/transfer/:userOrOrgId', function (req, res, next) {
        var newOwnerId = req.params.userOrOrgId,
            projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName),
            userId = getUserId(req),
            data = {
                newOwnerId: newOwnerId,
                projectId: projectId,
                username: userId
            };

        safeStorage.transferProject(data)
            .then(function (newProjectId) {
                return metadataStorage.getProject(newProjectId);
            })
            .then(function (projectData) {
                res.json(projectData);
            })
            .catch(function (err) {
                if (err.message.toLowerCase().indexOf('no such') > -1) {
                    res.status(404);
                } else if (err.message.toLowerCase().indexOf('not authorized') > -1) {
                    res.status(403);
                }
                next(err);
            });
    });

    router.get('/projects/:ownerId/:projectName/commits', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                before: Date.now(), // current time
                number: parseInt(req.query.n, 10) || 100 // asks for the last 100 commits from the time specified above
            };

        safeStorage.getCommits(data)
            .then(function (result) {
                res.json(result);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.get('/projects/:ownerId/:projectName/commits/:commitHash', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            commitHash = StorageUtil.getHashTaggedHash(req.params.commitHash),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                before: commitHash,
                number: 1
            };

        safeStorage.getCommits(data)
            .then(function (result) {
                res.json(result[0]);
            })
            .catch(function (err) {
                if (err.message.indexOf('not exist') > -1 || err.message.indexOf('Not authorized to read') > -1) {
                    err.status = 404;
                }
                next(err);
            });
    });

    paths = ['/projects/:ownerId/:projectName/commits/:commitHash/export',
        '/projects/:ownerId/:projectName/commits/:commitHash/export/*'];
    router.get(paths, ensureAuthenticated, function (req, res, next) {
        if (req.params[0] === undefined || req.params[0] === '') {
            exportProject(req, res, next);
        } else {
            exportModel(req, res, next);
        }
    });

    paths = ['/projects/:ownerId/:projectName/commits/:commitHash/tree',
        '/projects/:ownerId/:projectName/commits/:commitHash/tree/*'];
    router.get(paths, ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                req.params.projectName),
            commitHash = StorageUtil.getHashTaggedHash(req.params.commitHash);

        loadNodePathByCommitHash(userId, projectId, commitHash,
            '/' + (req.params[0] === undefined ? '' : req.params[0]))
            .then(function (nodeObj) {
                res.json(nodeObj);
            })
            .catch(function (err) {
                if (err.message.indexOf('not exist') > -1 || err.message.indexOf('Not authorized to read') > -1) {
                    err.status = 404;
                }
                next(err);
            });
    });

    router.get('/projects/:ownerId/:projectName/compare/:branchOrCommitA...:branchOrCommitB',
        ensureAuthenticated,
        function (req, res, next) {
            var userId = getUserId(req),
                projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                workerParameters = {
                    command: CONSTANTS.SERVER_WORKER_REQUESTS.DIFF,
                    projectId: projectId,
                    branchOrCommitA: req.params.branchOrCommitA,
                    branchOrCommitB: req.params.branchOrCommitB,
                };

            getNewJWToken(userId)
                .then(function (token) {
                    workerParameters.webgmeToken = token;
                    return Q.ninvoke(middlewareOpts.workerManager, 'request', workerParameters);
                })
                .then(function (result) {
                    res.json(result);
                })
                .catch(function (err) {
                    next(err);
                });
        });

    router.get('/projects/:ownerId/:projectName/branches', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName)
            };

        safeStorage.getBranches(data)
            .then(function (result) {
                res.json(result);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.get('/projects/:ownerId/:projectName/branches/:branchId', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                branchName: req.params.branchId
            };

        safeStorage.getLatestCommitData(data)
            .then(function (result) {
                res.json(result);
            })
            .catch(function (err) {
                if (err.message.indexOf('not exist') > -1) {
                    err.status = 404;
                }
                next(err);
            });
    });

    paths = ['/projects/:ownerId/:projectName/branches/:branchId/export',
        '/projects/:ownerId/:projectName/branches/:branchId/export/*'];
    router.get(paths, ensureAuthenticated, function (req, res, next) {
        if (req.params[0] === undefined || req.params[0] === '') {
            exportProject(req, res, next);
        } else {
            exportModel(req, res, next);
        }
    });

    router.patch('/projects/:ownerId/:projectName/branches/:branchId', function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                branchName: req.params.branchId,
                oldHash: req.body.oldHash,
                newHash: req.body.newHash
            };

        safeStorage.setBranchHash(data)
            .then(function () {
                res.sendStatus(200);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.put('/projects/:ownerId/:projectName/branches/:branchId', function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                branchName: req.params.branchId,
                hash: req.body.hash
            };

        safeStorage.createBranch(data)
            .then(function () {
                res.sendStatus(201);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.delete('/projects/:ownerId/:projectName/branches/:branchId', function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                branchName: req.params.branchId
            };

        safeStorage.deleteBranch(data)
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.get('/projects/:ownerId/:projectName/branches/:branchId/commits', ensureAuthenticated,
        function (req, res, next) {
            var userId = getUserId(req),
                data = {
                    username: userId,
                    projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                        req.params.projectName),
                    start: req.params.branchId,
                    number: parseInt(req.query.n, 10) || 100
                };

            safeStorage.getHistory(data)
                .then(function (result) {
                    res.json(result);
                })
                .catch(function (err) {
                    if (err.message.indexOf('not exist') > -1) {
                        err.status = 404;
                    }
                    next(err);
                });
        }
    );

    paths = ['/projects/:ownerId/:projectName/branches/:branchId/tree',
        '/projects/:ownerId/:projectName/branches/:branchId/tree/*'];
    router.get(paths, ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                req.params.projectName),
            data = {
                username: userId,
                projectId: projectId,
                branchName: req.params.branchId
            };

        safeStorage.getBranchHash(data)
            .then(function (branchHash) {
                if (!branchHash) {
                    throw new Error('Branch does not exist ' + req.params.branchId);
                }
                return loadNodePathByCommitHash(userId, projectId, branchHash,
                    '/' + (req.params[0] === undefined ? '' : req.params[0]));
            })
            .then(function (dataObj) {
                res.json(dataObj);
            })
            .catch(function (err) {
                if (err.message.indexOf('not exist') > -1 || err.message.indexOf('Not authorized to read') > -1) {
                    err.status = 404;
                }
                next(err);
            });
    });

    router.get('/projects/:ownerId/:projectName/tags', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName)
            };

        safeStorage.getTags(data)
            .then(function (result) {
                res.json(result);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.get('/projects/:ownerId/:projectName/tags/:tagId', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName)
            };

        safeStorage.getTags(data)
            .then(function (result) {
                if (result.hasOwnProperty(req.params.tagId) === true) {
                    res.redirect(req.baseUrl + '/projects/' + req.params.ownerId + '/' + req.params.projectName +
                        '/commits/' + result[req.params.tagId].substring(1));
                } else {
                    res.sendStatus(404);
                }
            })
            .catch(function (err) {
                next(err);
            });
    });

    paths = ['/projects/:ownerId/:projectName/tags/:tagId/export',
        '/projects/:ownerId/:projectName/tags/:tagId/export/*'];

    router.get(paths, ensureAuthenticated, function (req, res, next) {
        if (req.params[0] === undefined || req.params[0] === '') {
            exportProject(req, res, next);
        } else {
            exportModel(req, res, next);
        }
    });

    paths = ['/projects/:ownerId/:projectName/tags/:tagId/tree',
        '/projects/:ownerId/:projectName/tags/:tagId/tree/*'];
    router.get(paths, ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                req.params.projectName),
            data = {
                username: userId,
                projectId: projectId
            };

        safeStorage.getTags(data)
            .then(function (tags) {
                if (tags.hasOwnProperty(req.params.tagId) !== true) {
                    throw new Error('Tag does not exist ' + req.params.tagId);
                }
                return loadNodePathByCommitHash(userId, projectId, tags[req.params.tagId],
                    '/' + (req.params[0] === undefined ? '' : req.params[0]));
            })
            .then(function (dataObj) {
                res.json(dataObj);
            })
            .catch(function (err) {
                if (err.message.indexOf('not exist') > -1 || err.message.indexOf('Not authorized to read') > -1) {
                    err.status = 404;
                }
                next(err);
            });
    });

    router.put('/projects/:ownerId/:projectName/tags/:tagId', function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                tagName: req.params.tagId,
                commitHash: req.body.hash
            };

        safeStorage.createTag(data)
            .then(function () {
                res.sendStatus(201);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.patch('/projects/:ownerId/:projectName/tags/:tagId', function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                tagName: req.params.tagId,
                commitHash: req.body.hash
            };

        safeStorage.deleteTag(data)
            .then(function () {
                return safeStorage.createTag(data);
            })
            .then(function () {
                res.sendStatus(200);
            })
            .catch(function (err) {
                next(err);
            });
    });

    router.delete('/projects/:ownerId/:projectName/tags/:tagId', function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                tagName: req.params.tagId
            };

        safeStorage.deleteTag(data)
            .then(function () {
                res.sendStatus(204);
            })
            .catch(function (err) {
                next(err);
            });
    });

    // webHooks
    router.get('/projects/:ownerId/:projectName/hooks', ensureAuthenticated, function (req, res, next) {
        var projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName),
            userId = getUserId(req),
            projectAuthParams = {
                entityType: authorizer.ENTITY_TYPES.PROJECT
            };

        authorizer.getAccessRights(userId, projectId, projectAuthParams)
            .then(function (projectAccess) {

                if (projectAccess && projectAccess.read) {
                    return metadataStorage.getProjectHooks(projectId);
                }

                res.status(403);
                throw new Error('Not authorized to read project [' + projectId + ']');
            })
            .then(function (hooks) {
                res.json(hooks);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such project') > -1) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.get('/projects/:ownerId/:projectName/hooks/:hookId', ensureAuthenticated, function (req, res, next) {
        var projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName),
            userId = getUserId(req),
            projectAuthParams = {
                entityType: authorizer.ENTITY_TYPES.PROJECT
            };

        authorizer.getAccessRights(userId, projectId, projectAuthParams)
            .then(function (projectAccess) {

                if (projectAccess && projectAccess.read) {
                    return metadataStorage.getProjectHook(projectId, req.params.hookId);
                }

                res.status(403);
                throw new Error('Not authorized to read project [' + projectId + ']');
            })
            .then(function (hook) {
                res.json(hook);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such project') > -1 || err.message.indexOf('no such hook') > -1) {
                    res.status(404);
                }

                next(err);
            });
    });

    router.put('/projects/:ownerId/:projectName/hooks/:hookId', ensureAuthenticated, function (req, res, next) {
        var projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName),
            userId = getUserId(req),
            projectAuthParams = {
                entityType: authorizer.ENTITY_TYPES.PROJECT
            };

        authorizer.getAccessRights(userId, projectId, projectAuthParams)
            .then(function (projectAccess) {
                if (projectAccess && projectAccess.write) {
                    return metadataStorage.addProjectHook(projectId, req.params.hookId, req.body);
                }

                res.status(403);
                throw new Error('Not authorized to modify project [' + projectId + ']');
            })
            .then(function (hook) {
                res.json(hook);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such project') > -1) {
                    res.status(404);
                } else if (err.message.indexOf('hook already exists') > -1) {
                    res.status(403);
                }
                next(err);
            });
    });

    router.patch('/projects/:ownerId/:projectName/hooks/:hookId', ensureAuthenticated, function (req, res, next) {
        var projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName),
            userId = getUserId(req),
            projectAuthParams = {
                entityType: authorizer.ENTITY_TYPES.PROJECT
            };

        authorizer.getAccessRights(userId, projectId, projectAuthParams)
            .then(function (projectAccess) {

                if (projectAccess && projectAccess.write) {
                    return metadataStorage.updateProjectHook(projectId, req.params.hookId, req.body);
                }

                res.status(403);
                throw new Error('Not authorized to modify project [' + projectId + ']');
            })
            .then(function (hook) {
                res.json(hook);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such project') > -1 || err.message.indexOf('no such hook') > -1) {
                    res.status(404);
                }
                next(err);
            });
    });

    router.delete('/projects/:ownerId/:projectName/hooks/:hookId', ensureAuthenticated, function (req, res, next) {
        var projectId = StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId, req.params.projectName),
            userId = getUserId(req),
            projectAuthParams = {
                entityType: authorizer.ENTITY_TYPES.PROJECT
            };

        authorizer.getAccessRights(userId, projectId, projectAuthParams)
            .then(function (projectAccess) {

                if (projectAccess && projectAccess.write) {
                    return metadataStorage.removeProjectHook(projectId, req.params.hookId);
                }

                res.status(403);
                throw new Error('Not authorized to modify project [' + projectId + ']');
            })
            .then(function (hooks) {
                res.json(hooks);
            })
            .catch(function (err) {
                if (err.message.indexOf('no such project') > -1 || err.message.indexOf('no such hook') > -1) {
                    res.status(404);
                }
                next(err);
            });
    });

    // squash
    router.put('/projects/:ownerId/:projectName/squash', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            data = {
                username: userId,
                projectId: StorageUtil.getProjectIdFromOwnerIdAndProjectName(req.params.ownerId,
                    req.params.projectName),
                fromCommit: req.body.fromCommit,
                toCommitOrBranch: req.body.toCommitOrBranch,
                message: req.body.message
            };

        safeStorage.squashCommits(data)
            .then(function () {
                res.sendStatus(201);
            })
            .catch(function (err) {
                next(err);
            });
    });

    logger.debug('creating list asset rules');

    router.get('/decorators', ensureAuthenticated, function (req, res) {
        var result = webgmeUtils.getComponentNames(gmeConfig.visualization.decoratorPaths);
        logger.debug('/decorators', {metadata: result});
        res.send(result);
    });

    // Plugins
    // TODO: These variables should not be defined here.
    // TODO: runningPlugins should be stored in a database.
    var runningPlugins = {};
    var PLUGIN_CONSTANTS = {
        RUNNING: 'RUNNING',
        FINISHED: 'FINISHED', // Could still be that result.success=false.
        ERROR: 'ERROR'
    };

    function getPlugin(name) {
        var pluginPath = 'plugin/' + name + '/' + name + '/' + name,
            Plugin,
            error,
            plugin;

        logger.debug('Configuration requested for plugin at', pluginPath);
        try {
            Plugin = requireJS(pluginPath);
        } catch (err) {
            error = err;
        }

        // This is weird, the second time requirejs simply returns with undefined.
        if (Plugin) {
            plugin = new Plugin();
            return plugin;
        } else {
            return error || new Error('Plugin is not available from: ' + pluginPath);
        }

    }

    router.get('/plugins', ensureAuthenticated, function (req, res) {
        var result = webgmeUtils.getComponentNames(gmeConfig.plugin.basePaths);
        logger.debug('/plugins', {metadata: result});
        res.send(result);
    });

    router.get('/plugins/metadata', ensureAuthenticated, function (req, res, next) {
        var pluginNames = webgmeUtils.getComponentNames(gmeConfig.plugin.basePaths),
            promises = [],
            basePath,
            i;

        for (i = 0; i < pluginNames.length; i += 1) {
            basePath = webgmeUtils.getBasePathByName(pluginNames[i], gmeConfig.plugin.basePaths);
            promises.push(Q.nfcall(fs.readFile, path.join(basePath, pluginNames[i], 'metadata.json'), 'utf8'));
        }

        Q.allSettled(promises)
            .then(function (fileRes) {
                var result = {};
                for (i = 0; i < fileRes.length; i += 1) {
                    if (fileRes[i].state === 'fulfilled') {
                        try {
                            result[pluginNames[i]] = JSON.parse(fileRes[i].value);
                        } catch (e) {
                            logger.error('Parsing metadata.json at "' +
                                path.join(basePath, pluginNames[i], 'metadata.json') + '", failed with error:\n' +
                                e.stack);
                        }
                    } else if (fileRes[i].state === 'rejected') {
                        if (fileRes[i].reason.code === 'ENOENT') {
                            logger.error('Plugin does not have a metadata.json', pluginNames[i]);
                        } else {
                            logger.error(fileRes[i].reason);
                        }
                    } else {
                        logger.error(new Error('Unknown q promise state'));
                    }
                }

                res.json(result);
            })
            .catch(next);
    });

    router.get(['/plugins/:pluginId/metadata', '/plugin/:pluginId/metadata'],
        ensureAuthenticated, function (req, res, next) {
            var basePath = webgmeUtils.getBasePathByName(req.params.pluginId, gmeConfig.plugin.basePaths);

            if (!basePath) {
                res.sendStatus(404);
                return;
            }

            Q.nfcall(fs.readFile, path.join(basePath, req.params.pluginId, 'metadata.json'), 'utf8')
                .then(function (content) {
                    res.json(JSON.parse(content));
                })
                .catch(function (err) {
                    if (err.code === 'ENOENT') {
                        res.sendStatus(404);
                    } else {
                        next(err);
                    }
                });
        });

    router.get(['/plugins/:pluginId/config', '/plugin/:pluginId/config'],
        ensureAuthenticated, function (req, res) {
            var plugin = getPlugin(req.params.pluginId);
            // TODO: In next release this should use metadata
            if (plugin instanceof Error) {
                logger.error(plugin);
                res.sendStatus(404);
            } else {
                res.send(plugin.getDefaultConfig());
            }
        });

    router.get(['/plugins/:pluginId/configStructure', '/plugin/:pluginId/configStructure'],
        ensureAuthenticated, function (req, res) {
            var plugin = getPlugin(req.params.pluginId);
            // TODO: In next release this should use metadata
            if (plugin instanceof Error) {
                logger.error(plugin);
                res.sendStatus(404);
            } else {
                res.send(plugin.getConfigStructure());
            }
        });

    function getPluginContext(req) {
        var userId = getUserId(req),
            pluginContext = {
                managerConfig: {
                    project: req.body.projectId,
                    branchName: req.body.branchName,
                    commit: req.body.commitHash,
                    activeNode: req.body.activeNode,
                    activeSelection: req.body.activeSelection,
                },
                pluginConfig: req.body.pluginConfig
            },
            workerParameters = {
                command: CONSTANTS.SERVER_WORKER_REQUESTS.EXECUTE_PLUGIN,
                name: req.params.pluginId,
                context: pluginContext
            };

        return getNewJWToken(userId)
            .then(function (token) {
                workerParameters.webgmeToken = token;

                return workerParameters;
            });
    }

    router.post(['/plugins/:pluginId/execute', '/plugin/:pluginId/execute'],
        function (req, res, next) {
            var resultId = GUID();

            getPluginContext(req)
                .then(function (context) {

                    middlewareOpts.workerManager.request(context, function (err, result) {
                        if (err) {
                            runningPlugins[resultId].status = PLUGIN_CONSTANTS.ERROR;
                            runningPlugins[resultId].err = err.message;
                        } else {
                            runningPlugins[resultId].status = PLUGIN_CONSTANTS.FINISHED;
                        }

                        runningPlugins[resultId].result = result;
                        runningPlugins[resultId].timeoutId = setTimeout(function () {
                            logger.warn('Plugin result timed out: ' + gmeConfig.plugin.serverResultTimeout + '[ms]',
                                resultId);
                            delete runningPlugins[resultId];
                        }, gmeConfig.plugin.serverResultTimeout);
                    });

                    runningPlugins[resultId] = {
                        status: PLUGIN_CONSTANTS.RUNNING,
                        //timeoutId: will be added after plugin finished
                        //result: null,
                        //error: null
                    };

                    res.send({resultId: resultId});
                })
                .catch(next);
        });

    router.post(['/plugins/:pluginId/run', '/plugin/:pluginId/run'],
        function (req, res, next) {
            getPluginContext(req)
                .then(function (context) {

                    middlewareOpts.workerManager.request(context, function (err, result) {
                        if (err && !result) {
                            next(err);
                        } else {
                            res.send(result);
                        }
                    });
                })
                .catch(next);
        });

    router.get(['/plugins/:pluginId/results/:resultId', '/plugin/:pluginId/results/:resultId'],
        ensureAuthenticated, function (req, res) {
            var pluginExecution = runningPlugins[req.params.resultId];
            logger.debug('Plugin-result request for ', req.params.pluginId, req.params.resultId);
            if (pluginExecution) {
                if (pluginExecution.status === PLUGIN_CONSTANTS.RUNNING) {
                    res.send(pluginExecution);
                } else {
                    // Remove the pluginExecution when it has finished or an error occurred.
                    clearTimeout(pluginExecution.timeoutId);
                    pluginExecution.timeoutId = undefined;
                    delete runningPlugins[req.params.resultId];
                    res.send(pluginExecution);
                }
            } else {
                res.sendStatus(404);
            }
        });

    // AddOns
    router.get(['/add-ons', '/addOns'], ensureAuthenticated, function (req, res) {
        var result = webgmeUtils.getComponentNames(gmeConfig.addOn.basePaths);
        logger.debug('/addOns', {metadata: result});
        res.send(result);
    });

    //router.get('/addOns/:addOnId/queryParams', ensureAuthenticated, function (req, res) {});
    //router.get('/addOns/:addOnId/queryParamsStructure', ensureAuthenticated, function (req, res) {});
    //router.post('/addOns/:addOnId/query', ensureAuthenticated, function (req, res) {});

    router.get('/seeds', ensureAuthenticated, function (req, res, next) {
        webgmeUtils.getSeedDictionary(gmeConfig)
            .then(function (seedDictionary) {
                logger.debug('/seeds', {metadata: seedDictionary});
                res.send(Object.keys(seedDictionary));
            })
            .catch(next);
    });

    router.get('/seeds/:seedName', ensureAuthenticated, function (req, res, next) {
        var seedName = req.params.seedName,
            userId = getUserId(req),
            webgmeToken;

        webgmeUtils.getSeedDictionary(gmeConfig)
            .then(function (seedDictionary) {
                if (seedDictionary.hasOwnProperty(seedName) === false) {
                    res.status(404);
                    throw new Error('Requested seed [' + seedName + '], does not exist among: '
                        + Object.keys(seedDictionary));
                } else if (seedToBlobHash.hasOwnProperty(seedName)) {
                    // It was already requested and exists on the blob-storage.
                    return seedToBlobHash[seedName];
                } else {
                    // Seed exists but hasn't been uploaded to blob-storage.
                    return getNewJWToken(userId)
                        .then(function (token) {
                            webgmeToken = token;

                            return Q.ninvoke(fs, 'readFile', seedDictionary[seedName]);
                        })
                        .then(function (content) {
                            var blobClient = new BlobClientClass({
                                serverPort: gmeConfig.server.port,
                                httpsecure: false,
                                server: '127.0.0.1',
                                webgmeToken: webgmeToken,
                                logger: logger.fork('BlobClient')
                            });

                            return blobClient.putFile(seedName + '.webgmex', content);
                        });
                }
            })
            .then(function (blobHash) {
                // TODO: Consider supporting metadata of seeds and parse and return it here..
                res.json({
                    blobHash: blobHash
                });
            })
            .catch(next);
    });

    // FIXME: This should be async
    function getVisualizersDescriptor() {
        //we merge the contents of the CONFIG.visualizerDescriptors by id
        var indexById = function (objectArray, id) {
                var i,
                    index = -1;
                for (i = 0; i < objectArray.length; i++) {
                    if (objectArray[i].id === id) {
                        index = i;
                        break;
                    }
                }

                return index;
            },
            getVisualizerDescriptor = function (path) {
                try {
                    var descriptor = fs.readFileSync(path, 'utf-8');
                    descriptor = JSON.parse(descriptor);
                    return descriptor;
                } catch (e) {
                    //we do not care much of the error just give back an empty array
                    logger.error(e);
                    return [];
                }
            },
            allVisualizersDescriptor = [],
            i, j;

        for (i = 0; i < gmeConfig.visualization.visualizerDescriptors.length; i++) {
            var descriptor = getVisualizerDescriptor(gmeConfig.visualization.visualizerDescriptors[i]);
            if (descriptor.length) {
                for (j = 0; j < descriptor.length; j++) {
                    var index = indexById(allVisualizersDescriptor, descriptor[j].id);
                    if (index !== -1) {
                        allVisualizersDescriptor[index] = descriptor[j];
                    } else {
                        allVisualizersDescriptor.push(descriptor[j]);
                    }
                }
            }
        }
        return allVisualizersDescriptor.sort(function (a, b) {
            if (a.id < b.id) {
                return -1;
            }
            if (a.id > b.id) {
                return 1;
            }
            return 0;
        });
    }

    // FIXME: this should be JSON
    router.get('/visualizers', ensureAuthenticated, function (req, res) {
        var result = getVisualizersDescriptor();
        logger.debug('/visualizers', {metadata: result});
        res.send(result);
    });

    router.get('/status', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req),
            result = {
                addresses: middlewareOpts.server.getAddresses(),
                addOns: null,
                serverWorkers: null,
                sockets: middlewareOpts.server.getSocketsInfo(),
                webSockets: null,
            };

        gmeAuth.getUser(userId)
            .then(function (userData) {
                if (gmeConfig.authentication.enable && !userData.siteAdmin) {
                    res.status(403);
                    throw new Error('site admin role is required for this operation');
                }

                result.webSockets = middlewareOpts.webSocket.getStatus();

                if (gmeConfig.addOn.enable) {
                    return middlewareOpts.addOnEventPropagator.getStatus({});
                } else {
                    return null;
                }
            })
            .then(function (addOnStatus) {
                result.addOns = addOnStatus;

                return Q.ninvoke(middlewareOpts.workerManager, 'getStatus');
            })
            .then(function (serverWorkersStatus) {
                result.serverWorkers = serverWorkersStatus;

                res.json(result);
            })
            .catch(next);
    });

    router.get(['/status/add-ons', '/addOnStatus'], ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req);

        if (gmeConfig.addOn.enable) {
            gmeAuth.getUser(userId)
                .then(function (userData) {
                    if (gmeConfig.authentication.enable && !userData.siteAdmin) {
                        res.status(403);
                        throw new Error('site admin role is required for this operation');
                    }

                    return middlewareOpts.addOnEventPropagator.getStatus({});
                })
                .then(function (status) {
                    res.json(status);
                })
                .catch(next);
        } else {
            res.sendStatus(404);
        }
    });

    router.get('/status/server-workers', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req);

        gmeAuth.getUser(userId)
            .then(function (userData) {
                if (gmeConfig.authentication.enable && !userData.siteAdmin) {
                    res.status(403);
                    throw new Error('site admin role is required for this operation');
                }

                return Q.ninvoke(middlewareOpts.workerManager, 'getStatus');
            })
            .then(function (status) {
                res.json(status);
            })
            .catch(next);
    });

    router.get('/status/web-sockets', ensureAuthenticated, function (req, res, next) {
        var userId = getUserId(req);

        gmeAuth.getUser(userId)
            .then(function (userData) {
                if (gmeConfig.authentication.enable && !userData.siteAdmin) {
                    res.status(403);
                    throw new Error('site admin role is required for this operation');
                }

                res.json(middlewareOpts.webSocket.getStatus());
            })
            .catch(next);
    });

    router.use('*', function (req, res, next) {
        res.status(404);
        next(new Error());
    });

    // error handling (NOTE: it is important to have this function signature with 4 arguments!)
    // eslint-disable-next-line
    router.use(function (err, req, res, next) {
        var errorMessage = {
                401: 'Authentication required',
                403: 'Forbidden',
                404: 'Not found'
            },
            message = err.message ? err.message : err;

        if (res.statusCode === 200) {
            if (err.message.indexOf('Not authorized') > -1) {
                err.status = err.status || 403;
            }
            res.status(err.status || 500);
        }

        if (errorMessage.hasOwnProperty(res.statusCode)) {
            message = errorMessage[res.statusCode];
        }

        if (res.statusCode === 500) {
            logger.error(err);
        }

        res.json({
            message: message,
            documentation_url: '',
            error: err.message ? err.message : err // FIXME: only in dev mode
        });
    });

    // attach the api to the requested path
    logger.debug('Supported api path: ' + versionedAPIPath);
    app.use(versionedAPIPath, router);

    logger.debug('Latest api path: ' + latestAPIPath);
    app.use(latestAPIPath, router);

    return Q();
}
982740
function buildWebhookEvent(options) {
  const webhookName = options.name + 'Webhook';
  let webhook = {
    Resources: {},
    Outputs: {}
  };

  validteWebhookOptions(options);

  webhook.Resources[webhookName + 'Resource'] = {
    Type: 'AWS::ApiGateway::Resource',
    Properties: {
      ParentId: cf.getAtt(webhookName + 'ApiGateway', 'RootResourceId'),
      RestApiId: cf.ref(webhookName + 'ApiGateway'),
      PathPart: options.name.toLowerCase()
    }
  };

  if (options.eventSources.webhook.method) {
    if (!options.eventSources.webhook.methodResponses) {
      options.eventSources.webhook.methodResponses = [
        {
          StatusCode: '200',
          ResponseModels: {
            'application/json': 'Empty'
          }
        },
        {
          StatusCode: '500',
          ResponseModels: {
            'application/json': 'Empty'
          }
        }
      ];
    } else if (!Array.isArray(options.eventSources.webhook.methodResponses)) {
      throw new Error('Webhook method responses is not an array');
    }

    if (!options.eventSources.webhook.integration) {
      options.eventSources.webhook.integration = {};
    }

    // sets safe defaults for missing parameters if integration object is passed
    options.eventSources.webhook.integration.Type = options.eventSources.webhook.integration.Type ? options.eventSources.webhook.integration.Type : 'AWS';
    options.eventSources.webhook.integration.IntegrationHttpMethod = options.eventSources.webhook.integration.IntegrationHttpMethod ? options.eventSources.webhook.integration.IntegrationHttpMethod : 'POST';
    options.eventSources.webhook.integration.Uri = options.eventSources.webhook.integration.Uri ? options.eventSources.webhook.integration.Uri : cf.join(['arn:aws:apigateway:', cf.region, ':lambda:path/2015-03-31/functions/', cf.getAtt(options.name, 'Arn'), '/invocations']);
    options.eventSources.webhook.integration.IntegrationResponses = options.eventSources.webhook.integration.IntegrationResponses ? options.eventSources.webhook.integration.IntegrationResponses : [{ StatusCode: '200' }, { StatusCode: '500', SelectionPattern: '^(?i)(error|exception).*'}];

    webhook.Resources[webhookName + 'Method'] = {
      Type: 'AWS::ApiGateway::Method',
      Properties: {
        RestApiId: cf.ref(webhookName + 'ApiGateway'),
        ResourceId: cf.ref(webhookName + 'Resource'),
        AuthorizationType: 'None',
        HttpMethod: options.eventSources.webhook.method.toUpperCase(),
        MethodResponses: options.eventSources.webhook.methodResponses,
        Integration: options.eventSources.webhook.integration
      }
    };
  }

  webhook.Resources[webhookName + 'Permission'] = {
    Type: 'AWS::Lambda::Permission',
    Properties: {
      FunctionName: cf.getAtt(options.name, 'Arn'),
      Action: 'lambda:InvokeFunction',
      Principal: 'apigateway.amazonaws.com',
      SourceArn: cf.join(['arn:aws:execute-api:', cf.region, ':', cf.accountId, ':', cf.ref(webhookName + 'ApiGateway'),'/*'])
    }
  };

  webhook.Resources[webhookName + 'ApiGateway'] = {
    Type: 'AWS::ApiGateway::RestApi',
    Properties: {
      Name: cf.stackName,
      FailOnWarnings: 'true'
    }
  };

  // randomizes deployment name so that code can be redeployed over an existing stage
  let apiDeploymentRandom = getApiDeploymentName();

  webhook.Resources[webhookName + 'ApiKey'] = {
    Type: 'AWS::ApiGateway::ApiKey',
    DependsOn: webhookName + apiDeploymentRandom,
    Properties: {
      Name: cf.stackName,
      Enabled: 'true',
      StageKeys: [
        {
          RestApiId: cf.ref(webhookName + 'ApiGateway'),
          StageName: 'prod'
        }
      ]
    }
  };

  webhook.Resources[webhookName + apiDeploymentRandom] = {
    Type: 'AWS::ApiGateway::Deployment',
    DependsOn: webhookName + 'Method',
    Properties: {
      RestApiId: cf.ref(webhookName + 'ApiGateway'),
      StageName: 'prod'
    }
  };

  webhook.Resources[webhookName + 'ApiLatencyAlarm'] = {
    Type: 'AWS::CloudWatch::Alarm',
    Properties: {
      EvaluationPeriods: '5',
      Statistic: 'Sum',
      Threshold: '4',
      AlarmDescription: 'https://github.com/mapbox/lambda-cfn/blob/master/alarms.md#ApiLatencyAlarm',
      Period: '60',
      AlarmActions: [
        cf.ref('ServiceAlarmSNSTopic')
      ],
      Namespace: 'AWS/ApiGateway',
      Dimensions: [
        {
          Name: 'APIName',
          Value: cf.stackName
        }
      ],
      ComparisonOperator: 'GreaterThanThreshold',
      MetricName: 'Latency'
    }
  };

  webhook.Resources[webhookName + 'Api4xxAlarm'] = {
    Type: 'AWS::CloudWatch::Alarm',
    Properties: {
      EvaluationPeriods: '5',
      Statistic: 'Sum',
      Threshold: '100',
      AlarmDescription: 'https://github.com/mapbox/lambda-cfn/blob/master/alarms.md#Api4xxAlarm',
      Period: '60',
      AlarmActions: [ cf.ref('ServiceAlarmSNSTopic') ],
      Namespace: 'AWS/ApiGateway',
      Dimensions: [
        {
          Name: 'APIName',
          Value: cf.stackName
        }
      ],
      ComparisonOperator: 'GreaterThanThreshold',
      MetricName: '4xxError'
    }
  };

  webhook.Resources[webhookName + 'ApiCountAlarm'] = {
    Type: 'AWS::CloudWatch::Alarm',
    Properties: {
      EvaluationPeriods: '5',
      Statistic: 'Sum',
      Threshold: '10000',
      AlarmDescription: 'https://github.com/mapbox/lambda-cfn/blob/master/alarms.md#ApiCountAlarm',
      Period: '60',
      AlarmActions: [
        cf.ref('ServiceAlarmSNSTopic')
      ],
      Namespace: 'AWS/ApiGateway',
      Dimensions: [
        {
          Name: 'APIName',
          Value: cf.stackName
        }
      ],
      ComparisonOperator: 'GreaterThanThreshold',
      MetricName: 'Count'
    }
  };

  webhook.Resources[webhookName + 'Permission'] = {
    Type: 'AWS::Lambda::Permission',
    Properties: {
      FunctionName: cf.getAtt(options.name, 'Arn'),
      Action: 'lambda:InvokeFunction',
      Principal: 'apigateway.amazonaws.com',
      SourceArn: cf.join(['arn:aws:execute-api:', cf.region, ':', cf.accountId, ':', cf.ref(webhookName + 'ApiGateway'), '/*'])
    }
  };

  webhook.Outputs[webhookName + 'APIEndpoint'] = {
    Value: cf.join(['https://', cf.ref(webhookName + 'ApiGateway'), '.execute-api.', cf.region, '.amazonaws.com/prod/', options.name.toLowerCase()])
  };

  if (options.eventSources.webhook.apiKey) {
    webhook.Resources[webhookName + 'Method'].Properties.ApiKeyRequired = 'true';
    webhook.Outputs[webhookName + 'ApiKey'] = {
      Value: cf.ref(webhookName + 'ApiKey')
    };
  }

  return webhook;
}
1329924
def make_request
      create_authorization

      options = {}
      options[:header] = authorization.headers.merge(
        'Authorization' => authorization.authorization_header
      )
      options[:query] = query if query.any?
      options[:body] = form_body if body

      http_response = @httpclient.request(method, url, options)
      @response = AwsResponse.new(self, http_response)

      freeze

      @response
    end
379659
function buildRoute(
  name,
  position,
  { NatGatewayId = null, GatewayId = null, InstanceId = null } = {},
) {
  const route = {
    Type: 'AWS::EC2::Route',
    Properties: {
      DestinationCidrBlock: '0.0.0.0/0',
      RouteTableId: {
        Ref: `${name}RouteTable${position}`,
      },
    },
  };

  if (NatGatewayId) {
    route.Properties.NatGatewayId = {
      Ref: NatGatewayId,
    };
  } else if (GatewayId) {
    route.Properties.GatewayId = {
      Ref: GatewayId,
    };
  } else if (InstanceId) {
    route.Properties.InstanceId = {
      Ref: InstanceId,
    };
  } else {
    throw new Error(
      'Unable to create route: either NatGatewayId, GatewayId or InstanceId must be provided',
    );
  }

  const cfName = `${name}Route${position}`;
  return {
    [cfName]: route,
  };
}
290096
def publish_apis(self, path='doc'):
        

        assert path

        if not self.apis:
            raise Exception("You must call .load_apis() before .publish_apis()")

        # Infer the live host url from pym-config.yaml
        proto = 'http'
        if hasattr(get_config(), 'aws_cert_arn'):
            proto = 'https'

        live_host = "%s://%s" % (proto, get_config().live_host)

        # Allow cross-origin calls
        CORS(self.app, resources={r"/%s/*" % path: {"origins": "*"}})

        # Add routes to serve api specs and redirect to petstore ui for each one
        for api_name, api_path in self.apis.items():

            api_filename = os.path.basename(api_path)
            log.info("Publishing api %s at /%s/%s" % (api_name, path, api_name))

            def redirect_to_petstore(live_host, api_filename):
                def f():
                    url = 'http://petstore.swagger.io/?url=%s/%s/%s' % (live_host, path, api_filename)
                    log.info("Redirecting to %s" % url)
                    return redirect(url, code=302)
                return f

            def serve_api_spec(api_path):
                def f():
                    with open(api_path, 'r') as f:
                        spec = f.read()
                        log.info("Serving %s" % api_path)
                        return Response(spec, mimetype='text/plain')
                return f

            self.app.add_url_rule('/%s/%s' % (path, api_name), str(uuid4()), redirect_to_petstore(live_host, api_filename))
            self.app.add_url_rule('/%s/%s' % (path, api_filename), str(uuid4()), serve_api_spec(api_path))

        return self