diff --git a/foftickets.js b/foftickets.js index 915adf6..9a3c4ed 100644 --- a/foftickets.js +++ b/foftickets.js @@ -3,6 +3,7 @@ const bodyParser = require('body-parser'); const session = require('express-session'); const QRCode=require('qrcode'); const crypto=require('crypto'); +const path=require('path'); const app = express(); app.set('view engine','ejs'); @@ -16,8 +17,8 @@ const QRSalt="!SaltyMagic5392370662"; // + Login with Password // + Login with Token // + Email Link -// Signup -// Set Password +// + Signup +// Change Password // Issue Tickets // Transfer Tickets Complicated page. (One ticket: static with transfer and QR code. Multi: buttons to transfer or show QR code) // Claim Tickets @@ -50,8 +51,8 @@ function hashQR(t,username) { // // There are two ways to log in: with a username/password or with a token. // -const users = { "teppy@egenesis.com" : { password: hashPW("x6321872X.1") , superuser:1 }, - "fallsonfire@gmail.com" : { password: hashPW("indiantreeonfire"), superuser:1 } +const users = { "teppy@egenesis.com" : { password: hashPW("x6321872X.1"), superuser:true }, + "fallsonfire@gmail.com" : { password: hashPW("indiantreeonfire"), superuser:false } }; const tickets = { "habitat-1" : { owner: "teppy@egenesis.com" , offered: "", paid: 0.00, used: false }, @@ -62,6 +63,8 @@ const tickets = { "habitat-1" : { owner: "teppy@egenesis.com" , offered: "", pa "habitat-6" : { owner: "teppy@egenesis.com" , offered: "", paid: 0.00 }, }; +const camps = { "habitat": 0 }; + const tokens = { "abc" : { username: "teppy@egenesis.com", expires: 0 } }; const tokensu = { "teppy@egenesis.com" : "abc" @@ -77,14 +80,21 @@ app.use(session({ // Middleware to protect routes function requireLogin(req, res, next) { - if (!req.session.username) { - return res.redirect('/login'); - } - next(); -} - + if (!req.session.username) return res.redirect('/login'); + next(); + } + +function requireSuperUser(req,res,next) { + console.log(req.session); + if (!req.session.superuser) return res.status(403).send(JSON.stringify( { error: "Forbidden without superuser flag" } )); + else next(); + } +app.get('/styles.css', (req, res) => { + res.setHeader('Content-Type', 'text/css'); + res.sendFile(path.join(__dirname, 'public', 'styles.css')); + }); function generateSecureToken(length = 8) { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; @@ -123,7 +133,7 @@ app.get('/logintoken', (req, res) => { const tokenData = tokens[tok]; if (!consumeToken(tok)) return res.status(200).send("Missing, Invalid or Expired Token."); req.session.username = tokenData.username; - req.session.superuser= tokenData.superuser; + req.session.superuser= users[tokenData.username].superuser; res.redirect('/transfer'); }); @@ -163,7 +173,6 @@ function categorizeTickets(username) { } - // Big Kahuna // If you have zero tickets, show something saying that // For each ticket owned, display options to offer it, use it, or (eventually) pay for it. @@ -205,8 +214,7 @@ app.get('/transfer', requireLogin, async (req,res) => { if (cat=="complex") return res.render('transfer',simpledata); }) -app.post("/toggle", (req,res) => { - console.log("Here is Tickets...",tickets); +app.post("/toggle", requireSuperUser, (req,res) => { const ticket=req.body.ticket; const isChecked = req.body.checked; tickets[ticket].used=isChecked; @@ -214,6 +222,17 @@ app.post("/toggle", (req,res) => { res.json({ message: 'Checkbox state received', checked: isChecked }); }) +app.post("/updateoffered", requireLogin, (req,res) => { + const ticket=req.body.ticket; + const offered=req.body.offered; + console.log("Ticket: ",ticket); + if (tickets[ticket].owner!=req.session.username) res.status(500).send("Ticket "+ticket+" owned by someone else"); + else if (tickets[ticket].used) res.status(500).send("Ticket "+ticket+" has already been used"); + else { + tickets[ticket].offered=offered; + res.json({ message: 'Updated owner of '+ticket+' to '+offered }); + } + }) app.get("/useticket",(req,res) => { let ticket=req.t; @@ -254,7 +273,6 @@ app.post('emaillink',(req,res) => { }) - app.get('/testemail', (req,res) => { client.sendEmail({ From: 'tickets@fallsonfire.net', @@ -331,7 +349,8 @@ app.post('/signup', (req, res) => { if (users[username]) { return res.send('User already exists. Try again'); } - users[username] = { password }; + users[username] = { password: hashPW(password) }; + console.log("Created new account:",username); res.redirect('/login'); }); @@ -372,10 +391,11 @@ app.get('/login', (req, res) => { }); app.post('/login', (req, res) => { - const { username, password } = req.body; - if (users[username] && users[username].password === hashPW(password)) { - req.session.username = username; - return res.redirect('/transfer'); + const { username, password, superuser } = req.body; + if (users[username] && users[username].password === hashPW(password)) { + req.session.username = username; + req.session.superuser = users[username].superuser; + return res.redirect('/transfer'); } res.send('Invalid username or password. Try again'); }); diff --git a/public/styles.css b/public/styles.css new file mode 100644 index 0000000..5047409 --- /dev/null +++ b/public/styles.css @@ -0,0 +1,31 @@ + + +/* Modal container */ +.modal { + display: none; /* Hidden by default */ + position: fixed; /* Stay in place */ + z-index: 1000; /* Sit on top */ + left: 0; + top: 0; + width: 100%; /* Full width */ + height: 100%; /* Full height */ + background-color: rgba(0, 0, 0, 0.5); /* Black with opacity */ +} + +/* Modal content */ +.modal-content { + background-color: white; + margin: 15% auto; /* Center the modal */ + padding: 20px; + border: 1px solid #888; + width: 80%; /* Adjust as needed */ +} + +/* Close button */ +.close { + color: black; + float: right; + font-size: 28px; + font-weight: bold; + cursor: pointer; +} diff --git a/views/superuser.ejs b/views/superuser.ejs new file mode 100644 index 0000000..ee1bbed --- /dev/null +++ b/views/superuser.ejs @@ -0,0 +1,9 @@ + + +
+