Skip to content

Commit ba269bd

Browse files
authored
feat: implements a new GET route /users?profile=true (#2201)
* adding new route for query param profile * removing some mixed changes of other commit * modified test cases and and controller logic * Implemented GET route /users?profile=true to fetch user's details * refactored: moved authentication logic from controller to middleware * test cases fo authCondition file * updated test cases and routes and middleware of users * bug fix for using only in test cases * code refactor and updated function naming
1 parent 9a5e799 commit ba269bd

File tree

7 files changed

+174
-1
lines changed

7 files changed

+174
-1
lines changed

controllers/users.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,26 @@ const getUsers = async (req, res) => {
113113
});
114114
}
115115

116+
const profile = req.query.profile === "true";
117+
118+
if (profile) {
119+
if (dev) {
120+
if (!req.userData.id) {
121+
return res.boom.badRequest("User ID not provided.");
122+
}
123+
124+
try {
125+
const result = await dataAccess.retrieveUsers({ id: req.userData.id });
126+
return res.send(result.user);
127+
} catch (error) {
128+
logger.error(`Error while fetching user: ${error}`);
129+
return res.boom.serverUnavailable(INTERNAL_SERVER_ERROR);
130+
}
131+
} else {
132+
return res.boom.badRequest("Route not found");
133+
}
134+
}
135+
116136
if (!transformedQuery?.days && transformedQuery?.filterBy === "unmerged_prs") {
117137
return res.boom.badRequest(`Days is required for filterBy ${transformedQuery?.filterBy}`);
118138
}
@@ -393,6 +413,7 @@ const getSelfDetails = async (req, res) => {
393413
* @param req.body {Object} - User object
394414
* @param res {Object} - Express response object
395415
*/
416+
396417
const updateSelf = async (req, res) => {
397418
try {
398419
const { id: userId, roles: userRoles, discordId } = req.userData;

middlewares/authenticateProfile.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const authenticateProfile = (authenticate) => {
2+
return async (req, res, next) => {
3+
if (req.query.profile === "true") {
4+
return await authenticate(req, res, next);
5+
}
6+
return next();
7+
};
8+
};
9+
10+
module.exports = authenticateProfile;

middlewares/validators/user.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ async function getUsers(req, res, next) {
196196
}),
197197
query: joi.string().optional(),
198198
q: joi.string().optional(),
199+
profile: joi.string().valid("true").optional(),
199200
filterBy: joi.string().optional(),
200201
days: joi.string().optional(),
201202
dev: joi.string().optional(),

routes/users.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ const checkIsVerifiedDiscord = require("../middlewares/verifydiscord");
1111
const { authorizeAndAuthenticate } = require("../middlewares/authorizeUsersAndService");
1212
const ROLES = require("../constants/roles");
1313
const { Services } = require("../constants/bot");
14+
const authenticateProfile = require("../middlewares/authenticateProfile");
1415

1516
router.post("/", authorizeAndAuthenticate([ROLES.SUPERUSER], [Services.CRON_JOB_HANDLER]), users.markUnverified);
1617
router.post("/update-in-discord", authenticate, authorizeRoles([SUPERUSER]), users.setInDiscordScript);
1718
router.post("/verify", authenticate, users.verifyUser);
1819
router.get("/userId/:userId", users.getUserById);
1920
router.patch("/self", authenticate, userValidator.updateUser, users.updateSelf);
20-
router.get("/", userValidator.getUsers, users.getUsers);
21+
router.get("/", authenticateProfile(authenticate), userValidator.getUsers, users.getUsers);
2122
router.get("/self", authenticate, users.getSelfDetails);
2223
router.get("/isDeveloper", authenticate, users.isDeveloper);
2324
router.get("/isUsernameAvailable/:username", authenticate, users.getUsernameAvailabilty);

test/integration/users.test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,63 @@ describe("Users", function () {
903903
return done();
904904
});
905905
});
906+
907+
it("Should return the logged-in user's details when profile and dev is true", function (done) {
908+
chai
909+
.request(app)
910+
.get("/users?profile=true&dev=true")
911+
.set("cookie", `${cookieName}=${jwt}`)
912+
.end((err, res) => {
913+
if (err) {
914+
return done(err);
915+
}
916+
expect(res).to.have.status(200);
917+
expect(res.body).to.be.a("object");
918+
expect(res.body).to.not.have.property("phone");
919+
expect(res.body).to.not.have.property("email");
920+
expect(res.body).to.not.have.property("chaincode");
921+
922+
return done();
923+
});
924+
});
925+
926+
it("Should throw an error when there is no feature flag given", function (done) {
927+
chai
928+
.request(app)
929+
.get("/users?profile=true")
930+
.set("cookie", `${cookieName}=${jwt}`)
931+
.end((err, res) => {
932+
if (err) {
933+
return done(err);
934+
}
935+
expect(res).to.have.status(400);
936+
expect(res.body).to.be.an("object");
937+
expect(res.body.message).to.equal("Route not found");
938+
return done();
939+
});
940+
});
941+
942+
it("Should return 401 if not logged in", function (done) {
943+
chai
944+
.request(app)
945+
.get("/users?profile=true&dev=true")
946+
.set("cookie", `${cookieName}=invalid_token`)
947+
.end((err, res) => {
948+
if (err) {
949+
return done();
950+
}
951+
952+
expect(res).to.have.status(401);
953+
expect(res.body).to.be.an("object");
954+
expect(res.body).to.eql({
955+
statusCode: 401,
956+
error: "Unauthorized",
957+
message: "Unauthenticated User",
958+
});
959+
960+
return done();
961+
});
962+
});
906963
});
907964

908965
describe("GET /users/self", function () {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const chai = require("chai");
2+
const sinon = require("sinon");
3+
const { expect } = chai;
4+
const authenticateProfile = require("../../../middlewares/authenticateProfile.js");
5+
6+
describe("authenticateProfile Middleware", function () {
7+
let req, res, next, authenticateStub, auth;
8+
9+
beforeEach(function () {
10+
authenticateStub = sinon.spy();
11+
auth = authenticateProfile(authenticateStub);
12+
13+
req = {
14+
query: {},
15+
};
16+
res = {
17+
boom: {
18+
unauthorized: sinon.spy(),
19+
forbidden: sinon.spy(),
20+
},
21+
};
22+
next = sinon.spy();
23+
});
24+
25+
it("should call authenticate when profile query is true", async function () {
26+
req.query.profile = "true";
27+
await auth(req, res, next);
28+
29+
expect(authenticateStub.withArgs(req, res, next).calledOnce).to.equal(true);
30+
expect(next.calledOnce).to.equal(false);
31+
});
32+
33+
it("should call next when profile query is not true", async function () {
34+
req.query.profile = "false";
35+
36+
await auth(req, res, next);
37+
38+
expect(authenticateStub.calledOnce).to.equal(false);
39+
expect(next.calledOnce).to.equal(true);
40+
});
41+
42+
it("should call next when profile query is missing", async function () {
43+
await auth(req, res, next);
44+
45+
expect(authenticateStub.calledOnce).to.equal(false);
46+
expect(next.calledOnce).to.equal(true);
47+
});
48+
});

test/unit/middlewares/user-validator.test.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,41 @@ describe("Middleware | Validators | User", function () {
472472
});
473473
expect(nextSpy.calledOnce).to.be.equal(false);
474474
});
475+
476+
it("Allows the request pass to next", async function () {
477+
const req = {
478+
query: {
479+
profile: "true",
480+
dev: "true",
481+
},
482+
};
483+
484+
const res = {};
485+
const next = sinon.spy();
486+
487+
await getUsers(req, res, next);
488+
expect(next.calledOnce).to.be.equal(true);
489+
});
490+
491+
it("Stops the request for passing on to next", async function () {
492+
const req = {
493+
query: {
494+
profile: "false",
495+
},
496+
};
497+
498+
const res = {
499+
boom: {
500+
badRequest: () => {},
501+
},
502+
};
503+
const nextSpy = sinon.spy();
504+
505+
await getUsers(req, res, nextSpy).catch((err) => {
506+
expect(err).to.be.an.instanceOf(Error);
507+
});
508+
expect(nextSpy.calledOnce).to.be.equal(false);
509+
});
475510
});
476511

477512
describe("validateGenerateUsernameQuery Middleware", function () {

0 commit comments

Comments
 (0)