From f9710d43876ac371f0b6cdeba8ac589d140b5138 Mon Sep 17 00:00:00 2001 From: Aarish <118203269+ImprobableGenius@users.noreply.github.com> Date: Sat, 24 May 2025 18:16:45 -0500 Subject: [PATCH 1/9] Fix insert request --- models/SiteModel.js | 4 ++-- routes/sites.js | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/models/SiteModel.js b/models/SiteModel.js index b5894b4..1b15056 100644 --- a/models/SiteModel.js +++ b/models/SiteModel.js @@ -17,10 +17,10 @@ class SiteModel { * @returns {Promise} - The result of the insert operation. */ async insert(name, domainName) { - const { error } = await supabase.from(siteModel.tableName).insert({ + const { data, error } = await supabase.from(SiteModel.tableName).insert({ name: name, domain_name: domainName, - }); + }).select(); if (error) { console.error('Error inserting site:', error); diff --git a/routes/sites.js b/routes/sites.js index 25db6db..9bf20b8 100644 --- a/routes/sites.js +++ b/routes/sites.js @@ -40,13 +40,15 @@ router.get('/:id', async function(req, res, next) { * // TODO: Implement error handling for duplicate domains * // TODO: Ability to add additional site properties (e.g., name, description) */ -router.post('/add/:domain', function(req, res, next) { - const domain = req.params.domain; - - const newSite = siteModel.insert(domain); +router.post('/add', async function(req, res, next) { + const domain = req.body.domain; + + const newSite = await siteModel.insert(domain, domain); + + console.log('New site created:', newSite); if (!newSite) { - return res.status(400).send('Error creating site'); + res.status(400).send('Error creating site'); } else { res.status(201).json(newSite); } From 1ef5815f651ec30d93117c9c1e567201de13e1dc Mon Sep 17 00:00:00 2001 From: Aarish <118203269+ImprobableGenius@users.noreply.github.com> Date: Sat, 24 May 2025 18:36:56 -0500 Subject: [PATCH 2/9] domain name validation logic --- helpers/utils.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 helpers/utils.js diff --git a/helpers/utils.js b/helpers/utils.js new file mode 100644 index 0000000..e9e7c46 --- /dev/null +++ b/helpers/utils.js @@ -0,0 +1,13 @@ +/** + * Utility functions for the application. + */ + +const isValidDomain = (domain) => { + // Regular expression to validate a domain name + const domainRegex = /^(?!:\/\/)([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/; + return domainRegex.test(domain); +} + +module.exports = { + isValidDomain +}; From 061f9121b9037ad3cad662201882a82186c08f6d Mon Sep 17 00:00:00 2001 From: Aarish <118203269+ImprobableGenius@users.noreply.github.com> Date: Sat, 24 May 2025 18:37:36 -0500 Subject: [PATCH 3/9] add insert validation --- models/SiteModel.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/models/SiteModel.js b/models/SiteModel.js index 1b15056..2a99592 100644 --- a/models/SiteModel.js +++ b/models/SiteModel.js @@ -3,6 +3,7 @@ */ const { supabase } = require('../auth'); +const { isValidDomain } = require('../helpers/utils'); class SiteModel { @@ -17,6 +18,21 @@ class SiteModel { * @returns {Promise} - The result of the insert operation. */ async insert(name, domainName) { + // validate inputs + if (!name || !domainName) { + throw new Error('Name and domain name are required to insert a site.'); + } + + // validate domain name format + if (!isValidDomain(domainName)) { + throw new Error('Invalid domain name format.'); + } + + // check if the domain name already exists + if (await this.getByDomainName(domainName).then(data => data.length !== 0)) { + throw new Error('Domain name already exists.'); + } + const { data, error } = await supabase.from(SiteModel.tableName).insert({ name: name, domain_name: domainName, @@ -64,6 +80,24 @@ class SiteModel { return data; } + /** + * Retrieves a site by its domain name. + * + * @param {string} domainName - The domain name of the site. + * + * @returns {Promise} - The site object. + */ + async getByDomainName(domainName) { + const { data, error } = await supabase.from(SiteModel.tableName).select('*').eq('domain_name', domainName); + + if (error) { + console.error('Error fetching site by domain name:', error); + throw error; + } + + return data; + } + } module.exports = SiteModel; \ No newline at end of file From c364e31ee38fbe5cdd7f563fec2a70e190f6184e Mon Sep 17 00:00:00 2001 From: Aarish <118203269+ImprobableGenius@users.noreply.github.com> Date: Sat, 24 May 2025 18:37:54 -0500 Subject: [PATCH 4/9] handle exceptions while adding the site --- routes/sites.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/routes/sites.js b/routes/sites.js index 9bf20b8..c6c8a38 100644 --- a/routes/sites.js +++ b/routes/sites.js @@ -36,16 +36,19 @@ router.get('/:id', async function(req, res, next) { * * Creates a new site with the provided domain name. * - * // TODO: Implement validation for domain name format - * // TODO: Implement error handling for duplicate domains * // TODO: Ability to add additional site properties (e.g., name, description) */ router.post('/add', async function(req, res, next) { const domain = req.body.domain; + let newSite = null; - const newSite = await siteModel.insert(domain, domain); - - console.log('New site created:', newSite); + // insert method passes a lot of validation errors to the caller + try { + newSite = await siteModel.insert(domain, domain); + } catch (error) { + console.error('Error creating site:', error); + return res.status(400).send('Error creating site: ' + error.message); + } if (!newSite) { res.status(400).send('Error creating site'); From 512d18ec2331179bd854eea49be5e6645d1e3086 Mon Sep 17 00:00:00 2001 From: Aarish <118203269+ImprobableGenius@users.noreply.github.com> Date: Sat, 24 May 2025 21:09:27 -0500 Subject: [PATCH 5/9] update index.js to show domain_name --- views/index.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/index.ejs b/views/index.ejs index 966c8f5..c2253c1 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -6,7 +6,7 @@
    <% for (let i = 0; i < sites.length; i++) { %> -
  • <%= sites[i].name %>
  • +
  • <%= sites[i].domain_name %>
  • <% } %>
From b9967a8e66d581799fbb259a84d0f31fd3ce1e6e Mon Sep 17 00:00:00 2001 From: Aarish <118203269+ImprobableGenius@users.noreply.github.com> Date: Sun, 25 May 2025 16:58:34 -0500 Subject: [PATCH 6/9] handle errors thrown by model incase there is any error while fetching the site --- routes/sites.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/routes/sites.js b/routes/sites.js index c6c8a38..92914ba 100644 --- a/routes/sites.js +++ b/routes/sites.js @@ -21,8 +21,14 @@ router.get('/', async function(req, res, next) { */ router.get('/:id', async function(req, res, next) { const siteId = req.params.id; + let site = null; - const site = await siteModel.getById(siteId); + try { + site = await siteModel.getById(siteId); + } catch (error) { + console.error('Error fetching site by ID:', error); + return res.status(400).send('Error fetching site: ' + error.message); + } if (!site) { return res.status(404).send('Site not found'); From f28328dcc4f5e940ac7333dd3e21f42b06a4f1d7 Mon Sep 17 00:00:00 2001 From: Aarish <118203269+ImprobableGenius@users.noreply.github.com> Date: Sun, 25 May 2025 17:06:37 -0500 Subject: [PATCH 7/9] Remove name from insert method - this is removed from db schema --- models/SiteModel.js | 5 ++--- routes/sites.js | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/models/SiteModel.js b/models/SiteModel.js index 2a99592..4875b4b 100644 --- a/models/SiteModel.js +++ b/models/SiteModel.js @@ -17,9 +17,9 @@ class SiteModel { * * @returns {Promise} - The result of the insert operation. */ - async insert(name, domainName) { + async insert(domainName) { // validate inputs - if (!name || !domainName) { + if (!domainName) { throw new Error('Name and domain name are required to insert a site.'); } @@ -34,7 +34,6 @@ class SiteModel { } const { data, error } = await supabase.from(SiteModel.tableName).insert({ - name: name, domain_name: domainName, }).select(); diff --git a/routes/sites.js b/routes/sites.js index 92914ba..f0753da 100644 --- a/routes/sites.js +++ b/routes/sites.js @@ -37,6 +37,29 @@ router.get('/:id', async function(req, res, next) { } }); +/** + * GET site by domain name. + * + * Returns a specific site by its domain name in JSON format. + */ +router.get('/:domain', async function(req, res, next) { + const domainName = req.params.domain; + let site = null; + + try { + site = await siteModel.getByDomainName(domainName); + } catch (error) { + console.error('Error fetching site by domain name:', error); + return res.status(400).send('Error fetching site: ' + error.message); + } + + if (!site || site.length === 0) { + return res.status(404).send('Site not found'); + } else { + res.json(site[0]); // Return the first match + } +}); + /** * POST create a new site. * @@ -50,7 +73,7 @@ router.post('/add', async function(req, res, next) { // insert method passes a lot of validation errors to the caller try { - newSite = await siteModel.insert(domain, domain); + newSite = await siteModel.insert(domain); } catch (error) { console.error('Error creating site:', error); return res.status(400).send('Error creating site: ' + error.message); From 57c393d9398924a5cec6657f94410c5d281ae81a Mon Sep 17 00:00:00 2001 From: Aarish <118203269+ImprobableGenius@users.noreply.github.com> Date: Sun, 25 May 2025 17:11:34 -0500 Subject: [PATCH 8/9] Add a method to fetch by domain --- routes/sites.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/sites.js b/routes/sites.js index f0753da..a2cb1e5 100644 --- a/routes/sites.js +++ b/routes/sites.js @@ -42,7 +42,7 @@ router.get('/:id', async function(req, res, next) { * * Returns a specific site by its domain name in JSON format. */ -router.get('/:domain', async function(req, res, next) { +router.get('/domain/:domain', async function(req, res, next) { const domainName = req.params.domain; let site = null; From f86bfee3f391615f76529050deff3fce0a11e81c Mon Sep 17 00:00:00 2001 From: Aarish <118203269+ImprobableGenius@users.noreply.github.com> Date: Sun, 25 May 2025 17:14:26 -0500 Subject: [PATCH 9/9] Updat name - getByDomainName() returns an array --- routes/sites.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/routes/sites.js b/routes/sites.js index a2cb1e5..7817f3c 100644 --- a/routes/sites.js +++ b/routes/sites.js @@ -44,19 +44,21 @@ router.get('/:id', async function(req, res, next) { */ router.get('/domain/:domain', async function(req, res, next) { const domainName = req.params.domain; - let site = null; + let sites = null; try { - site = await siteModel.getByDomainName(domainName); + sites = await siteModel.getByDomainName(domainName); } catch (error) { console.error('Error fetching site by domain name:', error); return res.status(400).send('Error fetching site: ' + error.message); } - if (!site || site.length === 0) { + console.log('Site found:', sites); + + if (!sites || sites.length === 0) { return res.status(404).send('Site not found'); } else { - res.json(site[0]); // Return the first match + res.json(sites[0]); // Return the first match } });