Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treasure hunt - Test build #17

Merged
merged 37 commits into from
Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
249f8aa
Team List page for admin and Timeout page done (kinda)
destryptor Mar 1, 2024
ffae772
Admin frontend completed with routes
destryptor Mar 1, 2024
5d3a0ef
Redundant (possibly) validation rules removed
destryptor Mar 1, 2024
fc99f2a
State transition with localStorage complete
destryptor Mar 2, 2024
5f45dcb
State transition fixes and Basic Model creation
destryptor Mar 6, 2024
fdde2ef
removed unused tests
ItsAnkan Mar 7, 2024
2c33811
added a small function to start/end the quiz
ItsAnkan Mar 7, 2024
d41e2ca
localstorage hehe
ItsAnkan Mar 7, 2024
4332bd8
fjbkjdfhasjd
ItsAnkan Mar 8, 2024
33073d4
States fixed yet again (with a bit of localStorage use)
destryptor Mar 8, 2024
e114af4
interface changes
ItsAnkan Mar 9, 2024
4faa332
DB stuff
Goose-Of-War Mar 9, 2024
e272f7c
Auth
Goose-Of-War Mar 9, 2024
7a52175
shrinkwrap mishap
Goose-Of-War Mar 9, 2024
c2e9b5d
Edit and list team work
Goose-Of-War Mar 9, 2024
ec852c1
interface works, almost
ItsAnkan Mar 9, 2024
09d1d46
test
ItsAnkan Mar 9, 2024
fed1621
leaning
ItsAnkan Mar 9, 2024
41fe10f
backen shii
ItsAnkan Mar 9, 2024
00e20a2
Onkon baka
destryptor Mar 9, 2024
7421f07
GIT SUCKS
destryptor Mar 9, 2024
277190d
Onkon lolicon
destryptor Mar 9, 2024
f42e7e0
Onkon in prison
destryptor Mar 9, 2024
63d90ad
Onkon's sentence increased
destryptor Mar 9, 2024
8524f53
Onkon's sentence++
destryptor Mar 9, 2024
180ce33
Onkon's sentence*=2
destryptor Mar 9, 2024
62c394f
why booli ;-;
ItsAnkan Mar 9, 2024
136a33d
nvm i get it ;-;
ItsAnkan Mar 9, 2024
4b71588
i need sleep
ItsAnkan Mar 9, 2024
7c8cb55
Onkon is slowly turning into a mad man
destryptor Mar 9, 2024
b72d2a8
Onkon is slowly turning into a mad man
destryptor Mar 9, 2024
c46b17f
Onkon was whacked by the jail super
destryptor Mar 9, 2024
b2eda3c
Onkon's sentence reduced by half
destryptor Mar 9, 2024
b573bd0
started ???
ItsAnkan Mar 9, 2024
c305abc
Onkon dropped the soap
destryptor Mar 9, 2024
0b40f46
ono
ItsAnkan Mar 9, 2024
0055b0f
didnt knwo she was underaged
ItsAnkan Mar 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions assets/styles/form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ button:hover {
background-color: #c90c0c;
}

button:disabled {
background-color: var(--light-pink);
}

.item {
display: flex;
flex-direction: column;
Expand Down
17 changes: 17 additions & 0 deletions database/Schemas/Location.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const mongoose = require('mongoose');

const locationSchema = new mongoose.Schema({
_id: { type: String, required: true },
name: { type: String, required: true },
pointerQuestion: [{ type: String, required: true }],
code: { type: String, required: true },
questions: [
{
question: { type: String, required: true },
answer: { type: Number, required: true }
}
],
keywords: [{ type: String, required: true }]
}, { collection: 'locations' });

module.exports = mongoose.model('Location', locationSchema);
9 changes: 9 additions & 0 deletions database/Schemas/RiddleQuestion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const mongoose = require('mongoose');

const riddleQuestionSchema = new mongoose.Schema({
_id: { type: String, required: true },
question: { type: String, required: true },
answer: { type: String, required: true }
}, { collection: 'riddle-questions' });

module.exports = mongoose.model('RiddleQuestion', riddleQuestionSchema);
27 changes: 27 additions & 0 deletions database/Schemas/Team.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const mongoose = require('mongoose');

const teamSchema = new mongoose.Schema({
_id: { type: Number, required: true },
name: { type: String, required: true },
isAdmin: Boolean,
password: { type: String, requred: true },
members: [
{
name: { type: String, required: true },
email: { type: String, required: true },
phone: { type: String, required: true }
}
],
status: { type: String, required: true },
questionsAttempted: { type: Number, required: true, default: 0 },
order: [
{
location: { type: Number, required: true },
pointer: { type: Number, required: true },
question: { type: Number, required: true }
}
],
timeout: { type: [Date, null] }
}, { collection: 'event-teams' });

module.exports = mongoose.model('Team', teamSchema);
9 changes: 9 additions & 0 deletions database/Schemas/TeamSession.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const mongoose = require('mongoose');

const sessionSchema = new mongoose.Schema({
_id: { type: String, required: true },
teamId: { type: Number, required: true },
timestamp: { type: Date, default: new Date() }
}, { collection: 'team-session' });

module.exports = mongoose.model('TeamSession', sessionSchema);
85 changes: 84 additions & 1 deletion database/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ const Session = require('./Schemas/Session');
const Questions = require('./Schemas/Questions');
const Records = require('./Schemas/Records');
const Results = require('./Schemas/Results');
// Treasure Hunt stuff
const Location = require('./Schemas/Location');
const Team = require('./Schemas/Team');
const TeamSession = require('./Schemas/TeamSession');

async function createUser (userData) {
const _id = userData.userID ?? (await User.find({ _id: { '$gt': 10000 } })).length + 10001;
Expand Down Expand Up @@ -171,6 +175,76 @@ async function getLiveResults (quizId) {
return await Results.find({ quizId }).lean().sort({ 'points': -1 });
}

// Treasure Hunt Methods

async function getLocations () {
return await Location.find().lean();
}

async function getTeams () {
return await Team.find({ isAdmin: [undefined, false] }).lean();
}

async function getTeamById (_id) {
return await Team.findById(_id);
}

async function validateTeam ({ username: teamId, password }) {
const team = await Team.findById(~~teamId);
if (!team) throw new Error('Team could not be found');
if (team.password === password) return team._id;
else throw new Error('Password does not match');
}

async function updateTeamDetails (ctx) {
const { id, name, members } = ctx;
const team = await Team.findById(id);
team.name = name;
team.members = members;
return await team.save();
}

async function updateTeamStatus (ctx) {
const { _id, status } = ctx;
const team = await Team.findById(_id);
team.status = status;
if (status === 'riddle-timeout') {
team.timeout = new Date(Date.now() + 120 * 1000);
setTimeout(async () => {
team.status = 'riddle-question';
team.timeout = null;
await team.save();
}, 120 * 1000);
} else if (status === 'location-code') {
team.questionsAttempted = ctx.questionNo;
}
return await team.save();
}

async function getTeamFromSessionID (sessionId) {
const session = await TeamSession.findById(sessionId);
const team = await Team.findById(session.teamId);
if (!team) throw new Error('Team Not Found');
else return team;
}

async function createTeamSession (teamId) {
// 3327: You Are My Special
const sessionId = [3, 3, 2, 7].map(i => (Math.random() + 1).toString(36).substring(2, 2 + i)).join('-');
const session = new TeamSession({
_id: sessionId,
teamId: teamId
});
await session.save();
return sessionId;
}

async function removeTeamSession (sessionId) {
// Use this if we want to remove sessions after logout
await Session.findByIdAndDelete(sessionId);
}


module.exports = {
createUser,
editUser,
Expand All @@ -190,5 +264,14 @@ module.exports = {
addLiveRecord,
addLiveResult,
updateLiveResult,
getLiveResults
getLiveResults,
getLocations,
getTeams,
getTeamById,
validateTeam,
updateTeamDetails,
updateTeamStatus,
getTeamFromSessionID,
createTeamSession,
removeTeamSession
};
58 changes: 50 additions & 8 deletions routers/admin-router.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,67 @@ const dbh = require('../database/handler');
const { body, validationResult } = require('express-validator');
const checkAdmin = require('./check-admin');

const teams = require('../src/samples/teams.json');
const riddleQuestions = require('../src/samples/riddleQuestions.json');

router.use('/', checkAdmin);

router.get('/', (req, res) => {
res.renderFile('admin/_admin.njk');
});

router.get('/edit-team', async (req, res) => {
const teamID = parseInt(req.query.teamID);
const team = await dbh.getTeamById(teamID);
return res.renderFile('admin/team-edit.njk', { team });
});

router.patch('/edit-team', [
body('id')
.isNumeric()
.trim()
.notEmpty().withMessage('No ID Provided'),
body('teamName')
.trim()
.notEmpty().withMessage('No Name Provided')
], async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
const errorMessages = errors.array().map(error => error.msg);
throw new Error(errorMessages[0]);
}
const team = {
id: req.body.id,
name: req.body.teamName,
members: [
{ name: req.body.name1, email: req.body.email1, phone: req.body.phone1 },
{ name: req.body.name2, email: req.body.email2, phone: req.body.phone2 },
{ name: req.body.name3, email: req.body.email3, phone: req.body.phone3 },
{ name: req.body.name4, email: req.body.email4, phone: req.body.phone4 }
].filter(i => i.name)
};
// const teamIndex = teams.findIndex(t => t.id === team.id);
// if (teamIndex === -1) {
// teams.push(team);
// }
await dbh.updateTeamDetails(team);
return res.status(200).send('Edited Successfully');
});


router.get('/list-users', async (req, res) => {
const users = await dbh.getUsers();
res.renderFile('admin/user-list.njk', { users });
});

router.get('/edit-user', async (req, res) => {
const username = req.query.username;
if (!username) return res.redirect('/admin/list-users');
const data = (await dbh.getUserByUsername(username)).toObject();
delete data.salt;
delete data.hash;
res.renderFile('admin/user-edit.njk', { ...data });
});
// router.get('/edit-user', async (req, res) => {
// const username = req.query.username;
// if (!username) return res.redirect('/admin/list-users');
// const data = (await dbh.getUserByUsername(username)).toObject();
// delete data.salt;
// delete data.hash;
// res.renderFile('admin/user-edit.njk', { ...data });
// });

router.patch('/edit-user', [
body('name')
Expand Down
108 changes: 54 additions & 54 deletions routers/auth-router.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const router = require('express').Router();
const dbh = require('../database/handler');
const { body, validationResult } = require('express-validator');

const profile = require('../src/profile.json');
// const profile = require('../src/profile.json');

router.use((req, res, next) => {
if (['/login', '/signup', '/logout'].indexOf(req.path) + 1 && PARAMS.mongoless)
Expand All @@ -22,15 +22,15 @@ router.get('/logout', (req, res) => {
return res.renderFile('auth/logout.njk');
});

router.get('/signup', (req, res) => {
if (req.loggedIn) return res.redirect('/');
return res.renderFile('auth/signup.njk');
});
// router.get('/signup', (req, res) => {
// if (req.loggedIn) return res.redirect('/');
// return res.renderFile('auth/signup.njk');
// });

router.get('/profile', (req, res) => {
if (!req.loggedIn) return res.redirect('/login');
return res.renderFile('auth/profile.njk', { user: req.user, pics: Object.entries(profile) });
});
// router.get('/profile', (req, res) => {
// if (!req.loggedIn) return res.redirect('/login');
// return res.renderFile('auth/profile.njk', { user: req.user, pics: Object.entries(profile) });
// });
// Post requests here

router.post('/login', [
Expand All @@ -47,49 +47,49 @@ router.post('/login', [
const errorMessages = errors.array().map(error => error.msg);
throw new Error(errorMessages[0]);
}
const userData = req.body;
const sessionID = await dbh.createSession(await dbh.validateUser(userData));
const teamData = req.body;
const sessionID = await dbh.createTeamSession(await dbh.validateTeam(teamData));
res.cookie('sessionID', sessionID);
res.send('logged in >w<');
});

router.post('/signup', [
body('name')
.trim()
.notEmpty().withMessage('No Name Provided'),
body('roll')
.trim()
.notEmpty().withMessage('No Roll Provided')
.matches(/^[12][890123][A-Z]{2}[0-9][A-Z0-9]{2}\d\d$/i).withMessage('Please provide a valid roll number'),
body('email')
.trim()
.notEmpty().withMessage('No Email Provided')
.isEmail().withMessage('Please provide a valid email'),
body('phone')
.trim()
.notEmpty().withMessage('No Phone Number Provided')
.isMobilePhone('en-IN').withMessage('Please provide a valid phone number'),
body('username')
.trim()
.notEmpty().withMessage('No Username Provided')
.isLength({ min: 3, max: 32 }).withMessage('Username must be between 3 and 32 characters long.')
.matches(/^\S+$/).withMessage('Username cannot contain whitespaces'),
body('password')
.trim()
.notEmpty().withMessage('No Password Provided')
.isLength({ min: 6, max: 32 }).withMessage('Password must be between 6 and 32 characters long.')
.matches(/^\S+$/).withMessage('Password cannot contain whitespaces')
], async (req, res) => {
if (req.loggedIn) return res.error('How are you signing up when you are already logged in, what is this power !');
const errors = validationResult(req);
if (!errors.isEmpty()) {
const errorMessages = errors.array().map(error => error.msg);
throw new Error(errorMessages[0]);
}
const sessionID = await dbh.createSession(await dbh.createUser(req.body));
res.cookie('sessionID', sessionID);
res.send('Registered Successfully UwU');
});
// router.post('/signup', [
// body('name')
// .trim()
// .notEmpty().withMessage('No Name Provided'),
// body('roll')
// .trim()
// .notEmpty().withMessage('No Roll Provided')
// .matches(/^[12][890123][A-Z]{2}[0-9][A-Z0-9]{2}\d\d$/i).withMessage('Please provide a valid roll number'),
// body('email')
// .trim()
// .notEmpty().withMessage('No Email Provided')
// .isEmail().withMessage('Please provide a valid email'),
// body('phone')
// .trim()
// .notEmpty().withMessage('No Phone Number Provided')
// .isMobilePhone('en-IN').withMessage('Please provide a valid phone number'),
// body('username')
// .trim()
// .notEmpty().withMessage('No Username Provided')
// .isLength({ min: 3, max: 32 }).withMessage('Username must be between 3 and 32 characters long.')
// .matches(/^\S+$/).withMessage('Username cannot contain whitespaces'),
// body('password')
// .trim()
// .notEmpty().withMessage('No Password Provided')
// .isLength({ min: 6, max: 32 }).withMessage('Password must be between 6 and 32 characters long.')
// .matches(/^\S+$/).withMessage('Password cannot contain whitespaces')
// ], async (req, res) => {
// if (req.loggedIn) return res.error('How are you signing up when you are already logged in, what is this power !');
// const errors = validationResult(req);
// if (!errors.isEmpty()) {
// const errorMessages = errors.array().map(error => error.msg);
// throw new Error(errorMessages[0]);
// }
// const sessionID = await dbh.createSession(await dbh.createUser(req.body));
// res.cookie('sessionID', sessionID);
// res.send('Registered Successfully UwU');
// });

app.post('/logout', async (req, res, next) => {
// If we may require them, then...
Expand All @@ -100,12 +100,12 @@ app.post('/logout', async (req, res, next) => {
return res.send('Signed out successfully. Mata ne.');
});

app.post('/edit-profile', async (req, res) => {
if (!req.loggedIn) return res.error('nande koko ni ??');
const response = await dbh.updateImage(req.user.username, profile[req.body.character]);
if (!response) throw new Error('Something went wrong');
return res.send('updated succesfully');
});
// app.post('/edit-profile', async (req, res) => {
// if (!req.loggedIn) return res.error('nande koko ni ??');
// const response = await dbh.updateImage(req.user.username, profile[req.body.character]);
// if (!response) throw new Error('Something went wrong');
// return res.send('updated succesfully');
// });

module.exports = {
route: '/',
Expand Down
Loading
Loading