Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions scripts/downgrade-users/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Use in Chromium-based browsers (Chrome, Edge, etc.):
1. Open the console (F12)
2. Copy the code from the file `downgradeUsers.js` and paste it into the console
3. Enter auth token into `AUTH_TOKEN`. The token can be obtained from a Tracker browser request. Log into Tracker, open the console (F12), go to the Network tab, refresh the page, find the latest request with the name `graphql`, go to the Headers tab, copy the value of the `Authorization` header.
4. Enter the URI for the Tracker instance into `TRACKER_URI`
5. Press Enter
6. Wait for the script to finish
7. Enjoy

CSV file format given in the example file `example.csv`.
102 changes: 102 additions & 0 deletions scripts/downgrade-users/downgradeUsers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
const AUTH_TOKEN = "";
const TRACKER_GRAPHQL_URI = "";

if (!AUTH_TOKEN) {
console.error("You must enter your auth token!");
}

if (!TRACKER_GRAPHQL_URI) {
console.error("You must enter the Tracker graphql URI!");
}

const csv2json = (str, delimiter = ",") => {
const titles = str
.slice(0, str.indexOf("\n"))
.replace(/["']/g, "")
.split(delimiter)
.map((str) => str.trim());
const rows = str.slice(str.indexOf("\n") + 1).split("\n");
return rows.map((row) => {
const values = row.split(delimiter);
return titles.reduce((object, curr, i) => {
object[curr] = values[i].replace(/["']/g, "").trim();
return object;
}, {});
});
};

const changeUserRole = async ({ email, role = "USER", orgId }) => {
const res = await fetch(TRACKER_GRAPHQL_URI, {
body: JSON.stringify({
query: `mutation {
updateUserRole(input: {
userName: "${email}",
role: ${role},
orgId: "${orgId}",
}) {
result {
...on UpdateUserRoleResult {
status
}
...on AffiliationError {
code
description
}
__typename
}
}
}`,
}),
headers: {
Accept: "application/json",
Authorization: AUTH_TOKEN,
"Content-Type": "application/json",
},
method: "POST",
});

return await res.json();
};

const [fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const content = (await file.text()).trim();
const downgradeUserList = csv2json(content, ",");

for await (const [key, val] of downgradeUserList.entries()) {
try {
const updateRoleRes = await changeUserRole({ email: val.userName, orgId: val.organizationId, role: "USER" });
if (updateRoleRes.data.updateUserRole.result["__typename"] === "AffiliationError") {
console.error(
`Error while updating "${val.email}" permission for organization "${val.organizationId}" to "USER": `,
val
);
downgradeUserList[key].success = false;
downgradeUserList[key].error = updateRoleRes.data.updateUserRole.result.description;
continue;
}
} catch (e) {
console.error(
`Error while updating "${val.email}" permission for organization "${val.organizationId}" to "USER": `,
val
);
downgradeUserList[key].success = false;
downgradeUserList[key].error = e;
}
downgradeUserList[key].success = true;
console.log(
`Successfully changed "${val.email}" permission for organization "${val.organizationId}" to "USER": `,
val
);
}

for (const val of downgradeUserList) {
if (val.error) {
console.error(
`Error while updating "${val.email}" permission for organization "${val.organizationId}" to "USER": `,
val
);
}
}

console.table(downgradeUserList.filter((val) => val.success === false));
3 changes: 3 additions & 0 deletions scripts/downgrade-users/example.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
userId,displayName,userName,totalCount,affiliationId,permission,organizationId,acronym,name,slug

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like in the script we're only using the orgId and userName values. Are the other headers necessary?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, not required for the script. The other stuff is there since that's the info we took from the export and it might be easier to vet with the extra columns. We can remove from example.csv no problem

exampleIdqd2a=,example name ,example1@example.com,2,e21e12eaw,ADMIN,2e21e12e,EO,Example Org,example-org
exampleIdqd2a=,example name ,example1@example.com,2,e21e12eaw,ADMIN,anrk30a=,AEO,Another Example,another-example