From 0acf95f20af77f17dd3f816d149c6ea7cead2b49 Mon Sep 17 00:00:00 2001
From: Jesus Galaz <jesusgalazr@icloud.com>
Date: Sun, 13 Oct 2024 11:04:35 +0200
Subject: [PATCH] User authentication implemented

---
 public/css/index.css | 117 +++++++++++++++++++++++++++++++++++++++++++
 public/css/login.css |  10 ++--
 public/css/main.css  |  20 +++-----
 public/js/auth.js    |  75 +++++++++++++++++++++++++++
 public/login.html    |  46 ++++++++++++++++-
 public/register.html |  20 +++++---
 routes/users.js      |  72 ++++++++++++++++++++++++++
 7 files changed, 334 insertions(+), 26 deletions(-)
 create mode 100644 public/css/index.css

diff --git a/public/css/index.css b/public/css/index.css
new file mode 100644
index 0000000..b0973e6
--- /dev/null
+++ b/public/css/index.css
@@ -0,0 +1,117 @@
+body {
+    font-family: "Arial", sans-serif;
+    background-color: #f5f5f5;
+    color: #333;
+    line-height: 1.6;
+    margin: 0;
+    padding: 0;
+  }
+  .container {
+    max-width: 600px;
+    margin: 2rem auto;
+    padding: 2rem;
+    background-color: #fff;
+    border-radius: 8px;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+  }
+  header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 2rem;
+  }
+  h1 {
+    font-size: 2rem;
+    font-weight: 300;
+    margin: 0;
+  }
+  #logout-btn {
+    background-color: transparent;
+    border: 1px solid #333;
+    color: #333;
+    padding: 0.5rem 1rem;
+    border-radius: 4px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+  }
+  #logout-btn:hover {
+    background-color: #333;
+    color: #fff;
+  }
+  #new-task-form {
+    display: flex;
+    margin-bottom: 2rem;
+  }
+  input[type="text"] {
+    flex-grow: 1;
+    padding: 0.75rem;
+    border: 1px solid #ddd;
+    border-radius: 4px 0 0 4px;
+    font-size: 1rem;
+  }
+  button[type="submit"] {
+    padding: 0.75rem 1.5rem;
+    background-color: #4caf50;
+    color: #fff;
+    border: none;
+    border-radius: 0 4px 4px 0;
+    cursor: pointer;
+    transition: background-color 0.3s ease;
+  }
+  button[type="submit"]:hover {
+    background-color: #45a049;
+  }
+  .task-list ul {
+    list-style-type: none;
+    padding: 0;
+  }
+  .task-list li {
+    background-color: #f9f9f9;
+    border-left: 4px solid #4caf50;
+    margin-bottom: 1rem;
+    padding: 1rem;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    transition: all 0.3s ease;
+  }
+  .task-list li:hover {
+    background-color: #f0f0f0;
+  }
+  .task-list li.completed {
+    border-left-color: #999;
+    opacity: 0.6;
+  }
+  .task-list li.completed span {
+    text-decoration: line-through;
+  }
+  .task-actions {
+    display: flex;
+    gap: 0.5rem;
+  }
+  .task-list li button {
+    background-color: transparent;
+    border: none;
+    cursor: pointer;
+    font-size: 1.2rem;
+    transition: color 0.3s ease;
+    padding: 0;
+    width: 24px;
+    height: 24px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  .complete-btn {
+    color: #4caf50;
+  }
+  .complete-btn:hover {
+    color: #45a049;
+  }
+  .delete-btn {
+    color: #d9534f;
+  }
+  .delete-btn:hover {
+    color: #c9302c;
+  }
+  
\ No newline at end of file
diff --git a/public/css/login.css b/public/css/login.css
index aa5f611..04ecf20 100644
--- a/public/css/login.css
+++ b/public/css/login.css
@@ -85,17 +85,19 @@ button:hover {
 }
 .success_message {
     display: none;
+    opacity: 0;
     color: #28a745;
     margin-top: 1rem;
-    font-size: 1rem;
+    font-size: 12px;
     text-align: center;
-    opacity: 0;
     transition: opacity 0.6s ease;
 }
+
 .success_message.show {
-    display: block;
+    display: block; 
     opacity: 1;
 }
+
 .register-link {
     text-align: center;
     margin-top: 1.5rem;
@@ -121,4 +123,4 @@ button:hover {
 }
 .login-link a:hover {
     text-decoration: underline;
-}
\ No newline at end of file
+}
diff --git a/public/css/main.css b/public/css/main.css
index 6b5e56b..8719569 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -1,18 +1,15 @@
-/* Reset default styles */
 body {
     margin: 0;
     padding: 0;
-    font-family:Verdana, Geneva, Tahoma, sans-serif;
+    font-family:Helvetica, Arial, sans-serif;
 }
 
-/* Container for the entire layout */
 .container {
     display: flex;
     flex-direction: column;
     min-height: 100vh;
 }
 
-/* Header styling */
 .header {
     background-color: #ddf;
     color: #000;
@@ -36,16 +33,14 @@ header button {
     gap: 10px;
 }
 
-/* Main content styling */
 .main-content {
     display: flex;
-    flex-grow: 1; /* Makes the main content stretch to fill the remaining space */
-    overflow-y: hidden; /* Hides overflow within the main content */
+    flex-grow: 1; 
+    overflow-y: hidden; 
 }
 
-/* Sidebar styling */
 .sidebar {
-    width: 200px; /* Adjust the width as needed */
+    width: 200px; 
     padding: 25px;
     background-color: #ddf;
 }
@@ -55,13 +50,12 @@ header button {
     padding: 0;
 }
 
-/* Task list styling */
 .task-list {
-    flex-grow: 1; /* Makes the task list stretch to fill the remaining space */
+    flex-grow: 1; 
     padding: 10px;
     padding-top: 25px;
-    overflow-y: auto; /* Enables vertical scrolling within the task list */
-    max-height: calc(100vh - 100px); /* Adjust the max-height as needed */
+    overflow-y: auto; 
+    max-height: calc(100vh - 100px); 
 }
 
 .task {
diff --git a/public/js/auth.js b/public/js/auth.js
index e69de29..0911918 100644
--- a/public/js/auth.js
+++ b/public/js/auth.js
@@ -0,0 +1,75 @@
+document.addEventListener('DOMContentLoaded', () => {
+  // Registro
+  const registerForm = document.getElementById('register-form');
+  if (registerForm) {
+    registerForm.addEventListener('submit', async (event) => {
+      event.preventDefault(); 
+
+      const username = document.getElementById('username').value;
+      const password = document.getElementById('password').value;
+
+      try {
+        const response = await fetch('/api/users/register', {
+          method: 'POST',
+          headers: {
+            'Content-Type': 'application/json',
+          },
+          body: JSON.stringify({ username, password }),
+        });
+
+        const result = await response.json();
+
+        if (response.ok) {
+          document.querySelector('.success_message').style.display = 'block';
+          document.querySelector('.error_text').textContent = '';
+          setTimeout(() => {
+            window.location.href = 'login.html';
+          }, 2000); 
+        } else {
+          document.querySelector('.error_text').textContent = result.error || 'Registration failed';
+          document.querySelector('.success_message').style.display = 'none';
+        }
+      } catch (error) {
+        console.error('Error:', error);
+        document.querySelector('.error_text').textContent = 'Server error. Please try again later.';
+      }
+    });
+  }
+
+  // Inicio de sesión
+  const loginForm = document.getElementById('login-form');
+  if (loginForm) {
+    loginForm.addEventListener('submit', async (event) => {
+      event.preventDefault(); 
+
+      const username = document.getElementById('username').value;
+      const password = document.getElementById('password').value;
+
+      try {
+        const response = await fetch('/api/users/login', {
+          method: 'POST',
+          headers: {
+            'Content-Type': 'application/json',
+          },
+          body: JSON.stringify({ username, password }),
+        });
+
+        const result = await response.json();
+
+        if (response.ok) {
+          document.querySelector('.success_message').style.display = 'block';
+          document.querySelector('.error_text').textContent = '';
+          setTimeout(() => {
+            window.location.href = 'index.html';
+          }, 2000);
+        } else {
+          document.querySelector('.error_text').textContent = result.error || 'Login failed';
+          document.querySelector('.success_message').style.display = 'none';
+        }
+      } catch (error) {
+        console.error('Error:', error);
+        document.querySelector('.error_text').textContent = 'Server error. Please try again later.';
+      }
+    });
+  }
+});
\ No newline at end of file
diff --git a/public/login.html b/public/login.html
index 931d251..9d90c07 100644
--- a/public/login.html
+++ b/public/login.html
@@ -4,7 +4,7 @@
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>Login</title>
-    <link rel="stylesheet" href="./css/login.css">
+    <link rel="stylesheet" href="./css/login.css" />
   </head>
   <body>
     <div class="login-container">
@@ -32,6 +32,50 @@
       </div>
 
       <div class="register-link">
+        <!DOCTYPE html>
+        <html lang="es">
+          <head>
+            <meta charset="UTF-8" />
+            <meta
+              name="viewport"
+              content="width=device-width, initial-scale=1.0"
+            />
+            <title>Login</title>
+            <link rel="stylesheet" href="./css/login.css" />
+          </head>
+          <body>
+            <div class="login-container">
+              <h2>Login</h2>
+              <form id="login-form">
+                <input
+                  type="text"
+                  class="uname"
+                  id="username"
+                  placeholder="Username"
+                  required
+                />
+                <input
+                  type="password"
+                  class="pass"
+                  id="password"
+                  placeholder="Password"
+                  required
+                />
+                <button type="submit" class="submit-login">Login</button>
+              </form>
+              <span class="error_text" style="color: red"></span>
+              <div class="success_message" style="display: none; color: green">
+                Login successful! Redirecting...
+              </div>
+
+              <div class="register-link">
+                Don't have an account? <a href="register.html">Register</a>.
+              </div>
+            </div>
+
+            <script src="./js/auth.js"></script>
+          </body>
+        </html>
         Don't have an account? <a href="register.html">Create one</a>.
       </div>
     </div>
diff --git a/public/register.html b/public/register.html
index 053c7f8..aeff643 100644
--- a/public/register.html
+++ b/public/register.html
@@ -4,35 +4,39 @@
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>Register</title>
-    <link rel="stylesheet" href="./css/login.css">
-
+    <link rel="stylesheet" href="./css/login.css" />
   </head>
   <body>
     <div class="register-container">
       <h2>Register</h2>
-      <form id="register-form" action="register.php" method="POST">
+      <form id="register-form">
         <input
           type="text"
           class="uname"
-          name="username"
+          id="username"
           placeholder="Username"
           required
         />
         <input
           type="password"
           class="pass"
-          name="password"
+          id="password"
           placeholder="Password"
           required
         />
         <button type="submit" class="submit-register">Register</button>
       </form>
-      <span class="error_text"></span>
-      <div class="success_message">Registration successful! Redirecting...</div>
 
-      <div class="login-link">
+      <span class="error_text" style="color: red"></span>
+      <div class="success_message" style="display: none; color: green">
+        Registration successful! Redirecting...
+      </div>
+
+      <div class="login-link" style="margin-top: 20px">
         Already have an account? <a href="login.html">Log in</a>.
       </div>
     </div>
+
+    <script src="./js/auth.js"></script>
   </body>
 </html>
diff --git a/routes/users.js b/routes/users.js
index e69de29..cf9fc04 100644
--- a/routes/users.js
+++ b/routes/users.js
@@ -0,0 +1,72 @@
+const express = require('express');
+const bcrypt = require('bcryptjs');
+const User = require('../models/user');
+const router = express.Router();
+
+// Register User
+router.post('/register', async (req, res) => {
+  const { username, password } = req.body;
+  
+  try {
+    // Verificar si el usuario ya existe
+    const existingUser = await User.findOne({ username });
+    if (existingUser) {
+      return res.status(400).json({ error: 'User already exists' });
+    }
+
+    // Encriptar la contraseña antes de guardarla
+    const hashedPassword = await bcrypt.hash(password, 10); 
+
+    // Crear un nuevo usuario con la contraseña encriptada
+    const user = new User({ username, password: hashedPassword });
+    await user.save();
+
+    res.status(201).json({ success: true, message: 'User registered successfully' });
+  } catch (error) {
+    console.error('Error saving user:', error);
+    res.status(500).json({ error: 'Server error' });
+  }
+});
+
+// LogIn User
+router.post('/login', async (req, res) => {
+  const { username, password } = req.body;
+  console.log('Attempting to log in:', username);
+
+  try {
+    const user = await User.findOne({ username });
+    console.log('User found:', user);
+
+    if (!user) {
+      return res.status(400).json({ error: 'Invalid username or password' });
+    }
+
+    const isMatch = await bcrypt.compare(password, user.password);
+    console.log('Password match:', isMatch);
+
+    if (!isMatch) {
+      return res.status(400).json({ error: 'Invalid username or password' });
+    }
+
+    req.session.user = { id: user._id, username: user.username };
+    console.log('User logged in:', req.session.user);
+
+    res.json({ success: true, message: 'Login successful' });
+  } catch (error) {
+    console.error('Login error:', error);
+    res.status(500).json({ error: 'Server error' });
+  }
+});
+
+
+// Cerrar sesión del usuario
+router.post('/logout', (req, res) => {
+  req.session.destroy(err => {
+    if (err) {
+      return res.status(500).json({ error: 'Logout failed' });
+    }
+    res.json({ success: true, message: 'Logged out successfully' });
+  });
+});
+
+module.exports = router;
\ No newline at end of file
-- 
GitLab