Skip to content

Commit

Permalink
New build of backend
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminJohnson2204 committed May 30, 2024
1 parent 7f22e2f commit 837fb44
Show file tree
Hide file tree
Showing 16 changed files with 547 additions and 111 deletions.
2 changes: 2 additions & 0 deletions backend/dist/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const http_errors_1 = require("http-errors");
const vsr_1 = __importDefault(require("./routes/vsr"));
const furnitureItem_1 = __importDefault(require("./routes/furnitureItem"));
const user_1 = __importDefault(require("./routes/user"));
const confirmationEmail_1 = __importDefault(require("./routes/confirmationEmail"));
const validateEnv_1 = __importDefault(require("./util/validateEnv"));
const app = (0, express_1.default)();
// initializes Express to accept JSON in the request/response body
Expand All @@ -29,6 +30,7 @@ app.use((0, cors_1.default)({
app.use("/api/user", user_1.default);
app.use("/api/vsr", vsr_1.default);
app.use("/api/furnitureItems", furnitureItem_1.default);
app.use("/api/confirmationEmail", confirmationEmail_1.default);
/**
* Error handler; all errors thrown by server are handled here.
* Explicit typings required here because TypeScript cannot infer the argument types.
Expand Down
51 changes: 51 additions & 0 deletions backend/dist/src/controllers/confirmationEmail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateConfirmationEmail = exports.getConfirmationEmail = void 0;
const express_validator_1 = require("express-validator");
const sanitize_html_1 = __importDefault(require("sanitize-html"));
const confirmationEmails_1 = require("../services/confirmationEmails");
const validationErrorParser_1 = __importDefault(require("../util/validationErrorParser"));
/**
* Retrieves the VSR confirmation email from the database.
*/
const getConfirmationEmail = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
try {
const confirmationEmail = yield (0, confirmationEmails_1.retrieveConfirmaionEmail)();
res.status(200).json({ html: confirmationEmail.html, papLogoHTML: confirmationEmails_1.PAP_LOGO_HTML });
}
catch (error) {
next(error);
}
});
exports.getConfirmationEmail = getConfirmationEmail;
const updateConfirmationEmail = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
const errors = (0, express_validator_1.validationResult)(req);
try {
(0, validationErrorParser_1.default)(errors);
const { html } = req.body;
const sanitizedHTML = (0, sanitize_html_1.default)(html, {
allowedTags: sanitize_html_1.default.defaults.allowedTags.concat([
// Frontend editor uses <ins> tags for underlining.
"ins",
]),
});
const updatedConfirmationEmail = yield (0, confirmationEmails_1.updateConfirmationEmail)(sanitizedHTML);
res.status(200).json(updatedConfirmationEmail);
}
catch (error) {
next(error);
}
});
exports.updateConfirmationEmail = updateConfirmationEmail;
49 changes: 48 additions & 1 deletion backend/dist/src/controllers/furnitureItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFurnitureItems = void 0;
exports.updateFurnitureItem = exports.deleteFurnitureItem = exports.createFurnitureItem = exports.getFurnitureItems = void 0;
const express_validator_1 = require("express-validator");
const http_errors_1 = __importDefault(require("http-errors"));
const furnitureItem_1 = __importDefault(require("../models/furnitureItem"));
const validationErrorParser_1 = __importDefault(require("../util/validationErrorParser"));
/**
* Gets all available furniture items in the database. Does not require authentication.
*/
Expand All @@ -32,3 +35,47 @@ const getFurnitureItems = (req, res, next) => __awaiter(void 0, void 0, void 0,
}
});
exports.getFurnitureItems = getFurnitureItems;
const createFurnitureItem = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
const errors = (0, express_validator_1.validationResult)(req);
try {
(0, validationErrorParser_1.default)(errors);
const furnitureItem = yield furnitureItem_1.default.create(req.body);
res.status(201).json(furnitureItem);
}
catch (error) {
next(error);
}
});
exports.createFurnitureItem = createFurnitureItem;
const deleteFurnitureItem = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
try {
const { id } = req.params;
const deletedFurnitureItem = yield furnitureItem_1.default.findByIdAndDelete(id);
if (deletedFurnitureItem === null) {
throw (0, http_errors_1.default)(404, "FurnitureItem not found at id " + id);
}
return res.status(204).send();
}
catch (error) {
next(error);
}
});
exports.deleteFurnitureItem = deleteFurnitureItem;
const updateFurnitureItem = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
const errors = (0, express_validator_1.validationResult)(req);
try {
const { id } = req.params;
(0, validationErrorParser_1.default)(errors);
const updatedFurnitureItem = yield furnitureItem_1.default.findByIdAndUpdate(id, req.body, {
new: true,
});
if (updatedFurnitureItem == null) {
throw (0, http_errors_1.default)(404, "Furniture Item not found at id " + id);
}
res.status(200).json(updatedFurnitureItem);
}
catch (error) {
next(error);
}
});
exports.updateFurnitureItem = updateFurnitureItem;
139 changes: 137 additions & 2 deletions backend/dist/src/controllers/user.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
Expand All @@ -12,8 +35,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getWhoAmI = void 0;
const user_1 = __importDefault(require("../models/user"));
exports.deleteUser = exports.notifyResetPassword = exports.changeUserPassword = exports.createUser = exports.getUsers = exports.getWhoAmI = void 0;
const firebase_1 = require("../services/firebase");
const user_1 = __importStar(require("../models/user"));
const express_validator_1 = require("express-validator");
const validationErrorParser_1 = __importDefault(require("../util/validationErrorParser"));
const http_errors_1 = __importDefault(require("http-errors"));
const emails_1 = require("../services/emails");
/**
* Retrieves data about the current user (their MongoDB ID, Firebase UID, and role).
* Requires the user to be signed in.
Expand All @@ -34,3 +62,110 @@ const getWhoAmI = (req, res, next) => __awaiter(void 0, void 0, void 0, function
}
});
exports.getWhoAmI = getWhoAmI;
/**
* Retrieves a list of all users in our database
*/
const getUsers = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
try {
const papUsers = yield user_1.default.find();
const displayUsers = [];
for (const papUser of papUsers) {
const { uid, _id } = papUser;
try {
const firebaseUser = yield firebase_1.firebaseAuth.getUser(uid);
const { displayName, email } = firebaseUser;
const displayUser = { _id, uid, displayName, email };
displayUsers.push(displayUser);
}
catch (error) {
next(error);
}
}
res.status(200).json(displayUsers);
}
catch (error) {
next(error);
}
});
exports.getUsers = getUsers;
/**
* Creates a new user, in both the Firebase and MongoDB databases
*/
const createUser = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
const errors = (0, express_validator_1.validationResult)(req);
try {
(0, validationErrorParser_1.default)(errors);
const { name, email, password } = req.body;
// First, call the Firebase API to create a new user
const firebaseUser = yield firebase_1.firebaseAuth.createUser({
displayName: name,
email,
password,
});
// Now, using the UID of the new Firebase user, create a user in our MongoDB database
const user = yield user_1.default.create({
uid: firebaseUser.uid,
// We can only create new staff accounts, not admin accounts.
role: user_1.UserRole.STAFF,
});
res.status(201).json(user);
}
catch (error) {
next(error);
}
});
exports.createUser = createUser;
/**
* Changes a user's password, finding the user by their UID
*/
const changeUserPassword = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
try {
const errors = (0, express_validator_1.validationResult)(req);
(0, validationErrorParser_1.default)(errors);
const { password } = req.body;
const { uid } = req.params;
const updatedUser = yield firebase_1.firebaseAuth.updateUser(uid, {
password,
});
yield (0, emails_1.sendPasswordChangedEmailToAdmin)(updatedUser.email);
res.status(200).json(updatedUser);
}
catch (error) {
next(error);
}
});
exports.changeUserPassword = changeUserPassword;
/**
* Sends an email to notify the user that their password has been reset.
*/
const notifyResetPassword = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
try {
const { userUid } = req;
const firebaseUser = yield firebase_1.firebaseAuth.getUser(userUid);
yield (0, emails_1.sendOwnPasswordChangedNotificationEmail)(firebaseUser.email);
yield (0, emails_1.sendPasswordChangedEmailToAdmin)(firebaseUser.email);
res.status(204).send();
}
catch (error) {
next(error);
}
});
exports.notifyResetPassword = notifyResetPassword;
/**
* Deletes a user from the Firebase and MongoDB databases
*/
const deleteUser = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
try {
const { uid } = req.params;
yield firebase_1.firebaseAuth.deleteUser(uid);
const deletedUser = yield user_1.default.deleteOne({ uid });
if (deletedUser === null) {
throw (0, http_errors_1.default)(404, "User not found at uid " + uid);
}
return res.status(204).send();
}
catch (error) {
next(error);
}
});
exports.deleteUser = deleteUser;
24 changes: 4 additions & 20 deletions backend/dist/src/controllers/vsr.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@ const http_errors_1 = __importDefault(require("http-errors"));
const furnitureItem_1 = __importDefault(require("../models/furnitureItem"));
const vsr_1 = __importDefault(require("../models/vsr"));
const emails_1 = require("../services/emails");
const vsrs_1 = require("../services/vsrs");
const validationErrorParser_1 = __importDefault(require("../util/validationErrorParser"));
const exceljs_1 = __importDefault(require("exceljs"));
const mongodb_1 = require("mongodb");
/**
* Gets all VSRs in the database. Requires the user to be signed in and have
* staff or admin permission.
*/
const getAllVSRS = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
try {
const vsrs = yield vsr_1.default.find();
const vsrs = yield (0, vsrs_1.retrieveVSRs)(req.query.search, req.query.status, req.query.incomeLevel, req.query.zipCode ? req.query.zipCode.split(",") : undefined, undefined);
res.status(200).json({ vsrs });
}
catch (error) {
Expand Down Expand Up @@ -238,30 +238,14 @@ const writeSpreadsheet = (plainVsrs, res) => __awaiter(void 0, void 0, void 0, f
yield workbook.xlsx.write(res);
});
const bulkExportVSRS = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b;
try {
const filename = "vsrs.xlsx";
const filename = `vsrs_${new Date().toISOString()}.xlsx`;
// Set some headers on the response so the client knows that a file is attached
res.set({
"Content-Disposition": `attachment; filename="${filename}"`,
"Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
let vsrs;
if (req.query.vsrIds && ((_a = req.query.vsrIds.length) !== null && _a !== void 0 ? _a : 0) > 0) {
// If the "vsrIds" query parameter exists and is non-empty, then find & export all VSRs
// with an _id in the vsrIds list
// Need to convert each ID string to an ObjectId object
const vsrObjectIds = (_b = req.query.vsrIds) === null || _b === void 0 ? void 0 : _b.split(",").map((_id) => new mongodb_1.ObjectId(_id));
vsrs = (yield vsr_1.default.find({
_id: {
$in: vsrObjectIds,
},
})).map((doc) => doc.toObject());
}
else {
// If the "vsrIds" query parameter is not provided or is empty, export all VSRs in the database
vsrs = (yield vsr_1.default.find()).map((doc) => doc.toObject());
}
const vsrs = yield (0, vsrs_1.retrieveVSRs)(req.query.search, req.query.status, req.query.incomeLevel, req.query.zipCode ? req.query.zipCode.split(",") : undefined, req.query.vsrIds ? req.query.vsrIds.split(",") : undefined);
yield writeSpreadsheet(vsrs, res);
}
catch (error) {
Expand Down
12 changes: 12 additions & 0 deletions backend/dist/src/models/confirmationEmail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mongoose_1 = require("mongoose");
/**
* A model for the confirmation email sent to veterans when they fill out the
* VSR. Only one instance of this model will ever exist at once.
*/
const confirmationEmailSchema = new mongoose_1.Schema({
// The HTML of the email
html: { type: String, required: true },
});
exports.default = (0, mongoose_1.model)("ConfirmationEmail", confirmationEmailSchema);
1 change: 1 addition & 0 deletions backend/dist/src/models/vsr.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,5 @@ const vsrSchema = new mongoose_1.Schema({
lastUpdated: { type: Date, required: true },
status: { type: String, required: true },
});
vsrSchema.index({ name: "text" });
exports.default = (0, mongoose_1.model)("VSR", vsrSchema);
36 changes: 36 additions & 0 deletions backend/dist/src/routes/confirmationEmail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const auth_1 = require("../middleware/auth");
const ConfirmationEmailController = __importStar(require("../controllers/confirmationEmail"));
const ConfirmationEmailValidator = __importStar(require("../validators/confirmationEmail"));
const router = express_1.default.Router();
router.get("/", auth_1.requireSignedIn, auth_1.requireAdmin, ConfirmationEmailController.getConfirmationEmail);
router.put("/", auth_1.requireSignedIn, auth_1.requireAdmin, ConfirmationEmailValidator.updateConfirmationEmail, ConfirmationEmailController.updateConfirmationEmail);
exports.default = router;
Loading

0 comments on commit 837fb44

Please sign in to comment.