-
Notifications
You must be signed in to change notification settings - Fork 277
Feature/one time user colors #735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 18 commits
2fed9ad
0f505b7
cd2c96d
5bd0f9a
5e4f75a
04c43e7
964dd56
0f65a11
146304a
01c8138
7a75444
54c94ce
f4d60d3
64f56cc
b210076
804c64c
b2c9c3c
b495022
807df54
2ecedb5
4b0df82
cc10b82
b8c7521
231cbef
48f6ef3
f322598
018f829
62fb581
542d504
7e0d00a
a522f0f
c723578
d76b090
c87fe9c
6aaafd7
c2151cd
0852243
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| const firestore = require("../utils/firestore"); | ||
| const userQuery = require("../models/userMigrations"); | ||
| const logger = require("../utils/logger"); | ||
| const { getRandomIndex } = require("../utils/helpers"); | ||
| const USER_COLORS = 10; | ||
| const MAX_TRANSACTION_WRITES = 499; | ||
heyrandhir marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| /** | ||
| * Returns the lists of usernames where default colors were added | ||
| * | ||
| * @param req {Object} - Express request object | ||
| * @param res {Object} - Express response object | ||
| */ | ||
|
|
||
| const addDefaultColors = async (req, res) => { | ||
| try { | ||
| const { usersArr, userModel } = await userQuery.addDefaultColors(); | ||
|
|
||
| const batchArray = []; | ||
| const users = []; | ||
| batchArray.push(firestore.batch()); | ||
| let operationCounter = 0; | ||
| let batchIndex = 0; | ||
| let totalCount = 0; | ||
|
|
||
| for (const user of usersArr) { | ||
| const colors = user.colors ?? {}; | ||
| if (user.colors === undefined) { | ||
isVivek99 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const userColorIndex = getRandomIndex(USER_COLORS); | ||
| colors.color_id = userColorIndex; | ||
| const docId = userModel.doc(user.id); | ||
| batchArray[parseInt(batchIndex)].set(docId, { ...user, colors }); | ||
isVivek99 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| operationCounter++; | ||
| totalCount++; | ||
| users.push(user.username); | ||
| if (operationCounter === MAX_TRANSACTION_WRITES) { | ||
| batchArray.push(firestore.batch()); | ||
| batchIndex++; | ||
| operationCounter = 0; | ||
| } | ||
| } | ||
| } | ||
| batchArray.forEach(async (batch) => await batch.commit()); | ||
heyrandhir marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
heyrandhir marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| return res.json({ | ||
| message: "User colors updated successfully!", | ||
| usersDetails: { count: totalCount, users }, | ||
| }); | ||
heyrandhir marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } catch (error) { | ||
| logger.error(`Error adding default colors to users: ${error}`); | ||
| return res.boom.badImplementation("Something went wrong. Please contact admin"); | ||
| } | ||
| }; | ||
|
|
||
| module.exports = { | ||
| addDefaultColors, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| const firestore = require("../utils/firestore"); | ||
| const userModel = firestore.collection("users"); | ||
|
|
||
| /** | ||
| * Adds default colors property | ||
| * @return {Promise<usersMigrated|Object>} | ||
heyrandhir marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| */ | ||
|
|
||
| const addDefaultColors = async () => { | ||
isVivek99 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| try { | ||
| const usersSnapshot = await userModel.get(); | ||
| const usersArr = []; | ||
|
||
|
|
||
| usersSnapshot.forEach((doc) => usersArr.push({ id: doc.id, ...doc.data() })); | ||
|
|
||
| return { usersArr, userModel }; | ||
heyrandhir marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } catch (err) { | ||
| logger.error("Error adding default colors to users", err); | ||
| throw err; | ||
| } | ||
| }; | ||
|
|
||
| module.exports = { | ||
| addDefaultColors, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ app.use("/users/status", require("./userStatus.js")); | |
| app.use("/users", require("./users.js")); | ||
| app.use("/profileDiffs", require("./profileDiffs.js")); | ||
| app.use("/wallet", require("./wallets.js")); | ||
| app.use("/migrations", require("./userMigrations.js")); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you are aware @ankushdharkar has strongly advised against approving pull requests that don't adhere to the correct naming convention. As https://discord.com/channels/673083527624916993/729399523268624405/1141334143867822081 |
||
| app.use("/extension-requests", require("./extensionRequests")); | ||
| app.use("/tags", require("./tags.js")); | ||
| app.use("/levels", require("./levels.js")); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| const express = require("express"); | ||
| const router = express.Router(); | ||
| const authenticate = require("../middlewares/authenticate"); | ||
| const authorizeRoles = require("../middlewares/authorizeRoles"); | ||
| const { SUPERUSER } = require("../constants/roles"); | ||
| const migrations = require("../controllers/userMigrations"); | ||
|
|
||
| router.patch("/addDefaultColorProperty", authenticate, authorizeRoles([SUPERUSER]), migrations.addDefaultColors); | ||
|
||
|
|
||
| module.exports = router; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -144,6 +144,9 @@ module.exports = () => { | |
| app_owner: true, | ||
| archived: true, | ||
| }, | ||
| colors: { | ||
| color_id: 2, | ||
isVivek99 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }, | ||
|
||
| picture: { | ||
| publicId: "profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar", | ||
| url: "https://res.cloudinary.com/realdevsquad/image/upload/v1667685133/profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar.jpg", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| const chai = require("chai"); | ||
| const { expect } = chai; | ||
| const chaiHttp = require("chai-http"); | ||
|
|
||
| const app = require("../../server"); | ||
| const authService = require("../../services/authService"); | ||
| const addUser = require("../utils/addUser"); | ||
| const cleanDb = require("../utils/cleanDb"); | ||
| // Import fixtures | ||
| const userData = require("../fixtures/user/user")(); | ||
| const superUser = userData[4]; | ||
| const nonSuperUser = userData[0]; | ||
| const userWithColorProperty = [userData[5].username]; | ||
| const colorBearingUsernames = [superUser.username, nonSuperUser.username]; | ||
isVivek99 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| const config = require("config"); | ||
| const cookieName = config.get("userToken.cookieName"); | ||
|
|
||
| chai.use(chaiHttp); | ||
|
|
||
| describe("userColorMigrations", function () { | ||
| let superUserId; | ||
| let superUserAuthToken; | ||
| let userId = ""; | ||
| let nonSuperUserId = ""; | ||
| beforeEach(async function () { | ||
| userId = await addUser(); | ||
| superUserId = await addUser(superUser); | ||
| nonSuperUserId = userId; | ||
| superUserAuthToken = authService.generateAuthToken({ userId: superUserId }); | ||
| }); | ||
|
|
||
| afterEach(async function () { | ||
| await cleanDb(); | ||
| }); | ||
|
|
||
| describe("PATCH /migrations/addDefaultColorProperty", function () { | ||
| it("Should return 401 if user is not a super user", function (done) { | ||
| const nonSuperUserJwt = authService.generateAuthToken({ userId: nonSuperUserId }); | ||
| chai | ||
| .request(app) | ||
| .patch(`/migrations/addDefaultColorProperty`) | ||
| .set("cookie", `${cookieName}=${nonSuperUserJwt}`) | ||
| .end((err, res) => { | ||
| if (err) { | ||
| return done(err); | ||
| } | ||
| expect(res).to.have.status(401); | ||
| expect(res.body).to.be.a("object"); | ||
| expect(res.body.message).to.equal("You are not authorized for this action."); | ||
| return done(); | ||
| }); | ||
| }); | ||
| it("Should add default color property to all users,using authorized user (super_user)", function (done) { | ||
| chai | ||
| .request(app) | ||
| .patch(`/migrations/addDefaultColorProperty`) | ||
| .set("cookie", `${cookieName}=${superUserAuthToken}`) | ||
| .end((err, res) => { | ||
| if (err) { | ||
| return done(err); | ||
| } | ||
|
|
||
| expect(res).to.have.status(200); | ||
| expect(res.body.usersDetails.count).to.be.equal(colorBearingUsernames.length); | ||
| const migratedUsernames = res.body.usersDetails.users; | ||
| expect(migratedUsernames).to.include( | ||
| colorBearingUsernames[0], | ||
| "Should add default color property to user without color property" | ||
| ); | ||
|
|
||
| expect(migratedUsernames).to.not.include.any.members( | ||
| userWithColorProperty, | ||
| "Should not modify color property of user with color object" | ||
| ); | ||
| return done(); | ||
| }); | ||
| }); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| /** | ||
| * Returns a random object from the array of colors to user | ||
| * @param array {array} : array containing objects | ||
| * @returns random Index number : index between the range 0 to array.length | ||
| */ | ||
| const getRandomIndex = (arrayLength = 10) => { | ||
heyrandhir marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
heyrandhir marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return Math.floor(Math.random() * arrayLength); | ||
| }; | ||
heyrandhir marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| module.exports = { | ||
| getRandomIndex, | ||
| }; | ||
Uh oh!
There was an error while loading. Please reload this page.