diff --git a/scripts/downgrade-users/README.md b/scripts/downgrade-users/README.md new file mode 100644 index 0000000000..d3a5560b33 --- /dev/null +++ b/scripts/downgrade-users/README.md @@ -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`. diff --git a/scripts/downgrade-users/downgradeUsers.js b/scripts/downgrade-users/downgradeUsers.js new file mode 100644 index 0000000000..fb733649ec --- /dev/null +++ b/scripts/downgrade-users/downgradeUsers.js @@ -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)); diff --git a/scripts/downgrade-users/example.csv b/scripts/downgrade-users/example.csv new file mode 100644 index 0000000000..f1ec6cf5a1 --- /dev/null +++ b/scripts/downgrade-users/example.csv @@ -0,0 +1,3 @@ +userId,displayName,userName,totalCount,affiliationId,permission,organizationId,acronym,name,slug +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