Skip to content

Commit

Permalink
Merge pull request particle-iot#26 from AntonPuko/oauth
Browse files Browse the repository at this point in the history
move app setup to app.js; seperate test settings
  • Loading branch information
jlkalberer authored Dec 7, 2016
2 parents b4d5423 + 4babcd8 commit 6ee27e7
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 119 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"prebuild": "npm run build:clean",
"start": "nodemon --exec babel-node ./src/main.js --watch src --watch ../spark-protocol/lib --ignore core_keys --ignore users --ignore webhooks",
"start:prod": "npm run build && node ./build/main.js",
"test": "NODE_ENV=test ava",
"test:watch": "NODE_ENV=test ava --watch"
"test": "ava",
"test:watch": "ava --watch"
},
"ava": {
"verbose": true,
Expand Down
74 changes: 74 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// @flow

import type {
$Application,
$Request,
$Response,
Middleware,
NextFunction,
} from 'express';
import type { Settings } from './types';

import bodyParser from 'body-parser';
import express from 'express';
import morgan from 'morgan';

import api from './views/api_v1';
import eventsV1 from './views/EventViews001';

// Routing
import routeConfig from './lib/RouteConfig';
import UsersController from './lib/controllers/UsersController';
import WebhookController from './lib/controllers/WebhookController';

export default (settings: Settings): $Application => {
const app = express();

const setCORSHeaders: Middleware = (
request: $Request,
response: $Response,
next: NextFunction,
): mixed => {
if (request.method === 'OPTIONS') {
response.set({
'Access-Control-Allow-Headers':
'X-Requested-With, Content-Type, Accept, Authorization',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Origin': '*',
'Access-Control-Max-Age': '300',
});
return response.sendStatus(204);
}
response.set({ 'Access-Control-Allow-Origin': '*' });
return next();
};

if (settings.logRequests) {
app.use(morgan('combined'));
}

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(setCORSHeaders);

routeConfig(
app,
[
new UsersController(settings.usersRepository),
new WebhookController(settings.webhookRepository),
],
settings,
);

eventsV1.loadViews(app);
api.loadViews(app);

const noRouteMiddleware: Middleware = (
request: $Request,
response: $Response,
): mixed => response.sendStatus(404);

app.use(noRouteMiddleware);

return app;
};
10 changes: 6 additions & 4 deletions src/lib/RouteConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import type {
Middleware,
NextFunction,
} from 'express';
import type { Settings } from '../types';
import type Controller from './controllers/Controller';

import OAuthModel from './OAuthModel';
import OAuthServer from 'express-oauth-server';
import settings from '../settings';

// TODO fix flow errors, come up with better name;
const maybe = (middleware: Middleware, condition: boolean): Middleware =>
Expand All @@ -34,9 +34,11 @@ const injectUserMiddleware = (): Middleware =>
};


export default (app: $Application, controllers: Array<Controller>) => {
// TODO figure out, may be I need to add oauth to app.oauth or app.locals.oauth
// to be able to inject user object in request.
export default (
app: $Application,
controllers: Array<Controller>,
settings: Settings,
) => {
const oauth = new OAuthServer({
accessTokenLifetime: settings.accessTokenLifetime,
allowBearerTokensInQueryString: true,
Expand Down
103 changes: 9 additions & 94 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,14 @@
/**
* Copyright (C) 2013-2014 Spark Labs, Inc. All rights reserved. - https://www.spark.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* You can download the source here: https://github.com/spark/spark-server
*
* @flow
*
*/

import type {
$Request,
$Response,
Middleware,
NextFunction,
} from 'express';

import bodyParser from 'body-parser';
import express from 'express';
import morgan from 'morgan';
import { DeviceServer } from 'spark-protocol';
import settings from './settings';

import utilities from './lib/utilities';
import logger from './lib/logger';

import api from './views/api_v1';
import eventsV1 from './views/EventViews001';

// Routing
import routeConfig from './lib/RouteConfig';
import UsersController from './lib/controllers/UsersController';
import WebhookController from './lib/controllers/WebhookController';
// @flow

import {
DeviceAttributeFileRepository,
DeviceServer,
ServerConfigFileRepository,
} from 'spark-protocol';
import utilities from './lib/utilities';
import logger from './lib/logger';
import createApp from './app';
import settings from './settings';

const NODE_PORT = process.env.NODE_PORT || 8080;

Expand All @@ -64,53 +26,7 @@ process.on('uncaughtException', (exception: Error) => {
logger.error(`Caught exception: ${exception.toString()} ${exception.stack}`);
});

export const app = express();

const setCORSHeaders: Middleware = (
request: $Request,
response: $Response,
next: NextFunction,
): mixed => {
if (request.method === 'OPTIONS') {
response.set({
'Access-Control-Allow-Headers':
'X-Requested-With, Content-Type, Accept, Authorization',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Origin': '*',
'Access-Control-Max-Age': '300',
});
return response.sendStatus(204);
}
response.set({ 'Access-Control-Allow-Origin': '*' });
return next();
};

if (process.env.NODE_ENV !== 'test') {
app.use(morgan('combined'));
}

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(setCORSHeaders);

routeConfig(app, [
new UsersController(settings.usersRepository),
new WebhookController(settings.webhookRepository),
]);

eventsV1.loadViews(app);
api.loadViews(app);

const noRouteMiddleware: Middleware = (
request: $Request,
response: $Response,
): mixed => response.sendStatus(404);

app.use(noRouteMiddleware);


console.log(`Starting server, listening on ${NODE_PORT}`);
app.listen(NODE_PORT);
const app = createApp(settings);

const deviceServer = new DeviceServer({
coreKeysDir: settings.coreKeysDir,
Expand All @@ -127,11 +43,10 @@ const deviceServer = new DeviceServer({
serverKeyPassFile: settings.serverKeyPassFile,
});

// TODO wny do we need next line? (Anton Puko)
global.server = deviceServer;
deviceServer.start();

app.listen(NODE_PORT, (): void => console.log(`express server started on port ${NODE_PORT}`));

utilities.getIPAddresses().forEach((ip: string): void =>
console.log(`Your server IP address is: ${ip}`),
console.log(`Your device server IP address is: ${ip}`),
);
19 changes: 3 additions & 16 deletions src/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,18 @@ import path from 'path';
import WebhookFileRepository from './lib/repository/WebhookFileRepository';
import UsersFileRepository from './lib/repository/UsersFileRepository';

const settings = {
export default {
accessTokenLifetime: 7776000, // 90 days,
baseUrl: 'http://localhost',
coreFlashTimeout: 90000,
coreKeysDir: path.join(__dirname, 'core_keys'),
coreRequestTimeout: 30000,
coreSignalTimeout: 30000,
isCoreOnlineTimeout: 2000,
loginRoute: '/oauth/token',
logRequests: true,
maxHooksPerDevice: 10,
maxHooksPerUser: 20,
loginRoute: '/oauth/token',
webhookRepository: new WebhookFileRepository(
path.join(__dirname, 'webhooks'),
),
Expand All @@ -52,17 +53,3 @@ const settings = {
PORT: 5683,
HOST: "localhost",
};

const testSettings = {
...settings,
coreKeysDir: path.join(__dirname, '../test/__test_data__/core_keys'),
usersRepository: new UsersFileRepository(
path.join(__dirname, '../test/__test_data__/users'),
),
webhookRepository: new WebhookFileRepository(
path.join(__dirname, '../test/__test_data__/webhooks'),
),
};

export default process.env.NODE_ENV === 'test' ? testSettings : settings;

22 changes: 22 additions & 0 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,25 @@ export type Repository<TModel> = {
getById: (id: string) => TModel,
update: (id: string, model: TModel) => TModel,
};

export type Settings = {
accessTokenLifetime: number,
baseUrl: string,
coreFlashTimeout: number,
coreKeysDir: string,
coreRequestTimeout: number,
coreSignalTimeout: number,
cryptoSalt: string,
HOST: string,
isCoreOnlineTimeout: number,
loginRoute: string,
logRequests: boolean,
maxHooksPerDevice: number,
maxHooksPerUser: number,
PORT: number,
serverKeyFile: string,
serverKeyPassEnvVar: ?string,
serverKeyPassFile: ?string,
usersRepository: Repository<*>,
webhookRepository: Repository<*>,
};
5 changes: 2 additions & 3 deletions test/UsersController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import type { TokenObject } from '../src/types';
import test from 'ava';
import request from 'supertest-as-promised';
import ouathClients from '../src/oauthClients.json';

import { app } from '../src/main';
import settings from '../src/settings';
import app from './testApp';
import settings from './settings';

const USER_CREDENTIALS = {
password: 'password',
Expand Down
36 changes: 36 additions & 0 deletions test/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// @flow

import path from 'path';
import WebhookFileRepository from '../src/lib/repository/WebhookFileRepository';
import UsersFileRepository from '../src/lib/repository/UsersFileRepository';

export default {
accessTokenLifetime: 7776000, // 90 days,
baseUrl: 'http://localhost',
coreFlashTimeout: 90000,
coreKeysDir: path.join(__dirname, '__test_data__/core_keys'),
coreRequestTimeout: 30000,
coreSignalTimeout: 30000,
isCoreOnlineTimeout: 2000,
loginRoute: '/oauth/token',
logRequests: false,
maxHooksPerDevice: 10,
maxHooksPerUser: 20,
usersRepository: new UsersFileRepository(
path.join(__dirname, '__test_data__/users'),
),
webhookRepository: new WebhookFileRepository(
path.join(__dirname, '__test_data__/webhooks'),
),

/**
* Your server crypto keys!
*/
cryptoSalt: 'aes-128-cbc',
serverKeyFile: "default_key.pem",
serverKeyPassFile: null,
serverKeyPassEnvVar: null,

PORT: 5683,
HOST: "localhost",
};
6 changes: 6 additions & 0 deletions test/testApp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @flow

import createApp from '../src/app';
import settings from './settings';

export default createApp(settings);

0 comments on commit 6ee27e7

Please sign in to comment.