Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions dbTools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const { v4: uuidv4 } = require('uuid')
const { Admin, ChatHistory, ChatMessage, FoodListing, Guest, Host, Reservation, Review, Warning, sequelize } = require('./models')
require('dotenv').config()

async function resetDB() {
console.log("Dropping tables...")
try {
await sequelize.drop()
console.log("Tables dropped!")
} catch (err) {
console.error(err)
}
}

async function clearFiles() {
console.log("Clearing files...")
const FileManager = require("./services/FileManager")
const setupResult = await FileManager.setup();
if (setupResult !== true) {
console.error(setupResult)
process.exit()
}

const deleteAllResult = await FileManager.deleteAll();
if (deleteAllResult !== true) {
console.error(deleteAllResult)
process.exit()
}
console.log("Files cleared!")
}

sequelize.sync({ alter: true })
.then(() => {
if (process.argv[2].toLowerCase() == "reset") {
resetDB()
} else if (process.argv[2].toLowerCase() == "clearfiles") {
clearFiles()
} else {
console.log("No tool activated.")
return
}
})
.catch(err => {
console.error(err)
process.exit()
})
30 changes: 28 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ require('./services/BootCheck').check()
const express = require('express');
const cors = require('cors');
const { v4: uuidv4 } = require('uuid')
const { FoodListing } = require('./models')
const { FoodListing, Host } = require('./models')
require('dotenv').config()

const env = process.env.DB_CONFIG || 'development';
Expand Down Expand Up @@ -58,7 +58,7 @@ app.use("/createAccount", require('./routes/identity/createAccount'));
app.use("/loginAccount", require('./routes/identity/loginAccount'));
app.use("/accountRecovery", require('./routes/identity/accountRecovery'));
app.use("/listings", require("./routes/listings/listings"));
app.use("/", require("./routes/orders/reservation"));
app.use("/", require("./routes/orders/listingDetails"));

async function onDBSynchronise() {
const currentDatetime = new Date()
Expand All @@ -85,6 +85,32 @@ async function onDBSynchronise() {
Universal.data["DUMMY_LISTING_ID"] = newListing.listingID
console.log(`Created dummy listing with ID: ${newListing.listingID}`)
}

const joshuasHost = await Host.findByPk("272d3d17-fa63-49c4-b1ef-1a3b7fe63cf4")
if (!joshuasHost) {
const newHost = await Host.create({
"userID": "272d3d17-fa63-49c4-b1ef-1a3b7fe63cf4",
"username": "Jamie Oliver",
"email": "jamie_oliver@gmail.com",
"password": "123456789",
"contactNum": "81118222",
"address": "12 Washington Avenue",
"emailVerified": false,
"favCuisine": "Mexican",
"mealsMatched": "0",
"foodRating": "4",
"hygieneGrade": "5",
"paymentImage": "https://savh.org.sg/wp-content/uploads/2020/05/QRCodeS61SS0119JDBS.png"
})

if (!newHost) {
console.log("WARNING: Failed to create dummy host.")
} else {
console.log("Created dummy host.")
}
} else {
console.log("Found dummy host existing already, skipping creation.")
}
}

// Start server
Expand Down
1 change: 0 additions & 1 deletion models/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ if (config.logging == true) {
* @type {Sequelize.Sequelize}
*/
let sequelize;
process.env.DB_MODE = "mysql"
if (process.env.DB_MODE == "mysql") {
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
Expand Down
2 changes: 1 addition & 1 deletion routes/cdn/contentDelivery.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ router.get("/getImageForListing", async (req, res) => {
return;
}
res.status(200).sendFile(findImageName.substring("SUCCESS: File path: ".length))
Logger.log(`CDN GETIMAGEFORLISTING: Image(s) for listing ${listingID} sent successfully.`)
// Logger.log(`CDN GETIMAGEFORLISTING: Image(s) for listing ${listingID} sent successfully.`)
return;
});

Expand Down
20 changes: 18 additions & 2 deletions routes/cdn/coreData.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,29 @@ const { FoodListing, Host, Guest, Admin } = require("../../models");
router.get("/listings", async (req, res) => { // GET all food listings
try {
const foodListings = await FoodListing.findAll();
foodListings.map(listing => listing.images = listing.images.split("|"));
foodListings.map(listing => (listing.images == null || listing.images == "") ? listing.images = [] : listing.images = listing.images.split("|"));
res.status(200).json(foodListings);
} catch (error) {
res.status(500).send("ERROR: Internal server error");
}
});

router.get("/getListing", async (req, res) => {
const listingID = req.query.id || req.body.listingID;
if (!listingID) {
res.status(400).send("ERROR: Listing ID not provided.")
return
}

const listing = await FoodListing.findByPk(listingID)
if (!listing || listing == null) {
res.status(404).send("ERROR: Listing not found")
return
}
res.json(listing)
return
})

router.get("/accountInfo", async (req, res) => { // GET account information
try {
const targetUserID = req.query.userID;
Expand Down Expand Up @@ -64,7 +80,7 @@ router.get("/accountInfo", async (req, res) => { // GET account information
accountInfo.mealsMatched = user.mealsMatched;
}

console.log(`Account info for userID ${targetUserID}: ${JSON.stringify(accountInfo)}`)
// console.log(`Account info for userID ${targetUserID}: ${JSON.stringify(accountInfo)}`)
res.status(200).json(accountInfo);

} catch (err) {
Expand Down
65 changes: 53 additions & 12 deletions routes/orders/reservation.js → routes/orders/listingDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,7 @@ const { FoodListing } = require('../../models')
const Universal = require('../../services/Universal');
const FileManager = require('../../services/FileManager');
const { storeFile } = require('../../middleware/storeFile');

router.get("/listingDetails", async (req, res) => {
const dummyListingID = Universal.data["DUMMY_LISTING_ID"]
const listing = await FoodListing.findByPk(dummyListingID)
if (!listing || listing == null) {
res.status(404).send("ERROR: Listing not found")
return
}
res.json(listing)
})
const Logger = require('../../services/Logger');

router.post("/uploadListingImage", async (req, res) => {
storeFile(req, res, async (err) => {
Expand All @@ -22,8 +13,7 @@ router.post("/uploadListingImage", async (req, res) => {
return
}

// const listingID = req.listingID
const listingID = Universal.data["DUMMY_LISTING_ID"]
const listingID = req.body.listingID
const listing = await FoodListing.findByPk(listingID)
if (!listing) {
res.status(404).send("ERROR: Listing not found.")
Expand All @@ -50,11 +40,60 @@ router.post("/uploadListingImage", async (req, res) => {
}
await listing.save()
res.send("SUCCESS: File uploaded successfully.")

Logger.log(`ORDERS LISTINGDETAILS UPLOADLISTINGIMAGE: Uploaded image '${req.file.filename}' for listing '${listingID}'.`)
return
}
})
})

router.post("/deleteListingImage", async (req, res) => {
if (!req.body.listingID || !req.body.imageName) {
res.status(400).send("ERROR: One or more required payloads were not provided.")
return
}

const listingID = req.body.listingID
const imageName = req.body.imageName

const listing = await FoodListing.findByPk(listingID)
if (!listing) {
res.status(404).send("ERROR: Listing not found.")
return
}

if (listing.images == null || !listing.images.split("|").includes(imageName)) {
res.status(404).send("ERROR: Image not found in listing.")
return
}

try {
const fileDelete = await FileManager.deleteFile(imageName)
if (fileDelete !== true) {
if (fileDelete != "ERROR: File does not exist.") {
Logger.log("ORDERS LISTINGDETAILS DELETELISTINGIMAGE ERROR: Failed to delete image from storage; error: " + fileDelete)
res.status(500).send("ERROR: Failed to delete image.")
return
} else {
Logger.log("ORDERS LISTINGDETAILS DELETELISTINGIMAGE WARNING: Unexpected FM response in deleting image from storage; response: " + fileDelete)
}
}

const listingImages = listing.images.split("|")
const newImages = listingImages.filter(image => image != imageName)
listing.images = newImages.join("|")
await listing.save()
} catch (err) {
Logger.log("ORDERS LISTINGDETAILS DELETELISTINGIMAGE ERROR: Failed to delete image attached to listing in database; error: " + err)
res.status(500).send("ERROR: Failed to delete image.")
return
}

Logger.log(`ORDERS LISTINGDETAILS DELETELISTINGIMAGE: Deleted image '${imageName}' from listing '${listingID}'.`)
res.send("SUCCESS: Image deleted successfully.")
return
})

router.post("/updateListing", async (req, res) => {
if (!req.body.listingID) {
res.status(400).send("ERROR: Listing ID not provided.")
Expand All @@ -71,6 +110,8 @@ router.post("/updateListing", async (req, res) => {
try {
listing.update(req.body)
await listing.save()

Logger.log(`ORDERS LISTINGDETAILS UPDATELISTING: Listing '${listingID}' updated.`)
res.send("SUCCESS: Listing updated successfully.")
return
} catch (err) {
Expand Down
18 changes: 18 additions & 0 deletions services/FileManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,24 @@ class FileManager {

return true;
}

static async deleteAll() {
if (!this.checkPermission()) { return "ERROR: FileManager operation permission denied." }
if (!this.#initialized) { return 'ERROR: FileManager must be setup first.' }

// Delete files on cloud storage
const deleteAllResult = await FireStorage.deleteAll();
if (deleteAllResult !== true) {
return `ERROR: ${deleteAllResult}`
}

// Clear file store context and file store
this.#fileStoreContext = {}
this.persistFileStoreContext();
this.cleanupNonmatchingFiles();

return true;
}
}

module.exports = FileManager;
12 changes: 12 additions & 0 deletions services/FireStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ class FireStorage {
}
}

static async deleteAll() {
if (!this.checkPermission()) { return "ERROR: FireStorage operation permission denied." }
if (!this.#initialized) { return 'ERROR: FireStorage must be initialized first.' }

try {
await this.#bucket.deleteFiles({ force: true });
return true;
} catch (err) {
return `ERROR: ${err}`
}
}

static async fileExistsAt(filePath) {
if (!this.checkPermission()) { return "ERROR: FireStorage operation permission denied." }
if (!this.#initialized) { return 'ERROR: FireStorage must be initialized first.' }
Expand Down