This commit is contained in:
2025-03-03 23:53:35 -05:00
parent 7eb5b42d99
commit 8a3ee3e18c
5 changed files with 47 additions and 25 deletions

View File

@@ -51,19 +51,20 @@ const QRSalt ="!SaltyMagic5392370662";
// + Turn ticket use on/off from Settings (Admin)
// + Turn email on/off from Settings (Admin)
// + Magic-link Login System
// Convert all the routes to use common.(user,superuser,etc)
// Display messages for all GET routes?
// Setting to deactivate transfers globally
// Option to "Email me my QR Code"
// Mass-import of individual tickets
// + Convert all the routes to use common.(user,superuser,etc)
// + Display messages for all GET routes?
// + Setting to deactivate transfers globally
// + Mass-import of individual tickets
// + 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)
// + Change most POST routes to end in redirect instead of render.
// Deactivate individual magic links (Admin)
// See how much each camp/ticket has paid (Admin)
// Purchase individual open camping tickets
// Maybe:
// Deactivate individual magic links (User)
// Option to "Email me my QR Code"
//
// ToDo, Later
// + Use a templating engine
@@ -135,10 +136,11 @@ function MagicLinkValid(email,hash) {
app.use((req, res, next) => {
res.locals.commonData = {
username: req.username, // Attach user info if available
username: req.username, // Attach user info if available
superuser: req.superuser,
error: req.session && req.session.error || null, // Flash error messages
message: req.session && req.session.message || null, // Flash success messages
settings: settings,
error: req.session && req.session.error || null, // Flash error messages
message: req.session && req.session.message || null, // Flash success messages
};
// Clear session-based flash messages after use
@@ -172,7 +174,7 @@ app.use((req, res, next) => {
let users={};
let tickets={};
let camps={};
let settings={ "enable-transfers":true };
let settings={ "enable-transfer":true };
function InitDatabase() {
for (const key in users ) delete users[key];
@@ -314,7 +316,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: {}, cantransfer:settings["enable-transfer"] };
const edit={ username:req.session.username, superuser:req.session.superuser, tickets: {}, settings:settings };
for (const t in tickets) if (tickets[t].owner==username && tickets[t].status=="i") {
edit.tickets[t]={};
edit.tickets[t].offered=tickets[t].offered;
@@ -329,7 +331,8 @@ 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: {}, cantransfer:settings["enable-transfer"] };
const edit={ username:req.session.username, superuser:req.session.superuser, tickets: {}, settings:settings };
console.log(edit);
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) {
@@ -351,9 +354,11 @@ app.get('/mytickets',requireLogin, async (req,res)=> {
const hash=hash1.digest("base64").slice(0,6);
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,
cantransfer:settings["enable-transfer"] });
const data={ 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,
settings: settings }
console.log(data);
return res.render("oneticket",data);
}
else return res.render("manytickets",edit);
});
@@ -373,7 +378,7 @@ app.get("/oneticket",requireLogin, async (req,res) => {
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,
cantransfer:settings["enable-transfer"] });
settings:settings });
});
@@ -403,9 +408,10 @@ app.post("/changestatus", requireSuperUser, (req,res) => {
res.json({ message: 'Status received', status: req.body.status });
})
// 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." });
if (!settings["enable-transfer"]) {
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;
@@ -634,8 +640,16 @@ app.post('/importfb',requireSuperUser,upload.single("file"),(req,res) => {
req.session.error="The CVS file did not parse correctly. Check console.";
return res.redirect("/settings");
}
console.log("Records:",records);
req.session.message="Imported Frostburn-style records.";
let count=0;
for (const item of records) {
if (!camps[item.camp]) camps[item.camp]={ leader:"", lastid:0 };
camps[item.camp].lastid++;
const ticket=item.camp+"-"+camps[item.camp].lastid;
tickets[ticket]={ owner:"", offered: item.email, paid:0.00, status:"i" };
console.log("Offered ",ticket," to ",item.email);
count++;
}
req.session.message="Imported "+count+" Frostburn-style records.";
return res.redirect("/settings");
});
});

View File

@@ -15,7 +15,7 @@
<div class="content">
<form id="editor" method="POST" action="/updateoffered2su">
<div id="server-response">Server Ready</div>
Camp Namex: <%=campname%><br>
Camp Name: <%=campname%><br>
Camp Leader: <%=leader%>
<table border="1">
<tr>

View File

@@ -26,7 +26,11 @@
<% for (const t in tickets) { %>
<tr>
<td><a href="oneticket?t=<%=t%>"><%=t%></a></td>
<td><input type="text" class="offered" value="<%=tickets[t].offered%>" name="<%=t%>"></td>
<% if (settings["enable-transfer"]) { %>
<td><input type="text" class="offered" value="<%=tickets[t].offered%>" name="<%=t%>"></td>
<% } else { %>
<td><%=tickets[t].offered%></td>
<% } %>
<td><%=tickets[t].paid>0 ? (tickets[t].paid/100).toFixed(2) : "No"%>
<td><button id="<%=t%>-action" type="button"> QRCode </button></td>
</tr>
@@ -34,7 +38,9 @@
<tr>
</tr>
</table>
<button id="Update" type="submit">Update Offered</button>
<% if (settings["enable-transfer"]) { %>
<button id="Update" type="submit">Update Offered</button>
<% } %>
</form>
</div>
<script>

View File

@@ -24,6 +24,7 @@
<% } else { %>
This ticket has already been paid for. ($<%=(paid/100).toFixed(2)%>)
<% } %>
<% if (settings["enable-transfer"]) { %>
<form id="editor" method="POST" action="/oneticket">
To transfer <%=ticket%>, enter the recipient's email address:<br>
<input type="hidden" name="ticket" value="<%=ticket%>">
@@ -31,6 +32,7 @@
<button id="Submit" type="submit">Transfer</button>
<br>
</form>
<% } %>
</div>
</body>
</html>

View File

@@ -10,7 +10,7 @@
<input type="checkbox" class="setting" name="enable-email" <%= settings["enable-email"] ? "checked" : "" %> >Enable Email<br>
<input type="checkbox" class="setting" name="enable-ticket-use" <%= settings["enable-ticket-use"] ? "checked" : "" %> >Enable Ticket Use<br>
<input type="checkbox" class="setting" name="enable-credit-cards" <%= settings["enable-credit-cards"] ? "checked" : "" %> >Enable Credit Cards<br>
<input type="checkbox" class="setting" name="enable-transfers" <%= settings["enable-transfers"] ? "checked" : "" %> >Enable Transfers<br>
<input type="checkbox" class="setting" name="enable-transfer" <%= settings["enable-transfer"] ? "checked" : "" %> >Enable Transfer<br>
<form action='/purge' method='post'>
<button type="submit" >Purge Revoked Tickets</button>
</form>