Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add initial api lookup endpoint for entities with test #288

Closed
wants to merge 83 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
0e5b432
feat: add initial api endpoint for work with test
May 28, 2019
45a2532
fix: push lock file to update dependencies in CI.
May 29, 2019
d1b5a4c
refactor: fetch work data from database
May 29, 2019
f8d4441
fix: test passed for work endpoint
May 29, 2019
6a5f38b
refactor: restrucure api section
May 31, 2019
5e374b5
fix: separate build for api and website and remove api routes from we…
May 31, 2019
ad91e9f
fix: update app for api in test file
May 31, 2019
3f9f83d
fix: work test
May 31, 2019
1e1225b
refactor: check keys on object via .all in work test
May 31, 2019
ee970c6
fix: handle request if work is not founded and add test for same
Jun 1, 2019
80e4bb2
feat: add more lookup endpoint for work like aliases and identifiers …
Jun 2, 2019
eb666e7
fix: insert identifier in testing
Jun 3, 2019
2fd5c44
refactor: move config to common section
Jun 3, 2019
39a8946
refactor: create entity using test-helper
Jun 3, 2019
080e4f6
fix: remove linting errors and handle errors for tests
Jun 3, 2019
7a2252b
refaxtor: clean api app.js
Jun 3, 2019
df9618a
refactor: add work type, replace langauge in place of languageId and …
Jun 3, 2019
27a0bc4
test: Refactor API work tests to use async/await
MonkeyDo Jun 5, 2019
5d0069f
test: Added WorkType and LanguageSet to entity creation test utility
MonkeyDo Jun 5, 2019
4c04fb0
refactor: Move some helpers to common code
MonkeyDo Jun 5, 2019
f85e706
refactor: Don't render HTML page for API error
MonkeyDo Jun 5, 2019
2da9746
fix: Ignore client and server when building API
MonkeyDo Jun 5, 2019
6775679
refactor: load entity data with middleware
Jun 6, 2019
89c9a85
refactor: use expect instead of should to make consistecy on tests
Jun 6, 2019
67c3931
test: Testing CI setup for testing expected API errors
MonkeyDo Jun 7, 2019
cd370bf
test: Trying another method to test expected API errors
MonkeyDo Jun 7, 2019
cc0288d
refactor: modify work tests to pass in CI
Jun 8, 2019
0838098
feat: add new endpoints for lookup of editions
Jun 8, 2019
2da5a76
fix: Fix BB-347 remedy null date for Editions without a releaseDate
MonkeyDo Jun 12, 2019
399ad10
Merge pull request #290 from bookbrainz/fix-BB-347
MonkeyDo Jun 12, 2019
73d313a
feat: add lookup endpoints for edition-group and author with basic tests
Jun 12, 2019
be73044
fix: fix BB-341 disable login and register links when redis is down
bimalkant-lauhny Jun 5, 2019
d89053d
css: Changed disabled navbar button style
MonkeyDo Jun 10, 2019
139255b
style(display): fixed lint issues
bimalkant-lauhny Jun 13, 2019
09ed149
fix: disable signup/login if redis down
bimalkant-lauhny Jun 13, 2019
66099eb
tests: Added Area when creating Author test entity
MonkeyDo Jun 13, 2019
d148968
feat: add publisher endpoints for lookup
Jun 13, 2019
cb6ff57
Merge pull request #289 from code-master5/disable-signup-redis-down
MonkeyDo Jun 13, 2019
a784222
fix: fix typo and replace entity in place of work for common function
Jun 13, 2019
07903ec
refactor: remove unnecessary file
Jun 13, 2019
b61b831
refactor: move common relation to helpers/utils and update error on i…
Jun 13, 2019
76b6da0
chore: Fix security alerts - update packages
MonkeyDo Jun 14, 2019
c32630c
Merge pull request #291 from bookbrainz/fix-sec-alerts
MonkeyDo Jun 14, 2019
e82d013
chore: Fix SEC-16
MonkeyDo Jun 14, 2019
163773d
Merge pull request #292 from bookbrainz/fix-sec-alerts
MonkeyDo Jun 14, 2019
6a9794b
feat: add tests for envalid endpoints and allow only get requests
Jun 17, 2019
6c5aac9
feat: add initial api endpoint for work with test
May 28, 2019
fcc757a
fix: push lock file to update dependencies in CI.
May 29, 2019
7d0617c
refactor: fetch work data from database
May 29, 2019
f245246
fix: test passed for work endpoint
May 29, 2019
b79ebda
refactor: restrucure api section
May 31, 2019
3571584
fix: separate build for api and website and remove api routes from we…
May 31, 2019
b9facf3
fix: update app for api in test file
May 31, 2019
a8bccb6
fix: work test
May 31, 2019
a0fee51
refactor: check keys on object via .all in work test
May 31, 2019
dcaa746
fix: handle request if work is not founded and add test for same
Jun 1, 2019
a2c26bf
feat: add more lookup endpoint for work like aliases and identifiers …
Jun 2, 2019
a23c2c6
fix: insert identifier in testing
Jun 3, 2019
7624e8c
refactor: move config to common section
Jun 3, 2019
493f8b1
refactor: create entity using test-helper
Jun 3, 2019
471e943
fix: remove linting errors and handle errors for tests
Jun 3, 2019
6cd3bba
refaxtor: clean api app.js
Jun 3, 2019
864b648
refactor: add work type, replace langauge in place of languageId and …
Jun 3, 2019
4d3e967
test: Refactor API work tests to use async/await
MonkeyDo Jun 5, 2019
b79e2d6
test: Added WorkType and LanguageSet to entity creation test utility
MonkeyDo Jun 5, 2019
a2d736a
refactor: Move some helpers to common code
MonkeyDo Jun 5, 2019
8158100
refactor: Don't render HTML page for API error
MonkeyDo Jun 5, 2019
ebcbe2f
fix: Ignore client and server when building API
MonkeyDo Jun 5, 2019
b352d13
refactor: load entity data with middleware
Jun 6, 2019
657aebc
refactor: use expect instead of should to make consistecy on tests
Jun 6, 2019
0df8910
test: Testing CI setup for testing expected API errors
MonkeyDo Jun 7, 2019
af86ffb
test: Trying another method to test expected API errors
MonkeyDo Jun 7, 2019
0608ad4
refactor: modify work tests to pass in CI
Jun 8, 2019
b0e2252
feat: add new endpoints for lookup of editions
Jun 8, 2019
d4b5a6c
feat: add lookup endpoints for edition-group and author with basic tests
Jun 12, 2019
7801e3a
tests: Added Area when creating Author test entity
MonkeyDo Jun 13, 2019
7e020bc
feat: add publisher endpoints for lookup
Jun 13, 2019
5496a03
fix: fix typo and replace entity in place of work for common function
Jun 13, 2019
43bb119
refactor: remove unnecessary file
Jun 13, 2019
9ef3a48
refactor: move common relation to helpers/utils and update error on i…
Jun 13, 2019
864b3f6
feat: add tests for envalid endpoints and allow only get requests
Jun 17, 2019
590c4bf
fix: resolve conflicts with master
Jun 17, 2019
704e2a3
Merge branch 'api' of https://github.com/akhilesh26/bookbrainz-site i…
Jun 17, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16,626 changes: 7,847 additions & 8,779 deletions package-lock.json

Large diffs are not rendered by default.

20 changes: 12 additions & 8 deletions package.json
Expand Up @@ -8,13 +8,15 @@
"clean": "./scripts/clean.sh",
"prepublishOnly": "npm run clean && npm run mkdirs && npm run copy-client-scripts",
"postinstall": "npm run prepublishOnly",
"build-server-js": "babel src --out-dir lib",
"build-server-js": "babel src --out-dir lib --ignore src/api",
"build-api-js": "babel src --out-dir lib --ignore 'src/server','src/client'",
"build-client-js": "./scripts/build-client-js.sh",
"build-less": "./scripts/build-less.sh",
"build": "npm run build-less && npm run build-client-js && npm run build-server-js",
"WIP-build-client-webpack": "cross-env NODE_ENV=production SSR=true webpack --progress --config webpack.client.js",
"prestart": "npm run build-less & npm run build-client-js & npm run build-server-js",
"start": "cross-env SSR=true node ./lib/server/app.js",
"start-api": "npm run build-api-js && node ./lib/api/app.js",
"debug": "cross-env DEBUG=bbsite NODE_ENV=development SSR=true babel-node src/server/app.js",
"debug-watch-server": "cross-env DEBUG=bbsite NODE_ENV=development SSR=true nodemon src/server/app.js --watch src/server --exec babel-node",
"lint": "eslint .",
Expand All @@ -41,21 +43,23 @@
"babel-runtime": "^6.23.0",
"bluebird": "^3.5.1",
"body-parser": "^1.14.1",
"bookbrainz-data": "^2.1.1",
"browserify": "^14.5.0",
"bookbrainz-data": "^2.2.1",
"browserify": "^16.2.3",
"chai-http": "^4.3.0",
"classnames": "^2.2.5",
"compression": "^1.7.1",
"connect-redis": "^3.0.1",
"debug": "^3.1.0",
"elasticsearch": "^15.2.0",
"express": "^4.16.2",
"express-session": "^1.10.1",
"faker": "^4.1.0",
"git-rev": "^0.2.1",
"http-status": "^1.0.0",
"immutable": "^3.8.2",
"influx": "^5.0.7",
"jsesc": "^2.5.1",
"lodash": "^4.17.10",
"lodash": "^4.17.11",
"log": "^1.4.0",
"moment": "^2.19.3",
"morgan": "^1.9.1",
Expand Down Expand Up @@ -118,23 +122,23 @@
"file-loader": "^2.0.0",
"flow-bin": "^0.69.0",
"husky": "^0.14.3",
"jsdoc": "^3.4.0",
"jsdoc": "^3.6.2",
"jsinspect": "^0.12.7",
"less": "^3.8.1",
"less-loader": "^4.1.0",
"lint-staged": "^6.0.0",
"mini-css-extract-plugin": "^0.4.1",
"mocha": "^4.1.0",
"mocha": "^5.0.3",
"nodemon": "^1.18.4",
"nyc": "^11.4.0",
"nyc": "^14.1.1",
"react-hot-loader": "^4.3.4",
"resolve-url-loader": "^2.3.0",
"rewire": "^3.0.2",
"style-loader": "^0.21.0",
"supertest": "^3.0.0",
"uuid": "^3.3.2",
"webpack": "^4.16.4",
"webpack-bundle-analyzer": "^2.13.1",
"webpack-bundle-analyzer": "^3.3.2",
"webpack-cli": "^3.1.0",
"webpack-dev-middleware": "^3.1.3",
"webpack-node-externals": "^1.7.2",
Expand Down
127 changes: 127 additions & 0 deletions src/api/app.js
@@ -0,0 +1,127 @@
/*
* Copyright (C) 2014-2015 Ben Ockmore
* 2015-2017 Sean Burke
* 2015 Leo Verto
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* eslint global-require: 'warn' */


import BookBrainzData from 'bookbrainz-data';
import Debug from 'debug';
import Promise from 'bluebird';
import {get as _get} from 'lodash';
import {allowOnlyGetMethod} from './helpers/utils';
import appCleanup from '../common/helpers/appCleanup';
import bodyParser from 'body-parser';
import compression from 'compression';
import config from '../common/helpers/config';
import express from 'express';
import logger from 'morgan';
import path from 'path';
import redis from 'connect-redis';
import routes from './routes';
import session from 'express-session';


Promise.config({
longStackTraces: true,
warnings: true
});

// Initialize application
const app = express();
app.locals.orm = BookBrainzData(config.database);


app.set('trust proxy', config.site.proxyTrust);

if (app.get('env') !== 'testing') {
app.use(logger('dev'));
}

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(compression());


const RedisStore = redis(session);
app.use(session({
cookie: {
maxAge: _get(config, 'session.maxAge', 2592000000),
secure: _get(config, 'session.secure', false)
},
resave: false,
saveUninitialized: false,
secret: config.session.secret,
store: new RedisStore({
host: _get(config, 'session.redis.host', 'localhost'),
port: _get(config, 'session.redis.port', 6379)
})
}));


// Set up routes
routes(app);

// Allow only get requests for now throw error for any other type of requests
app.all('/*', allowOnlyGetMethod);

// Catch 404 and forward to error handler
app.use((req, res, next) => {
res.status(404).send({message: `Incorrect endpoint ${req.path}`});
});


const debug = Debug('bbapi');

const DEFAULT_API_PORT = 9098;
app.set('port', process.env.PORT || DEFAULT_API_PORT); // eslint-disable-line no-process-env,max-len

const server = app.listen(app.get('port'), () => {
debug(`Express server listening on port ${server.address().port}`);
});

/* eslint-disable no-console */
function cleanupFunction() {
return new Promise((resolve, reject) => {
console.log('Cleaning up before closing');
server.close((err) => {
if (err) {
console.log('Error while closing server connections');
reject(err);
}
else {
console.log('Closed all server connections. Bye bye!');
resolve();
}
});
// force-kill after X milliseconds.
if (config.site.forceExitAfterMs) {
setTimeout(() => {
reject(new Error(`Cleanup function timed out after ${config.site.forceExitAfterMs} ms`));
}, config.site.forceExitAfterMs);
}
});
}
/* eslint-enable no-console */

// Run cleanup function
appCleanup(cleanupFunction);

export default server;
19 changes: 19 additions & 0 deletions src/api/helpers/entityLoader.js
@@ -0,0 +1,19 @@
import * as commonUtils from '../../common/helpers/utils';


export function makeEntityLoader(modelName, relations, errMessage) {
return async (req, res, next) => {
const {orm} = req.app.locals;
if (commonUtils.isValidBBID(req.params.bbid)) {
try {
const entityData = await orm.func.entity.getEntity(orm, modelName, req.params.bbid, relations);
res.locals.entity = entityData;
return next();
}
catch (err) {
return res.status(404).send({message: errMessage});
}
}
return res.status(406).send({message: 'BBID is not valid uuid'});
};
}
131 changes: 131 additions & 0 deletions src/api/helpers/formatEntityData.js
@@ -0,0 +1,131 @@
/*
* Copyright (C) 2019 Akhilesh Kumar
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

/* eslint-disable */
import _ from 'lodash';

function getDefaultAlias(entity: object){
return {
name: _.get(entity, 'defaultAlias.name', null),
sortName: _.get(entity, 'defaultAlias.sortName', null),
aliasLanguage: _.get(entity, 'defaultAlias.language.name', null)
}
}

function getLanguages(entity: object) {
return _.get(entity, 'languageSet.languages', []).map((language) => language.name)
}

export function getWorkBasicInfo(work: object) {
return _.isNil(work) ? null :
{
bbid: _.get(work, 'bbid', null),
defaultAlias: getDefaultAlias(work),
disambiguation: _.get(work, 'disambiguation.comment', null),
languages: getLanguages(work),
workType: _.get(work, 'workType.label', null),
entityType: _.get(work, 'type', null)
};
}

export function getEditionBasicInfo(edition: object) {

return _.isNil(edition) ? null :
{
bbid: _.get(edition, 'bbid', null),
defaultAlias: getDefaultAlias(edition),
languages: getLanguages(edition),
disambiguation: _.get(edition, 'disambiguation.comment', null),
hight: _.get(edition, 'hight', null),
width: _.get(edition, 'width', null),
depth: _.get(edition, 'depth', null),
pages: _.get(edition, 'pages', null),
releaseEventDates: _.get(edition, 'releaseEventSet.releaseEvents', []).map((event) => event.date),
editionFormat: _.get(edition, 'editionFormat.label', null),
weight: _.get(edition, 'weight', null),
status: _.get(edition, 'editionStatus.label', null)
}
}

export function getEditionGroupBasicInfo(editionGroup: object) {
return _.isNil(editionGroup) ? null :
{
bbid: _.get(editionGroup, 'bbid', null),
defaultAlias: getDefaultAlias(editionGroup),
disambiguation: _.get(editionGroup, 'disambiguation.comment', null),
type: _.get(editionGroup, 'editionGroupType.label')
}
}

export function getAuthorBasicInfo(author: object) {
return _.isNil(author) ? null :
{
bbid: _.get(author, 'bbid', null),
defaultAlias: getDefaultAlias(author),
disambiguation: _.get(author, 'disambiguation.comment', null),
type: _.get(author, 'authorType.label', null),
gender: _.get(author, 'gender.name', null),
beginArea: _.get(author, 'beginArea.name', null),
beginDate: _.get(author, 'beginDate', null),
ended: _.get(author, 'ended', null),
endArea: _.get(author, 'endArea.name', null),
endDate: _.get(author, 'endDate', null)
}
}

export function getPublisherBasicInfo(publisher: object) {
return _.isNil(publisher) ? null :
{
bbid: _.get(publisher, 'bbid', null),
defaultAlias: getDefaultAlias(publisher),
disambiguation: _.get(publisher, 'disambiguation.comment', null),
type: _.get(publisher, 'publisherType.label', null),
area: _.get(publisher, 'area.name', null),
beginDate: _.get(publisher, 'beginDate', null),
ended: _.get(publisher, 'ended', null),
endDate: _.get(publisher, 'endDate', null)
}
}

export function getEntityAliases(entity: object) {
return _.isNil(entity) ? null :
{
bbid: _.get(entity, 'bbid', null),
aliases: _.get(entity, 'aliasSet.aliases', []).map((alias) => {
return {
name: alias.name,
sortName: alias.sortName,
aliasLanguage: alias.language.name,
primary: alias.primary
};
})
};
}

export function getEntityIdentifiers(entity: object) {
return _.isNil(entity) ? null :
{
bbid: _.get(entity, 'bbid', null),
identifiers: _.get(entity, 'identifierSet.identifiers', []).map((identifier) => {
return {
type: identifier.type.label,
value: identifier.value
};
})
};
}
29 changes: 29 additions & 0 deletions src/api/helpers/utils.js
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2019 Akhilesh Kumar
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

export const aliasesRelation = ['aliasSet.aliases.language'];
export const identifiersRelation = ['identifierSet.identifiers.type'];

export function allowOnlyGetMethod(req, res, next) {
if (req.method === 'GET') {
return next();
}
return res.set('Allow', 'GET')
.status(405)
.send({message: `${req.method} method for the "${req.path}" route is not supported. Only GET method is allowed`});
}