-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
192 lines (167 loc) · 5.75 KB
/
server.js
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/**
* This is the main server script that provides the API endpoints
* The script uses the database helper in /src
* The endpoints retrieve, update, and return data to the page handlebars files
*
* The API returns the front-end UI handlebars pages, or
* Raw json if the client requests it with a query parameter ?raw=json
*/
// Utilities we need
const fs = require("fs");
const path = require("path");
const env = require("dotenv");
env.config()
// Require the fastify framework and instantiate it
const fastify = require("fastify")({
// Set this to true for detailed logging:
logger: false,
});
// Setup our static files
fastify.register(require("@fastify/static"), {
root: path.join(__dirname, "public"),
prefix: "/", // optional: default '/'
});
// Formbody lets us parse incoming forms
fastify.register(require("@fastify/formbody"));
// View is a templating manager for fastify
fastify.register(require("@fastify/view"), {
engine: {
handlebars: require("handlebars"),
},
});
// Load and parse SEO data
const seo = require("./src/seo.json");
if (seo.url === "glitch-default") {
seo.url = `https://${process.env.PROJECT_DOMAIN}.glitch.me`;
}
// We use a module for handling database operations in /src
const data = require("./src/data.json");
const db = require("./src/" + data.database);
/**
* Home route for the app
*
* Return the poll options from the database helper script
* The home route may be called on remix in which case the db needs setup
*
* Client can request raw data using a query parameter
*/
fastify.get("/", async (request, reply) => {
/*
Params is the data we pass to the client
- SEO values for front-end UI but not for raw data
*/
let params = request.query.raw ? {} : { seo: seo };
// Get the available choices from the database
const options = await db.getOptions();
if (options) {
params.optionNames = options.map((choice) => choice.language);
params.optionCounts = options.map((choice) => choice.picks);
}
// Let the user know if there was a db error
else params.error = data.errorMessage;
// Check in case the data is empty or not setup yet
if (options && params.optionNames.length < 1)
params.setup = data.setupMessage;
// ADD PARAMS FROM TODO HERE
// Send the page options or raw JSON data if the client requested it
return request.query.raw
? reply.send(params)
: reply.view("/src/pages/index.hbs", params);
});
/**
* Post route to process user vote
*
* Retrieve vote from body data
* Send vote to database helper
* Return updated list of votes
*/
fastify.post("/", async (request, reply) => {
// We only send seo if the client is requesting the front-end ui
let params = request.query.raw ? {} : { seo: seo };
// Flag to indicate we want to show the poll results instead of the poll form
params.results = true;
let options;
// We have a vote - send to the db helper to process and return results
if (request.body.language) {
options = await db.processVote(request.body.language);
if (options) {
// We send the choices and numbers in parallel arrays
params.optionNames = options.map((choice) => choice.language);
params.optionCounts = options.map((choice) => choice.picks);
}
}
params.error = options ? null : data.errorMessage;
// Return the info to the client
return request.query.raw
? reply.send(params)
: reply.view("/src/pages/index.hbs", params);
});
/**
* Admin endpoint returns log of votes
*
* Send raw json or the admin handlebars page
*/
fastify.get("/logs", async (request, reply) => {
let params = request.query.raw ? {} : { seo: seo };
// Get the log history from the db
params.optionHistory = await db.getLogs();
// Let the user know if there's an error
params.error = params.optionHistory ? null : data.errorMessage;
// Send the log list
return request.query.raw
? reply.send(params)
: reply.view("/src/pages/admin.hbs", params);
});
/**
* Admin endpoint to empty all logs
*
* Requires authorization (see setup instructions in README)
* If auth fails, return a 401 and the log list
* If auth is successful, empty the history
*/
fastify.post("/reset", async (request, reply) => {
let params = request.query.raw ? {} : { seo: seo };
/*
Authenticate the user request by checking against the env key variable
- make sure we have a key in the env and body, and that they match
*/
if (
!request.body.key ||
request.body.key.length < 1 ||
!process.env.ADMIN_KEY ||
request.body.key !== process.env.ADMIN_KEY
) {
console.error(`Auth ${request.body.key} == ${process.env.ADMIN_KEY}`);
console.error("Auth fail");
fastify.log.error("Auth fail");
// Auth failed, return the log data plus a failed flag
params.failed = "Você inseriu credenciais inválidas!";
// Get the log list
params.optionHistory = await db.getLogs();
} else {
// We have a valid key and can clear the log
params.optionHistory = await db.clearHistory();
console.log("Limpando banco de dados!!");
fastify.log.info("Limpando banco de dados!!");
// Check for errors - method would return false value
params.error = params.optionHistory ? null : data.errorMessage;
}
// Send a 401 if auth failed, 200 otherwise
const status = params.failed ? 401 : 200;
// Send an unauthorized status code if the user credentials failed
return request.query.raw
? reply.status(status).send(params)
: reply.status(status).view("/src/pages/admin.hbs", params);
});
// Run the server and report out to the logs
fastify.listen(
{ port: process.env.PORT, host: "localhost" },
function (err, address) {
if (err) {
fastify.log.error(err);
process.exit(1);
}
console.log(`Your app is listening on ${address}`);
fastify.log.info(`server listening on ${address}`);
}
);