Commit e2b661cb authored by Evgeniy Zaitsev's avatar Evgeniy Zaitsev
Browse files

v0.0.2

parent 50415da3
root = true
[*]
indent_style = tab
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
{
"extends": ["google"],
"rules": {
"max-len": [2, 120, 2],
"indent": [2, "tab",{
"SwitchCase": 1
}],
"camelcase": [2, {
"properties": "never"
}],
"require-jsdoc": 0,
"no-debugger": 1
},
"env": {
"es6": true,
"node": true
}
}
.idea
node_modules
run.js
service-sdk-releases
service-sdk-releases
\ No newline at end of file
'use strict';
const koa = require('koa');
const validate = require('koa-validate');
const Promise = require('bluebird');
const mysql = require('mysql');
const tablesNames = require('./constants/tablesNames');
const throwResponseErrorIfNeed = require('./lib/throwResponseErrorIfNeed');
const connectToMySql = require('./lib/connectToMySql');
const createTables = require('./lib/createTables');
const logger = require('./lib/logger');
const errors = require('./middlewares/errors');
const router = require('./router');
const app = koa();
validate(app);
app.use(errors);
app.use(require('koa-bodyparser')());
app.use(router.routes());
module.exports = Promise.coroutine(main);
function * main(config) {
app.env = config.env || 'production';
app.context.tablesNames = tablesNames;
app.context.db = mysql.createConnection(config.mySql);
app.context.logger = logger;
app.context.config = config;
app.context.throwResponseErrorIfNeed = throwResponseErrorIfNeed.bind(app.context);
Promise.promisifyAll(app.context.db);
yield * connectToMySql.call(app.context);
yield * createTables.call(app.context);
app.listen(config.httpPort);
logger.log(__filename, `App is listening on port: ${config.httpPort}`);
return app;
}
module.exports = {
INSTANCES: 'instances',
PROJECTS: 'projects'
};
'use strict';
class ResponseError {
constructor(msg, status) {
if (typeof msg === 'string') {
this.message = msg;
} else {
this.message = msg;
}
this.status = status;
}
}
module.exports = ResponseError;
'use strict';
function * connectToMySql() {
try {
yield this.db.connectAsync();
this.logger.log(__filename, 'MySql connected');
} catch (err) {
this.logger.error(__filename, `MySql connect error: ${err}`);
throw err;
}
}
module.exports = connectToMySql;
'use strict';
function * createTables() {
try {
yield this.db.queryAsync(`
CREATE TABLE IF NOT EXISTS \`${this.config.mySql.database}\`.\`${this.tablesNames.INSTANCES}\` (
\`id\` CHAR(36) NOT NULL,
\`name\` CHAR(255) NOT NULL,
\`auth_endpoint\` CHAR(255) NOT NULL,
\`feed_endpoint\` CHAR(255) NOT NULL,
PRIMARY KEY (\`id\`),
UNIQUE INDEX \`id_UNIQUE\` (\`id\` ASC)
)
`);
yield this.db.queryAsync(`
CREATE TABLE IF NOT EXISTS \`${this.config.mySql.database}\`.\`${this.tablesNames.PROJECTS}\` (
\`id\` CHAR(36) NOT NULL,
\`name\` CHAR(255) NOT NULL,
\`config\` TEXT NOT NULL,
\`feed_uuid\` CHAR(36) NOT NULL,
PRIMARY KEY (\`id\`),
UNIQUE INDEX \`id_UNIQUE\` (\`id\` ASC)
)
`);
this.logger.log(__filename, 'tables created successfully');
} catch (err) {
this.logger.error(err);
throw err;
}
}
module.exports = createTables;
'use strict';
const debug = require('debug');
const log = debug('service-sdk:log');
const error = debug('service-sdk:error');
module.exports = {
log() {
log.apply(null, arguments);
},
error() {
error.apply(null, arguments);
}
};
'use strict';
function serialize(obj, prefix) {
const res = [];
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
const strKey = prefix ? prefix + '[' + key + ']' : key;
const value = obj[strKey];
if (typeof value === 'object') {
res.push(serialize(value, strKey));
} else {
res.push(`${strKey}=${encodeURIComponent(value)}`);
}
}
}
return res.join("&");
}
module.exports = serialize;
'use strict';
const ResponseError = require('../lib/ResponseError');
function throwResponseErrorIfNeed(error, message) {
if (error) {
throw new ResponseError(message || error, 400);
}
}
module.exports = throwResponseErrorIfNeed;
function * checkInstanceId(next) {
const instanceId = this.checkParams('instanceId').isUUID().value;
this.logger.log(__filename, 'instance id:', instanceId);
this.throwResponseErrorIfNeed(this.errors);
const query = `SELECT * FROM \`${this.tablesNames.INSTANCES}\` WHERE \`id\` = "${[instanceId]}"`;
const instances = yield this.db.queryAsync(query);
const instance = instances[0];
this.logger.log(__filename, 'instance:', JSON.stringify(instance));
this.throwResponseErrorIfNeed(!instance, 'your instance is not registered');
this.state.instance = instance;
yield next;
}
module.exports = checkInstanceId;
function * checkInstanceId(next) {
const projectId = this.checkParams('projectId').isUUID().value;
this.logger.log(__filename, 'project id:', projectId);
this.throwResponseErrorIfNeed(this.errors);
const query = `SELECT * FROM \`${this.tablesNames.PROJECTS}\` WHERE \`id\` = "${projectId}"`;
const projects = yield this.db.queryAsync(query);
const project = projects[0];
this.logger.log(__filename, 'project:', JSON.stringify(project));
this.throwResponseErrorIfNeed(!project, 'your project is not registered');
project.config = JSON.parse(project.config);
this.state.project = project;
yield next;
}
module.exports = checkInstanceId;
const sha1 = require('sha1');
const serialize = require('../lib/serialize');
function * checkToken(next) {
const salt = this.checkHeader('x-lvis-salt').notBlank().value;
const signature = this.checkHeader('x-lvis-signature').notBlank().value;
this.logger.log(__filename, 'headers:', JSON.stringify({salt, signature}));
this.throwResponseErrorIfNeed(this.errors);
const signeableContent = this.request.path + this.request.querystring + serialize(this.request.body);
const privateSignature = sha1(this.config.accessToken + signeableContent + salt);
this.logger.log(__filename, 'private signature:', privateSignature);
this.throwResponseErrorIfNeed(privateSignature !== signature, 'Invalid access token');
yield next;
}
module.exports = checkToken;
'use strict';
const ResponseError = require('../lib/ResponseError');
function * errors(next) {
try {
yield next;
} catch (err) {
this.status = err.status || 500;
if (err instanceof Error) {
this.body = {
message: err.message
};
this.logger.error(err);
} else if (err instanceof ResponseError) {
this.body = typeof err.message === 'string' ? {message: err.message} : err.message;
this.logger.error(__filename, JSON.stringify(err.message));
}
}
}
module.exports = errors;
{
"name": "service-sdk",
"version": "0.0.2",
"private": true,
"description": "Service SDK for LViS",
"keywords": [],
"author": "",
"license": "",
"main": "app.js",
"dependencies": {
"bluebird": "^3.4.6",
"debug": "^2.2.0",
"koa": "^1.2.4",
"koa-bodyparser": "^2.2.0",
"koa-json": "^1.1.3",
"koa-router": "^5.4.0",
"koa-validate": "^1.0.7",
"mysql": "^2.11.1",
"sha1": "^1.1.1"
},
"scripts": {
"start": "node app.js",
"lint": "eslint ./**/*.js"
},
"devDependencies": {
"eslint": "^3.7.1",
"eslint-config-google": "^0.6.0"
}
}
'use strict';
function * get() {
const eventId = this.checkParams('eventId').isUUID().value;
this.logger.log(__filename, 'GET', 'event id:', eventId);
this.throwResponseErrorIfNeed(this.errors);
this.body = this.config.analyticsCallback(this.state.instance, this.state.project, eventId);
}
module.exports = {get: get};
const router = require('koa-router')();
const checkToken = require('../middlewares/checkToken');
const checkInstanceId = require('../middlewares/checkInstanceId');
const checkProjectId = require('../middlewares/checkProjectId');
const lvis = require('./lvis');
const project = require('./project');
const analytics = require('./analytics');
router
.post('/lvis', checkToken, lvis.post)
.post('/lvis/:instanceId/project', checkToken, checkInstanceId, project.post)
.put('/lvis/:instanceId/project/:projectId', checkToken, checkInstanceId, checkProjectId, project.put)
.del('/lvis/:instanceId/project/:projectId', checkToken, checkInstanceId, checkProjectId, project.del)
.get(
'/lvis/:instanceId/project/:projectId/events/:eventId/analytics_tab',
checkToken, checkInstanceId, checkProjectId, analytics.get
)
;
module.exports = router;
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment