Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
47 changes: 24 additions & 23 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
const express = require('express')
const logger = require('morgan')
const cors = require('cors')

const contactsRouter = require('./routes/api/contacts')

const app = express()

const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short'

app.use(logger(formatsLogger))
app.use(cors())
app.use(express.json())

app.use('/api/contacts', contactsRouter)

app.use((req, res) => {
res.status(404).json({ message: 'Not found' })
})

const express = require('express');
const app = express();
const cors = require('cors');
const morgan = require('morgan');
const bodyParser = require('body-parser');

// Import routes
const authRoutes = require('./routes/authRoutes');
const userRoutes = require('./routes/userRoutes');

// Middlewares
app.use(morgan('dev')); // Logging middleware
app.use(cors()); // Enable CORS
app.use(bodyParser.json()); // Parse incoming JSON requests

// Use routes
app.use('/api/auth', authRoutes);
app.use('/api/users', userRoutes);

// Error handler middleware
app.use((err, req, res, next) => {
res.status(500).json({ message: err.message })
})
console.error(err);
res.status(500).json({ message: 'Internal Server Error' });
});

module.exports = app
module.exports = app;
67 changes: 67 additions & 0 deletions controllers/authController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const User = require('../models/userModel');
require('dotenv').config();

const register = async (req, res, next) => {
try {
const { email, password } = req.body;

if (!email || !password) {
return res.status(400).json({ message: 'Email and password are required' });
}

const existingUser = await User.findOne({ email });
if (existingUser) {
return res.status(400).json({ message: 'Email already in use' });
}

const hashedPassword = await bcrypt.hash(password, 10);

const newUser = await User.create({ email, password: hashedPassword });

res.status(201).json({
message: 'User registered successfully',
email: newUser.email,
});
} catch (error) {
console.error('Error during registration:', error.message);
next(error);
}
};

const login = async (req, res, next) => {
try {
const { email, password } = req.body;

if (!email || !password) {
return res.status(400).json({ message: 'Email and password are required' });
}

const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ message: 'Invalid email or password' });
}

const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
return res.status(401).json({ message: 'Invalid email or password' });
}

if (!process.env.JWT_SECRET) {
throw new Error('JWT_SECRET is not defined');
}
const token = jwt.sign(
{ id: user._id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);

res.json({ token });
} catch (error) {
console.error('Error during login:', error.message);
next(error);
}
};

module.exports = { register, login };
5 changes: 5 additions & 0 deletions controllers/usersController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const getCurrentUser = (req, res) => {
res.json({ id: req.user.id, email: req.user.email });
};

module.exports = { getCurrentUser };
18 changes: 18 additions & 0 deletions dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Use Node.js image
FROM node:18

# Set working directory
WORKDIR /app

# Copy package.json and install dependencies
COPY package.json ./
RUN npm install

# Copy application code
COPY . .

# Expose application port
EXPOSE 3000

# Start the server
CMD ["npm", "start"]
21 changes: 21 additions & 0 deletions middlewares/authMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const jwt = require('jsonwebtoken');

const authMiddleware = (req, res, next) => {
const authHeader = req.headers.authorization;

if (!authHeader) {
return res.status(401).json({ message: 'Authorization header is missing' });
}

const token = authHeader.split(' ')[1];

try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (error) {
return res.status(401).json({ message: 'Invalid or expired token' });
}
};

module.exports = authMiddleware;
9 changes: 9 additions & 0 deletions middlewares/errorMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const errorMiddleware = (err, req, res, next) => {
const status = err.status || 500;
const message = err.message || 'Internal Server Error';

console.error(`[Error] ${message}`);
res.status(status).json({ message });
};

module.exports = errorMiddleware;
23 changes: 23 additions & 0 deletions middlewares/validationMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const Joi = require('joi');

const validateBody = schema => (req, res, next) => {
const { error } = schema.validate(req.body);

if (error) {
return res.status(400).json({ message: error.details[0].message });
}

next();
};

const userRegistrationSchema = Joi.object({
email: Joi.string().email().required(),
password: Joi.string().min(6).required(),
});

const userLoginSchema = Joi.object({
email: Joi.string().email().required(),
password: Joi.string().required(),
});

module.exports = { validateBody, userRegistrationSchema, userLoginSchema };
19 changes: 0 additions & 19 deletions models/contacts.js

This file was deleted.

62 changes: 0 additions & 62 deletions models/contacts.json

This file was deleted.

26 changes: 26 additions & 0 deletions models/userModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');

const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
});

userSchema.pre('save', async function (next) {
if (this.isModified('password')) {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
}
next();
});

const User = mongoose.model('User', userSchema);

module.exports = User;
3 changes: 0 additions & 3 deletions nodemon.json

This file was deleted.

Loading