Skip to content

Commit 823579b

Browse files
authored
Stop collecting github access token and remove it from existing user's data (#1227)
* wrote scripts and tests * forgot to add this file * fixing test errors * implemented batch instead of promise.all to send update request to firestore * fixed test and resolved comments * fixed tests * forgot to fix this * forgot to fix this * preventing object sink * preventing object sink * fixing function call object sink warning * ignore object sink * resolved comments by randhir * resolved comments * fixing tests
1 parent 30e630f commit 823579b

File tree

6 files changed

+140
-4
lines changed

6 files changed

+140
-4
lines changed

controllers/auth.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ const githubAuth = (req, res, next) => {
2626
userData = {
2727
github_id: user.username,
2828
github_display_name: user.displayName,
29-
tokens: {
30-
githubAccessToken: accessToken,
31-
},
3229
};
3330

3431
const { userId, incompleteUserDetails } = await users.addOrUpdate(userData);

controllers/users.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,26 @@ const setInDiscordScript = async (req, res) => {
577577
await setInDiscordFalseScript();
578578
return res.json({ message: "Successfully added the in_discord field to false for all users" });
579579
} catch (err) {
580-
return res.status(500).json({ message: INTERNAL_SERVER_ERROR });
580+
return res.boom.badImplementation({ message: INTERNAL_SERVER_ERROR });
581+
}
582+
};
583+
584+
const removeTokens = async (req, res) => {
585+
try {
586+
const users = await userQuery.fetchUsersWithToken();
587+
588+
if (!users.length) {
589+
return res.status(404).json({ message: "No users found with github Token!" });
590+
}
591+
592+
await userQuery.removeGitHubToken(users);
593+
594+
return res.status(200).json({
595+
message: "Github Token removed from all users!",
596+
usersFound: users.length,
597+
});
598+
} catch (err) {
599+
return res.boom.badImplementation({ message: INTERNAL_SERVER_ERROR });
581600
}
582601
};
583602

@@ -628,5 +647,6 @@ module.exports = {
628647
nonVerifiedDiscordUsers,
629648
setInDiscordScript,
630649
markUnverified,
650+
removeTokens,
631651
updateRoles,
632652
};

models/users.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,56 @@ const fetchAllUsers = async () => {
572572
return users;
573573
};
574574

575+
const fetchUsersWithToken = async () => {
576+
try {
577+
const users = [];
578+
const usersRef = await userModel.where("tokens", "!=", false).get();
579+
usersRef.forEach((user) => {
580+
users.push(userModel.doc(user.id));
581+
});
582+
return users;
583+
} catch (err) {
584+
logger.error(`Error while fetching all users with tokens field: ${err}`);
585+
throw err;
586+
}
587+
};
588+
589+
const removeGitHubToken = async (users) => {
590+
try {
591+
const length = users.length;
592+
593+
let numberOfBatches = length / 500;
594+
const remainder = length % 500;
595+
596+
if (remainder) {
597+
numberOfBatches = numberOfBatches + 1;
598+
}
599+
600+
const batchArray = [];
601+
for (let i = 0; i < numberOfBatches; i++) {
602+
const batch = firestore.batch();
603+
batchArray.push(batch);
604+
}
605+
606+
let batchIndex = 0;
607+
let operations = 0;
608+
609+
for (let i = 0; i < length; i++) {
610+
batchArray[batchIndex].update(users[i], { tokens: admin.firestore.FieldValue.delete() });
611+
operations++;
612+
613+
if (operations === 500) {
614+
batchIndex++;
615+
operations = 0;
616+
}
617+
}
618+
619+
await Promise.all(batchArray.map(async (batch) => await batch.commit()));
620+
} catch (err) {
621+
logger.error(`Error while deleting tokens field: ${err}`);
622+
throw err;
623+
}
624+
};
575625
module.exports = {
576626
addOrUpdate,
577627
fetchPaginatedUsers,
@@ -592,4 +642,6 @@ module.exports = {
592642
getUserImageForVerification,
593643
getDiscordUsers,
594644
fetchAllUsers,
645+
fetchUsersWithToken,
646+
removeGitHubToken,
595647
};

routes/users.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ router.get("/self", authenticate, users.getSelfDetails);
1919
router.get("/isUsernameAvailable/:username", authenticate, users.getUsernameAvailabilty);
2020
router.get("/chaincode", authenticate, users.generateChaincode);
2121
router.get("/search", userValidator.validateUserQueryParams, users.filterUsers);
22+
router.patch("/remove-tokens", authenticate, authorizeRoles([SUPERUSER]), users.removeTokens);
23+
2224
router.get("/:username", users.getUser);
2325
router.get("/:userId/intro", authenticate, authorizeRoles([SUPERUSER]), users.getUserIntro);
2426
router.put("/self/intro", authenticate, userValidator.validateJoinData, users.addUserIntro);

test/integration/users.test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const { userPhotoVerificationData } = require("../fixtures/user/photo-verificati
3737
const Sinon = require("sinon");
3838
const { INTERNAL_SERVER_ERROR } = require("../../constants/errorMessages");
3939
const photoVerificationModel = firestore.collection("photo-verification");
40+
4041
chai.use(chaiHttp);
4142

4243
describe("Users", function () {
@@ -1502,4 +1503,31 @@ describe("Users", function () {
15021503
});
15031504
});
15041505
});
1506+
1507+
describe("PATCH /users/remove-tokens", function () {
1508+
before(async function () {
1509+
await addOrUpdate(userData[0]);
1510+
await addOrUpdate(userData[1]);
1511+
await addOrUpdate(userData[2]);
1512+
await addOrUpdate(userData[3]);
1513+
});
1514+
after(async function () {
1515+
await cleanDb();
1516+
});
1517+
it("should remove all the users with token field", function (done) {
1518+
chai
1519+
.request(app)
1520+
.patch("/users/remove-tokens")
1521+
.set("Cookie", `${cookieName}=${superUserAuthToken}`)
1522+
.end((err, res) => {
1523+
if (err) {
1524+
return done(err);
1525+
}
1526+
expect(res).to.have.status(200);
1527+
expect(res.body.message).to.be.equal("Github Token removed from all users!");
1528+
expect(res.body.usersFound).to.be.equal(3);
1529+
return done();
1530+
});
1531+
});
1532+
});
15051533
});

test/unit/models/users.test.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,41 @@ describe("users", function () {
220220
expect(data[0]).to.have.all.keys([...Object.keys(joinData[0]), "id"]);
221221
});
222222
});
223+
224+
describe("remove github token from users", function () {
225+
beforeEach(async function () {
226+
const addUsersPromises = [];
227+
userDataArray.forEach((user) => {
228+
addUsersPromises.push(userModel.add(user));
229+
});
230+
await Promise.all(addUsersPromises);
231+
});
232+
233+
afterEach(async function () {
234+
await cleanDb();
235+
});
236+
237+
it("return array of users", async function () {
238+
const data = await users.fetchUsersWithToken();
239+
expect(data).to.be.not.equal(null);
240+
});
241+
it('removes token field from user"s data', async function () {
242+
const userRef = await users.fetchUsersWithToken();
243+
const dataBefore = await userRef[1].get();
244+
const beforeRemoval = Object.keys(dataBefore.data()).includes("tokens");
245+
expect(beforeRemoval).to.be.equal(true);
246+
await users.removeGitHubToken(userRef);
247+
const dataAfter = await userRef[1].get();
248+
const afterRemoval = Object.keys(dataAfter.data()).includes("tokens");
249+
expect(afterRemoval).to.be.equal(false);
250+
});
251+
252+
it("throws error if id is not found in db", async function () {
253+
try {
254+
await users.removeGitHubToken("1223");
255+
} catch (error) {
256+
expect(error).to.be.instanceOf(Error);
257+
}
258+
});
259+
});
223260
});

0 commit comments

Comments
 (0)