From a16426268222bbb7dc55ffa8041a9ba33f92f098 Mon Sep 17 00:00:00 2001 From: Eric Fithian Date: Wed, 10 Apr 2024 16:50:02 -0600 Subject: [PATCH] added 3 functions, getPublicVendors, getPublicVendorById, getSelfVendor. Now get all vendors route is admin protected. --- backend/controllers/VendorController.js | 82 +++++++++++++++++-- backend/routes/VendorRouter.js | 14 +++- frontend/src/objects/Vendor.js | 4 +- .../src/services/Vendors/VendorsRepository.js | 30 +++++++ .../src/services/Vendors/VendorsService.js | 47 +++++++++++ sql-scripts/init.sql | 3 +- 6 files changed, 169 insertions(+), 11 deletions(-) diff --git a/backend/controllers/VendorController.js b/backend/controllers/VendorController.js index a6a9784..beff784 100644 --- a/backend/controllers/VendorController.js +++ b/backend/controllers/VendorController.js @@ -102,6 +102,26 @@ const getVendors = async (req, res, next) => { } }; +const getPublicVendors = async (req, res, next) => { + try { + // Retrieve all public vendors from the database + const vendors = await db.manyOrNone( + 'SELECT * FROM vendor_full WHERE is_public = TRUE', + ); + // If vendors are found, add them to res.locals.data + if (vendors.length) { + res.locals.data = vendors; + next(); // Proceed to the next middleware or route handler + } else { + // If no vendors are found, send a message indicating this + res.status(404).json({message: 'No vendors found'}); + } + } catch (error) { + console.error(error); + res.status(500).json({error: 'Internal Server Error'}); + } +}; + const getVendorById = async (req, res, next) => { const {vendorId} = req.params; @@ -123,10 +143,52 @@ const getVendorById = async (req, res, next) => { } }; +const getPublicVendorById = async (req, res, next) => { + const {vendorId} = req.params; + + try { + const vendor = await db.oneOrNone( + 'SELECT * FROM vendor_full WHERE vendor_id = $1 AND is_public = TRUE', + [vendorId], + ); + if (vendor) { + // Store the vendor data in res.locals.data for the middleware + res.locals.data = vendor; + next(); // Pass control to the next middleware + } else { + res.status(404).json({message: 'Vendor not found'}); + } + } catch (err) { + console.error(err); + res.status(500).json({error: 'Internal Server Error'}); + } +}; + +const getSelfVendor = async (req, res, next) => { + const vendor = res.locals.vendor; + + try { + const selfVendor = await db.oneOrNone( + 'SELECT * FROM vendor_full WHERE vendor_id = $1', + [vendor.vendor_id], + ); + if (selfVendor) { + // Store the vendor data in res.locals.data for the middleware + res.locals.data = selfVendor; + next(); // Pass control to the next middleware + } else { + res.status(404).json({message: 'Vendor not found'}); + } + } catch (err) { + console.error(err); + res.status(500).json({error: 'Internal Server Error'}); + } +}; + // Registers the vendor in the database const createVendor = async (req, res, next) => { // Get the values from the request body - const {name, email, phoneNumber, password, website} = req.body; + const {name, email, phoneNumber, password, website, is_public} = req.body; // Checks if the required fields are present if (!password || !email || !name) { @@ -156,9 +218,10 @@ const createVendor = async (req, res, next) => { email, \ phone_number, \ password, \ - website\ - ) VALUES ($1, $2, $3, $4, $5)', - [name, email, phoneNumber, passwordHash, website], + website, \ + is_public\ + ) VALUES ($1, $2, $3, $4, $5, $6)', + [name, email, phoneNumber, passwordHash, website, is_public], ); } catch (err) { // Duplicate emails are not allowed @@ -268,6 +331,7 @@ const updateVendor = async (req, res, next) => { phone_number, password, website, + is_public, } = req.body; // Hashes the password using bcrypt @@ -288,9 +352,10 @@ const updateVendor = async (req, res, next) => { email = $2, \ phone_number = $3, \ password = $4, \ - website = $5 \ - WHERE vendor_id = $6', - [name, email, phone_number, passwordHash, website, vendorId], + website = $5, \ + is_public = $6 \ + WHERE vendor_id = $7', + [name, email, phone_number, passwordHash, website, is_public, vendorId], ); } catch (err) { // Duplicate emails are not allowed @@ -373,8 +438,11 @@ const verifyVendorHasSameVendorId = async (req, res, next) => { module.exports = { getVendor, getVendors, + getPublicVendors, createVendor, getVendorById, + getPublicVendorById, + getSelfVendor, authenticateVendor, createEventRequest, getEventRequest, diff --git a/backend/routes/VendorRouter.js b/backend/routes/VendorRouter.js index b0726a0..0418f94 100644 --- a/backend/routes/VendorRouter.js +++ b/backend/routes/VendorRouter.js @@ -3,8 +3,11 @@ const router = express.Router(); const { getVendor, getVendors, + getPublicVendors, createVendor, getVendorById, + getPublicVendorById, + getSelfVendor, authenticateVendor, createEventRequest, getEventRequest, @@ -28,11 +31,20 @@ const { router.post('/login', getVendor, authenticateVendor, signToken, sendSuccessResponse); // Fetches all vendors -router.get('/', getVendors, sendSuccessResponse); +router.get('/', verify('admin'), getVendors, sendSuccessResponse); + +// Fetches public vendors +router.get('/public', getPublicVendors, sendSuccessResponse); // Fetches a single vendor by ID router.get('/:vendorId', getVendorById, sendSuccessResponse); +// Fetches a single vendor by ID that is public +router.get('/public/:vendorId', verify('admin'), getPublicVendorById, sendSuccessResponse); + +// Fetches vendor that is self +router.get('/self', verify('vendor'), getSelfVendor, sendSuccessResponse); + // Creates a new vendor router.post('/', createVendor, sendSuccessResponse); diff --git a/frontend/src/objects/Vendor.js b/frontend/src/objects/Vendor.js index 0cb6f8f..1482f4c 100644 --- a/frontend/src/objects/Vendor.js +++ b/frontend/src/objects/Vendor.js @@ -9,13 +9,13 @@ export default class Vendor { website: string - (Optional) website of the vendor. phone_number: string - (Optional) phone number of the vendor. */ - constructor(id, name, email, website = undefined, phoneNumber = undefined, image = undefined) { - this.id = id; + constructor(id, name, email, website = undefined, phoneNumber = undefined, image = undefined, isPublic = false) { this.name = name; this.email = email; this.website = website; this.phoneNumber = phoneNumber; this.image = image; + this.is_public = isPublic; } // Create a vendor object from json representation diff --git a/frontend/src/services/Vendors/VendorsRepository.js b/frontend/src/services/Vendors/VendorsRepository.js index 7202173..d5406ae 100644 --- a/frontend/src/services/Vendors/VendorsRepository.js +++ b/frontend/src/services/Vendors/VendorsRepository.js @@ -13,6 +13,16 @@ export default class VendorsRepository { } } + async getPublicVendors() { + try { + const response = await this.httpClient.axiosInstance.get('/vendors/public'); + return response.data; + } catch (error) { + console.error('Error fetching public vendors'); + return undefined; + } + } + async getVendorById(vendorId) { try { const response = await this.httpClient.axiosInstance.get(`/vendors/${vendorId}`); @@ -23,6 +33,26 @@ export default class VendorsRepository { } } + async getPublicVendorById(vendorId) { + try { + const response = await this.httpClient.axiosInstance.get(`/vendors/public/${vendorId}`); + return response.data; + } catch (error) { + console.error(`Error fetching public vendor with ID ${vendorId}:`); + return undefined; + } + } + + async getSelfVendor() { + try { + const response = await this.httpClient.axiosInstance.get('/vendors/self'); + return response.data; + } catch (error) { + console.error('Error fetching self vendor:'); + return undefined; + } + } + async authenticateVendor(vendorData) { try { const response = await this.httpClient.axiosInstance.post('vendors/login', vendorData); diff --git a/frontend/src/services/Vendors/VendorsService.js b/frontend/src/services/Vendors/VendorsService.js index 9b4f664..f4f5d0a 100644 --- a/frontend/src/services/Vendors/VendorsService.js +++ b/frontend/src/services/Vendors/VendorsService.js @@ -23,6 +23,23 @@ export default class VendorsService { )); } + async getPublicVendors() { + const vendorsData = await this.vendorsRepository.getPublicVendors(); + if (vendorsData == undefined) { + return undefined; + } + + return vendorsData.map((data) => new Vendor( + data.vendor_id, + data.name, + data.email, + data.website, + data.phone_number, + data.image, + data.is_public, + )); + } + async getVendorById(vendorId) { const vendorData = await this.vendorsRepository.getVendorById(vendorId); return new Vendor( @@ -32,6 +49,33 @@ export default class VendorsService { vendorData.website, vendorData.phone_number, vendorData.image, + vendorData.is_public, + ); + } + + async getPublicVendorById(vendorId) { + const vendorData = await this.vendorsRepository.getVendorById(vendorId); + return new Vendor( + vendorData.vendor_id, + vendorData.name, + vendorData.email, + vendorData.website, + vendorData.phone_number, + vendorData.image, + vendorData.is_public, + ); + } + + async getSelfVendor() { + const vendorData = await this.vendorsRepository.getOwnProfile(); + return new Vendor( + vendorData.vendor_id, + vendorData.name, + vendorData.email, + vendorData.website, + vendorData.phone_number, + vendorData.image, + vendorData.is_public, ); } @@ -53,6 +97,7 @@ export default class VendorsService { website: vendor.website, phoneNumber: vendor.phoneNumber, image: vendor.image, + is_public: data.is_public, }; return await this.vendorsRepository.createVendor(vendorData); } @@ -63,6 +108,7 @@ export default class VendorsService { email: vendor.email, website: vendor.website, phone_number: vendor.phoneNumber, + is_public: vendor.is_public, }; return await this.vendorsRepository.updateSelfVendor(vendorData); } @@ -74,6 +120,7 @@ export default class VendorsService { website: vendor.website, phoneNumber: vendor.phoneNumber, image: vendor.image, + is_public: vendor.is_public, }; return await this.vendorsRepository.updateVendor(vendor.vendorId, vendorData); } diff --git a/sql-scripts/init.sql b/sql-scripts/init.sql index ac3674c..d5b39e9 100644 --- a/sql-scripts/init.sql +++ b/sql-scripts/init.sql @@ -17,7 +17,8 @@ CREATE TABLE IF NOT EXISTS Vendors ( phone_number VARCHAR(31), website VARCHAR(2083), email VARCHAR(320) UNIQUE NOT NULL, - password VARCHAR(255) NOT NULL -- Remember to hash the passwords before storing + password VARCHAR(255) NOT NULL, -- Remember to hash the passwords before storing + is_public BOOLEAN DEFAULT FALSE ); -- Vendor Profile Picutres table