-
Notifications
You must be signed in to change notification settings - Fork 0
First PR (Linked express router, added backend routes and some test routes, implemented error handling) #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
6e60826
Added file
Sadliquid 41eb3c2
Merge pull request #2 from MakanMatch/main
Prakhar896 ce84a48
Merge pull request #7 from MakanMatch/main
Prakhar896 ed46f25
Added backend routes for creating sample host, creating food listings…
Sadliquid 2fd7411
Implemented image upload to Firebase Cloud Storage
Sadliquid e6ef66c
Added updating of images to the firebase public url for rendering on UI
Sadliquid 8606c8c
Updated host UUID (hardcoded)
Sadliquid 6c1220a
Fixed bug regarding SVG uploads
Sadliquid 1bdd544
Tidied up imports and used Logger for successful image uploads
Sadliquid d11f681
Re-organised middleware
Sadliquid 206e53d
Thoroughly enhanced robust-ness of backend logic, and error handling.…
Sadliquid f3336ec
Adjusted date-time formatting to conform to ISO string standard
Sadliquid 4c9c0af
Standardised all responses to include status codes
Sadliquid 45ddf16
Added in missing milliseconds in ISO string format. very very small c…
Sadliquid fe7790e
Moved Logger logging statement to API endpoint where image is actuall…
Sadliquid d8e6bf6
Placed all constants in one line and removed custom length for genera…
Sadliquid 7a95ef2
Updated imports, simplified createHost route and removed verifyListing
Sadliquid e1c7544
Combined endpoints and fixed image bug
Sadliquid a7abd97
Added additional check if requested image is tied to correct listing
Sadliquid 7d57969
merging paths
Prakhar896 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| const path = require('path'); | ||
|
|
||
| const ListingsFileFilter = function (req, file, cb) { | ||
| const allowedMIMETypes = /jpeg|jpg|png|svg\+xml/; | ||
| const allowedExtensions = /jpeg|jpg|png|svg/; | ||
|
|
||
| const mimetype = allowedMIMETypes.test(file.mimetype); | ||
| const extname = allowedExtensions.test(path.extname(file.originalname).toLowerCase()); | ||
|
|
||
| if (mimetype && extname) { | ||
| cb(null, true); | ||
| } else { | ||
| cb(new Error('Only .jpeg, .jpg, .png, and .svg files are allowed'), false); | ||
| } | ||
| }; | ||
|
|
||
| module.exports = ListingsFileFilter; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| const multer = require('multer'); | ||
| const path = require('path'); | ||
| const { v4: uuidv4 } = require('uuid'); | ||
| const ListingsFileFilter = require('./ListingsFileFilter'); | ||
|
|
||
|
|
||
| const storage = multer.diskStorage({ | ||
| destination: (req, file, callback) => { | ||
| callback(null, path.join(__dirname, '../FileStore')) | ||
| }, | ||
| filename: (req, file, callback) => { | ||
| callback(null, uuidv4() + path.extname(file.originalname)) | ||
| } | ||
| }) | ||
|
|
||
| const ListingsStoreFile = multer({ | ||
| storage: storage, | ||
| limits: { fileSize: 1024 * 1024 * 10 }, | ||
| fileFilter: ListingsFileFilter | ||
| }) | ||
| .single('images') | ||
|
|
||
| module.exports = ListingsStoreFile; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| const express = require("express"); | ||
| const multer = require("multer"); | ||
| const router = express.Router(); | ||
| const { FoodListing } = require("../../models"); | ||
| const { Host } = require("../../models"); | ||
| const Universal = require("../../services/Universal"); | ||
| const FileManager = require("../../services/FileManager"); | ||
| const ListingsStoreFile = require("../../middleware/ListingsStoreFile"); | ||
|
|
||
| router.post("/createHost", async (req, res) => { | ||
| // POST a new host before creating a food listing | ||
| const data = req.body; | ||
| try { | ||
| const newHost = await Host.create(data); | ||
| res.status(200).json({ | ||
| message: "Host created successfully!", | ||
| newHost, | ||
| }); | ||
| } catch (error) { | ||
| console.error("Error creating host:", error); | ||
| res.status(400).json({ | ||
| error: "One or more required payloads were not provided.", | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
| router.get("/hostInfo", async (req, res) => { | ||
| try { | ||
| // GET host info before displaying listing's host name | ||
| const hostInfo = await Host.findByPk( | ||
| "272d3d17-fa63-49c4-b1ef-1a3b7fe63cf4" | ||
| ); // hardcoded for now | ||
| if (hostInfo) { | ||
| res.status(200).json(hostInfo); | ||
| } else { | ||
| res.status(404).json({ error: "Host not found" }); | ||
| } | ||
| } catch (error) { | ||
| console.error("Error fetching host info:", error); | ||
| res.status(500).json({ error: "Failed to fetch host info" }); | ||
| } | ||
| }); | ||
|
|
||
| router.get("/", async (req, res) => { | ||
| // GET all food listings | ||
| try { | ||
| const foodListings = await FoodListing.findAll(); | ||
| res.status(200).json(foodListings); | ||
| } catch (error) { | ||
| console.error("Error retrieving food listings:", error); | ||
| res.status(500).json({ error: "Internal server error" }); | ||
| } | ||
| }); | ||
|
|
||
| // Flow: addListing -> refreshes -> fetchListings -> Image component sources from /getImageForListing?listingID=<value>&imageName=<value> -> send file back down -> Image component renders | ||
|
|
||
| router.get("/getImageForListing", async (req, res) => { | ||
| const { listingID, imageName } = req.query; | ||
| if (!listingID || !imageName) { | ||
| res.status(400).send("ERROR: Invalid request parameters."); | ||
| console.error("Invalid request parameters."); | ||
| return; | ||
| } | ||
|
|
||
| // Find the listing | ||
| const findListing = await FoodListing.findByPk(listingID); | ||
| const findImageName = await FileManager.prepFile(imageName); | ||
| if (!findImageName) { | ||
| res.status(404).send("ERROR: Image not found."); | ||
| console.error("Image not found."); | ||
| return; | ||
| } | ||
| if (!findListing) { | ||
| res.status(404).send("ERROR: Listing not found."); | ||
| console.error("Listing not found."); | ||
| return; | ||
| } | ||
| if (findListing.images !== imageName) { | ||
| res.status(404).send("ERROR: Requested image does not belong to its corresponding listing."); | ||
| console.error("Requested image does not belong to its corresponding listing."); | ||
| return; | ||
| } | ||
| res.status(200).sendFile(findImageName.substring("SUCCESS: File path: ".length)) | ||
| return; | ||
| }); | ||
|
|
||
| router.post("/addListing", async (req, res) => { | ||
|
Sadliquid marked this conversation as resolved.
|
||
| ListingsStoreFile(req, res, async (err) => { | ||
| console.log(req.body); | ||
| if ( | ||
| !req.body.title || | ||
| !req.body.shortDescription || | ||
| !req.body.longDescription || | ||
| !req.body.portionPrice || | ||
| !req.body.totalSlots || | ||
| !req.body.datetime | ||
| ) { | ||
| res.status(400).send( | ||
| "One or more required payloads were not provided" | ||
| ); | ||
| return; | ||
| } else { | ||
| if (err instanceof multer.MulterError) { | ||
| console.error("Multer error:", err); | ||
| res.status(400).send("Image upload error"); | ||
| } else if (err) { | ||
| console.error("Unknown error occured during upload:", err); | ||
| res.status(500).send("Internal server error"); | ||
| } else if (!req.file) { | ||
| res.status(400).send("No file was selected to upload"); | ||
| } else { | ||
| const uploadImageResponse = await FileManager.saveFile( | ||
| req.file.filename | ||
| ); | ||
| if (uploadImageResponse) { | ||
| const formattedDatetime = req.body.datetime + ":00.000Z"; | ||
| const listingDetails = { | ||
| listingID: Universal.generateUniqueID(), | ||
| title: req.body.title, | ||
| images: req.file.filename, | ||
| shortDescription: req.body.shortDescription, | ||
| longDescription: req.body.longDescription, | ||
| portionPrice: req.body.portionPrice, | ||
| totalSlots: req.body.totalSlots, | ||
| datetime: formattedDatetime, | ||
| approxAddress: "Yishun, Singapore", // hardcoded for now | ||
| address: | ||
| "1 North Point Dr, #01-164/165 Northpoint City, Singapore 768019", // hardcoded for now | ||
| hostID: "272d3d17-fa63-49c4-b1ef-1a3b7fe63cf4", // hardcoded for now | ||
| published: true, | ||
| }; | ||
| const addListingResponse = await FoodListing.create( | ||
| listingDetails | ||
| ); | ||
| if (addListingResponse) { | ||
| res.status(200).json({ | ||
| message: "Food listing created successfully", | ||
| listingDetails, | ||
| }); | ||
| return; | ||
| } else { | ||
| res.status(400).send("Failed to create food listing"); | ||
| return; | ||
| } | ||
| } else { | ||
| res.status(400).send("Failed to upload image"); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| module.exports = router; | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will need to change to
findListing.images.split("|")later on. Do take note.