diff --git a/Sean/inusers.js b/Sean/inusers.js deleted file mode 100644 index e29bcd2..0000000 --- a/Sean/inusers.js +++ /dev/null @@ -1,136 +0,0 @@ -const allUsers = <%- JSON.stringify(allUsers) %>; - -document.getElementById('downloadButton').addEventListener('click', function () { - console.log('Download button clicked'); - downloadExcel(allUsers); -}); - -document.getElementById('addUserLink').addEventListener('click', function () { - document.getElementById('downloadButtonContainer').style.display = 'none'; - document.getElementById('userDataContainer').style.display = 'none'; - document.getElementById('createUserForm').style.display = 'block'; -}); - -document.getElementById('userDataLink').addEventListener('click', function () { - document.getElementById('downloadButtonContainer').style.display = 'block'; - document.getElementById('userDataContainer').style.display = 'block'; - document.getElementById('createUserForm').style.display = 'none'; -}); - -document.getElementById('userForm').addEventListener('submit', function (event) { - event.preventDefault(); - - // Use FormData directly - const formData = new FormData(document.getElementById('userForm')); - - // Check password complexity - const password = formData.get('password'); - const confirmPassword = formData.get('confirmPassword'); - - if (!isStrongPassword(password)) { - alert('Password does not meet complexity requirements. It must be at least 10 characters long and include at least one uppercase letter, one lowercase letter, one digit, and one symbol.'); - return; - } - - // Check if passwords match - if (password !== confirmPassword) { - alert('Passwords do not match. Please enter the same password in both fields.'); - return; - } - - // Make a fetch request - fetch('/createUser', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - name: formData.get('name'), - username: formData.get('username'), - email: formData.get('email'), - password: password, // Use the validated password - jobTitle: formData.get('jobTitle'), - }), - }) - .then(response => { - if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); - } - return response.json(); - }) - .then(data => { - console.log('Success:', data); - - // Show an alert with the received data - alert(`User Registered!`); - - // Optionally, you can clear the form or take other actions after registration - document.getElementById('userForm').reset(); - }) - .catch(error => { - console.error('Fetch Error:', error); - }); - }); - - // Function to validate password complexity - function isStrongPassword(password) { - // Password must be at least 10 characters long - if (password.length < 10) { - return false; - } - - // Password must contain at least one uppercase letter - if (!/[A-Z]/.test(password)) { - return false; - } - - // Password must contain at least one lowercase letter - if (!/[a-z]/.test(password)) { - return false; - } - - // Password must contain at least one digit - if (!/\d/.test(password)) { - return false; - } - - // Password must contain at least one symbol - if (!/[!@#$%^&*(),.?":{}|<>]/.test(password)) { - return false; - } - - return true; - } - - - function downloadExcel(allUsers) { - if (allUsers && allUsers.length > 0) { - const workbook = new ExcelJS.Workbook(); - const worksheet = workbook.addWorksheet('All Users'); - const headers = ['Name', 'Username', 'Email', 'Password', 'Last Login', 'Job Title']; - worksheet.addRow(headers); - allUsers.forEach(user => { - const rowData = [ - user.name || '', - user.username || '', - user.email || '', - user.password || '', - user.lastLogin ? new Date(user.lastLogin).toLocaleString('en-US', { timeZone: 'Asia/Singapore' }) : '', - user.jobTitle || '' - ]; - worksheet.addRow(rowData); - }); - workbook.xlsx.writeBuffer().then(buffer => { - const currentDate = new Date(); - const formattedDate = currentDate.toISOString().split('T')[0]; - const formattedTime = currentDate.toTimeString().split(' ')[0].replace(/:/g, '-'); - const fileName = `user_data_${formattedDate}_${formattedTime}.xlsx`; - const blob = new Blob([buffer], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - }); - saveAs(blob, fileName); - }); - } else { - console.error('No data available for download.'); - } - } diff --git a/Sean/models/User.js b/Sean/models/User.js index 8cda275..d4c831b 100644 --- a/Sean/models/User.js +++ b/Sean/models/User.js @@ -37,6 +37,9 @@ module.exports = (sequelize) => { reset_token_expiry: { type: DataTypes.DATE, }, + sessionid: { + type: DataTypes.STRING, + }, }, { hooks: { beforeCreate: async (user) => { diff --git a/Sean/server.js b/Sean/server.js index ea3ead6..278a374 100644 --- a/Sean/server.js +++ b/Sean/server.js @@ -1,7 +1,7 @@ const express = require("express"); const session = require("express-session"); const rateLimit = require('express-rate-limit'); - +const cookieParser = require('cookie-parser'); const bodyParser = require("body-parser"); const bcrypt = require("bcrypt"); const crypto = require("crypto"); @@ -10,21 +10,37 @@ const otpGenerator = require('otp-generator'); const { body, validationResult } = require('express-validator'); const validator = require('validator'); const { format } = require('date-fns'); - +const helmet = require('helmet'); const { Sequelize } = require('sequelize'); const { transporter } = require("./modules/nodeMailer"); - const { sequelize, User } = require("./modules/mysql"); const userLogs= require('./models/userLogs')(sequelize); // Adjust the path based on your project structure const app = express(); + +const nonce = crypto.randomBytes(16).toString('base64'); + +console.log('Nonce:', nonce); + app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); +app.use(cookieParser()); const PORT = process.env.PORT || 3000; require("dotenv").config(); app.use(bodyParser.urlencoded({ extended: true })); app.set("view engine", "ejs"); +app.use( + helmet.contentSecurityPolicy({ + directives: { + defaultSrc: ["'self'",`'nonce-${nonce}'`], + scriptSrc: ["'self'",`'nonce-${nonce}'`,"'strict-dynamic'", 'cdn.jsdelivr.net', 'fonts.googleapis.com', 'stackpath.bootstrapcdn.com', 'code.jquery.com', 'cdnjs.cloudflare.com'], + styleSrc: ["'self'",`'nonce-${nonce}'`, 'cdn.jsdelivr.net', 'fonts.googleapis.com'], + imgSrc: ["'self'"], + fontSrc: ["'self'", 'fonts.gstatic.com'], + }, + }) + ); app.use(session({ secret: process.env.key, @@ -189,7 +205,20 @@ app.post("/verify-otp", [ } const sessionToken = crypto.randomBytes(32).toString('hex'); - + const username = req.body.username; // Replace with the actual username + + User.update({ sessionid: sessionToken }, { where: { username } }) + .then(([rowsUpdated]) => { + if (rowsUpdated > 0) { + console.log(`SessionId updated for user: ${username}`); + } else { + console.error('User not found.'); + } + }) + .catch(error => { + console.error('Error updating sessionId:', error); + }); + req.session.authenticated = true; req.session.username = req.body.username; req.session.sessionToken = sessionToken; @@ -200,7 +229,6 @@ app.post("/verify-otp", [ // Log anti-CSRF token console.log(`Generated Anti-CSRF Token: ${csrfTokenSession}`); - // Set CSRF token as a cookie res.cookie('sessionToken', sessionToken, { secure: true, httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000) }); // Expires in 1 day console.log(`Generated Session Token: ${sessionToken}`); @@ -232,6 +260,7 @@ app.post("/verify-otp", [ } else { console.log("Session destroyed."); // Log the logout activity using Sequelize + await User.update({ sessionid: null }, { where: { username } }) await userLogs.create({ username, activity: "User logged out. Session destroyed." }); // Clear the session token cookie res.clearCookie('sessionToken'); @@ -267,7 +296,7 @@ app.post("/verify-otp", [ const currentUsername = req.session.username; // Render the inusers page with JSON data - res.render("inusers", { allUsers, csrfToken: csrfTokenSession, currentUsername }); + res.render("inusers", { nonce: nonce, allUsers, csrfToken: csrfTokenSession, currentUsername }); } catch (error) { console.error("Error fetching all users:", error); res.status(500).send("Internal Server Error"); @@ -324,6 +353,14 @@ app.post( return res.status(400).json({ errors: errors.array() }); } + const sessionTokencookie = req.cookies['sessionToken']; + + // Verify sessionToken with the one stored in the database + const user = await User.findOne({ where: { sessionid: sessionTokencookie } }); + + if (!user) { + return res.status(403).json({ error: 'Invalid sessionToken' }); + } // Validate the anti-CSRF token const submittedCSRFToken = req.body.csrf_token; @@ -595,7 +632,14 @@ app.post("/reset-password", async (req, res) => { if (!csrfTokenSession || submittedCSRFToken !== csrfTokenSession) { return res.status(403).json({ error: 'CSRF token mismatch' }); } + const sessionTokencookie = req.cookies['sessionToken']; + // Verify sessionToken with the one stored in the database + const user = await User.findOne({ where: { sessionid: sessionTokencookie } }); + + if (!user) { + return res.status(403).json({ error: 'Invalid sessionToken' }); + } // Sanitize the inputs const sanitizedUsername = validator.escape(username); const sanitizedPassword = validator.escape(password); @@ -686,7 +730,6 @@ app.get('/api/users', async (req, res) => { app.get('/api/searchUser', async (req, res) => { const { username } = req.query; - console.log(username); try { // Find the user in the database by username const user = await User.findOne({ where: { username } }); @@ -709,13 +752,22 @@ app.delete('/api/deleteUser/:username', async (req, res) => { const { username } = req.params; const creatorUsername = req.session.username; - try { - // Extract CSRF token from the request body + try { + // Retrieve sessionToken from cookies + const sessionTokencoookie = req.cookies['sessionToken']; + // Retrieve CSRF token from the request body const { csrfToken } = req.body; - + console.log(csrfToken); // Compare CSRF token with the one stored in the session if (csrfToken !== csrfTokenSession) { return res.status(403).json({ success: false, error: 'CSRF token mismatch' }); + } + + // Verify sessionToken with the one stored in the database + const user = await User.findOne({ where: { sessionid: sessionTokencoookie } }); + + if (!user) { + return res.status(403).json({ success: false, error: 'Invalid sessionToken or user not found' }); } // Log deletion activity to UserLogs model diff --git a/Sean/views/LOGO.PNG b/Sean/views/LOGO.PNG deleted file mode 100644 index eeecb45..0000000 Binary files a/Sean/views/LOGO.PNG and /dev/null differ diff --git a/Sean/views/forgot-password.css b/Sean/views/forgot-password.css new file mode 100644 index 0000000..12183d1 --- /dev/null +++ b/Sean/views/forgot-password.css @@ -0,0 +1,58 @@ +body { + font-family: 'Arial', sans-serif; + background-color: #f4f4f4; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + height: 100vh; + } + + h1 { + text-align: center; + color: #333; + } + + form { + background-color: #fff; + padding: 20px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + width: 300px; + } + + label { + display: block; + margin-bottom: 8px; + color: #555; + } + + input { + width: 100%; + padding: 8px; + margin-bottom: 16px; + border: 1px solid #ccc; + border-radius: 4px; + } + + button { + background-color: #4caf50; + color: #fff; + padding: 10px; + border: none; + border-radius: 4px; + cursor: pointer; + width: 100%; + } + + button:hover { + background-color: #45a049; + } + .error-message { + color: red; + margin-top: 10px; + } + .success-message { + color: green; + margin-top: 10px; + } \ No newline at end of file diff --git a/Sean/views/forgot-password.ejs b/Sean/views/forgot-password.ejs index af82f99..b13f3bb 100644 --- a/Sean/views/forgot-password.ejs +++ b/Sean/views/forgot-password.ejs @@ -5,66 +5,7 @@ Forgot Password - Your Website - +
diff --git a/Sean/views/home.js b/Sean/views/home.js deleted file mode 100644 index 883f205..0000000 --- a/Sean/views/home.js +++ /dev/null @@ -1,107 +0,0 @@ -document.addEventListener("DOMContentLoaded", async function () { - console.log("DOM Loaded"); - - // Extract data from sensorData - const sensorData = JSON.parse('<%- JSON.stringify(sensorData) %>'); - console.log("Sensor Data:", sensorData); - - // Fetch location names from the server - const locationNames = await fetch('/api/locations') // Adjust the API endpoint - .then(response => response.json()) - .then(data => data.map(location => ({ id: location.id, name: location.name }))) - .catch(error => console.error('Error fetching location names:', error)); - - - - // Group sensorData by locationid - const groupedData = groupBy(sensorData, 'locationid'); - - // Get the content div - const contentDiv = document.getElementById('content'); - - // Create a chart for each location - Object.keys(groupedData).forEach(locationId => { - const locationData = groupedData[locationId]; - - // Find the corresponding location name - const locationName = locationNames.find(location => location.id === parseInt(locationId, 10))?.name || `Unknown Location ${locationId}`; - - // Create a container for the chart - const container = document.createElement('div'); - container.className = 'chart-container'; - - // Create a title for the container with location name - const title = document.createElement('h4'); - title.textContent = `Location: ${locationName}`; - container.appendChild(title); - - // Get labels (Location IDs) - const labels = locationData.map(data => new Date(data.createdAt).toLocaleString('en-US', { timeZone: 'Asia/Singapore' })); - - // Create datasets for each measurement - const datasets = [ - { - label: 'CO', - data: locationData.map(data => data.measurement.co), - backgroundColor: 'rgba(255, 99, 132, 0.5)', // Red color - }, - { - label: 'O3', - data: locationData.map(data => data.measurement.o3), - backgroundColor: 'rgba(54, 162, 235, 0.5)', // Blue color - }, - { - label: 'NO2', - data: locationData.map(data => data.measurement.no2), - backgroundColor: 'rgba(255, 206, 86, 0.5)', // Yellow color - }, - { - label: 'SO2', - data: locationData.map(data => data.measurement.so2), - backgroundColor: 'rgba(75, 192, 192, 0.5)', // Green color - }, - ]; - - // Create a canvas element for each location - const canvas = document.createElement('canvas'); - canvas.width = 400; - canvas.height = 200; - - // Append canvas to the container - container.appendChild(canvas); - - // Append container to the content div - contentDiv.appendChild(container); - - // Create a bar chart for each location - const ctx = canvas.getContext('2d'); - new Chart(ctx, { - type: 'bar', - data: { - labels: labels, - datasets: datasets, - }, - options: { - scales: { - x: { - beginAtZero: true, - }, - y: { - beginAtZero: true, - }, - }, - }, - }); - }); - - // Helper function to group data by a specified key - function groupBy(arr, key) { - return arr.reduce((acc, obj) => { - const groupKey = obj[key]; - acc[groupKey] = acc[groupKey] || []; - acc[groupKey].push(obj); - return acc; - }, {}); - } - }); - \ No newline at end of file diff --git a/Sean/views/index.js b/Sean/views/index.js deleted file mode 100644 index 5ee6953..0000000 --- a/Sean/views/index.js +++ /dev/null @@ -1,64 +0,0 @@ -const express = require('express'); -const router = express.Router(); -const mysql = require('mysql'); - -// Replace with your MySQL connection details -const mysqlConfig = { - host: process.env.host, - user: process.env.user, - password: process.env.password, - database: process.env.database, - timezone: 'Z', // Set the timezone to UTC -}; - -const mysqlConnection = mysql.createConnection(mysqlConfig); - -// Middleware to check if the user is authenticated -function isAuthenticated(req, res, next) { - if (req.session && req.session.authenticated) { - return next(); - } else { - res.redirect('/login'); - } -} - -// InUsers route (renders the InUsers tab) -router.get('/', isAuthenticated, (req, res) => { - // Fetch all user data from the database - const userDataQuery = 'SELECT * FROM users'; - - mysqlConnection.query(userDataQuery, (error, userData) => { - if (error) { - console.error('Error fetching user data:', error); - res.status(500).send('Internal Server Error'); - return; - } - - // Render the inusers page with user data - res.render('inusers', { userData: userData }); - }); -}); - -// User Data route -router.get('/userdata', isAuthenticated, (req, res) => { - // Fetch all user data from the database - const userDataQuery = 'SELECT * FROM users'; - - mysqlConnection.query(userDataQuery, (error, userData) => { - if (error) { - console.error('Error fetching user data:', error); - res.status(500).send('Internal Server Error'); - return; - } - - // Render the user-data page with user data - res.render('user-data', { userData: userData }); - }); -}); - -// Edit User Data route -router.get('/edituserdata', isAuthenticated, (req, res) => { - res.render('edit-user-data'); -}); - -module.exports = router; diff --git a/Sean/views/inusers.ejs b/Sean/views/inusers.ejs index 10ade93..1975b70 100644 --- a/Sean/views/inusers.ejs +++ b/Sean/views/inusers.ejs @@ -7,7 +7,7 @@ In-House Users - + @@ -173,19 +173,21 @@
- - - - - - - - - + + + + + + + + diff --git a/Sean/views/inusers.js b/Sean/views/inusers.js index ad9f951..6ca1f73 100644 --- a/Sean/views/inusers.js +++ b/Sean/views/inusers.js @@ -33,7 +33,7 @@ $(document).ready(function () { $('#logsContainer').hide(); $('#additional-text').hide(); $('#additional-text2').hide(); - $('#additional-text2').hide(); + $('#additional-text3').hide(); }); $('#searchUserButton').on('click', function () { @@ -124,6 +124,7 @@ $('#searchResultsList').on('click', '.deleteUserButton', function () { headers: { 'Content-Type': 'application/json', }, + credentials: 'include', // Include cookies in the request body: JSON.stringify({ csrfToken }), // Include CSRF token in the request body }) .then(response => { @@ -243,8 +244,8 @@ function resetFormFields() { method: 'POST', headers: { 'Content-Type': 'application/json', - }, + credentials: 'include', // Include cookies in the request body: JSON.stringify({ name: name, username: username, @@ -330,6 +331,7 @@ $('#resetPasswordForm').on('submit', function (e) { headers: { 'Content-Type': 'application/json', }, + credentials: 'include', // Include cookies in the request body: JSON.stringify({ username: username, password: password, @@ -356,8 +358,6 @@ $('#resetPasswordForm').on('submit', function (e) { $('#resetPassword').val(''); $('#resetConfirmPassword').val(''); - // You might want to hide the reset password form after submission - $('#resetPasswordFormContainer').hide(); }) .catch(error => { // Handle 404 error separately to show an alert diff --git a/Sean/views/login.css b/Sean/views/login.css new file mode 100644 index 0000000..65e544c --- /dev/null +++ b/Sean/views/login.css @@ -0,0 +1,67 @@ +body { + font-family: 'Arial', sans-serif; + background-color: #f4f4f4; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + height: 100vh; + } + + .login-container { + background-color: #fff; + padding: 20px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + width: 300px; + margin: auto; /* Center the container horizontally */ + } + + h1 { + text-align: center; + color: #333; + } + + form { + margin-top: 20px; + } + + label { + display: block; + margin-bottom: 8px; + color: #555; + } + + input { + width: calc(100% - 16px); /* Adjust the width and center the input */ + padding: 8px; + margin-bottom: 16px; + border: 1px solid #ccc; + border-radius: 4px; + } + + button { + background-color: #4caf50; + color: #fff; + padding: 10px; + border: none; + border-radius: 4px; + cursor: pointer; + width: 100%; + } + + button:hover { + background-color: #45a049; + } + + .reset-link-container { + text-align: center; + margin-top: 10px; + } + + .reset-link { + color: #4caf50; + text-decoration: underline; + cursor: pointer; + } + \ No newline at end of file diff --git a/Sean/views/login.ejs b/Sean/views/login.ejs index ec63272..8d73368 100644 --- a/Sean/views/login.ejs +++ b/Sean/views/login.ejs @@ -4,75 +4,7 @@ Login - Eco Saver - +
diff --git a/Sean/views/loginstyle.css b/Sean/views/loginstyle.css deleted file mode 100644 index ce9377d..0000000 --- a/Sean/views/loginstyle.css +++ /dev/null @@ -1,146 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap'); -*{ - margin: 0; - padding: 0; - box-sizing: border-box; - font-family: 'Poppins',sans-serif; -} -body{ - height: 100vh; - display: flex; - justify-content: center; - align-items: center; - padding: 10px; - background: linear-gradient(135deg, #71b7e6, #9b59b6); -} -.container{ - max-width: 700px; - width: 100%; - background-color: #fff; - padding: 25px 30px; - border-radius: 5px; - box-shadow: 0 5px 10px rgba(0,0,0,0.15); -} -.container .title{ - font-size: 25px; - font-weight: 500; - position: relative; -} -.container .title::before{ - content: ""; - position: absolute; - left: 0; - bottom: 0; - height: 3px; - width: 30px; - border-radius: 5px; - background: linear-gradient(135deg, #71b7e6, #9b59b6); -} -.content form .user-details{ - display: flex; - flex-wrap: wrap; - justify-content: space-between; - margin: 20px 0 12px 0; -} -form .user-details .input-box{ - margin-bottom: 15px; - width: calc(100% / 2 - 20px); -} -form .input-box span.details{ - display: block; - font-weight: 500; - margin-bottom: 5px; -} -.user-details .input-box input{ - height: 45px; - width: 100%; - outline: none; - font-size: 16px; - border-radius: 5px; - padding-left: 15px; - border: 1px solid #ccc; - border-bottom-width: 2px; - transition: all 0.3s ease; -} -.user-details .input-box input:focus, -.user-details .input-box input:valid{ - border-color: #9b59b6; -} - form .gender-details .gender-title{ - font-size: 20px; - font-weight: 500; - } - form .category{ - display: flex; - width: 80%; - margin: 14px 0 ; - justify-content: space-between; - } - form .category label{ - display: flex; - align-items: center; - cursor: pointer; - } - form .category label .dot{ - height: 18px; - width: 18px; - border-radius: 50%; - margin-right: 10px; - background: #d9d9d9; - border: 5px solid transparent; - transition: all 0.3s ease; -} - #dot-1:checked ~ .category label .one, - #dot-2:checked ~ .category label .two, - #dot-3:checked ~ .category label .three{ - background: #9b59b6; - border-color: #d9d9d9; - } - form input[type="radio"]{ - display: none; - } - form .button{ - height: 45px; - margin: 35px 0 - } - form .button input{ - height: 100%; - width: 100%; - border-radius: 5px; - border: none; - color: #fff; - font-size: 18px; - font-weight: 500; - letter-spacing: 1px; - cursor: pointer; - transition: all 0.3s ease; - background: linear-gradient(135deg, #71b7e6, #9b59b6); - } - form .button input:hover{ - /* transform: scale(0.99); */ - background: linear-gradient(-135deg, #71b7e6, #9b59b6); - } - @media(max-width: 584px){ - .container{ - max-width: 100%; -} -form .user-details .input-box{ - margin-bottom: 15px; - width: 100%; - } - form .category{ - width: 100%; - } - .content form .user-details{ - max-height: 300px; - overflow-y: scroll; - } - .user-details::-webkit-scrollbar{ - width: 5px; - } - } - @media(max-width: 459px){ - .container .content .category{ - flex-direction: column; - } -} \ No newline at end of file diff --git a/Sean/views/otp.css b/Sean/views/otp.css new file mode 100644 index 0000000..bfa99d8 --- /dev/null +++ b/Sean/views/otp.css @@ -0,0 +1,50 @@ +body { + font-family: Arial, sans-serif; + background-color: #f4f4f4; + text-align: center; + margin: 50px; +} + +h2 { + color: #333; +} + +form { + max-width: 300px; + margin: 20px auto; + padding: 20px; + background-color: #fff; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); +} + +label { + display: block; + margin-bottom: 8px; + color: #333; +} + +input { + width: 100%; + padding: 10px; + margin-bottom: 20px; + box-sizing: border-box; +} + +button { + background-color: #4caf50; + color: #fff; + padding: 10px 15px; + border: none; + border-radius: 4px; + cursor: pointer; +} + +button:hover { + background-color: #45a049; +} + +.error { + color: red; + margin-top: 10px; +} \ No newline at end of file diff --git a/Sean/views/otp.ejs b/Sean/views/otp.ejs index 1966179..f9c5d0d 100644 --- a/Sean/views/otp.ejs +++ b/Sean/views/otp.ejs @@ -4,58 +4,7 @@ Enter OTP - +

Enter OTP

diff --git a/Sean/views/responsive.css b/Sean/views/responsive.css deleted file mode 100644 index a16942e..0000000 --- a/Sean/views/responsive.css +++ /dev/null @@ -1,162 +0,0 @@ -/* Responsive CSS Here */ -@media screen and (max-width: 950px) { - .nav-img { - height: 25px; - } - .nav-option { - gap: 30px; - } - .nav-option h3 { - font-size: 15px; - } - .report-topic-heading, - .item1, - .items { - width: 800px; - } - } - - @media screen and (max-width: 850px) { - .nav-img { - height: 30px; - } - .nav-option { - gap: 30px; - } - .nav-option h3 { - font-size: 20px; - } - .report-topic-heading, - .item1, - .items { - width: 700px; - } - .navcontainer { - width: 100vw; - position: absolute; - transition: all 0.6s ease-in-out; - top: 0; - left: -100vw; - } - .nav { - width: 100%; - position: absolute; - } - .navclose { - left: 00px; - } - .searchbar { - display: none; - } - .main { - padding: 40px 30px 30px 30px; - } - .searchbar2 { - width: 100%; - display: flex; - margin: 0 0 40px 0; - justify-content: center; - } - .searchbar2 input { - width: 250px; - height: 42px; - border-radius: 50px 0 0 50px; - background-color: var(--background-color3); - padding: 0 20px; - font-size: 15px; - border: 2px solid var(--secondary-color); - } - } - - @media screen and (max-width: 490px) { - .message { - display: none; - } - .logosec { - width: 100%; - justify-content: space-between; - } - .logo { - font-size: 20px; - } - .menuicn { - height: 25px; - } - .nav-img { - height: 25px; - } - .nav-option { - gap: 25px; - } - .nav-option h3 { - font-size: 12px; - } - .nav-upper-options { - gap: 15px; - } - .recent-Articles { - font-size: 20px; - } - .report-topic-heading, - .item1, - .items { - width: 550px; - } - } - - @media screen and (max-width: 400px) { - .recent-Articles { - font-size: 17px; - } - .view { - width: 60px; - font-size: 10px; - height: 27px; - } - .report-header { - height: 60px; - padding: 10px 10px 5px 10px; - } - .searchbtn img { - height: 20px; - } - } - - @media screen and (max-width: 320px) { - .recent-Articles { - font-size: 12px; - } - .view { - width: 50px; - font-size: 8px; - height: 27px; - } - .report-header { - height: 60px; - padding: 10px 5px 5px 5px; - } - .t-op { - font-size: 12px; - } - .t-op-nextlvl { - font-size: 10px; - } - .report-topic-heading, - .item1, - .items { - width: 300px; - } - .report-body { - padding: 10px; - } - .label-tag { - width: 70px; - } - .searchbtn { - width: 40px; - } - .searchbar2 input { - width: 180px; - } - } - \ No newline at end of file diff --git a/Sean/views/setup-mfa.ejs b/Sean/views/setup-mfa.ejs deleted file mode 100644 index a0ddd23..0000000 --- a/Sean/views/setup-mfa.ejs +++ /dev/null @@ -1,10 +0,0 @@ - -

Setup Multi-Factor Authentication

-

Scan the QR code below with your authenticator app:

-QR Code - -
- - - -
diff --git a/package-lock.json b/package-lock.json index 08346ff..8bf6c65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1156,6 +1156,11 @@ "function-bind": "^1.1.2" } }, + "helmet": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", + "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==" + }, "htmlparser2": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",