Skip to content

Commit

Permalink
KAN-3-user-service-add-session-management-to-user (#4)
Browse files Browse the repository at this point in the history
* KAN-3 | Added session management logic to code base

* prettier fixes
  • Loading branch information
AvinashMudunuri authored Jul 14, 2024
1 parent c13f61e commit e83ad87
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 15 deletions.
25 changes: 22 additions & 3 deletions controllers/userController.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
const userService = require('../domain/user/services/userService');
const userService = require('../domain/services/userService');
const sessionService = require('../domain/services/sessionService');
class UserController {
async login(req, res) {
try {
const { email, password } = req.body;
const token = await userService.login(email, password);
const user = await userService.login(email, password);
await sessionService.createSession({
userId: user.id,
token: user.token,
});
res.status(200).json({
token,
token: user.token,
});
} catch (ex) {
res.status(400).json({
Expand All @@ -14,6 +19,20 @@ class UserController {
}
}

async logout(req, res) {
try {
const token = req.header('Authorization').replace('Bearer ', '');
await sessionService.deleteSession(token);
res.status(200).json({
message: 'Logout Successful',
});
} catch (e) {
res.status(500).json({
error: 'Could not logout, please try again',
});
}
}

async createUser(req, res) {
try {
const user = await userService.createUser(req.body);
Expand Down
10 changes: 10 additions & 0 deletions domain/models/session.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;

const sessionSchema = new Schema({
userId: { type: Schema.Types.ObjectId, required: true, ref: 'User' },
token: { type: String, required: true, unique: true },
created_at: { type: Date, default: Date.now },
});

module.exports = mongoose.model('Session', sessionSchema);
3 changes: 2 additions & 1 deletion domain/user/models/user.js → domain/models/user.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const config = require('../../../config/config');
const config = require('../../config/config');
const { Schema } = mongoose;

const userSchema = new Schema({
Expand All @@ -28,6 +28,7 @@ userSchema.methods.generateToken = async function () {
{
id: this.id,
role: this.role,
name: this.name,
},
config.jwtSecret,
{ expiresIn: '1h' }
Expand Down
16 changes: 16 additions & 0 deletions domain/repositories/sessionRepository.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const Session = require('../models/session');

class SessionRepository {
async createSession(data) {
const session = new Session(data);
return await session.save();
}
async deleteSession(token) {
return await Session.findOneAndDelete({ token });
}
async findByToken(token) {
return await Session.findOne({ token });
}
}

module.exports = new SessionRepository();
File renamed without changes.
15 changes: 15 additions & 0 deletions domain/services/sessionService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const sessionRepository = require('../repositories/sessionRepository');

class SessionService {
async createSession(data) {
return await sessionRepository.createSession(data);
}
async deleteSession(token) {
return await sessionRepository.deleteSession(token);
}
async getSessionByToken(token) {
return await sessionRepository.findByToken(token);
}
}

module.exports = new SessionService();
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
const userRepository = require('../repositories/userRepository');
const {
setRedisKey,
deleteRedisKey,
} = require('../../../infrastructure/redis');
const { setRedisKey, deleteRedisKey } = require('../../infrastructure/redis');
class UserService {
async createUser(data) {
const existingUser = await userRepository.findByEmail(data.email);
Expand Down Expand Up @@ -54,7 +51,10 @@ class UserService {
if (!isMatch) {
throw new Error('Invalid credentials');
}
return user.generateToken();
return {
id: user._id,
token: await user.generateToken(),
};
}
}

Expand Down
2 changes: 1 addition & 1 deletion middleware/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const auth = (req, res, next) => {

try {
// Verify token
jwt.verify(actualToken, config.jwtSecret, (err, decoded) => {
jwt.verify(actualToken, config.jwtSecret, async (err, decoded) => {
if (err) {
return res.status(401).json({ msg: err });
}
Expand Down
4 changes: 4 additions & 0 deletions routes/userRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ router.post('/auth/register', async (req, res) =>

router.post('/auth/login', async (req, res) => userController.login(req, res));

router.post('/auth/logout', async (req, res) =>
userController.logout(req, res)
);

router.get('/', auth, grantAccess('readOwn', 'profile'), async (req, res) =>
userController.getAllUsers(req, res)
);
Expand Down
2 changes: 1 addition & 1 deletion test/api/userApi.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const {
deleteRedisKey,
disconnectRedis,
} = require('../../infrastructure/redis');
const User = require('../../domain/user/models/user');
const User = require('../../domain/models/user');

const chai = require('chai');
const expect = chai.expect;
Expand Down
8 changes: 4 additions & 4 deletions test/domain/user/userService.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const {
disconnectRedis,
} = require('../../../infrastructure/redis');

const User = require('../../../domain/user/models/user');
const userService = require('../../../domain/user/services/userService');
const User = require('../../../domain/models/user');
const userService = require('../../../domain/services/userService');

const expect = chai.expect;
chai.use(chaiHttp);
Expand Down Expand Up @@ -86,8 +86,8 @@ describe('User Service', function () {

it('Should login an existing user', async () => {
const userData = { email: 'john@example.com', password: 'john123' };
const token = await userService.login(userData.email, userData.password);
expect(token).to.be.a('string');
const user = await userService.login(userData.email, userData.password);
expect(user.token).to.be.a('string');
});
});

Expand Down

0 comments on commit e83ad87

Please sign in to comment.