-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #116 from Akan45/loginback
Register Backend Implementation
- Loading branch information
Showing
13 changed files
with
1,634 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
MONGO_URI="mongo_db_url" | ||
JWT_SECRET="Your_JWT-SECRET_KEY" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
|
||
import express from 'express'; | ||
import cors from 'cors'; | ||
import bodyParser from 'body-parser'; | ||
import authRoutes from '../routes/authRoutes.js'; | ||
|
||
const app = express(); | ||
|
||
// Middleware | ||
app.use(cors()); | ||
app.use(express.json({ limit: '16kb' })); | ||
app.use(express.urlencoded({ extended: true, limit: '16kb' })); | ||
app.use(bodyParser.json()); | ||
app.use(bodyParser.urlencoded({ extended: true })); | ||
|
||
|
||
// Routes | ||
app.use('/api/v1/auth', authRoutes); // Authentication routes | ||
|
||
export { app }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import mongoose from 'mongoose'; | ||
import dotenv from 'dotenv' | ||
|
||
dotenv.config() | ||
// Database connection | ||
export const dbConnect = async () => { | ||
const url = process.env.MONGO_URI; | ||
|
||
if (!url) { | ||
console.error('No URL received from env. Check .env file path.'); | ||
process.exit(1); | ||
} | ||
|
||
try { | ||
await mongoose.connect(url, { | ||
useNewUrlParser: true, | ||
useUnifiedTopology: true, | ||
}); | ||
console.log('MongoDB connected'); | ||
} catch (err) { | ||
console.error('Database connection error:', err); | ||
process.exit(1); // Exit process with failure | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import dotenv from 'dotenv'; | ||
import { dbConnect } from './dbconnect.js'; | ||
import { app } from './app.js'; | ||
|
||
// Load environment variables | ||
dotenv.config(); | ||
|
||
console.log('Starting app. MONGO_URI:', process.env.MONGO_URI); | ||
|
||
// Connect to the database and start the server | ||
dbConnect() | ||
.then(() => { | ||
const PORT = process.env.PORT || 3000; | ||
app.listen(PORT, () => { | ||
console.log(`App is running on port ${PORT} and DB connected`); | ||
}); | ||
}) | ||
.catch((err) => { | ||
console.error('Database connection failed:', err); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import jwt from 'jsonwebtoken'; | ||
import User from '../models/User.js'; | ||
|
||
// User Registration | ||
export const registerUser = async (req, res) => { | ||
const { username, email, password, dob, location } = req.body; | ||
|
||
// Check for required fields | ||
if (!username || !email || !password) { | ||
return res.status(400).send({ error: "Username, email, and password are required." }); | ||
} | ||
|
||
try { | ||
// Check if the user already exists | ||
const userExists = await User.findOne({ email }); | ||
|
||
if (userExists) { | ||
return res.status(400).send({ message: 'User already exists' }); | ||
} | ||
|
||
// Create a new user | ||
const user = new User({ | ||
username, | ||
email, | ||
password, | ||
dob, // Optional field | ||
location, // Optional field | ||
}); | ||
|
||
await user.save(); | ||
console.log('User saved successfully'); | ||
|
||
// Generate JWT token | ||
const token = jwt.sign({ id: user._id }, "THIS_IS_A_JWT_SECRET", { | ||
expiresIn: '1h', | ||
}); | ||
|
||
// Respond with success message and token | ||
res.status(201).send({ | ||
message: 'User created successfully', | ||
token, | ||
}); | ||
} catch (error) { | ||
console.error('Error during user registration:', error); | ||
res.status(500).send({ message: 'Server error', error: error.message }); | ||
} | ||
}; | ||
|
||
// User Login | ||
export const loginUser = async (req, res) => { | ||
const { email, password } = req.body; | ||
|
||
try { | ||
const user = await User.findOne({ email }); | ||
|
||
if (!user) { | ||
console.log("User does not exist"); | ||
return res.status(400).send({ message: 'Invalid credentials user' }); | ||
} | ||
|
||
const isPasswordMatch = await user.matchPassword(password); | ||
|
||
if (!isPasswordMatch) { | ||
console.log("Password doesn't match"); | ||
return res.status(400).send({ message: 'Invalid credentials password' }); | ||
} | ||
|
||
const token = jwt.sign({ id: user._id }, "THIS_IS_A_JWT_SECRET", { | ||
expiresIn: '1h', | ||
}); | ||
|
||
res.send({ | ||
message: 'Login successful', | ||
token, | ||
}); | ||
} catch (error) { | ||
console.error('Error during user login:', error); | ||
res.status(500).send({ message: 'Server error', error: error.message }); | ||
} | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import jwt from 'jsonwebtoken'; | ||
|
||
const authUser = async (req, res, next) => { | ||
try { | ||
// Extract the Authorization header | ||
const authHeader = req.headers.authorization; // Note: Headers are case-insensitive | ||
|
||
if (!authHeader) { | ||
return res.status(401).json({ error: "No token found. Please log in first." }); | ||
} | ||
|
||
// Split the Bearer token | ||
const token = authHeader.split(' ')[1]; // Assumes format: "Bearer token" | ||
|
||
if (!token) { | ||
return res.status(401).json({ error: "Malformed token. Authorization failed." }); | ||
} | ||
|
||
// Verify the token | ||
const decoded = jwt.verify(token, "THIS_IS_A_JWT_SECRET"); // Replace with your secret key | ||
|
||
// Add user data to request for downstream handlers | ||
req.user = decoded; | ||
|
||
// Pass control to the next middleware or route handler | ||
next(); | ||
} catch (error) { | ||
console.error("Error verifying token:", error.message); | ||
|
||
// Handle specific JWT errors | ||
if (error.name === 'TokenExpiredError') { | ||
return res.status(401).json({ error: "Token expired. Please log in again." }); | ||
} else if (error.name === 'JsonWebTokenError') { | ||
return res.status(401).json({ error: "Invalid token. Authorization failed." }); | ||
} | ||
|
||
// Catch-all for unexpected errors | ||
res.status(500).json({ error: "Internal server error during authentication." }); | ||
} | ||
}; | ||
|
||
export {authUser}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import mongoose from 'mongoose'; | ||
import bcrypt from 'bcryptjs'; | ||
|
||
// User schema | ||
const userSchema = new mongoose.Schema({ | ||
username: { | ||
type: String, | ||
required: true, | ||
unique: true, | ||
}, | ||
email: { | ||
type: String, | ||
required: true, | ||
unique: true, | ||
}, | ||
password: { | ||
type: String, | ||
required: true, | ||
}, | ||
inSightsCount: { | ||
type: Number, | ||
default: 0, | ||
}, | ||
createdOn: { | ||
type: Date, | ||
default: Date.now, // Automatically set to the current date and time | ||
}, | ||
dob: { | ||
type: Date, // Date of Birth field | ||
required: false, // Optional field | ||
}, | ||
location: { | ||
type: String, // Can store city, state, or country | ||
required: false, // Optional field | ||
}, | ||
}); | ||
|
||
// Hash password before saving | ||
userSchema.pre('save', async function (next) { | ||
if (!this.isModified('password')) { | ||
return next(); | ||
} | ||
const salt = await bcrypt.genSalt(10); | ||
this.password = await bcrypt.hash(this.password, salt); | ||
next(); | ||
}); | ||
|
||
// Method to compare password for login | ||
userSchema.methods.matchPassword = async function (enteredPassword) { | ||
return await bcrypt.compare(enteredPassword, this.password); | ||
}; | ||
|
||
const User = mongoose.model('User', userSchema); | ||
|
||
export default User; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import express from 'express'; | ||
import { registerUser, loginUser } from '../controller/authController.js'; | ||
const router = express.Router(); | ||
|
||
// Register Route | ||
router.post('/signup', registerUser); | ||
|
||
// Login Route | ||
router.post('/login', loginUser); | ||
|
||
export default router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
document.addEventListener('DOMContentLoaded', function() { | ||
const signupForm = document.getElementById('signupForm'); | ||
if (signupForm) { | ||
signupForm.addEventListener('submit', handleSignupSubmit); | ||
} | ||
}); | ||
|
||
function handleSignupSubmit(event) { | ||
event.preventDefault(); // Prevent the default form submission | ||
|
||
const username = document.getElementById('username').value; | ||
const email = document.getElementById('email').value; | ||
const password = document.getElementById('password').value; | ||
const confirmPassword = document.getElementById('confirmPassword').value; | ||
|
||
if (password !== confirmPassword) { | ||
alert('Passwords do not match'); | ||
return; | ||
} | ||
|
||
const formData = { username, email, password }; | ||
|
||
|
||
fetch('http://localhost:3000/api/v1/auth/signup', { | ||
|
||
method: 'POST', | ||
headers: { 'Content-Type': 'application/json' }, | ||
body: JSON.stringify(formData), | ||
}) | ||
.then(response => response.json()) | ||
.then(data => { | ||
if (data.token) { | ||
alert('Signup successful! You are now logged in.'); | ||
localStorage.setItem('authToken', data.token); | ||
window.location.href = '/SCD-Profile-Score/'; | ||
} else { | ||
alert('Signup failed: ' + data.message); | ||
} | ||
}) | ||
.catch(error => console.error('Error:', error)); | ||
} | ||
|
Oops, something went wrong.