refactors LoggerController with LogsRouter
This commit is contained in:
@@ -2,53 +2,85 @@ var LoggerController = require('../src/Controllers/LoggerController').LoggerCont
|
|||||||
var FileLoggerAdapter = require('../src/Adapters/Logger/FileLoggerAdapter').FileLoggerAdapter;
|
var FileLoggerAdapter = require('../src/Adapters/Logger/FileLoggerAdapter').FileLoggerAdapter;
|
||||||
|
|
||||||
describe('LoggerController', () => {
|
describe('LoggerController', () => {
|
||||||
it('can check valid master key of request', (done) => {
|
it('can check process a query witout throwing', (done) => {
|
||||||
// Make mock request
|
// Make mock request
|
||||||
var request = {
|
var query = {};
|
||||||
auth: {
|
|
||||||
isMaster: true
|
var loggerController = new LoggerController(new FileLoggerAdapter());
|
||||||
},
|
|
||||||
query: {}
|
expect(() => {
|
||||||
|
loggerController.getLogs(query).then(function(res) {
|
||||||
|
expect(res.length).toBe(0);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('properly validates dateTimes', (done) => {
|
||||||
|
expect(LoggerController.validDateTime()).toBe(null);
|
||||||
|
expect(LoggerController.validDateTime("String")).toBe(null);
|
||||||
|
expect(LoggerController.validDateTime(123456).getTime()).toBe(123456);
|
||||||
|
expect(LoggerController.validDateTime("2016-01-01Z00:00:00").getTime()).toBe(1451606400000);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can set the proper default values', (done) => {
|
||||||
|
// Make mock request
|
||||||
|
var result = LoggerController.parseOptions();
|
||||||
|
expect(result.size).toEqual(10);
|
||||||
|
expect(result.order).toEqual('desc');
|
||||||
|
expect(result.level).toEqual('info');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can process a query witout throwing', (done) => {
|
||||||
|
// Make mock request
|
||||||
|
var query = {
|
||||||
|
from: "2016-01-01Z00:00:00",
|
||||||
|
until: "2016-01-01Z00:00:00",
|
||||||
|
size: 5,
|
||||||
|
order: 'asc',
|
||||||
|
level: 'error'
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = LoggerController.parseOptions(query);
|
||||||
|
|
||||||
|
expect(result.from.getTime()).toEqual(1451606400000);
|
||||||
|
expect(result.until.getTime()).toEqual(1451606400000);
|
||||||
|
expect(result.size).toEqual(5);
|
||||||
|
expect(result.order).toEqual('asc');
|
||||||
|
expect(result.level).toEqual('error');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can check process a query witout throwing', (done) => {
|
||||||
|
// Make mock request
|
||||||
|
var query = {
|
||||||
|
from: "2015-01-01",
|
||||||
|
until: "2016-01-01",
|
||||||
|
size: 5,
|
||||||
|
order: 'desc',
|
||||||
|
level: 'error'
|
||||||
};
|
};
|
||||||
|
|
||||||
var loggerController = new LoggerController(new FileLoggerAdapter());
|
var loggerController = new LoggerController(new FileLoggerAdapter());
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
loggerController.handleGET(request);
|
loggerController.getLogs(query).then(function(res) {
|
||||||
|
expect(res.length).toBe(0);
|
||||||
|
done();
|
||||||
|
})
|
||||||
}).not.toThrow();
|
}).not.toThrow();
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can check invalid construction of controller', (done) => {
|
it('should throw without an adapter', (done) => {
|
||||||
// Make mock request
|
|
||||||
var request = {
|
|
||||||
auth: {
|
|
||||||
isMaster: true
|
|
||||||
},
|
|
||||||
query: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
var loggerController = new LoggerController();
|
var loggerController = new LoggerController();
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
loggerController.handleGET(request);
|
loggerController.getLogs();
|
||||||
}).toThrow();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can check invalid master key of request', (done) => {
|
|
||||||
// Make mock request
|
|
||||||
var request = {
|
|
||||||
auth: {
|
|
||||||
isMaster: false
|
|
||||||
},
|
|
||||||
query: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
var loggerController = new LoggerController(new FileLoggerAdapter());
|
|
||||||
|
|
||||||
expect(() => {
|
|
||||||
loggerController.handleGET(request);
|
|
||||||
}).toThrow();
|
}).toThrow();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|||||||
67
spec/LogsRouter.spec.js
Normal file
67
spec/LogsRouter.spec.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
var LogsRouter = require('../src/Routers/LogsRouter').LogsRouter;
|
||||||
|
var LoggerController = require('../src/Controllers/LoggerController').LoggerController;
|
||||||
|
var FileLoggerAdapter = require('../src/Adapters/Logger/FileLoggerAdapter').FileLoggerAdapter;
|
||||||
|
|
||||||
|
const loggerController = new LoggerController(new FileLoggerAdapter());
|
||||||
|
|
||||||
|
describe('LogsRouter', () => {
|
||||||
|
it('can check valid master key of request', (done) => {
|
||||||
|
// Make mock request
|
||||||
|
var request = {
|
||||||
|
auth: {
|
||||||
|
isMaster: true
|
||||||
|
},
|
||||||
|
query: {},
|
||||||
|
config: {
|
||||||
|
loggerController: loggerController
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var router = new LogsRouter();
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
router.handleGET(request);
|
||||||
|
}).not.toThrow();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can check invalid construction of controller', (done) => {
|
||||||
|
// Make mock request
|
||||||
|
var request = {
|
||||||
|
auth: {
|
||||||
|
isMaster: true
|
||||||
|
},
|
||||||
|
query: {},
|
||||||
|
config: {
|
||||||
|
loggerController: undefined // missing controller
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var router = new LogsRouter();
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
router.handleGET(request);
|
||||||
|
}).toThrow();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can check invalid master key of request', (done) => {
|
||||||
|
// Make mock request
|
||||||
|
var request = {
|
||||||
|
auth: {
|
||||||
|
isMaster: false
|
||||||
|
},
|
||||||
|
query: {},
|
||||||
|
config: {
|
||||||
|
loggerController: loggerController
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var router = new LogsRouter();
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
router.handleGET(request);
|
||||||
|
}).toThrow();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -27,6 +27,7 @@ export class Config {
|
|||||||
this.database = DatabaseAdapter.getDatabaseConnection(applicationId);
|
this.database = DatabaseAdapter.getDatabaseConnection(applicationId);
|
||||||
this.filesController = cacheInfo.filesController;
|
this.filesController = cacheInfo.filesController;
|
||||||
this.pushController = cacheInfo.pushController;
|
this.pushController = cacheInfo.pushController;
|
||||||
|
this.loggerController = cacheInfo.loggerController;
|
||||||
this.oauth = cacheInfo.oauth;
|
this.oauth = cacheInfo.oauth;
|
||||||
|
|
||||||
this.mount = mount;
|
this.mount = mount;
|
||||||
|
|||||||
@@ -1,35 +1,55 @@
|
|||||||
import { Parse } from 'parse/node';
|
import { Parse } from 'parse/node';
|
||||||
import PromiseRouter from '../PromiseRouter';
|
import PromiseRouter from '../PromiseRouter';
|
||||||
import rest from '../rest';
|
|
||||||
|
|
||||||
const Promise = Parse.Promise;
|
const Promise = Parse.Promise;
|
||||||
const INFO = 'info';
|
|
||||||
const ERROR = 'error';
|
|
||||||
const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000;
|
const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
// only allow request with master key
|
export const LogLevel = {
|
||||||
let enforceSecurity = (auth) => {
|
INFO: 'info',
|
||||||
if (!auth || !auth.isMaster) {
|
ERROR: 'error'
|
||||||
throw new Parse.Error(
|
|
||||||
Parse.Error.OPERATION_FORBIDDEN,
|
|
||||||
'Clients aren\'t allowed to perform the ' +
|
|
||||||
'get' + ' operation on logs.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that date input is valid
|
export const LogOrder = {
|
||||||
let isValidDateTime = (date) => {
|
DESCENDING: 'desc',
|
||||||
if (!date || isNaN(Number(date))) {
|
ASCENDING: 'asc'
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LoggerController {
|
export class LoggerController {
|
||||||
|
|
||||||
constructor(loggerAdapter) {
|
constructor(loggerAdapter, loggerOptions) {
|
||||||
this._loggerAdapter = loggerAdapter;
|
this._loggerAdapter = loggerAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check that date input is valid
|
||||||
|
static validDateTime(date) {
|
||||||
|
if (!date) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
date = new Date(date);
|
||||||
|
|
||||||
|
if (!isNaN(date.getTime())) {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static parseOptions(options = {}) {
|
||||||
|
let from = LoggerController.validDateTime(options.from) ||
|
||||||
|
new Date(Date.now() - 7 * MILLISECONDS_IN_A_DAY);
|
||||||
|
let until = LoggerController.validDateTime(options.until) || new Date();
|
||||||
|
let size = Number(options.size) || 10;
|
||||||
|
let order = options.order || LogOrder.DESCENDING;
|
||||||
|
let level = options.level || LogLevel.INFO;
|
||||||
|
|
||||||
|
return {
|
||||||
|
from,
|
||||||
|
until,
|
||||||
|
size,
|
||||||
|
order,
|
||||||
|
level,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Returns a promise for a {response} object.
|
// Returns a promise for a {response} object.
|
||||||
// query params:
|
// query params:
|
||||||
@@ -38,41 +58,21 @@ export class LoggerController {
|
|||||||
// until (optional) End time for the search. Defaults to current time.
|
// until (optional) End time for the search. Defaults to current time.
|
||||||
// order (optional) Direction of results returned, either “asc” or “desc”. Defaults to “desc”.
|
// order (optional) Direction of results returned, either “asc” or “desc”. Defaults to “desc”.
|
||||||
// size (optional) Number of rows returned by search. Defaults to 10
|
// size (optional) Number of rows returned by search. Defaults to 10
|
||||||
handleGET(req) {
|
getLogs(options= {}) {
|
||||||
if (!this._loggerAdapter) {
|
if (!this._loggerAdapter) {
|
||||||
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
||||||
'Logger adapter is not availabe');
|
'Logger adapter is not availabe');
|
||||||
}
|
}
|
||||||
|
|
||||||
let promise = new Parse.Promise();
|
let promise = new Parse.Promise();
|
||||||
let from = (isValidDateTime(req.query.from) && new Date(req.query.from)) ||
|
|
||||||
new Date(Date.now() - 7 * MILLISECONDS_IN_A_DAY);
|
options = LoggerController.parseOptions(options);
|
||||||
let until = (isValidDateTime(req.query.until) && new Date(req.query.until)) || new Date();
|
|
||||||
let size = Number(req.query.size) || 10;
|
this._loggerAdapter.query(options, (result) => {
|
||||||
let order = req.query.order || 'desc';
|
promise.resolve(result);
|
||||||
let level = req.query.level || INFO;
|
|
||||||
enforceSecurity(req.auth);
|
|
||||||
this._loggerAdapter.query({
|
|
||||||
from,
|
|
||||||
until,
|
|
||||||
size,
|
|
||||||
order,
|
|
||||||
level,
|
|
||||||
}, (result) => {
|
|
||||||
promise.resolve({
|
|
||||||
response: result
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
getExpressRouter() {
|
|
||||||
let router = new PromiseRouter();
|
|
||||||
router.route('GET','/logs', (req) => {
|
|
||||||
return this.handleGET(req);
|
|
||||||
});
|
|
||||||
return router;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LoggerController;
|
export default LoggerController;
|
||||||
|
|||||||
60
src/Routers/LogsRouter.js
Normal file
60
src/Routers/LogsRouter.js
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { Parse } from 'parse/node';
|
||||||
|
import PromiseRouter from '../PromiseRouter';
|
||||||
|
|
||||||
|
// only allow request with master key
|
||||||
|
let enforceSecurity = (auth) => {
|
||||||
|
if (!auth || !auth.isMaster) {
|
||||||
|
throw new Parse.Error(
|
||||||
|
Parse.Error.OPERATION_FORBIDDEN,
|
||||||
|
'Clients aren\'t allowed to perform the ' +
|
||||||
|
'get' + ' operation on logs.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LogsRouter extends PromiseRouter {
|
||||||
|
|
||||||
|
mountRoutes() {
|
||||||
|
this.route('GET','/logs', (req) => {
|
||||||
|
return this.handleGET(req);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a promise for a {response} object.
|
||||||
|
// query params:
|
||||||
|
// level (optional) Level of logging you want to query for (info || error)
|
||||||
|
// from (optional) Start time for the search. Defaults to 1 week ago.
|
||||||
|
// until (optional) End time for the search. Defaults to current time.
|
||||||
|
// order (optional) Direction of results returned, either “asc” or “desc”. Defaults to “desc”.
|
||||||
|
// size (optional) Number of rows returned by search. Defaults to 10
|
||||||
|
handleGET(req) {
|
||||||
|
if (!req.config || !req.config.loggerController) {
|
||||||
|
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
||||||
|
'Logger adapter is not availabe');
|
||||||
|
}
|
||||||
|
|
||||||
|
let promise = new Parse.Promise();
|
||||||
|
let from = req.query.from;
|
||||||
|
let until = req.query.until;
|
||||||
|
let size = req.query.size;
|
||||||
|
let order = req.query.order
|
||||||
|
let level = req.query.level;
|
||||||
|
enforceSecurity(req.auth);
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
from,
|
||||||
|
until,
|
||||||
|
size,
|
||||||
|
order,
|
||||||
|
level,
|
||||||
|
}
|
||||||
|
|
||||||
|
return req.config.loggerController.getLogs(options).then((result) => {
|
||||||
|
return Promise.resolve({
|
||||||
|
response: result
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LogsRouter;
|
||||||
@@ -30,6 +30,7 @@ import { SchemasRouter } from './Routers/SchemasRouter';
|
|||||||
import { IAPValidationRouter } from './Routers/IAPValidationRouter';
|
import { IAPValidationRouter } from './Routers/IAPValidationRouter';
|
||||||
import { PushRouter } from './Routers/PushRouter';
|
import { PushRouter } from './Routers/PushRouter';
|
||||||
import { FilesRouter } from './Routers/FilesRouter';
|
import { FilesRouter } from './Routers/FilesRouter';
|
||||||
|
import { LogsRouter } from './Routers/LogsRouter';
|
||||||
|
|
||||||
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
|
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
|
||||||
import { LoggerController } from './Controllers/LoggerController';
|
import { LoggerController } from './Controllers/LoggerController';
|
||||||
@@ -168,7 +169,7 @@ function ParseServer({
|
|||||||
new FunctionsRouter(),
|
new FunctionsRouter(),
|
||||||
new SchemasRouter(),
|
new SchemasRouter(),
|
||||||
new PushRouter(),
|
new PushRouter(),
|
||||||
new LoggerController(loggerAdapter).getExpressRouter(),
|
new LogsRouter(),
|
||||||
new IAPValidationRouter()
|
new IAPValidationRouter()
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user