Untitled

 avatar
unknown
javascript
a year ago
8.3 kB
5
Indexable
require("dotenv").config() // lets me use dot env to store sensitive data

// importing my librarys
const express = require("express");
const path = require("path");
const jwt = require("jsonwebtoken");
const bcrypt = require('bcrypt');
const cookieParser = require("cookie-parser");
// importing files
const pool = require('./database.js');
const publicDir = path.join(__dirname, "./public");
const viewsDir = path.join(__dirname, "./views");
//setting up web server
const app = express();
app.set("view engine", "hbs");
app.set("views", viewsDir);

app.use(express.static(publicDir));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.use(cookieParser())


//routes
app.get("/", (req, res) => {
  res.render("index");
});



app.get("/quiz", (req, res) => {

  const token = req.cookies.AuthToken;

  if (!token) {
    // Token is missing
    res.sendStatus(401).send("token invalid");
    return;
  }

  jwt.verify(token, process.env.SECRET_ACCESS_TOKEN, (err, decoded) => {
    if (err) {
      // Token is invalid
      res.sendStatus(401).send("token invalid");
    } else {
      // Check if the user is a parent
      if (decoded.isParent) {
        // Parent accounts are not allowed to access stats
        res.sendStatus(403).send("parents are not allowed here"); // Forbidden
      } else {
        // User is not a parent, continue with protected logic

        // Query to select a random question from the QuestionInfo table
        pool.query('SELECT * FROM QuestionInfo ORDER BY RAND() LIMIT 1', (error, results, fields) => {
          if (error) {
            console.error('Error retrieving random question:', error);
            res.status(500).send('Error retrieving random question');
            return;
          }
          // Assuming there's at least one question returned from the query
          const randomQuestion = results[0];
          let answer1 = randomQuestion.Answers[0]
          let answer2 = randomQuestion.Answers[1]
          let answer3 = randomQuestion.Answers[2]
          let answer4 = randomQuestion.Answers[3]

          res.render("quiz", { question: randomQuestion, answer1: answer1, answer2: answer2, answer3: answer3, answer4: answer4 });

        });
      }
    }
  });
});



app.get("/stats", (req, res) => {
  const token = req.cookies.AuthToken;

  if (!token) {
    // Token is missing
    res.sendStatus(401);
    return;
  }

  jwt.verify(token, process.env.SECRET_ACCESS_TOKEN, (err, decoded) => {
    if (err) {
      // Token is invalid
      res.sendStatus(401);
    } else {
      // Token is valid, continue with protected logic
      res.render("stats");
    }
  });
});



app.get("/signup", (req, res) => {
  res.render("signup");
});



app.get("/login", (req, res) => {
  res.render("login");
});



app.post('/signup', async (req, res) => {


  let userData = {
    UserEmail: req.body.Email,
    UserName: req.body.Name,
    UserHashedPassword: await HashPassword(req.body.Password),
    ParentName: req.body.ParentName,
    ParentEmail: req.body.ParentEmail,
    ParentHashedPassword: await HashPassword(req.body.ParentPassword),
    Course: req.body.Course
  };

  // Insert the user data into the database
  pool.query('INSERT INTO UserInfo SET ?', userData, (error, results, fields) => {
    if (error) {
      console.error('Error inserting user data:', error);
      res.status(500).send('Error inserting user data');
      return;
    }
    console.log('User data inserted successfully');
    res.status(200).redirect('/');
  });

  const user = {
    email: req.body.Email,
    isParent: false
  }


  const token = jwt.sign(user, process.env.SECRET_ACCESS_TOKEN, { expiresIn: '1m' });
  res.cookie('AuthToken', token, { httpOnly: false, maxAge: 60000 });
});



app.post('/login', (req, res) => {
  const isParent = req.body.isParent ? true : false; // Is login sent by a parent?

  if (isParent) { // If the login request is sent from a parent
    const email = req.body.email;
    const enteredPassword = req.body.password;

    pool.query('SELECT ParentHashedPassword FROM UserInfo WHERE ParentEmail = ?', [email], async (error, results, fields) => {
      if (error) {
        console.error('Error querying database:', error);
        res.status(500).send('Error querying database');
        return;
      }

      if (results.length === 0) {
        // User not found
        res.status(401).send('Invalid email or password');
        return;
      }

      const hashedPassword = results[0].ParentHashedPassword;

      try {
        const isMatch = await ComparePasswords(enteredPassword, hashedPassword);

        if (!isMatch) {
          // Incorrect password
          res.status(401).send('Invalid email or password');
          return;
        }

        // Password is correct, proceed with authentication

        const user = {
          email: email,
          isParent: isParent
        };

        const token = jwt.sign(user, process.env.SECRET_ACCESS_TOKEN, { expiresIn: '1m' });
        res.cookie('AuthToken', token, { httpOnly: false, maxAge: 60000 });
        res.redirect('/');
      } catch (error) {
        console.error('Error comparing passwords:', error);
        res.status(500).send('Error comparing passwords');
      }
    });

  } else { // if the login is from a studen account
    const email = req.body.email;
    const enteredPassword = req.body.password;

    pool.query('SELECT UserHashedPassword FROM UserInfo WHERE UserEmail = ?', [email], async (error, results, fields) => {
      if (error) {
        console.error('Error querying database:', error);
        res.status(500).send('Error querying database');
        return;
      }

      if (results.length === 0) {
        // User not found
        res.status(401).send('Invalid email or password');
        return;
      }

      const hashedPassword = results[0].UserHashedPassword;

      try {
        const isMatch = await ComparePasswords(enteredPassword, hashedPassword);

        if (!isMatch) {
          // Incorrect password
          res.status(401).send('Invalid email or password');
          return;
        }

        // Password is correct, proceed with authentication

        const user = {
          email: email,
          isParent: isParent
        };

        const token = jwt.sign(user, process.env.SECRET_ACCESS_TOKEN, { expiresIn: '1m' });
        res.cookie('AuthToken', token, { httpOnly: false, maxAge: 60000 });
        res.redirect('/');
      } catch (error) {
        console.error('Error comparing passwords:', error);
        res.status(500).send('Error comparing passwords');
      }
    });
  }
});



app.post('/answer', (req, res) => {
  const answer = req.body.answer;
  const questionId = req.body.questionId;

  // Query the database to retrieve the correct answer for the given questionId
  pool.query('SELECT CorrectAnswer FROM QuestionInfo WHERE QuestionID = ?', [questionId], (error, results, fields) => {
    if (error) {
      console.error('Error retrieving correct answer:', error);
      return res.status(500).json({ error: 'Internal server error' });
    }
    console.log(results)
    // Assuming there's exactly one result (since QuestionID is unique)
    if (results.length !== 1) {
      return res.status(400).json({ error: 'Question not found' });
    }

    const correctAnswer = results[0].CorrectAnswer;

    // Check if the submitted answer is correct
    const isCorrect = (answer === correctAnswer);

    res.json({ isCorrect });
  });
});



async function HashPassword(password) {
  const salt = await bcrypt.genSalt();
  const HashedPassword = await bcrypt.hash(password, salt)
  return HashedPassword
}

async function ComparePasswords(EnteredPassword, HashedPassword) {
  return bcrypt.compare(EnteredPassword, HashedPassword)
    .then((result) => {
      return result;
    })
    .catch((error) => {
      console.error('Error comparing passwords:', error);
      throw error;
    });
}



app.listen(3000, () => {
  console.log("server started on port 3000");
});
Editor is loading...
Leave a Comment