You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

149 lines
4.7 KiB

// ==UserScript==
// @name kood.tech QOL
// @description Buttons for managing auditor repository read access from intra
// @match https://01.kood.tech/*
// @grant none
// @version 1.2
// @author spitko
// ==/UserScript==
const api = "/git/api/v1/";
function insertToggleAccessButton(auditorElement) {
auditorElement.dataset.processed = true;
let username = auditorElement.querySelector(".ellipsis-01").innerText;
hasAccess(username).then((access) => {
let button = document.createElement("button");
button.textContent = access ? "✅" : "❌";
button.onclick = function (e, newAccess) {
if (e) {
e.preventDefault();
}
const shouldGrantAccess =
newAccess !== undefined ? newAccess : button.textContent !== "✅";
if ((button.textContent === "✅") === shouldGrantAccess) {
return;
}
if (shouldGrantAccess) {
grantAccess(username).then(() => {
button.textContent = "✅";
});
} else {
revokeAccess(username).then(() => {
button.textContent = "❌";
});
}
};
button.className = "ml2-01 repo-access-button";
auditorElement.firstChild.insertAdjacentElement("beforeend", button);
});
}
function insertToggleAllButtons(auditRequired) {
let div = document.createElement("div");
div.innerText = "Grant/revoke read access for all auditors: ";
div.className = "mt3-01";
let grantButton = document.createElement("button");
grantButton.textContent = "✅";
grantButton.onclick = function () {
document.querySelectorAll(".repo-access-button").forEach((button) => {
button.onclick(false, true);
});
};
div.appendChild(grantButton);
let revokeButton = document.createElement("button");
revokeButton.textContent = "❌";
revokeButton.className = "ml1-01";
revokeButton.onclick = function () {
document.querySelectorAll(".repo-access-button").forEach((button) => {
button.onclick(false, false);
});
};
div.appendChild(revokeButton);
auditRequired.parentNode.insertAdjacentElement("beforeend", div);
auditRequired.dataset.processed = true;
}
async function hasAccess(username) {
const res = await fetch(
api + `repos/${getRepo()}/collaborators/${username}`,
{ headers: { Authorization: `token ${getToken()}` } }
);
return res.ok;
}
async function grantAccess(username) {
return await fetch(api + `repos/${getRepo()}/collaborators/${username}`, {
headers: {
Authorization: `token ${getToken()}`,
"Content-Type": "application/json",
},
method: "PUT",
body: `{"permission": "read"}`,
});
}
async function revokeAccess(username) {
return await fetch(api + `repos/${getRepo()}/collaborators/${username}`, {
headers: { Authorization: `token ${getToken()}` },
method: "DELETE",
});
}
function getToken() {
return localStorage.getItem("token");
}
function getRepo() {
let repoURL = document.querySelector('a[data-test="repoLink"]').innerText;
return repoURL.match(/\/git\/(.+)$/)[1];
}
const observer = new MutationObserver(function (mutations) {
mutations.forEach((mutation) => {
if (mutation.type === "childList") {
mutation.target
.querySelectorAll('[data-test="audit"]:not([data-processed])')
.forEach((elem) => {
insertToggleAccessButton(elem);
});
mutation.target
.querySelectorAll('[data-test="auditRequired"]:not([data-processed])')
.forEach((elem) => {
insertToggleAllButtons(elem);
});
mutation.target
.querySelectorAll("#verificationCode-01:not([data-processed])")
.forEach((elem) => {
let input = elem.querySelector("input");
input.addEventListener("keyup", function (event) {
if (event.keyCode === 13) {
document
.querySelectorAll(`input[value="true"]`)
.forEach((elem) => elem.click());
document.querySelector("#submit-btn").click();
}
});
elem.dataset.processed = true;
});
}
});
});
if (getToken()) {
observer.observe(document.body, { childList: true, subtree: true });
}
// Add button for saving token to localStorage
// https://01.kood.tech/git/user/settings/applications
if (location.href.match(/git\/user\/settings\/applications/)) {
const tokenDiv = document.querySelector("div.ui.info.message.flash-info");
const button = document.createElement("button");
button.textContent = "Save to localStorage";
button.className = "ui button";
button.onclick = function () {
localStorage.setItem("token", tokenDiv.firstElementChild.innerText);
alert("Token saved!");
};
tokenDiv.insertAdjacentElement("beforeend", button);
}