From f0ef9c621c55566073b6e082359492cdaf350f53 Mon Sep 17 00:00:00 2001 From: Teppy Date: Fri, 21 Feb 2025 20:54:53 -0500 Subject: [PATCH] changes --- foftickets.js | 78 +++++++++++++++++++++------------------------ views/oneticket.ejs | 63 +++++++++++++++++++----------------- views/settings.ejs | 1 + 3 files changed, 70 insertions(+), 72 deletions(-) diff --git a/foftickets.js b/foftickets.js index 36316e8..ba2d34c 100644 --- a/foftickets.js +++ b/foftickets.js @@ -43,12 +43,14 @@ const QRSalt ="!SaltyMagic5392370662"; // + Magic-link Login System // Setting to deactivate transfers globally // Mass-import of individual tickets -// Cookie based QR code functionality -// Create Account (User) -// Change Password (User) +// + Cookie based QR code functionality +// + Create Account (User) +// + Change Password (User) +// Change most POST routes to end in redirect instead of render. // Deactivate individual magic links (User) // Deactivate individual magic links (Admin) // See how much each camp/ticket has paid (Admin) +// Purchase individual open camping tickets // // ToDo, Later // + Use a templating engine @@ -140,7 +142,7 @@ function MagicLinkValid(email,hash) { let users={}; let tickets={}; let camps={}; -let settings={}; +let settings={ "enable-transfers":true }; function InitDatabase() { for (const key in users ) delete users[key]; @@ -287,7 +289,7 @@ app.post('/moretickets', requireSuperUser, (req,res) => { app.get('/manytickets', requireLogin, (req,res) => { let username=req.session.username; - const edit={ username:req.session.username, superuser:req.session.superuser, tickets: {} }; + const edit={ username:req.session.username, superuser:req.session.superuser, tickets: {}, cantransfer:settings["enable-transfer"] }; for (const t in tickets) if (tickets[t].owner==username && tickets[t].status=="i") { edit.tickets[t]={}; edit.tickets[t].offered=tickets[t].offered; @@ -302,7 +304,7 @@ app.get('/mytickets',requireLogin, async (req,res)=> { let claimed=0; let owned=0; let theticket=""; - const edit={ username:req.session.username, superuser:req.session.superuser, tickets: {} }; + const edit={ username:req.session.username, superuser:req.session.superuser, tickets: {}, cantransfer:settings["enable-transfer"] }; for (const t in tickets) { if (tickets[t].status=="i" && tickets[t].offered==username) { claimed++; tickets[t].owner=username; tickets[t].offered=""; } // LOG if (tickets[t].status=="i" && tickets[t].owner==username) { @@ -325,7 +327,8 @@ app.get('/mytickets',requireLogin, async (req,res)=> { const useurl=MainURL+'/useticket?t='+theticket+'&h='+hashQR(theticket,username); const dataURL=await QRCode.toDataURL(useurl); return res.render("oneticket",{ username:username, superuser:req.session.superuser, message:message, magiclink:GetMagicLink(username), - ticket:theticket, offered:tickets[theticket].offered, paid:tickets[theticket].paid, qrcode:dataURL, useurl:useurl }); + ticket:theticket, offered:tickets[theticket].offered, paid:tickets[theticket].paid, qrcode:dataURL, useurl:useurl, + cantransfer:settings["enable-transfer"] }); } else return res.render("manytickets",edit); }); @@ -333,9 +336,9 @@ app.get('/mytickets',requireLogin, async (req,res)=> { app.get("/oneticket",requireLogin, async (req,res) => { let username=req.session.username; let ticket=req.query.t; - console.log("Ticket ",tickets); - if (tickets[ticket]) console.log("Onwer ",tickets[ticket].owner); - if (!tickets[ticket] || tickets[ticket].owner!=username) return res.render("error", { username:username, superuser:req.session.superuser, message: "You are not the owner of ticket "+ticket }); + if (!tickets[ticket]) return res.render("error",{ username:username, superuser:req.session.superuser, message: "Ticket not found: "+ticket }); + if (req.session.superuser) username=tickets[ticket].owner; + else if (tickets[ticket].owner!=username) return res.render("error", { username:username, superuser:req.session.superuser, message: "You are not the owner of ticket "+ticket }); let offered=tickets[ticket].offered; let message=""; const hash0=crypto.createHash('sha256'); @@ -344,17 +347,18 @@ app.get("/oneticket",requireLogin, async (req,res) => { const useurl=MainURL+'/useticket?t='+ticket+'&h='+hashQR(ticket,username); const dataURL=await QRCode.toDataURL(MainURL+'/useticket?t='+ticket+'&h='+hashQR(ticket,username)); return res.render("oneticket", { username:username, superuser:req.session.superuser, message:message, magiclink:GetMagicLink(username), - ticket:ticket, offered:tickets[ticket].offered, paid:tickets[ticket].paid, qrcode:dataURL, useurl:useurl }); + ticket:ticket, offered:tickets[ticket].offered, paid:tickets[ticket].paid, qrcode:dataURL, useurl:useurl, + cantransfer:settings["enable-transfer"] }); }); -app.post('/oneticket',requireLogin, async (req,res) => { // Make sure the ticket is owned by trhe logged in user! +app.post('/oneticket',requireLogin, async (req,res) => { // Make sure the ticket is owned by the logged in user! let username=req.session.username; let ticket=req.body.ticket; if (!tickets[ticket] || tickets[ticket].owner!=username) return res.render("error", { username:username, superuser:req.session.superuser, message: "You are not the owner of ticket "+ticket }); let offered=req.body.offered; let message=""; - if (tickets[ticket].owner==username && tickets[ticket].status=="i") { + if (req.session.cantransfer && tickets[ticket].owner==username && tickets[ticket].status=="i") { tickets[ticket].offered=offered; // LOG EmailTickets(offered); } @@ -363,8 +367,7 @@ app.post('/oneticket',requireLogin, async (req,res) => { // Make sure the ticket const hash=hash1.digest("base64").slice(0,6); const dataURL=await QRCode.toDataURL(MainURL+'/useticket?t='+ticket+'&h='+hashQR(ticket,username)); const useurl=MainURL+'/useticket?t='+ticket+'&h='+hashQR(ticket,username); - return res.render("oneticket", { username:username, superuser:req.session.superuser, message:message, magiclink:GetMagicLink(username), - ticket:ticket, offered:tickets[ticket].offered, paid:tickets[ticket].paid, qrcode:dataURL, useurl:useurl }); + return res.redirect("/"); }); @@ -375,20 +378,9 @@ app.post("/changestatus", requireSuperUser, (req,res) => { res.json({ message: 'Status received', status: req.body.status }); }) -app.post("/updateoffered", requireLogin, (req,res) => { - const ticket=req.body.ticket; - const offered=req.body.offered; - if (tickets[ticket].owner!=req.session.username) res.status(500).send("Ticket "+ticket+" owned by someone else"); - else if (tickets[ticket].status=="u") res.status(500).send("Ticket "+ticket+" has already been used"); - else if (tickets[ticket].status=="r") res.status(500).send("Ticket "+ticket+" was revoked"); - else { - tickets[ticket].offered=offered; // LOG - res.json({ message: 'Updated owner of '+ticket+' to '+offered }); - } - }) - // Need a SuperUser version of this app.post("/updateoffered2", requireLogin, (req,res) => { + if (!req.cantransfer) return res.render("error",{ message: "Transfer functionality has been disabled by the admin." }); const changes={}; for (ticket in req.body) if (tickets[ticket] && tickets[ticket].owner==req.session.username && req.body[ticket]!=tickets[ticket].offered) { if (!(req.body[ticket] in changes)) changes[req.body[ticket]]=0; @@ -399,7 +391,7 @@ app.post("/updateoffered2", requireLogin, (req,res) => { tickets[ticket].offered=req.body[ticket]; } for (email in changes) EmailTickets(email); - return res.redirect("manytickets"); + return res.redirect("/manytickets"); }) @@ -437,15 +429,17 @@ app.post("/updateticketsu", requireSuperUser, (req,res) => { app.get("/useticket",(req,res) => { let ticket=req.query.t; let hash=req.query.h; - if (!tickets[ticket]) return res.status(500).send("Ticket "+ticket+" not found."); - if (hashQR(ticket,tickets[ticket].owner)!=hash) return res.status(500).send("Ticket "+ticket+" was transferred to "+tickets[ticket].owner); - if (tickets[ticket].status!="i") return res.status(500).send("Ticket "+ticket+" has already been used."); + if (!tickets[ticket]) return res.render("error", { message: "Ticket "+ticket+" not found." }); + if (tickets[ticket].status!="i") return res.render("error", { message: "Ticket "+ticket+" has already been used." }); + if (hashQR(ticket,tickets[ticket].owner)!=hash) return res.render("error", { message: "Ticket "+ticket+" was transferred to "+tickets[ticket].owner }); let paid_message=tickets[ticket].paid; - if (tickets[ticket].paid==0) paid_message="This ticket has not been paid for. Encourage a donation at the gate."; - if (settings['enable-ticket-use']) { - tickets[ticket].status="u"; // LOG - return res.send("

Welcome, "+tickets[ticket].owner+" to Falls on Fire!
Ticket "+ticket+" has now been used.


"+paid_message); - } else return res.send("

Your ticket is good, "+tickets[ticket].owner+"
The server is not in Event Mode, so Ticket "+ticket+" is still valid.
"+paid_message); + if (tickets[ticket].paid==0) paid_message="
This ticket has not been paid for. Encourage a donation at the gate."; + if (!settings['enable-ticket-use']) + return res.render("message", { message: "Your ticket is good, "+tickets[ticket].owner+". The server is not in Event Mode, so Ticket "+ticket+" is still valid."+paid_message }); + if (req.cookies["fof_scanqr"]!="on") + return res.render("message", { message: "Ticket "+ticket+" owned by "+tickets[ticket].owner+" is good, but scanning on this device has not been enabled."+paid_message }); + tickets[ticket].status="u"; // LOG + return res.render("message", { message: "Welcome, "+tickets[ticket].owner+" to Falls on Fire! Ticket "+ticket+" has now been used."+paid_message }); }) @@ -606,29 +600,29 @@ app.get('/settings',requireSuperUser, (req,res) => { app.post('/wipedb',requireSuperUser, (req,res) => { InitDatabase(); - res.render('settings',{ username:req.session.username, superuser:req.session.superuser, message: "Wiped the database, but not the logfile." }) + res.redirect("/"); }); -app.post('/serialize',requireSuperUser, (req,res) => { +app.post('/serialize',requireSuperUser, async (req,res) => { SerializeAll(); - res.render('settings',{ username:req.session.username, superuser:req.session.superuser, message: "Wrote database to disk." }) + return res.redirect("/settings"); }); app.post('/deserialize',requireSuperUser, (req,res) => { DeserializeAll(); - res.render('settings',{ username:req.session.username, superuser:req.session.superuser, message: "Read database from disk." }) + return res.redirect("/"); // Since we may be overwriting session }); app.post('/purge',requireSuperUser, (req,res) => { let count=0; for (const t in tickets) if (tickets[t].status=='r') { count++; delete tickets[t]; } - res.render('settings',{ username:req.session.username, superuser:req.session.superuser, message: "Purged "+count+" revoked tickets" }) + return res.redirect("/settings"); }); app.post('/update-setting', requireSuperUser, (req, res) => { settings[req.body.name]=req.body.checked; res.json({ success: true, message: 'Checkbox state updated successfully' }); -}); + }); app.post('/pay0',requireLogin,(req,res) => { return res.render("pay",{ username:req.session.username, superuser:req.session.superuser, ticket:req.body.ticket, amount:req.body.amount }); diff --git a/views/oneticket.ejs b/views/oneticket.ejs index 460ad23..76880d0 100644 --- a/views/oneticket.ejs +++ b/views/oneticket.ejs @@ -1,33 +1,36 @@ - - Your Ticket - - - - <%- include('partials/nav') %> -
- To use <%=ticket%>, visit this URL: <%=useurl%>
- Or scan this QR Code:
- QR Code
- <% if (paid==0) { %> - Tickets are pay-what-you-can, minimum $1, suggested $50.
- To pay for this ticket by credit card, enter an amount: -
- - - -
- <% } else { %> - This ticket has already been paid for. ($<%=(paid/100).toFixed(2)%>) - <% } %> -
- To transfer <%=ticket%>, enter the recipient's email address:
- - - -
-
-
- + + Your Ticket + + + + <%- include('partials/nav') %> +
+ <% if (superuser) { %> + Note: This page is being displayed as Superuser.
+ <% } %> + To use <%=ticket%>, visit this URL: <%=useurl%>
+ Or scan this QR Code:
+ QR Code
+ <% if (paid==0) { %> + Tickets are pay-what-you-can, minimum $1, suggested $50.
+ To pay for this ticket by credit card, enter an amount: +
+ + + +
+ <% } else { %> + This ticket has already been paid for. ($<%=(paid/100).toFixed(2)%>) + <% } %> +
+ To transfer <%=ticket%>, enter the recipient's email address:
+ + + +
+
+
+ diff --git a/views/settings.ejs b/views/settings.ejs index 02cf81f..6d41968 100644 --- a/views/settings.ejs +++ b/views/settings.ejs @@ -10,6 +10,7 @@ Enable Email
Enable Ticket Use
Enable Credit Cards
+ Enable Transfers