Skip to content

Commit

Permalink
Validate user permissions again
Browse files Browse the repository at this point in the history
Fixes #64
  • Loading branch information
violine1101 committed Oct 23, 2022
1 parent 8bcb6fe commit a6b6e2f
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 17 deletions.
1 change: 1 addition & 0 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"src/content/dropdown.js",
"src/content/postpone.js",
"src/content/sorting.js",
"src/content/permissionCheck.js",
"src/content/content.js"
]
}],
Expand Down
19 changes: 19 additions & 0 deletions src/background/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ import { reportError } from '../util/errorReporting.js';
import { getMessages, triggerMessageUpdate } from '../util/messages.js';
import { getCustomSortIndex, getPostponeAction, getPrefix, setCustomSortIndex, setPopupMessage } from '../util/storage.js';

/**
* @type {{
* user?: string;
* value: boolean;
* }}
*/
let permissionCache = {
user: undefined,
value: false,
};

(async () => {
await setPopupMessage(undefined);

Expand All @@ -26,6 +37,14 @@ import { getCustomSortIndex, getPostponeAction, getPrefix, setCustomSortIndex, s
case 'set-custom-sort-index':
await setCustomSortIndex(message.index);
return;
case 'get-permission-cache':
return permissionCache;
case 'set-permission-cache':
permissionCache = {
user: message.user,
value: message.value
};
return;
case 'show-error':
console.error(`Received error message: ${message.errorMessage}`);
await showErrorBadge(message.errorMessage);
Expand Down
9 changes: 7 additions & 2 deletions src/content/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ function init() {
modifyWikifield(
element,
element.getAttribute('issue-key').split('-')[0].toLowerCase(),
editorCount++,
!isVolunteerUser()
editorCount++
);
} catch (error) {
await sendErrorMessage(error);
Expand Down Expand Up @@ -49,6 +48,12 @@ function init() {
}

(async () => {
try {
userIsVolunteer = await queryPermissions();
} catch (error) {
await sendErrorMessage(error);
}

try {
const messagesReply = await browser.runtime.sendMessage({ id: 'messages-request' });
categories = messagesReply.categories;
Expand Down
5 changes: 4 additions & 1 deletion src/content/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ function getMessageButton(editorCount, disabled) {
* @param {HTMLTextAreaElement} textArea The text area that this dropdown is for
* @param {string} project The project the current ticket is in
* @param {number} editorCount A unique identifier for this wikifield
* @param {disabled} disabled Whether the dropdown button is disabled
*
* @returns {boolean} Whether the dropdown could be successfully added
*/
Expand Down Expand Up @@ -206,7 +207,9 @@ function addDropdownToWikifield(element, textArea, project, editorCount, disable
* @param {string} project The project the current ticket is in
* @param {number} editorCount A unique identifier for this wikifield
*/
function modifyWikifield(element, project, editorCount, disabled) {
function modifyWikifield(element, project, editorCount) {
const disabled = !userIsVolunteer;

element.classList.add('mojira-helper-messages-field');

var textArea = element.querySelector('textarea');
Expand Down
84 changes: 84 additions & 0 deletions src/content/permissionCheck.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const permissionCheckError = 'An error occurred while trying to validate Mojira permissions.\n';

/**
* Parses the JSON response and checks if the currently logged-in user is in a user group other than `users`.
* @param {string} response The API response, hopefully in JSON format
*
* @returns {boolean} whether the user is in at least one non-`users` group
* @throws {string} if there's no valid JSON or the JSON does not follow the API scheme.
*/
function parsePermissionResponse(response) {
try {
const json = JSON.parse(response);

const groups = json.groups?.items;
if (!groups) throw 'The API response is malformed and does not include groups.';

return groups.filter(group => group.name !== 'users').length > 0;
} catch (error) {
if (error instanceof SyntaxError) {
throw `${permissionCheckError}The server returned invalid JSON: ${error.message}`;
} else {
throw `${permissionCheckError}${error}`;
}
}
}

/**
* Checks if the currently logged in user is a volunteer user (moderator / helper).
*
* @returns {Promise<boolean>} true is the logged in user is a helper+, false otherwise.
* @throws {string} if an error occurs
*/
function queryPermissions() {
return new Promise(async (resolve, reject) => {
const httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = async () => {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
try {
const perm = parsePermissionResponse(httpRequest.responseText);
resolve(perm);
} catch (error) {
reject(error);
}
}
reject(
`${permissionCheckError}The server returned status code ${httpRequest.status} ${httpRequest.statusText}.`
);
}
}

try {
httpRequest.open('GET', 'https://bugs.mojang.com/rest/api/2/myself?expand=groups');
httpRequest.send();
} catch (error) {
reject(`${permissionCheckError}${error}`);
}
});
}

/**
* Checks if the currently logged in user is a volunteer user (moderator / helper).
* Uses the value from the cache unless the user name has changed.
*
* @returns {Promise<boolean>} true if the logged in user is a helper+, false otherwise.
* @throws {string} if an error occurr.
*/
async function validatePermissions() {
const userName = document.querySelector('meta[name=ajs-remote-user]')?.attributes?.getNamedItem('content')?.value;

if (!userName) {
await browser.runtime.sendMessage({ id: 'set-permission-cache', user: undefined, value: false });
return false;
}

const permissionCache = await browser.runtime.sendMessage({ id: 'get-permission-cache' });
if (permissionCache.user === userName) {
return permissionCache.value;
}

const userPermissions = queryPermissions();
await browser.runtime.sendMessage({ id: 'set-permission-cache', user: userName, value: userPermissions });
return userPermissions;
}
5 changes: 0 additions & 5 deletions src/content/styling.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
border-radius: 0 !important;
}

.mojira-helper-messages-textarea-disabled {
border: 1px solid #cc2e2e !important;
border-radius: 0 !important;
}

.mojira-helper-messages-textarea-shortcut-only {
border: 1px solid #cc722e !important;
}
Expand Down
9 changes: 0 additions & 9 deletions src/content/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,3 @@ async function sendErrorMessage(error) {
console.error('Error while reporting error message:', err);
}
}

/**
* Checks if the currently logged in user is a volunteer user (moderator / helper), only works on issue pages
* @returns {Boolean} true if the logged in user is a helper+, false otherwise
*/
function isVolunteerUser() {
let opsbar = document.querySelector('div#opsbar-opsbar-transitions');
return opsbar && opsbar.children.length > 0;
}
3 changes: 3 additions & 0 deletions src/content/vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,6 @@ let postponeAction = 'none';

/** @type {number} */
let customSortIndex = 0;

/** @type {boolean} */
let userIsVolunteer = false;

0 comments on commit a6b6e2f

Please sign in to comment.