run/idp-sql/app.js (82 lines of code) (raw):
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
'use strict';
const {getVotes, getVoteCount, insertVote} = require('./cloud-sql');
const express = require('express');
const {buildRenderedHtml} = require('./handlebars');
const {authenticateJWT, requestLogger} = require('./middleware');
const app = express();
app.use(express.static(__dirname + '/static'));
// Automatically parse request body as form data.
app.use(express.urlencoded({extended: false}));
app.use(express.json());
// Set Content-Type for all responses for these routes.
app.use((req, res, next) => {
res.set('Content-Type', 'text/html');
next();
});
app.get('/', requestLogger, async (req, res) => {
try {
// Query the total count of "CATS" from the database.
const catsResult = await getVoteCount('CATS');
const catsTotalVotes = parseInt(catsResult[0].count);
// Query the total count of "DOGS" from the database.
const dogsResult = await getVoteCount('DOGS');
const dogsTotalVotes = parseInt(dogsResult[0].count);
// Query the last 5 votes from the database.
const votes = await getVotes();
// Calculate and set leader values.
let leadTeam = '';
let voteDiff = 0;
let leaderMessage = '';
if (catsTotalVotes !== dogsTotalVotes) {
if (catsTotalVotes > dogsTotalVotes) {
leadTeam = 'CATS';
voteDiff = catsTotalVotes - dogsTotalVotes;
} else {
leadTeam = 'DOGS';
voteDiff = dogsTotalVotes - catsTotalVotes;
}
leaderMessage = `${leadTeam} are winning by ${voteDiff} vote${
voteDiff > 1 ? 's' : ''
}.`;
} else {
leaderMessage = 'CATS and DOGS are evenly matched!';
}
// Add variables to Handlebars.js template
const renderedHtml = await buildRenderedHtml({
votes: votes,
catsCount: catsTotalVotes,
dogsCount: dogsTotalVotes,
leadTeam: leadTeam,
voteDiff: voteDiff,
leaderMessage: leaderMessage,
});
res.status(200).send(renderedHtml);
} catch (err) {
const message = `Error when querying the Cloud SQL database: ${err}`;
req.logger.error(message); // request-based logger with trace support
res
.status(500)
.send('Unable to load page; see logs for more details.')
.end();
}
});
app.post('/', requestLogger, authenticateJWT, async (req, res) => {
// Get decoded Id Platform user id
const uid = req.uid;
// Get the team from the request and record the time of the vote.
const {team} = req.body;
const timestamp = new Date();
if (!team || (team !== 'CATS' && team !== 'DOGS')) {
res.status(400).send('Invalid team specified.').end();
return;
}
// Create a vote record to be stored in the database.
const vote = {
candidate: team,
time_cast: timestamp,
uid,
};
// Save the data to the database.
try {
await insertVote(vote);
req.logger.info({message: 'vote_inserted', vote}); // request-based logger with trace support
} catch (err) {
req.logger.error(`Error while attempting to submit vote: ${err}`);
res
.status(500)
.send('Unable to cast vote; see logs for more details.')
.end();
return;
}
res.status(200).send(`Successfully voted for ${team} at ${timestamp}`).end();
});
module.exports = app;