-
Notifications
You must be signed in to change notification settings - Fork 273
GitHub duplication Fixed and Migration #1044
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 68 commits
5941bc5
5aad16d
7358662
0c2e8ce
0ee25fd
d54f16a
4e5aff3
9afcbd0
0fbfc9a
cc487d9
a5ca925
f01f146
558dd2d
adaf3cb
8d8232c
e88520b
2e0838b
65f4545
fcac418
a45e5c8
63cf7d0
45b2f3b
9ee96fc
0fb5eca
0d60558
7c6d7aa
e1e57a9
a481fb6
66b6e07
b25554d
75d682f
aa0f615
fa249fc
241df6a
88aaabd
7353c58
e56cd15
2bdff72
d59ae9e
d1b213c
eccbbd5
9c0fa42
f61ff70
7bcdb26
348ce2b
5247952
468b057
1f04c76
8e9414e
421c736
3d11b0b
20f0b3e
34f235c
ae3bfd8
9569688
5484294
d20932d
6d309e3
240ccb9
d0ed63c
c3bd1db
2dc68a5
e9a0819
ed2dfc3
7b57924
97f0959
0dfda95
b2c933e
8158773
31ad08a
708d57e
7f79193
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 |
---|---|---|
@@ -1,3 +1,5 @@ | ||
const axios = require("axios"); | ||
prakashchoudhary07 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const firestore = require("../utils/firestore"); | ||
const chaincodeQuery = require("../models/chaincodes"); | ||
const userQuery = require("../models/users"); | ||
const profileDiffsQuery = require("../models/profileDiffs"); | ||
|
@@ -593,6 +595,74 @@ const filterUsers = async (req, res) => { | |
} | ||
}; | ||
|
||
// one time script function to perform the migration - adding github_user_id field to the document | ||
const migrate = async (req, res) => { | ||
RitikJaiswal75 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
const usersNotFound = []; | ||
let countUserFound = 0; | ||
let countUserNotFound = 0; | ||
try { | ||
// Fetch user data from GitHub API for each document in the users collection | ||
// divided by 500 because firestore api guarantee that we can process in batch of 500. | ||
const usersSnapshot = await firestore.collection("users").get(); | ||
const totalUsers = usersSnapshot.docs.length; | ||
const batchCount = Math.ceil(totalUsers / 500); | ||
// Create batch write operations for each batch of documents | ||
for (let i = 0; i < batchCount; i++) { | ||
const batchDocs = usersSnapshot.docs.slice(i * 500, (i + 1) * 500); | ||
Comment on lines
+581
to
+584
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. rather than doing this why not directly fetch just 500 from db itself? something like paginated ones. 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. It will lead to extra reads on our database as in firestore it reads all the documents up from the startAt document id and also this is simpler in terms of code readability |
||
const batchWrite = firestore.batch(); | ||
const batchWrites = []; | ||
for (const userDoc of batchDocs) { | ||
const githubUsername = userDoc.data().github_id; | ||
const username = userDoc.data().username; | ||
const userId = userDoc.id; | ||
batchWrite.update(userDoc.ref, { github_user_id: null }); | ||
batchWrites.push( | ||
axios | ||
.get(`https://api.github.com/users/${githubUsername}`, { | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
auth: { | ||
username: config.get("githubOauth.clientId"), | ||
password: config.get("githubOauth.clientSecret"), | ||
}, | ||
}) | ||
.then((response) => { | ||
const githubUserId = response.data.id; | ||
batchWrite.update(userDoc.ref, { github_user_id: `${githubUserId}` }); | ||
countUserFound++; | ||
}) | ||
.catch((error) => { | ||
countUserNotFound++; | ||
const invalidUsers = { userId, username, githubUsername }; | ||
usersNotFound.push(invalidUsers); | ||
if (error.response && error.response.status === 404) { | ||
logger.error("GitHub user not found", error); | ||
} else { | ||
logger.error("An error occurred at axios.get:", error); | ||
} | ||
}) | ||
); | ||
} | ||
await Promise.all(batchWrites); | ||
heyrandhir marked this conversation as resolved.
Show resolved
Hide resolved
|
||
await batchWrite.commit(); | ||
} | ||
|
||
return res.status(200).json({ | ||
message: "Result of migration", | ||
data: { | ||
totalUsers: totalUsers, | ||
usersUpdated: countUserFound, | ||
usersNotUpdated: countUserNotFound, | ||
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 we are sending this i think we should add the reason as well for not updating. 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. There can be different reasons. So IMO, in such a case we can check our logs for the reason |
||
invalidUsersDetails: usersNotFound, | ||
}, | ||
}); | ||
} catch (error) { | ||
logger.error(`Error while Updating all users: ${error}`); | ||
return res.boom.badImplementation(INTERNAL_SERVER_ERROR); | ||
} | ||
}; | ||
|
||
const nonVerifiedDiscordUsers = async (req, res) => { | ||
const data = await userQuery.getDiscordUsers(); | ||
return res.json(data); | ||
|
@@ -626,6 +696,7 @@ module.exports = { | |
addDefaultArchivedRole, | ||
getUserSkills, | ||
filterUsers, | ||
migrate, | ||
verifyUserImage, | ||
getUserImageForVerification, | ||
nonVerifiedDiscordUsers, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
const githubUserInfo = require("../auth/githubUserInfo")(); | ||
|
||
/** | ||
* User info for GitHub auth response | ||
* Multiple responses can be added to the array if required | ||
* | ||
* @return {Object} | ||
*/ | ||
module.exports = () => { | ||
return [ | ||
{ | ||
username: "ankur", | ||
first_name: "Ankur", | ||
last_name: "Narkhede", | ||
yoe: 0, | ||
img: "./img.png", | ||
linkedin_id: "ankurnarkhede", | ||
github_id: githubUserInfo[0].username, | ||
github_display_name: githubUserInfo[0].displayName, | ||
isMember: true, | ||
phone: "1234567890", | ||
email: "[email protected]", | ||
roles: { | ||
member: true, | ||
}, | ||
tokens: { | ||
githubAccessToken: "githubAccessToken", | ||
}, | ||
status: "active", | ||
profileURL: "https://abcde.com", | ||
picture: { | ||
publicId: "profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar", | ||
url: "https://res.cloudinary.com/realdevsquad/image/upload/v1667685133/profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar.jpg", | ||
}, | ||
incompleteUserDetails: false, | ||
}, | ||
]; | ||
}; | ||
shubhamsinghbundela marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ module.exports = () => { | |
yoe: 0, | ||
img: "./img.png", | ||
linkedin_id: "ankurnarkhede", | ||
github_user_id: githubUserInfo[0].id, | ||
github_id: githubUserInfo[0].username, | ||
github_display_name: githubUserInfo[0].displayName, | ||
isMember: true, | ||
|
@@ -44,6 +45,7 @@ module.exports = () => { | |
last_name: "Bhandarkar", | ||
yoe: 0, | ||
img: "./img.png", | ||
github_user_id: "23654780", | ||
github_id: "whydonti", | ||
linkedin_id: "nikhil-bhandarkar", | ||
twitter_id: "whatifi", | ||
|
@@ -60,6 +62,7 @@ module.exports = () => { | |
last_name: "Gajjewar", | ||
yoe: 0, | ||
img: "./img.png", | ||
github_user_id: "23654788", | ||
github_id: "cartmanishere", | ||
linkedin_id: "pranav-gajjewar", | ||
twitter_id: "PGajjewar", | ||
|
@@ -80,6 +83,7 @@ module.exports = () => { | |
yoe: 3, | ||
img: "./img.png", | ||
linkedin_id: "sagarbajpai", | ||
github_user_id: "23654790", | ||
github_id: "sagarbajpai", | ||
github_display_name: "Sagar Bajpai", | ||
phone: "1234567890", | ||
|
@@ -105,6 +109,7 @@ module.exports = () => { | |
yoe: 10, | ||
img: "./img.png", | ||
linkedin_id: "ankushdharkar", | ||
github_user_id: "23654700", | ||
github_id: "ankushdharkar", | ||
github_display_name: "Ankush Dharkar", | ||
phone: "1234567890", | ||
|
@@ -131,6 +136,7 @@ module.exports = () => { | |
yoe: 0, | ||
img: "./img.png", | ||
linkedin_id: "ankitabannore", | ||
github_user_id: "23654725", | ||
github_id: "Ankita2002-Fr", | ||
github_display_name: "Ankita Bannore", | ||
isMember: true, | ||
|
@@ -155,6 +161,7 @@ module.exports = () => { | |
last_name: "Chaudhari", | ||
yoe: 0, | ||
img: "./img.png", | ||
github_user_id: "23654583", | ||
github_id: "mehulkchaudhari", | ||
linkedin_id: "mehulkchaudhari", | ||
twitter_id: "mehulkchaudhari", | ||
|
@@ -180,6 +187,7 @@ module.exports = () => { | |
yoe: 0, | ||
img: "./img.png", | ||
linkedin_id: "ankurnarkhede", | ||
github_user_id: "23654236", | ||
github_id: "ankur1234", | ||
github_display_name: "ankur-xyz", | ||
phone: "1234567890", | ||
|
@@ -188,6 +196,7 @@ module.exports = () => { | |
{ | ||
username: "ritvik", | ||
github_id: "RitvikJamwal75", | ||
github_user_id: "23654123", | ||
first_name: "Ritvik", | ||
yoe: 1, | ||
picture: { | ||
|
@@ -218,6 +227,7 @@ module.exports = () => { | |
linkedin_id: "tanishqsingla", | ||
github_id: "tanishqsingla", | ||
github_display_name: "Tanishq Singla", | ||
github_user_id: "26207583", | ||
phone: "1234567890", | ||
email: "[email protected]", | ||
tokens: { | ||
|
@@ -240,6 +250,7 @@ module.exports = () => { | |
linkedin_id: "darthvader", | ||
github_id: "darthvader", | ||
github_display_name: "Darth Vader", | ||
github_user_id: "3188964", | ||
phone: "1234567890", | ||
email: "[email protected]", | ||
tokens: { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
const chai = require("chai"); | ||
const axios = require("axios"); | ||
const { expect } = chai; | ||
const chaiHttp = require("chai-http"); | ||
|
||
shubham-y marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
@@ -26,6 +27,7 @@ const userStatusModel = require("../../models/userStatus"); | |
|
||
const cookieName = config.get("userToken.cookieName"); | ||
const { userPhotoVerificationData } = require("../fixtures/user/photo-verification"); | ||
const githubUserInfo = require("../fixtures/auth/githubUserInfo")(); | ||
const Sinon = require("sinon"); | ||
const { INTERNAL_SERVER_ERROR } = require("../../constants/errorMessages"); | ||
const photoVerificationModel = firestore.collection("photo-verification"); | ||
|
@@ -1229,4 +1231,80 @@ describe("Users", function () { | |
}); | ||
}); | ||
}); | ||
|
||
describe("POST /users/migrate", function () { | ||
let fetchStub; | ||
|
||
beforeEach(async function () { | ||
fetchStub = Sinon.stub(axios, "get"); | ||
}); | ||
|
||
afterEach(async function () { | ||
Sinon.restore(); | ||
}); | ||
|
||
it("Should update the user", async function () { | ||
|
||
fetchStub.resolves({ | ||
data: githubUserInfo[0]._json, | ||
}); | ||
const usersMigrateResponse = await chai | ||
.request(app) | ||
.post(`/users/migrate`) | ||
shubham-y marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.set("Cookie", `${cookieName}=${superUserAuthToken}`); | ||
expect(usersMigrateResponse).to.have.status(200); | ||
expect(usersMigrateResponse.body).to.eql({ | ||
|
||
message: "Result of migration", | ||
data: { | ||
totalUsers: 2, | ||
usersUpdated: 2, | ||
usersNotUpdated: 0, | ||
invalidUsersDetails: [], | ||
}, | ||
}); | ||
const usersResponse = await chai.request(app).get(`/users`).set("cookie", `${cookieName}=${superUserAuthToken}`); | ||
expect(usersResponse).to.have.status(200); | ||
usersResponse.body.users.forEach((document) => { | ||
expect(document).to.have.property(`github_user_id`); | ||
iamYashSinha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
}); | ||
it("Should return details of users with invalid github username", async function () { | ||
fetchStub.rejects({ response: { status: 404 } }); | ||
RitikJaiswal75 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const usersMigrateResponse = await chai | ||
.request(app) | ||
.post(`/users/migrate`) | ||
.set("Cookie", `${cookieName}=${superUserAuthToken}`); | ||
expect(usersMigrateResponse).to.have.status(200); | ||
expect(usersMigrateResponse.body.message).to.be.equal("Result of migration"); | ||
expect(usersMigrateResponse.body).to.have.property("data"); | ||
expect(usersMigrateResponse.body.data).to.have.property("totalUsers"); | ||
expect(usersMigrateResponse.body.data.totalUsers).to.be.equal(2); | ||
expect(usersMigrateResponse.body.data).to.have.property("usersUpdated"); | ||
expect(usersMigrateResponse.body.data.usersUpdated).to.be.equal(0); | ||
expect(usersMigrateResponse.body.data).to.have.property("usersNotUpdated"); | ||
expect(usersMigrateResponse.body.data.usersNotUpdated).to.be.equal(2); | ||
expect(usersMigrateResponse.body.data).to.have.property("invalidUsersDetails"); | ||
usersMigrateResponse.body.data.invalidUsersDetails.forEach((document) => { | ||
expect(document).to.have.property("userId"); | ||
expect(document).to.have.property("username"); | ||
expect(document).to.have.property("githubUsername"); | ||
}); | ||
}); | ||
it("Should return unauthorized error when not logged in", function (done) { | ||
chai | ||
.request(app) | ||
.post(`/users/migrate`) | ||
.end((err, res) => { | ||
if (err) { | ||
return done(err); | ||
} | ||
expect(res).to.have.status(401); | ||
expect(res.body).to.eql({ | ||
statusCode: 401, | ||
error: "Unauthorized", | ||
message: "Unauthenticated User", | ||
}); | ||
return done(); | ||
}); | ||
}); | ||
}); | ||
}); |
Uh oh!
There was an error while loading. Please reload this page.