-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
178 lines (154 loc) · 5.39 KB
/
app.js
File metadata and controls
178 lines (154 loc) · 5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
const express = require("express");
const bodyParser = require("body-parser");
const awsDecrypt = require("./config/awsDecrypt");
// Import controllers
const apiDoc = require("./api/controllers/apiDoc.js");
const createPatronV0_2 = require("./api/controllers/v0.2/createPatron.js");
const createPatronV0_3 = require("./api/controllers/v0.3/endpoints.js");
const BarcodeDb = require("./db");
const app = express();
const pathName = `${process.cwd()}/config/deploy_${app.get("env")}.env`;
require("dotenv").config({ path: pathName });
// Decrypt any database credentials if on QA or production for the NYPL AWS
// environment. Then create the single database instance in the app.
async function initDatabase() {
let dbUser;
let dbHost;
let dbPassword;
if (process.env.NODE_ENV === "development") {
dbUser = process.env.DB_USER;
dbHost = process.env.DB_HOST;
dbPassword = process.env.DB_PASSWORD;
} else {
dbUser = await awsDecrypt.decryptKMS(process.env.DB_USER);
dbHost = await awsDecrypt.decryptKMS(process.env.DB_HOST);
dbPassword = await awsDecrypt.decryptKMS(process.env.DB_PASSWORD);
}
// Initialize the connection to the database.
// This is done here so we can have one instance and one connection to the
// database for however many times the lambda is used for.
const db = BarcodeDb({
user: dbUser,
host: dbHost,
password: dbPassword,
// These are constant and don't need to be encrypted or decrypted.
database: process.env.DB_DATABASE,
port: process.env.DB_PORT,
});
// Once we get the database class instance, initialize it by creating the
// table and inserting the seed data if it's not in the database already.
db.init();
}
initDatabase();
/**
* allowCrossDomain
* Set up the middleware to support CORS. It will be used in every response.
* @param {HTTP request} req
* @param {HTTP response} res
* @param {next}
*/
function allowCrossDomain(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
}
// Support CORS
app.use(allowCrossDomain);
// The parser for interpret JSON in req.body
app.use(bodyParser.json());
// The parser for interpret URL parameters
app.use(
bodyParser.urlencoded({
extended: true,
})
);
/**
* deprecatedEndpoint
* For deprecated endpoints, send a note to use the v0.3 endpoints.
* @param {HTTP request} req
* @param {HTTP response} res
*/
function deprecatedEndpoint(req, res) {
return res.status(400).header("Content-Type", "application/json").json({
status: 400,
type: "deprecated-endpoint",
title: "Deprecated Endpoint",
detail:
"This endpoint is deprecated. Use the v0.3 endpoints and find more information on https://github.com/NYPL/dgx-patron-creator-service/wiki",
});
}
/**
* v2Error(err, req)
* Format the response for errors on v0.2 routes
*
* @param {error object} err
* @param {HTTP request} req
*/
// eslint-disable-next-line no-unused-vars
function v2Error(err, req) {
return {
status_code_from_card_ils: null,
status: err.status,
type: "invalid-request",
message: `Request body: ${err.body}`,
detail: "The patron creator did not forward the request to the ILS.",
};
}
/**
* errorHandler
* Rendering the error response if the request to this service fails.
* We need "next" here as the forth argument following the Express's convention
* @param {error object} err
* @param {HTTP request} req
* @param {HTTP response} res
*/
function errorHandler(err, req, res, next) {
console.error(
`status_code: ${err.status}, ` +
// eslint-disable-next-line quotes
'type: "invalid-request", ' +
// eslint-disable-next-line prettier/prettier
+`message: "Request body: ${err.body}"`
);
let jsonError;
if (req.url.includes("v0.2")) {
jsonError = v2Error(err, req);
}
res.status(err.status).json(jsonError);
next();
}
// Error handling
app.use(errorHandler);
const router = express.Router();
// This route will make a request for swaggerDoc.json
app.get("/docs/patrons-validations", apiDoc.renderApiDoc);
// The base of the endpoints.
app.use("/api", router);
// These endpoints are now deprecated. Send a note
router.route("/v0.1/patrons/").post(deprecatedEndpoint);
router.route("/v0.1/validations/username").post(deprecatedEndpoint);
router.route("/v0.1/validations/address").post(deprecatedEndpoint);
// New validation will be part of the `patrons` endpoint.
router.route("/v0.2/patrons/").post(createPatronV0_2.createPatron);
// The new validation endpoints.
router.route("/v0.3/validations/username").post(createPatronV0_3.checkUsername);
router.route("/v0.3/validations/address").post(createPatronV0_3.checkAddress);
// Check if a patron is eligible to create dependent juvenile accounts.
router
.route("/v0.3/patrons/dependent-eligibility")
.get(createPatronV0_3.checkDependentEligibility);
// Endpoints to create ILS accounts.
router.route("/v0.3/patrons/dependents").post(createPatronV0_3.createDependent);
router.route("/v0.3/patrons/").post(createPatronV0_3.createPatron);
// Do not listen to connections in the Lambda environment.
if (!process.env.AWS_LAMBDA_FUNCTION_NAME) {
const port = process.env.PORT || 3001;
app.listen(port, () => {
console.info(`Server started on port ${port}`);
});
}
module.exports = app;