From 7779c21cdb4a4ede91982d3bb535245c66649a7b Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 16 Oct 2020 17:37:34 -0500 Subject: [PATCH 01/52] Update enum.js add status flag, EventStatus --- public/js/enum.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/public/js/enum.js b/public/js/enum.js index 21a3090e..af1cfee0 100644 --- a/public/js/enum.js +++ b/public/js/enum.js @@ -1,3 +1,14 @@ var ProjectStatus = { Starting:"Starting", InProgress:"In Progress", OnHold:"On Hold", Succeed:"Succeed", Failed:"Failed", Maintaining:"Maintaining" -}; \ No newline at end of file +}; + +/* +| status code | meaning | +|-------------|-----------| +| 0 | active | +| 1 | cancelled | + */ +const EventStatus = { + Active: 0, + Cancelled: 1 +} From 19f792663f798e72fefbf6488dec1be7164a7799 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 16 Oct 2020 17:40:28 -0500 Subject: [PATCH 02/52] Update index.ejs display cancelled events' title strikethroughed --- views/event/index.ejs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/views/event/index.ejs b/views/event/index.ejs index 077e5a2c..f54bfef3 100644 --- a/views/event/index.ejs +++ b/views/event/index.ejs @@ -50,9 +50,11 @@ <% } %>
-

<%= eventsSet[i].title %>

-

<%= eventsSet[i].event_time.toDateString() + " " + eventsSet[i].event_time.toLocaleTimeString() %>

-

<%= eventsSet[i].location %>

+ <% if (eventsSet[i].status === 1) { %> +

[Cancelled] <%= eventsSet[i].title %>

+ <% } else { %> +

<%= eventsSet[i].title %>

+ <% } %>

<%= eventsSet[i].description %>

<% if (auth([all_user_role.Developer, all_user_role.Admin, From a7ecf59e46eac2d4028a17226a63e5b4f55d1ff1 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 16 Oct 2020 17:40:37 -0500 Subject: [PATCH 03/52] Update index.ejs fix typo --- views/event/index.ejs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/views/event/index.ejs b/views/event/index.ejs index f54bfef3..c3709e8d 100644 --- a/views/event/index.ejs +++ b/views/event/index.ejs @@ -15,7 +15,7 @@ Create Event <% } %> - <% if (eventsSet.length == 0) { %> + <% if (eventsSet.length === 0) { %>

Sorry! Currently, there are no events available

<% } else { %>
@@ -55,6 +55,8 @@ <% } else { %>

<%= eventsSet[i].title %>

<% } %> +

<%= eventsSet[i].event_time.toDateString() + " " + eventsSet[i].event_time.toLocaleTimeString() %>

+

<%= eventsSet[i].location %>

<%= eventsSet[i].description %>

<% if (auth([all_user_role.Developer, all_user_role.Admin, From 7bc23bbbb5ea30a1d5b70885d5113531ef16b7fb Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 16 Oct 2020 17:42:00 -0500 Subject: [PATCH 04/52] Update event_db.js add a new db operation, changeEventStatusCodeById, which changes event's status to a given status code. --- server/event_db.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/server/event_db.js b/server/event_db.js index fbdaa5e4..7f403f0d 100644 --- a/server/event_db.js +++ b/server/event_db.js @@ -91,4 +91,18 @@ exports.removeEventById = function (eventId, callback) { callback('No matching event id'); } }); -} \ No newline at end of file +} + +exports.changeEventStatusCodeById = function (eventId, statusCode, callback) { + let query = `update event set status = $2 where id = $1;`; + db.query(query, [eventId, statusCode], function (err, result) { + if (err) { + callback(err); + } + if (result.rowCount > 0) { + callback(null); + } else { + callback('No matching event id'); + } + }); +} From 4d830b748ad3bd481cd0b11316c9bb6bae660210 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 16 Oct 2020 17:44:36 -0500 Subject: [PATCH 05/52] Update event_api.js add a new api, changeEventStatus, which updates event's status to a given status code --- routes/event/event_api.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/routes/event/event_api.js b/routes/event/event_api.js index 337bd719..639b5433 100644 --- a/routes/event/event_api.js +++ b/routes/event/event_api.js @@ -82,4 +82,29 @@ router.post('/removeEvent', function(req, res, next){ }); }); +router.post('/changeEventStatus', function(req, res, next){ + let roles = [authService.UserRole.Developer, + authService.UserRole.Admin, + authService.UserRole.EventExecutive]; // event executive can create event + + authService.authorizationCheck(roles, req.session.uid, function(err, authorized){ + if (err) { + res.status(400).json({msg: 'Database Error'}); + return; + } + else if(!authorized){ + res.status(403).json({msg: 'Not Authorized'}); + return; + } + event_db.changeEventStatusCodeById(req.body.event_id, req.body.new_status_code, function (err) { + if(err){ + console.log(err); + res.status(400).json({msg: 'Failed to remove'}); + return; + } + res.json({}); + }); + }); +}); + module.exports = router; From 529efe931ef80f81b7d9fb1e4f92e782dcf86c44 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 16 Oct 2020 17:45:02 -0500 Subject: [PATCH 06/52] Update edit.ejs fix typo --- views/event/edit.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/event/edit.ejs b/views/event/edit.ejs index 0429fd12..c6c4c11f 100644 --- a/views/event/edit.ejs +++ b/views/event/edit.ejs @@ -6,7 +6,7 @@ \ No newline at end of file From 068fca979ca3614c2e5d98cda8fd724ee1bf684f Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 16 Oct 2020 18:09:16 -0500 Subject: [PATCH 13/52] Update head.ejs move modal/confirmation box from event --- views/template/head.ejs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/views/template/head.ejs b/views/template/head.ejs index 5e7f1825..9ed38746 100644 --- a/views/template/head.ejs +++ b/views/template/head.ejs @@ -47,4 +47,22 @@ url_with_https = function (old_url) { } return old_url; } -%> \ No newline at end of file +%> + + From 9167c42158762fa2e6ff77933dfc0da2007e9f2c Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 30 Oct 2020 18:36:16 -0500 Subject: [PATCH 14/52] send followed event information for render --- routes/event/event.js | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/routes/event/event.js b/routes/event/event.js index 1b536721..46dedab9 100644 --- a/routes/event/event.js +++ b/routes/event/event.js @@ -11,26 +11,39 @@ router.get('/', function (req, res, next) { res.status(400).json({msg: 'Database Error'}); return; } - user_db.getUserRoleByUid(req.session.uid, function (err, user_role) { + user_db.getUserFollowedEventsByUid(req.session.uid, (err, followed_event) => { if (err) { res.status(400).json({msg: 'Database Error'}); return; } - eventsSet = eventsSet.sort(function (a, b) { - return a.event_time - b.event_time - }) - let now = new Date(); - now = new Date(now - (5.5 * 60 * 60 * 1000)); - var centerIdx = eventsSet.length - 1; - for (var i = eventsSet.length - 1; i >= 0; i--) { - // show the event thats coming up soon - if (eventsSet[i].event_time < now) { - break; + user_db.getUserRoleByUid(req.session.uid, function (err, user_role) { + if (err) { + res.status(400).json({msg: 'Database Error'}); + return; } - centerIdx = i; - } - res.render('event/index', {eventsSet: eventsSet, uid: req.session.uid, all_user_role: authService.UserRole, user_role: user_role, centerIdx: centerIdx}); - }); + eventsSet = eventsSet.sort(function (a, b) { + return a.event_time - b.event_time + }) + let now = new Date(); + now = new Date(now - (5.5 * 60 * 60 * 1000)); + var centerIdx = eventsSet.length - 1; + for (var i = eventsSet.length - 1; i >= 0; i--) { + // show the event thats coming up soon + if (eventsSet[i].event_time < now) { + break; + } + centerIdx = i; + } + res.render('event/index', { + followed_event: JSON.parse(followed_event), + eventsSet: eventsSet, + uid: req.session.uid, + all_user_role: authService.UserRole, + user_role: user_role, + centerIdx: centerIdx + }); + }); + }) }); }); From ae6497342e3eadc2deb8bbe462229b6549792319 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 30 Oct 2020 18:36:45 -0500 Subject: [PATCH 15/52] query followed events, follow event, and unfollow event --- server/user_db.js | 63 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/server/user_db.js b/server/user_db.js index f911c292..2b70a7b0 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -303,3 +303,66 @@ exports.resetPassword = function(password, email, user_id, callback) { } }); }; + +exports.getUserFollowedEventsByUid = (user_id, callback) => { + if (!user_id) { + return callback(null, '[]'); + } + let query = 'SELECT followed_event FROM user_profile WHERE uid = $1'; + db.query(query, [user_id], (err, result) => { + if (err) { + callback(err); + } else { + callback(null, result.rows[0]['followed_event']); + } + }); +} + +exports.followEvent = function(uid, eid, callback) { + db.query('BEGIN;'); + let query = 'SELECT followed_event FROM user_profile WHERE uid = $1 FOR UPDATE;'; + db.query(query, [uid], function (err, result) { + if (err) { + db.query('COMMIT;'); + callback(err); + } else { + var followed_event = JSON.parse(result.rows[0]['followed_event']); + followed_event.push(parseInt(eid)); + query = 'UPDATE user_profile SET followed_event = ' + "'" + JSON.stringify(followed_event) + "'" + ' WHERE uid = $1;'; + db.query(query, [uid], function (err_update) { + db.query('COMMIT;'); + if (err_update) { + callback(err_update); + } else { + callback(null); + } + }); + } + }); +}; + +exports.unfollowEvent = function(uid, eid, callback) { + db.query('BEGIN;'); + let query = 'SELECT followed_event FROM user_profile WHERE uid = $1 FOR UPDATE;'; + db.query(query, [uid], function (err, result) { + if (err) { + db.query('COMMIT;'); + callback(err); + } else { + var followed_event = JSON.parse(result.rows[0]['followed_event']); + const index = followed_event.indexOf(parseInt(eid)); + if (index > -1) { + followed_event.splice(index, 1); + } + query = 'UPDATE user_profile SET followed_event = ' + "'" + JSON.stringify(followed_event) + "'" + ' WHERE uid = $1;'; + db.query(query, [uid], function (err_update) { + db.query('COMMIT;'); + if (err_update) { + callback(err_update); + } else { + callback(null); + } + }); + } + }); +}; From 36de5dfab8a5b5088a54f3a9cceee5f7dd6be4a5 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 30 Oct 2020 18:36:59 -0500 Subject: [PATCH 16/52] follow event and unfollow event api --- routes/event/event_api.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/routes/event/event_api.js b/routes/event/event_api.js index 639b5433..ed1a6e92 100644 --- a/routes/event/event_api.js +++ b/routes/event/event_api.js @@ -1,5 +1,6 @@ const express = require('express'); const event_db = require('../../server/event_db'); +const user_db = require('../../server/user_db'); const router = express.Router(); const authService = require('../services/authorization_service'); @@ -107,4 +108,26 @@ router.post('/changeEventStatus', function(req, res, next){ }); }); +router.post('/followEvent', function(req, res, next) { + user_db.followEvent(req.body.uid, req.body.eid, ((err) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Failed to follow event'}); + return; + } + res.json({}); + })) +}); + +router.post('/unfollowEvent', function(req, res, next) { + user_db.unfollowEvent(req.body.uid, req.body.eid, ((err) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Failed to unfollow event'}); + return; + } + res.json({}); + })) +}); + module.exports = router; From 753ed645e49e5680768c378496ec0b1c13005a34 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 30 Oct 2020 18:37:50 -0500 Subject: [PATCH 17/52] follow/unfollow evenet button --- views/event/index.ejs | 71 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/views/event/index.ejs b/views/event/index.ejs index b22e9fff..3c045c86 100644 --- a/views/event/index.ejs +++ b/views/event/index.ejs @@ -6,6 +6,54 @@ + + <% include ../template/nav.ejs %>
@@ -62,13 +110,26 @@ <% } %> <% } %>

<%= eventsSet[i].description %>

- <% if (auth([all_user_role.Developer, - all_user_role.Admin, - all_user_role.EventExecutive], user_role)) { %>
- Edit Event + <% + var canFollow = true; + for (var j = 0; j < followed_event.length; j++) { + if (followed_event[j] === eventsSet[i].id) { + canFollow = false; + } + } + %> + <% if (canFollow) { %> + + <% } else { %> + + <% } %> + <% if (auth([all_user_role.Developer, + all_user_role.Admin, + all_user_role.EventExecutive], user_role)) { %> + Edit Event + <% } %>
- <% } %>
<% if (i < eventsSet.length - 1) { %> Date: Fri, 13 Nov 2020 19:53:09 -0600 Subject: [PATCH 18/52] Allow notification bar to show customized message --- views/template/nav.ejs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/views/template/nav.ejs b/views/template/nav.ejs index cd0065ab..a4814ffc 100644 --- a/views/template/nav.ejs +++ b/views/template/nav.ejs @@ -2,7 +2,17 @@ $(function () { const urlParams = new URLSearchParams(window.location.search); const status = urlParams.get('status'); + var msg = urlParams.get('msg').replaceAll('_', ' '); + if (!msg) { + msg = 'Your submission has successfully been saved!'; + } if(status == 's'){ + $('#notification-bar').css("visibility","visible"); + $('#notification-msg').html(msg); + $('#notification-bar').fadeOut(4000, "swing"); + } + // TODO, set notification bar color to red + if(status == 'f'){ $('#notification-bar').css("visibility","visible"); $('#notification-bar').fadeOut(4000, "swing"); } @@ -41,5 +51,5 @@
-

Your submission has successfully been saved!

+

Your submission has successfully been saved!

From 0a7e80c735b7a831872bcebaaf22872e32d93038 Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Fri, 13 Nov 2020 19:53:23 -0600 Subject: [PATCH 19/52] Page to show a list of followed events --- views/event/followed.ejs | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 views/event/followed.ejs diff --git a/views/event/followed.ejs b/views/event/followed.ejs new file mode 100644 index 00000000..b1e0515e --- /dev/null +++ b/views/event/followed.ejs @@ -0,0 +1,57 @@ + + + + <% include ../template/head.ejs %> + + + + + + + +<% include ../template/nav.ejs %> +
+ +
+
+

Search:

+
+
+ +
+
+ + + + + + + + + + + + <% if (event_set.length === 0) { %> + + + + <% } %> + + <% event_set.forEach(function(event) { %> + > + + + + + + <% }); %> + + +
Event NameEvent DetailLocationTime
You are not following any event.
<%= event.title %><%= event.description %><%= event.event_time.toLocaleTimeString() %><%= event.location %>
+
+ +<% include ../template/footer.ejs %> + + \ No newline at end of file From f5da8260420a220147674567441929bfb34acfc0 Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Fri, 13 Nov 2020 19:53:47 -0600 Subject: [PATCH 20/52] to followed page --- routes/event/event.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/routes/event/event.js b/routes/event/event.js index 46dedab9..f9d9c2c9 100644 --- a/routes/event/event.js +++ b/routes/event/event.js @@ -98,4 +98,38 @@ router.get('/edit', function (req, res, next) { }); }); +router.get('/followed', function (req, res, next) { + let uid = req.query.user_id ? req.query.user_id : req.session.uid; + authService.authorizationCheck(null, req.session.uid, function(err, authorized){ + if (err) { + console.log(err); + res.status(400).json({msg: 'Database Error'}); + } + else if(!authorized) { + res.redirect('/login'); + } else { + user_db.getUserFollowedEventsByUid(uid, (err, followed_events) => { + event_db.getEventSet((err, event_set) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Database Error'}); + } + let followed_event_ids = JSON.parse(followed_events); + let followed_event_set = []; + + event_set.forEach(function(event) { + if (followed_event_ids.includes(event.id)) { + followed_event_set.push(event); + } + }); + + res.render('event/followed', { + event_set: followed_event_set + }); + }) + }) + } + }); +}); + module.exports = router; From 6e33037c099577ed599e54b2d7adbd7007f4d5e7 Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Fri, 13 Nov 2020 19:54:31 -0600 Subject: [PATCH 21/52] RSVP email, email service is temporarily blocked --- routes/event/event.js | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/routes/event/event.js b/routes/event/event.js index f9d9c2c9..e5892da0 100644 --- a/routes/event/event.js +++ b/routes/event/event.js @@ -2,6 +2,7 @@ const express = require('express'); const router = express.Router(); const event_db = require("../../server/event_db"); const user_db = require("../../server/user_db"); +const emailService = require('../services/email_service'); const authService = require('../services/authorization_service'); router.get('/', function (req, res, next) { @@ -132,4 +133,51 @@ router.get('/followed', function (req, res, next) { }); }); +router.get('/rsvp', function (req, res, next) { + let event_id = req.query.id; + let uid = req.query.user_id ? req.query.user_id : req.session.uid; + authService.authorizationCheck(null, req.session.uid, function(err, authorized){ + if (err) { + console.log(err); + res.status(400).json({msg: 'Database Error'}); + } + else if(!authorized) { + res.redirect('/login'); + } else { + + user_db.getUserById(uid, (err, user_info) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Database Error'}); + } + + let user_email = user_info.email; + + event_db.getEventById(event_id, (err, event_info) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Database Error'}); + } + + const emailDetail = { + to: user_email, + subject: event_info.title, + html: event_info.description + }; + + res.redirect('/event?status=s&msg=RSVP_email_has_been_sent'); + /* + emailService.sendEmail(emailDetail, function(err){ + if(err){ + console.log(err); + res.redirect('/event?status=f'); + } + }); + */ + }); + }); + } + }); +}); + module.exports = router; From 7a155d4def70cf547bab299cfe4a5d5551f6a279 Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Fri, 13 Nov 2020 19:54:49 -0600 Subject: [PATCH 22/52] Followed event and RSVP button --- views/event/index.ejs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/views/event/index.ejs b/views/event/index.ejs index 3c045c86..a474c1a1 100644 --- a/views/event/index.ejs +++ b/views/event/index.ejs @@ -57,6 +57,9 @@ <% include ../template/nav.ejs %>
+ <% if (uid) { %> + My Followed Events + <% } %> <% if (auth([all_user_role.Developer, all_user_role.Admin, all_user_role.EventExecutive], user_role)) { %> @@ -124,6 +127,7 @@ <% } else { %> <% } %> + RSVP <% if (auth([all_user_role.Developer, all_user_role.Admin, all_user_role.EventExecutive], user_role)) { %> From 150bb62898d56dc7a7adfd4557ca99cfae6a4288 Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Fri, 13 Nov 2020 21:37:12 -0600 Subject: [PATCH 23/52] update notification bar. The color of bar changes depending on s/f value. --- views/template/nav.ejs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/views/template/nav.ejs b/views/template/nav.ejs index a4814ffc..651c7c61 100644 --- a/views/template/nav.ejs +++ b/views/template/nav.ejs @@ -2,18 +2,18 @@ $(function () { const urlParams = new URLSearchParams(window.location.search); const status = urlParams.get('status'); - var msg = urlParams.get('msg').replaceAll('_', ' '); - if (!msg) { - msg = 'Your submission has successfully been saved!'; - } - if(status == 's'){ + // notification message each word in the msg should be separated by _ + const msg = urlParams.get('msg').replaceAll('_', ' ') || 'Your submission has successfully been saved!'; + if(status === 's'){ $('#notification-bar').css("visibility","visible"); + $('#notification-bar').css("background-color","#51a351"); $('#notification-msg').html(msg); $('#notification-bar').fadeOut(4000, "swing"); } - // TODO, set notification bar color to red - if(status == 'f'){ + if(status === 'f'){ $('#notification-bar').css("visibility","visible"); + $('#notification-bar').css("background-color","#fa8072"); + $('#notification-msg').html(msg); $('#notification-bar').fadeOut(4000, "swing"); } }) From c8a3fa4386027338330062afb2a8bb77f0c17b5c Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Fri, 13 Nov 2020 21:37:44 -0600 Subject: [PATCH 24/52] background-color is set inside ejs file --- public/css/style.css | 1 - 1 file changed, 1 deletion(-) diff --git a/public/css/style.css b/public/css/style.css index bea0a1bc..6692a0d9 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -360,7 +360,6 @@ input::-webkit-calendar-picker-indicator { padding-top: 10px; z-index: 1050; font-size: 15px; - background-color: #51a351; color: #ffffff; text-align: center; border-bottom-left-radius: 20px 10px; From bc2762ae94a0c0887afe6f8bdaa1af97d067d64f Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Fri, 13 Nov 2020 21:38:07 -0600 Subject: [PATCH 25/52] enable email --- routes/event/event.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/routes/event/event.js b/routes/event/event.js index e5892da0..faf6f408 100644 --- a/routes/event/event.js +++ b/routes/event/event.js @@ -161,19 +161,18 @@ router.get('/rsvp', function (req, res, next) { const emailDetail = { to: user_email, - subject: event_info.title, - html: event_info.description + subject: '[Coding 4 Good] ' + event_info.title, + html: "This email regards event" + event_info.title + "
" + event_info.description + "." }; - res.redirect('/event?status=s&msg=RSVP_email_has_been_sent'); - /* - emailService.sendEmail(emailDetail, function(err){ + emailService.sendEmail(emailDetail, (err) => { if(err){ console.log(err); - res.redirect('/event?status=f'); + res.redirect('/event?status=f&msg=Failed_to_send_RSVP_email'); + } else { + res.redirect('/event?status=s&msg=RSVP_email_has_been_sent'); } - }); - */ + }) }); }); } From bcc60582ac8464a237de370ba6788f5c5b357fc7 Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Fri, 13 Nov 2020 21:40:17 -0600 Subject: [PATCH 26/52] not sure if this should be changed not sure if this should be changed. When I am testing email service, with path = /app/.., file not exists error was thrown. --- routes/services/email_service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/services/email_service.js b/routes/services/email_service.js index 336bade3..1a952faf 100644 --- a/routes/services/email_service.js +++ b/routes/services/email_service.js @@ -29,7 +29,7 @@ exports.sendEmail = function(emailDetail, callback){ Please do not reply to this email.`, attachments: [{ filename: 'icon.jpg', - path: '/app/public/img/icon.jpg', + path: './public/img/icon.jpg', cid: 'club-icon' }] } From 9c172bd6d6691b43ff93f9ddb8ed8f175d62e68e Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Thu, 19 Nov 2020 01:45:19 -0600 Subject: [PATCH 27/52] Update user_db.js add a new api for checking if user has profile --- server/user_db.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/server/user_db.js b/server/user_db.js index 2b70a7b0..e191386f 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -304,11 +304,30 @@ exports.resetPassword = function(password, email, user_id, callback) { }); }; +exports.hasProfile = (user_id, callback) => { + if (!user_id) { + callback(null, 'NO_USR_ID'); + return; + } + let query = 'SELECT * FROM user_profile WHERE uid = $1;'; + db.query(query, [user_id], (err, result) => { + if (err) { + callback(err); + } else { + if (result.rows[0]) + callback(null, 'TRUE'); + else + callback(null, 'FALSE'); + } + }); +} + exports.getUserFollowedEventsByUid = (user_id, callback) => { if (!user_id) { - return callback(null, '[]'); + callback(null, '[]'); + return; } - let query = 'SELECT followed_event FROM user_profile WHERE uid = $1'; + let query = 'SELECT followed_event FROM user_profile WHERE uid = $1;'; db.query(query, [user_id], (err, result) => { if (err) { callback(err); From 2319fa470454d4683febcc85ebe06a41571d90f4 Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Thu, 19 Nov 2020 01:46:22 -0600 Subject: [PATCH 28/52] Update event.js add an if statement to check db error --- routes/event/event.js | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/routes/event/event.js b/routes/event/event.js index faf6f408..94003bc2 100644 --- a/routes/event/event.js +++ b/routes/event/event.js @@ -110,25 +110,30 @@ router.get('/followed', function (req, res, next) { res.redirect('/login'); } else { user_db.getUserFollowedEventsByUid(uid, (err, followed_events) => { - event_db.getEventSet((err, event_set) => { - if (err) { - console.log(err); - res.status(400).json({msg: 'Database Error'}); - } - let followed_event_ids = JSON.parse(followed_events); - let followed_event_set = []; - - event_set.forEach(function(event) { - if (followed_event_ids.includes(event.id)) { - followed_event_set.push(event); + if (err) { + console.log(err); + res.status(400).json({msg: 'Database Error'}); + } else { + event_db.getEventSet((err, event_set) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Database Error'}); } - }); + let followed_event_ids = JSON.parse(followed_events); + let followed_event_set = []; + + event_set.forEach(function (event) { + if (followed_event_ids.includes(event.id)) { + followed_event_set.push(event); + } + }); - res.render('event/followed', { - event_set: followed_event_set + res.render('event/followed', { + event_set: followed_event_set + }); }); - }) - }) + } + }); } }); }); From d1d104808253c03ee43097725122c100a34807cd Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Thu, 19 Nov 2020 01:46:34 -0600 Subject: [PATCH 29/52] Update event.js add a guard to check if user has profile. --- routes/event/event.js | 65 +++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/routes/event/event.js b/routes/event/event.js index 94003bc2..aa5669d6 100644 --- a/routes/event/event.js +++ b/routes/event/event.js @@ -6,45 +6,56 @@ const emailService = require('../services/email_service'); const authService = require('../services/authorization_service'); router.get('/', function (req, res, next) { + let uid = req.session.uid; event_db.getEventSet(function (err, eventsSet) { if (err) { console.log(err); res.status(400).json({msg: 'Database Error'}); return; } - user_db.getUserFollowedEventsByUid(req.session.uid, (err, followed_event) => { + user_db.hasProfile(uid, (err, predicate) => { if (err) { res.status(400).json({msg: 'Database Error'}); return; } - user_db.getUserRoleByUid(req.session.uid, function (err, user_role) { - if (err) { - res.status(400).json({msg: 'Database Error'}); - return; - } - eventsSet = eventsSet.sort(function (a, b) { - return a.event_time - b.event_time - }) - let now = new Date(); - now = new Date(now - (5.5 * 60 * 60 * 1000)); - var centerIdx = eventsSet.length - 1; - for (var i = eventsSet.length - 1; i >= 0; i--) { - // show the event thats coming up soon - if (eventsSet[i].event_time < now) { - break; + if (predicate === 'TRUE' || predicate === 'NO_USR_ID') { + user_db.getUserFollowedEventsByUid(uid, (err, followed_event) => { + if (err) { + res.status(400).json({msg: 'Database Error'}); + return; } - centerIdx = i; - } - res.render('event/index', { - followed_event: JSON.parse(followed_event), - eventsSet: eventsSet, - uid: req.session.uid, - all_user_role: authService.UserRole, - user_role: user_role, - centerIdx: centerIdx + user_db.getUserRoleByUid(req.session.uid, function (err, user_role) { + if (err) { + res.status(400).json({msg: 'Database Error'}); + return; + } + eventsSet = eventsSet.sort(function (a, b) { + return a.event_time - b.event_time + }) + let now = new Date(); + now = new Date(now - (5.5 * 60 * 60 * 1000)); + var centerIdx = eventsSet.length - 1; + for (var i = eventsSet.length - 1; i >= 0; i--) { + // show the event thats coming up soon + if (eventsSet[i].event_time < now) { + break; + } + centerIdx = i; + } + res.render('event/index', { + followed_event: JSON.parse(followed_event), + eventsSet: eventsSet, + uid: req.session.uid, + all_user_role: authService.UserRole, + user_role: user_role, + centerIdx: centerIdx + }); + }); }); - }); - }) + } else { + res.redirect('../profile?status=f&msg=Please_update_your_profile'); + } + }); }); }); From 93032bafd69754270e0a66a3da9d674e9a9d1e9e Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Thu, 19 Nov 2020 01:53:55 -0600 Subject: [PATCH 30/52] Update nav.ejs fix the msg issue --- views/template/nav.ejs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/views/template/nav.ejs b/views/template/nav.ejs index 651c7c61..5dddeea9 100644 --- a/views/template/nav.ejs +++ b/views/template/nav.ejs @@ -2,18 +2,19 @@ $(function () { const urlParams = new URLSearchParams(window.location.search); const status = urlParams.get('status'); - // notification message each word in the msg should be separated by _ - const msg = urlParams.get('msg').replaceAll('_', ' ') || 'Your submission has successfully been saved!'; - if(status === 's'){ - $('#notification-bar').css("visibility","visible"); - $('#notification-bar').css("background-color","#51a351"); - $('#notification-msg').html(msg); - $('#notification-bar').fadeOut(4000, "swing"); - } - if(status === 'f'){ - $('#notification-bar').css("visibility","visible"); - $('#notification-bar').css("background-color","#fa8072"); + if (status) { + // notification message each word in the msg should be separated by _ + let msg = urlParams.get('msg'); + if (msg) + msg = msg.replaceAll('_', ' '); + else + msg = 'Your submission has successfully been saved!'; + $('#notification-bar').css("visibility", "visible"); $('#notification-msg').html(msg); + if (status === 's') + $('#notification-bar').css("background-color", "#51a351"); + if (status === 'f') + $('#notification-bar').css("background-color", "#fa8072"); $('#notification-bar').fadeOut(4000, "swing"); } }) From 2164118b905e298596d2d14e76d74969f794965c Mon Sep 17 00:00:00 2001 From: Yi Chen Date: Thu, 19 Nov 2020 01:54:37 -0600 Subject: [PATCH 31/52] Update email_service.js revert back --- routes/services/email_service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/services/email_service.js b/routes/services/email_service.js index 1a952faf..336bade3 100644 --- a/routes/services/email_service.js +++ b/routes/services/email_service.js @@ -29,7 +29,7 @@ exports.sendEmail = function(emailDetail, callback){ Please do not reply to this email.`, attachments: [{ filename: 'icon.jpg', - path: './public/img/icon.jpg', + path: '/app/public/img/icon.jpg', cid: 'club-icon' }] } From bcf865c9fc6e16d2741cc0d1e7d9c40e39fe7f90 Mon Sep 17 00:00:00 2001 From: Jialuo Gao Date: Sun, 29 Nov 2020 15:09:40 -0600 Subject: [PATCH 32/52] Minor auth update --- routes/event/event_api.js | 8 ++++++++ server/user_db.js | 6 ++++-- views/event/edit.ejs | 1 - 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/routes/event/event_api.js b/routes/event/event_api.js index 29e0b7ef..f781ba32 100644 --- a/routes/event/event_api.js +++ b/routes/event/event_api.js @@ -108,6 +108,10 @@ router.post('/changeEventStatus', function(req, res, next){ }); router.post('/followEvent', function(req, res, next) { + if(!req.body.uid){ + res.status(403).json({msg: 'Not Authorized'}); + return; + } user_db.followEvent(req.body.uid, req.body.eid, ((err) => { if (err) { console.log(err); @@ -119,6 +123,10 @@ router.post('/followEvent', function(req, res, next) { }); router.post('/unfollowEvent', function(req, res, next) { + if(!req.body.uid){ + res.status(403).json({msg: 'Not Authorized'}); + return; + } user_db.unfollowEvent(req.body.uid, req.body.eid, ((err) => { if (err) { console.log(err); diff --git a/server/user_db.js b/server/user_db.js index 5a62e748..5ece1daf 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -341,10 +341,11 @@ exports.followEvent = function(uid, eid, callback) { followed_event.push(parseInt(eid)); query = 'UPDATE user_profile SET followed_event = ' + "'" + JSON.stringify(followed_event) + "'" + ' WHERE uid = $1;'; db.query(query, [uid], function (err_update) { - db.query('COMMIT;'); if (err_update) { + db.query('ROLLBACK;') callback(err_update); } else { + db.query('COMMIT;'); callback(null); } }); @@ -367,10 +368,11 @@ exports.unfollowEvent = function(uid, eid, callback) { } query = 'UPDATE user_profile SET followed_event = ' + "'" + JSON.stringify(followed_event) + "'" + ' WHERE uid = $1;'; db.query(query, [uid], function (err_update) { - db.query('COMMIT;'); if (err_update) { + db.query('ROLLBACK;') callback(err_update); } else { + db.query('COMMIT;'); callback(null); } }); diff --git a/views/event/edit.ejs b/views/event/edit.ejs index 54e9a493..22e54f28 100644 --- a/views/event/edit.ejs +++ b/views/event/edit.ejs @@ -208,7 +208,6 @@
<% include ../template/footer.ejs %> - \ No newline at end of file From 07790480cd0c2ada70813f74091c1021628f66ba Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 00:57:57 -0600 Subject: [PATCH 33/52] Fork a child process to run the rsvp sender --- app.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app.js b/app.js index 8266f81a..1c8fb481 100644 --- a/app.js +++ b/app.js @@ -81,4 +81,7 @@ if (process.env.INSTALL === 'yes' || args[0] === 'install') { }); } +const child_process = require('child_process'); +child_process.fork('rsvp_sender'); + module.exports = app; From f37160ac0a98d97e78f280c06c078c580d6e3378 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 00:58:12 -0600 Subject: [PATCH 34/52] Create rsvp_sender.js --- rsvp_sender.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 rsvp_sender.js diff --git a/rsvp_sender.js b/rsvp_sender.js new file mode 100644 index 00000000..665f56dd --- /dev/null +++ b/rsvp_sender.js @@ -0,0 +1,56 @@ +const nodemailer = require('nodemailer'); +const user_db = require('./server/user_db'); +const event_db = require('./server/event_db'); + + +setInterval(() => { + user_db.getAllEntriesFromUserEvent((err, user_event_entries) => { + if (err) { + console.log("Failed to get all entries from user event"); + return; + } + user_event_entries.rows.forEach((row) => { + const uid = row.uid; + const rsvp_events = JSON.parse(row.rsvp_events); + rsvp_events.forEach((rsvp_event) => { + event_db.getEventById(rsvp_event, (err, event_info) => { + if (!err) { + let now = new Date(); + // TODO: !!!!!!!! + if (!(now.toLocaleDateString() === event_info.event_time.toLocaleDateString())) { + user_db.getUserEmailById(uid, (err, user_email) => { + if (!err) { + let mail_options = { + from: process.env.EMAILUSER, + to: user_email.email, + subject: 'Event Reminder: ' + event_info.title, + text: event_info.description, + }; + let transporter = nodemailer.createTransport({ + service: 'gmail', + auth: { + user: process.env.EMAILUSER, + pass: process.env.EMAILPASS, + } + }); + transporter.sendMail(mail_options, (err, info) => { + if (err) { + console.log(err); + } else { + user_db.unrsvpEvent(uid, event_info.id, (err) => { + if (err) { + console.log(err); + } + console.log('Email sent: ' + info.response); + }); + } + }); + } + }); + } + } + }); + }); + }) + }); +}, 1000); From 4993d2bef08518e5f2fa5a35199744309b983682 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 00:59:23 -0600 Subject: [PATCH 35/52] Change RSVP related events from GET to POST --- views/event/index.ejs | 62 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/views/event/index.ejs b/views/event/index.ejs index a474c1a1..e6c3bf19 100644 --- a/views/event/index.ejs +++ b/views/event/index.ejs @@ -52,6 +52,52 @@ window.location.href = "/login"; } } + + function rsvp_event(eid, uid) { + if (uid) { + $(".rsvp-button").attr('enabled', false); + $.ajax({ + url: "/event/rsvpEvent", + method: "POST", + dataType: "json", + data: { + uid: uid, + eid: eid + }, + success: function () { + window.location.href = "/event?status=s"; + }, + error: function (jqXHR, textStatus, errorThrown) { + $(".rsvp-button").attr('disabled', false); + } + }); + } else { + window.location.href = "/login"; + } + } + + function unrsvp_event(eid, uid) { + if (uid) { + $(".unrsvp-button").attr('enabled', false); + $.ajax({ + url: "/event/unrsvpEvent", + method: "POST", + dataType: "json", + data: { + uid: uid, + eid: eid + }, + success: function () { + window.location.href = "/event?status=s"; + }, + error: function (jqXHR, textStatus, errorThrown) { + $(".unrsvp-button").attr('disabled', false); + } + }); + } else { + window.location.href = "/login"; + } + } @@ -116,18 +162,28 @@
<% var canFollow = true; - for (var j = 0; j < followed_event.length; j++) { - if (followed_event[j] === eventsSet[i].id) { + for (var j = 0; j < followed_events.length; j++) { + if (followed_events[j] === eventsSet[i].id) { canFollow = false; } } + var canRSVP = true; + for (var j = 0; j < rsvp_events.length; j++) { + if (rsvp_events[j] === eventsSet[i].id) { + canRSVP = false; + } + } %> <% if (canFollow) { %> <% } else { %> <% } %> - RSVP + <% if (canRSVP) { %> + + <% } else { %> + + <% } %> <% if (auth([all_user_role.Developer, all_user_role.Admin, all_user_role.EventExecutive], user_role)) { %> From 24b3d07206caf9b3ee7418b28cb7776894df7f38 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:00:11 -0600 Subject: [PATCH 36/52] Get user's email by provided user_id --- server/user_db.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/user_db.js b/server/user_db.js index 5ece1daf..15b80e80 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -276,6 +276,17 @@ exports.getUserByEmail = function(email, callback){ }); }; +exports.getUserEmailById = (user_id, callback) => { + const query = 'SELECT email FROM users WHERE id=$1;'; + db.query(query, [user_id], (err, result) => { + if (err) { + callback(err); + } else { + callback(null, result.rows[0]); + } + }) +} + exports.resetPassword = function(password, email, user_id, callback) { var saltRounds = 10; bcrypt.hash(password, saltRounds, function(err, hash) { From 4ea1f3a65b9fcebf410f50e8ee74d7e7c554e5ff Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:00:45 -0600 Subject: [PATCH 37/52] Get user's followed events by user id --- server/user_db.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/server/user_db.js b/server/user_db.js index 15b80e80..078d4d47 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -325,12 +325,30 @@ exports.hasProfile = (user_id, callback) => { }); } +/** + * Get events that the user corresponding to the `user_id` has followed. + * If `user_id` is empty, i.e. no user logs in, or the user has not followed any events, return `[]` + * @param user_id user id + * @param callback callback function + */ exports.getUserFollowedEventsByUid = (user_id, callback) => { if (!user_id) { callback(null, '[]'); return; } - let query = 'SELECT followed_event FROM user_profile WHERE uid = $1;'; + const query = 'SELECT * FROM user_event WHERE uid = $1;'; + db.query(query, [user_id], (err, result) => { + if (err) { + callback(err); + } else { + if (result.rows[0]) { + callback(null, result.rows[0].followed_events); + } else { + callback(null, '[]'); + } + } + }); +} db.query(query, [user_id], (err, result) => { if (err) { callback(err); From ada821ccf8c7f3fbfb52d69c96bd400f60b18d65 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:01:04 -0600 Subject: [PATCH 38/52] Get user RSVP events by user id --- server/user_db.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/server/user_db.js b/server/user_db.js index 078d4d47..f4aa808c 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -349,6 +349,31 @@ exports.getUserFollowedEventsByUid = (user_id, callback) => { } }); } + +/** + * Get events that the user corresponding to the `user_id` has RSVP. + * If `user_id` is empty, i.e. no user logs in, or the user has not followed any events, return `[]` + * @param user_id user id + * @param callback callback function + */ +exports.getUserRSVPEventsByUid = (user_id, callback) => { + if (!user_id) { + callback(null, '[]'); + return; + } + const query = 'SELECT * FROM user_event WHERE uid = $1;'; + db.query(query, [user_id], (err, result) => { + if (err) { + callback(err); + } else { + if (result.rows[0]) { + callback(null, result.rows[0].rsvp_events); + } else { + callback(null, '[]'); + } + } + }); +} db.query(query, [user_id], (err, result) => { if (err) { callback(err); From 3d70fed433a7da97e385670205115031a11b2679 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:01:36 -0600 Subject: [PATCH 39/52] Check if the user has entry inside the user_event table --- server/user_db.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/server/user_db.js b/server/user_db.js index f4aa808c..16e0de0b 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -374,7 +374,22 @@ exports.getUserRSVPEventsByUid = (user_id, callback) => { } }); } + +/** + * Check if `user_id` has an entry (row) inside the `user_event` table + * @param user_id user id + * @param callback callback function + */ +exports.hasUserEventEntry = (user_id, callback) => { + const query = 'SELECT EXISTS(SELECT 1 FROM user_event WHERE uid = $1);' db.query(query, [user_id], (err, result) => { + if (err) { + callback(err); + } else { + callback(null, result.rows[0].exists) + } + }); +} if (err) { callback(err); } else { From 8ad0284e8d6d2c973b95d896c10cdd2728720d9b Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:01:56 -0600 Subject: [PATCH 40/52] Create an new entry and add the event --- server/user_db.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/server/user_db.js b/server/user_db.js index 16e0de0b..d2ba791f 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -390,10 +390,20 @@ exports.hasUserEventEntry = (user_id, callback) => { } }); } + +/** + * Create an entry corresponding to `user_id` and add the `event_id` to `followed_events` in the entry + * @param user_id user id + * @param event_id event id + * @param callback callback function + */ +exports.createEntryAndFollowEvent = (user_id, event_id, callback) => { + const insert = 'INSERT INTO user_event (uid, followed_events, rsvp_events) VALUES ($1, $2, $3)'; + db.query(insert, [user_id, JSON.stringify([parseInt(event_id)]), "[]"], (err) => { if (err) { callback(err); } else { - callback(null, result.rows[0]['followed_event']); + callback(null); } }); } From af14eda2610c963f72f196136705e14d04371cf3 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:03:46 -0600 Subject: [PATCH 41/52] Get all entries from user_event table --- server/user_db.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/user_db.js b/server/user_db.js index d2ba791f..0a398c06 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -458,3 +458,14 @@ exports.unfollowEvent = function(uid, eid, callback) { } }); }; + +exports.getAllEntriesFromUserEvent = (callback) => { + const query = 'SELECT * FROM user_event'; + db.query(query, [], (err, result) => { + if (err) { + callback(err); + } else { + callback(null, result); + } + }); +} From e551b67f615ab871a82e4b09256a65107564a700 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:04:08 -0600 Subject: [PATCH 42/52] Un RSVP an event --- server/user_db.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server/user_db.js b/server/user_db.js index 0a398c06..4a23086d 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -436,17 +436,22 @@ exports.unfollowEvent = function(uid, eid, callback) { db.query('BEGIN;'); let query = 'SELECT followed_event FROM user_profile WHERE uid = $1 FOR UPDATE;'; db.query(query, [uid], function (err, result) { + +exports.unrsvpEvent = function(user_id, event_id, callback) { + db.query('BEGIN;'); + let query = 'SELECT rsvp_events FROM user_event WHERE uid = $1 FOR UPDATE;'; + db.query(query, [user_id], function (err, result) { if (err) { db.query('COMMIT;'); callback(err); } else { - var followed_event = JSON.parse(result.rows[0]['followed_event']); - const index = followed_event.indexOf(parseInt(eid)); + const followed_event = JSON.parse(result.rows[0]['rsvp_events']); + const index = followed_event.indexOf(parseInt(event_id)); if (index > -1) { followed_event.splice(index, 1); } - query = 'UPDATE user_profile SET followed_event = ' + "'" + JSON.stringify(followed_event) + "'" + ' WHERE uid = $1;'; - db.query(query, [uid], function (err_update) { + query = 'UPDATE user_event SET rsvp_events = ' + "'" + JSON.stringify(followed_event) + "'" + ' WHERE uid = $1;'; + db.query(query, [user_id], function (err_update) { if (err_update) { db.query('ROLLBACK;') callback(err_update); From 70ae62dad66ba545a58b3ef1d038dc179be6f86a Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:04:17 -0600 Subject: [PATCH 43/52] RSVP an event --- server/user_db.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/server/user_db.js b/server/user_db.js index 4a23086d..6d3b99b1 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -437,6 +437,30 @@ exports.unfollowEvent = function(uid, eid, callback) { let query = 'SELECT followed_event FROM user_profile WHERE uid = $1 FOR UPDATE;'; db.query(query, [uid], function (err, result) { +exports.rsvpEvent = function(user_id, event_id, callback) { + db.query('BEGIN;'); + let query = 'SELECT rsvp_events FROM user_event WHERE uid = $1 FOR UPDATE;'; + db.query(query, [user_id], function (err, result) { + if (err) { + db.query('COMMIT;'); + callback(err); + } else { + const followed_event = JSON.parse(result.rows[0]['rsvp_events']); + followed_event.push(parseInt(event_id)); + query = 'UPDATE user_event SET rsvp_events = ' + "'" + JSON.stringify(followed_event) + "'" + ' WHERE uid = $1;'; + db.query(query, [user_id], function (err_update) { + if (err_update) { + db.query('ROLLBACK;') + callback(err_update); + } else { + db.query('COMMIT;'); + callback(null); + } + }); + } + }); +}; + exports.unrsvpEvent = function(user_id, event_id, callback) { db.query('BEGIN;'); let query = 'SELECT rsvp_events FROM user_event WHERE uid = $1 FOR UPDATE;'; From 4dc7e0b8da3e78e8f039757302aaf7c70080fe0e Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:04:33 -0600 Subject: [PATCH 44/52] Create an entry and RSVP the event --- server/user_db.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/server/user_db.js b/server/user_db.js index 6d3b99b1..caf49e4b 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -437,6 +437,23 @@ exports.unfollowEvent = function(uid, eid, callback) { let query = 'SELECT followed_event FROM user_profile WHERE uid = $1 FOR UPDATE;'; db.query(query, [uid], function (err, result) { +/** + * Create an entry corresponding to `user_id` and add the `event_id` to `rsvp_events` in the entry + * @param user_id user id + * @param event_id event id + * @param callback callback function + */ +exports.createEntryAndRSVPEvent = (user_id, event_id, callback) => { + const insert = 'INSERT INTO user_event (uid, followed_events, rsvp_events) VALUES ($1, $2, $3)'; + db.query(insert, [user_id, "[]", JSON.stringify([parseInt(event_id)])], (err) => { + if (err) { + callback(err); + } else { + callback(null); + } + }); +} + exports.rsvpEvent = function(user_id, event_id, callback) { db.query('BEGIN;'); let query = 'SELECT rsvp_events FROM user_event WHERE uid = $1 FOR UPDATE;'; From 6d32bf6ceba14e6c427bd738210c5dc4c8b51f59 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:04:45 -0600 Subject: [PATCH 45/52] Unfollow an event --- server/user_db.js | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/server/user_db.js b/server/user_db.js index caf49e4b..d7a15898 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -432,10 +432,32 @@ exports.followEvent = function(uid, eid, callback) { }); }; -exports.unfollowEvent = function(uid, eid, callback) { +exports.unfollowEvent = function(user_id, event_id, callback) { db.query('BEGIN;'); - let query = 'SELECT followed_event FROM user_profile WHERE uid = $1 FOR UPDATE;'; - db.query(query, [uid], function (err, result) { + let query = 'SELECT followed_events FROM user_event WHERE uid = $1 FOR UPDATE;'; + db.query(query, [user_id], function (err, result) { + if (err) { + db.query('COMMIT;'); + callback(err); + } else { + const followed_event = JSON.parse(result.rows[0]['followed_events']); + const index = followed_event.indexOf(parseInt(event_id)); + if (index > -1) { + followed_event.splice(index, 1); + } + query = 'UPDATE user_event SET followed_events = ' + "'" + JSON.stringify(followed_event) + "'" + ' WHERE uid = $1;'; + db.query(query, [user_id], function (err_update) { + if (err_update) { + db.query('ROLLBACK;') + callback(err_update); + } else { + db.query('COMMIT;'); + callback(null); + } + }); + } + }); +}; /** * Create an entry corresponding to `user_id` and add the `event_id` to `rsvp_events` in the entry From 167e2e31973b36c340f8718442b3891e361f4d31 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:04:53 -0600 Subject: [PATCH 46/52] Follow an event --- server/user_db.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/server/user_db.js b/server/user_db.js index d7a15898..e14cb804 100644 --- a/server/user_db.js +++ b/server/user_db.js @@ -408,18 +408,18 @@ exports.createEntryAndFollowEvent = (user_id, event_id, callback) => { }); } -exports.followEvent = function(uid, eid, callback) { +exports.followEvent = function(user_id, event_id, callback) { db.query('BEGIN;'); - let query = 'SELECT followed_event FROM user_profile WHERE uid = $1 FOR UPDATE;'; - db.query(query, [uid], function (err, result) { + let query = 'SELECT followed_events FROM user_event WHERE uid = $1 FOR UPDATE;'; + db.query(query, [user_id], function (err, result) { if (err) { db.query('COMMIT;'); callback(err); } else { - var followed_event = JSON.parse(result.rows[0]['followed_event']); - followed_event.push(parseInt(eid)); - query = 'UPDATE user_profile SET followed_event = ' + "'" + JSON.stringify(followed_event) + "'" + ' WHERE uid = $1;'; - db.query(query, [uid], function (err_update) { + const followed_event = JSON.parse(result.rows[0]['followed_events']); + followed_event.push(parseInt(event_id)); + query = 'UPDATE user_event SET followed_events = ' + "'" + JSON.stringify(followed_event) + "'" + ' WHERE uid = $1;'; + db.query(query, [user_id], function (err_update) { if (err_update) { db.query('ROLLBACK;') callback(err_update); From dbdebc745c0127bea57488e462a7cf1cf76af87d Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:05:11 -0600 Subject: [PATCH 47/52] Move to event_api --- routes/event/event.js | 46 ------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/routes/event/event.js b/routes/event/event.js index aa5669d6..f2bea905 100644 --- a/routes/event/event.js +++ b/routes/event/event.js @@ -149,50 +149,4 @@ router.get('/followed', function (req, res, next) { }); }); -router.get('/rsvp', function (req, res, next) { - let event_id = req.query.id; - let uid = req.query.user_id ? req.query.user_id : req.session.uid; - authService.authorizationCheck(null, req.session.uid, function(err, authorized){ - if (err) { - console.log(err); - res.status(400).json({msg: 'Database Error'}); - } - else if(!authorized) { - res.redirect('/login'); - } else { - - user_db.getUserById(uid, (err, user_info) => { - if (err) { - console.log(err); - res.status(400).json({msg: 'Database Error'}); - } - - let user_email = user_info.email; - - event_db.getEventById(event_id, (err, event_info) => { - if (err) { - console.log(err); - res.status(400).json({msg: 'Database Error'}); - } - - const emailDetail = { - to: user_email, - subject: '[Coding 4 Good] ' + event_info.title, - html: "This email regards event" + event_info.title + "
" + event_info.description + "." - }; - - emailService.sendEmail(emailDetail, (err) => { - if(err){ - console.log(err); - res.redirect('/event?status=f&msg=Failed_to_send_RSVP_email'); - } else { - res.redirect('/event?status=s&msg=RSVP_email_has_been_sent'); - } - }) - }); - }); - } - }); -}); - module.exports = router; From 9ad0f7ba0426487e342e725ae9d6109ee33902ee Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:05:48 -0600 Subject: [PATCH 48/52] Rely on user_event rather than user_profile --- routes/event/event.js | 63 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/routes/event/event.js b/routes/event/event.js index f2bea905..72e74387 100644 --- a/routes/event/event.js +++ b/routes/event/event.js @@ -7,54 +7,53 @@ const authService = require('../services/authorization_service'); router.get('/', function (req, res, next) { let uid = req.session.uid; - event_db.getEventSet(function (err, eventsSet) { + event_db.getEventSet(function (err, events_set) { if (err) { console.log(err); res.status(400).json({msg: 'Database Error'}); return; } - user_db.hasProfile(uid, (err, predicate) => { + user_db.getUserRoleByUid(uid, (err, user_role) => { if (err) { + console.log(err); res.status(400).json({msg: 'Database Error'}); return; } - if (predicate === 'TRUE' || predicate === 'NO_USR_ID') { - user_db.getUserFollowedEventsByUid(uid, (err, followed_event) => { + user_db.getUserFollowedEventsByUid(uid, (err, followed_events) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Database Error'}); + return; + } + user_db.getUserRSVPEventsByUid(uid, (err, rsvp_events) => { if (err) { + console.log(err); res.status(400).json({msg: 'Database Error'}); return; } - user_db.getUserRoleByUid(req.session.uid, function (err, user_role) { - if (err) { - res.status(400).json({msg: 'Database Error'}); - return; - } - eventsSet = eventsSet.sort(function (a, b) { - return a.event_time - b.event_time - }) - let now = new Date(); - now = new Date(now - (5.5 * 60 * 60 * 1000)); - var centerIdx = eventsSet.length - 1; - for (var i = eventsSet.length - 1; i >= 0; i--) { - // show the event thats coming up soon - if (eventsSet[i].event_time < now) { - break; - } - centerIdx = i; + events_set = events_set.sort((event_a, event_b) => { + return event_a.event_time - event_b.event_time + }) + let now = new Date(); + now = new Date(now - (5.5 * 60 * 60 * 1000)); + let center_idx = events_set.length - 1; + for (let i = events_set.length - 1; i >= 0; i--) { + if (events_set[i].event_time < now) { + break; } - res.render('event/index', { - followed_event: JSON.parse(followed_event), - eventsSet: eventsSet, - uid: req.session.uid, - all_user_role: authService.UserRole, - user_role: user_role, - centerIdx: centerIdx - }); + center_idx = i; + } + res.render('event/index', { + followed_events: JSON.parse(followed_events), + rsvp_events: JSON.parse(rsvp_events), + eventsSet: events_set, + uid: req.session.uid, + all_user_role: authService.UserRole, + user_role: user_role, + centerIdx: center_idx }); }); - } else { - res.redirect('../profile?status=f&msg=Please_update_your_profile'); - } + }); }); }); }); From cad51e7a0bb011bafabdce4f7c3c9925db94be65 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:05:55 -0600 Subject: [PATCH 49/52] Update event.js --- routes/event/event.js | 1 - 1 file changed, 1 deletion(-) diff --git a/routes/event/event.js b/routes/event/event.js index 72e74387..c6d926d6 100644 --- a/routes/event/event.js +++ b/routes/event/event.js @@ -2,7 +2,6 @@ const express = require('express'); const router = express.Router(); const event_db = require("../../server/event_db"); const user_db = require("../../server/user_db"); -const emailService = require('../services/email_service'); const authService = require('../services/authorization_service'); router.get('/', function (req, res, next) { From 5f2d1f3c54a71d65daf3848f20f5f8b580a9e335 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:06:53 -0600 Subject: [PATCH 50/52] Un RSVP --- routes/event/event_api.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/routes/event/event_api.js b/routes/event/event_api.js index f781ba32..6cc80860 100644 --- a/routes/event/event_api.js +++ b/routes/event/event_api.js @@ -137,4 +137,20 @@ router.post('/unfollowEvent', function(req, res, next) { })) }); + +router.post('/unrsvpEvent', function(req, res, next) { + if(!req.body.uid){ + res.status(403).json({msg: 'Not Authorized'}); + return; + } + user_db.unrsvpEvent(req.body.uid, req.body.eid, ((err) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Failed to unfollow event'}); + return; + } + res.json({}); + })) +}); + module.exports = router; From b6511421c6fe530b59636d5373d342dcc7213462 Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:07:01 -0600 Subject: [PATCH 51/52] RSVP --- routes/event/event_api.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/routes/event/event_api.js b/routes/event/event_api.js index 6cc80860..d2df7fc2 100644 --- a/routes/event/event_api.js +++ b/routes/event/event_api.js @@ -137,6 +137,39 @@ router.post('/unfollowEvent', function(req, res, next) { })) }); +router.post('/rsvpEvent', function (req, res, next) { + if(!req.body.uid){ + res.status(403).json({msg: 'Not Authorized'}); + return; + } + user_db.hasUserEventEntry(req.body.uid, (err, has_entry) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Failed to check entry'}); + return; + } + if (has_entry) { + user_db.rsvpEvent(req.body.uid, req.body.eid, (err) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Failed to RSVP event'}); + return; + } + + res.json({}); + }); + } else { + user_db.createEntryAndRSVPEvent(req.body.uid, req.body.eid, (err) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Failed to create entry and RSVP event'}); + return; + } + res.json({}); + }); + } + }); +}); router.post('/unrsvpEvent', function(req, res, next) { if(!req.body.uid){ From df4680779769e98053f8e7b929e46e674c59623b Mon Sep 17 00:00:00 2001 From: Reid Chen Date: Fri, 22 Jan 2021 01:07:38 -0600 Subject: [PATCH 52/52] Update event_api.js --- routes/event/event_api.js | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/routes/event/event_api.js b/routes/event/event_api.js index d2df7fc2..90efb77a 100644 --- a/routes/event/event_api.js +++ b/routes/event/event_api.js @@ -112,14 +112,32 @@ router.post('/followEvent', function(req, res, next) { res.status(403).json({msg: 'Not Authorized'}); return; } - user_db.followEvent(req.body.uid, req.body.eid, ((err) => { + user_db.hasUserEventEntry(req.body.uid, (err, has_entry) => { if (err) { console.log(err); - res.status(400).json({msg: 'Failed to follow event'}); + res.status(400).json({msg: 'Failed to check entry'}); return; } - res.json({}); - })) + if (has_entry) { + user_db.followEvent(req.body.uid, req.body.eid, (err) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Failed to follow event'}); + return; + } + res.json({}); + }); + } else { + user_db.createEntryAndFollowEvent(req.body.uid, req.body.eid, (err) => { + if (err) { + console.log(err); + res.status(400).json({msg: 'Failed to create entry and follow event'}); + return; + } + res.json({}); + }) + } + }); }); router.post('/unfollowEvent', function(req, res, next) {