Skip to content

Commit 657de3f

Browse files
authored
Merge pull request #1258 from Satyam005/feature/fetching-user-device-info-mobile-auth
`GET` route for fetching user device info for qr-code mobile auth
2 parents 823579b + e3552c6 commit 657de3f

File tree

9 files changed

+194
-2
lines changed

9 files changed

+194
-2
lines changed

constants/errorMessages.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ module.exports = {
66
DATA_ADDED_SUCCESSFULLY: "User Device Info added successfully!",
77
USER_DATA_ALREADY_PRESENT: "The authentication document has already been created",
88
BAD_REQUEST: "BAD_REQUEST",
9+
INVALID_QUERY_PARAM: "Invalid Query Parameters Passed",
910
FILE_TOO_LARGE: (size) => `File too large, max accepted size is ${size} MB`,
1011
};

controllers/auth.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,27 @@ const updateAuthStatus = async (req, res) => {
119119
}
120120
};
121121

122+
const fetchUserDeviceInfo = async (req, res) => {
123+
try {
124+
const deviceId = req.query.device_id;
125+
const userDeviceInfoData = await QrCodeAuthModel.retrieveUserDeviceInfo(deviceId);
126+
if (!userDeviceInfoData.userExists) {
127+
return res.boom.notFound(`User with id ${deviceId} does not exist.`);
128+
}
129+
return res.json({
130+
message: "Authentication document retrieved successfully.",
131+
data: { ...userDeviceInfoData.data },
132+
});
133+
} catch (error) {
134+
logger.error(`Error while fetching user: ${error}`);
135+
return res.boom.badImplementation(SOMETHING_WENT_WRONG);
136+
}
137+
};
138+
122139
module.exports = {
123140
githubAuth,
124141
signout,
125142
storeUserDeviceInfo,
126143
updateAuthStatus,
144+
fetchUserDeviceInfo,
127145
};

middlewares/validators/qrCodeAuth.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,22 @@ const validateAuthStatus = async (req, res, next) => {
3232
}
3333
};
3434

35+
const validateFetchingUserDocument = async (req, res, next) => {
36+
const schema = joi.object().strict().keys({
37+
device_id: joi.string().required(),
38+
});
39+
40+
try {
41+
await schema.validateAsync(req.query);
42+
next();
43+
} catch (error) {
44+
logger.error(`Invalid Query Parameters Passed`);
45+
res.boom.badRequest(`Invalid Query Parameters Passed`);
46+
}
47+
};
48+
3549
module.exports = {
3650
storeUserDeviceInfo,
3751
validateAuthStatus,
52+
validateFetchingUserDocument,
3853
};

models/levels.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ const addLevel = async (levelData) => {
2727
const deleteLevel = async (id) => {
2828
try {
2929
await levelModel.doc(id).delete();
30-
return;
3130
} catch (err) {
3231
logger.error("Error in deleting Level", err);
3332
throw err;

models/qrCodeAuth.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,28 @@ const storeUserDeviceInfo = async (userDeviceInfoData) => {
5454
}
5555
};
5656

57+
const retrieveUserDeviceInfo = async (deviceId) => {
58+
try {
59+
const queryDocument = await QrCodeAuthModel.where("device_id", "==", deviceId).get();
60+
const userData = queryDocument.docs[0];
61+
62+
if (!userData) {
63+
return {
64+
userExists: false,
65+
};
66+
}
67+
return {
68+
userExists: true,
69+
data: userData.data(),
70+
};
71+
} catch (err) {
72+
logger.error("Error in retrieving user device info", err);
73+
throw err;
74+
}
75+
};
76+
5777
module.exports = {
5878
updateStatus,
5979
storeUserDeviceInfo,
80+
retrieveUserDeviceInfo,
6081
};

routes/auth.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ router.get("/github/callback", auth.githubAuth);
1212

1313
router.get("/signout", auth.signout);
1414

15+
router.get("/qr-code-auth", userDeviceInfoValidator.validateFetchingUserDocument, auth.fetchUserDeviceInfo);
16+
1517
router.post("/qr-code-auth", userDeviceInfoValidator.storeUserDeviceInfo, auth.storeUserDeviceInfo);
18+
1619
router.patch(
1720
"/qr-code-auth/authorization_status/:authorization_status",
1821
authenticate,

test/integration/qrCodeAuth.test.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,62 @@ describe("QrCodeAuth", function () {
160160
});
161161
});
162162
});
163+
164+
describe("GET call for fetching user device info", function () {
165+
let userId = "";
166+
let userDeviceInfoData;
167+
beforeEach(async function () {
168+
userId = await addUser(user);
169+
userDeviceInfoData = {
170+
...userDeviceInfoDataArray[0],
171+
user_id: userId,
172+
authorization_status: "NOT_INIT",
173+
access_token: "ACCESS_TOKEN",
174+
};
175+
});
176+
afterEach(async function () {
177+
await cleanDb();
178+
});
179+
180+
it("should successfully fetch the user device info", function (done) {
181+
qrCodeAuthModel.storeUserDeviceInfo(userDeviceInfoData).then((response) => {
182+
chai
183+
.request(app)
184+
.get(`/auth/qr-code-auth?device_id=${response.userDeviceInfoData.device_id}`)
185+
.end((err, res) => {
186+
if (err) {
187+
return done(err);
188+
}
189+
expect(res).to.have.status(200);
190+
expect(res.body).to.be.a("object");
191+
expect(res.body.data.user_id).to.be.a("string");
192+
expect(res.body.data.device_info).to.be.a("string");
193+
expect(res.body.data.device_id).to.be.a("string");
194+
expect(res.body.data.authorization_status).to.be.a("string");
195+
expect(res.body.data.access_token).to.be.a("string");
196+
expect(res.body.message).to.equal(`Authentication document retrieved successfully.`);
197+
198+
return done();
199+
});
200+
});
201+
});
202+
203+
it("should fail with 404, when the document is not found", function (done) {
204+
chai
205+
.request(app)
206+
.get(`/auth/qr-code-auth?device_id=${userDeviceInfoData.device_id}`)
207+
.end((err, res) => {
208+
if (err) {
209+
return done(err);
210+
}
211+
212+
expect(res).to.have.status(404);
213+
expect(res.body).to.be.a("object");
214+
expect(res.body.message).to.equal(`User with id ${userDeviceInfoData.device_id} does not exist.`);
215+
expect(res.body.error).to.equal("Not Found");
216+
217+
return done();
218+
});
219+
});
220+
});
163221
});

test/unit/middlewares/qrCodeAuthValidator.test.js

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
const Sinon = require("sinon");
2-
const { validateAuthStatus, storeUserDeviceInfo } = require("../../../middlewares/validators/qrCodeAuth");
2+
const {
3+
validateAuthStatus,
4+
storeUserDeviceInfo,
5+
validateFetchingUserDocument,
6+
} = require("../../../middlewares/validators/qrCodeAuth");
37
const { expect } = require("chai");
48
const { userDeviceInfoDataArray } = require("../../fixtures/qrCodeAuth/qrCodeAuth");
59
describe("qrCodeAuth", function () {
@@ -65,4 +69,39 @@ describe("qrCodeAuth", function () {
6569
expect(nextSpy.callCount).to.be.equal(0);
6670
});
6771
});
72+
73+
describe("test get call validator", function () {
74+
it("Allows request to pass on valid params", async function () {
75+
const req = {
76+
query: {
77+
device_id: "DEVICE_ID",
78+
},
79+
};
80+
81+
const res = {};
82+
83+
const nextSpy = Sinon.spy();
84+
await validateFetchingUserDocument(req, res, nextSpy);
85+
expect(nextSpy.callCount).to.be.equal(1);
86+
});
87+
88+
it("Does not allow request to pass on invalid params", async function () {
89+
const req = {
90+
query: {
91+
user_id: "ID",
92+
device_type: "DEVICE_TYPE",
93+
},
94+
};
95+
96+
const res = {
97+
boom: {
98+
badRequest: () => {},
99+
},
100+
};
101+
102+
const nextSpy = Sinon.spy();
103+
await validateFetchingUserDocument(req, res, nextSpy);
104+
expect(nextSpy.callCount).to.be.equal(0);
105+
});
106+
});
68107
});

test/unit/models/qrCodeAuth.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,42 @@ describe("mobile auth", function () {
7878
expect(response.userExists).to.be.equal(false);
7979
});
8080
});
81+
82+
describe("retrieveUserDeviceInfo", function () {
83+
it("should fetch the user device info for mobile auth", async function () {
84+
const userData = userDataArray[0];
85+
const { userId } = await users.addOrUpdate(userData);
86+
87+
const userDeviceInfoData = {
88+
...userDeviceInfoDataArray[0],
89+
user_id: userId,
90+
authorization_status: "NOT_INIT",
91+
access_token: "ACCESS_TOKEN",
92+
};
93+
94+
await qrCodeAuth.storeUserDeviceInfo(userDeviceInfoData);
95+
const response = await qrCodeAuth.retrieveUserDeviceInfo(userDeviceInfoData.device_id);
96+
const userDeviceInfo = response.data;
97+
const {
98+
user_id: userID,
99+
device_info: deviceInfo,
100+
device_id: deviceId,
101+
authorization_status: authorizationStatus,
102+
access_token: accessToken,
103+
} = userDeviceInfo;
104+
105+
const data = (await qrCodeAuthModel.doc(userId).get()).data();
106+
107+
Object.keys(userDeviceInfo).forEach((key) => {
108+
expect(userDeviceInfo[key]).to.deep.equal(data[key]);
109+
});
110+
111+
expect(response).to.be.an("object");
112+
expect(userID).to.be.a("string");
113+
expect(deviceInfo).to.be.a("string");
114+
expect(deviceId).to.be.a("string");
115+
expect(authorizationStatus).to.be.a("string");
116+
expect(accessToken).to.be.a("string");
117+
});
118+
});
81119
});

0 commit comments

Comments
 (0)