Skip to content

Enterprise support #24

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
26 changes: 26 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
"version": "1.0.0",
"description": "Show github contributor's stats (# of Issues/PRs)",
"main": "index.js",
"dependencies": {},
"dependencies": {
"webext-domain-permission-toggle": "0.0.2",
"webext-dynamic-content-scripts": "^5.0.1"
},
"devDependencies": {
"chrome-webstore-upload-cli": "^1.0.3"
},
Expand Down
6 changes: 5 additions & 1 deletion src/background.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/* global chrome */
/* global chrome DCE DCS */

// GitHub Enterprise support
DCE.addContextMenu();
DCS.addToFutureTabs();

// launch options page on first run
chrome.runtime.onInstalled.addListener((details) => {
Expand Down
18 changes: 13 additions & 5 deletions src/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ const getCurrentUser = () => $(".js-menu-target img").attr("alt").slice(1) || ""
const isPrivate = () => $(".label-private").length > 0;
let statsScope = "repo";

const isEnterprise = window.location.hostname !== 'github.com';
const githubURLBase = isEnterprise ? `${window.location.hostname}/api/v3` : 'api.github.com';
const githubURL = `https://${githubURLBase}`;

function getContributor() {
let $contributor = $(".timeline-comment-wrapper .timeline-comment-header-text strong a");
if ($contributor.length) {
Expand Down Expand Up @@ -71,10 +75,10 @@ function contributorCount({access_token, contributor, user, repoPath, old = {},
repo = undefined;
repoPath = "__self";
}

let searchURL = buildUrl({
access_token,
base: "https://api.github.com/search/issues",
base: `${githubURL}/search/issues`,
order: "asc",
per_page: "1",
q: {
Expand Down Expand Up @@ -330,11 +334,15 @@ function update({ contributor, repoPath, currentNum, user }) {
if (storageRes.prs || storageRes.issues) {
updateTextNodes(appendPRText(currentNum, storageRes));
} else {
getSyncStorage({ "access_token": null })
const token = isEnterprise ? "enterprise_access_token" : "access_token";

getSyncStorage({ [token]: null })
.then((res) => {
const access_token = isEnterprise ? res.enterprise_access_token : res.access_token;

Promise.all([
contributorCount({ old: storageRes, user, access_token: res.access_token, type: "pr", contributor, repoPath}),
contributorCount({ old: storageRes, user, access_token: res.access_token, type: "issue", contributor, repoPath})
contributorCount({ old: storageRes, user, access_token, type: "pr", contributor, repoPath}),
contributorCount({ old: storageRes, user, access_token, type: "issue", contributor, repoPath})
])
.then(([prInfo, issueInfo]) => {
let repoInfo = Object.assign(prInfo, issueInfo);
Expand Down
10 changes: 9 additions & 1 deletion src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,19 @@
"permissions": [
"https://github.com/*/*",
"storage",
"identity"
"identity",
"contextMenus",
"activeTab"
],
"optional_permissions": [
"http://*/*",
"https://*/*"
],
"background": {
"persistent": false,
"scripts": [
"vendor/webext-domain-permission-toggle.js",
"vendor/webext-dynamic-content-scripts.js",
"background.js"
]
},
Expand Down
2 changes: 2 additions & 0 deletions src/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ <h5>Github's Search API Rate Limit</h5>
</p>
<h1>Access Token</h1>
<input type="text" id="token-input" placeholder="Paste your access token here">
<h1>Enterprise Access Token</h1>
<input type="text" id="enterprise-token-input" placeholder="Paste your enterprise access token here">
<p id="feedback"></p>
</section>
<section>
Expand Down
13 changes: 10 additions & 3 deletions src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,35 @@

document.addEventListener("DOMContentLoaded", () => {
const accessTokenInput = document.getElementById("token-input");
const enterpriseAccessTokenInput = document.getElementById("enterprise-token-input");
const oauthLink = document.getElementById("use-oauth");
const clearCacheLink = document.getElementById("clear-cache");
const showPrivateReposInput = document.getElementById("show-private-repos");

getSyncStorage({ "access_token": null, "_showPrivateRepos": null })
.then(({ access_token, _showPrivateRepos }) => {
getSyncStorage({ "access_token": null, "enterprise_access_token": null, "_showPrivateRepos": null })
.then(({ access_token, enterprise_access_token, _showPrivateRepos }) => {
if (access_token) accessTokenInput.value = access_token;
if (enterprise_access_token) enterpriseAccessTokenInput.value = enterprise_access_token;
if (_showPrivateRepos) showPrivateReposInput.checked = _showPrivateRepos;
});

accessTokenInput.addEventListener("change", () => {
setSyncStorage({ "access_token": accessTokenInput.value });
});

enterpriseAccessTokenInput.addEventListener("change", () => {
setSyncStorage({ "enterprise_access_token": enterpriseAccessTokenInput.value });
});

oauthLink.addEventListener("click", () => {
getTokenFromOauth();
});

clearCacheLink.addEventListener("click", () => {
let temp = accessTokenInput.value;
let temp2 = enterpriseAccessTokenInput.value;
chrome.storage.sync.clear(() => {
setSyncStorage({ "access_token": temp });
setSyncStorage({ "access_token": temp, "enterprise_access_token": temp2 });
document.querySelector("#feedback").textContent = "Storage Cleared";
});
});
Expand Down
49 changes: 49 additions & 0 deletions src/vendor/webext-domain-permission-toggle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// https://github.com/bfred-it/webext-domain-permission-toggle

const DCE = {
addContextMenu(options) {
const contextMenuId = 'webext-domain-permission-toggle:add-permission';

const {name: extensionName} = chrome.runtime.getManifest();

options = Object.assign({
title: `Enable ${extensionName} on this domain`,
reloadOnSuccess: `Do you want to reload this page to apply ${extensionName}?`
}, options);

// This has to happen onInstalled in Event Pages
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: contextMenuId,
title: options.title,
contexts: ['page_action', 'browser_action'],
documentUrlPatterns: [
'http://*/*',
'https://*/*'
]
});
});

chrome.contextMenus.onClicked.addListener(async ({menuItemId}, {tabId, url}) => {
if (menuItemId !== contextMenuId) {
return;
}
chrome.permissions.request({
origins: [
`${new URL(url).origin}/*`
]
}, granted => {
if (chrome.runtime.lastError) {
console.error(`Error: ${chrome.runtime.lastError.message}`);
alert(`Error: ${chrome.runtime.lastError.message}`);
} else if (granted && options.reloadOnSuccess && confirm(options.reloadOnSuccess)) {
chrome.tabs.reload(tabId);
}
});
});
}
};

if (typeof module === 'object') {
module.exports = DCE;
}
113 changes: 113 additions & 0 deletions src/vendor/webext-dynamic-content-scripts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// https://github.com/bfred-it/webext-dynamic-content-scripts
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.DCS = global.DCS || {})));
}(this, (function (exports) { 'use strict';

function interopDefault(ex) {
return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex;
}

function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}

var webextContentScriptPing = createCommonjsModule(function (module) {
// https://github.com/bfred-it/webext-content-script-ping

/**
* Ping responder
*/
document.__webextContentScriptLoaded = true;

/**
* Pinger
*/
function pingContentScript(tab) {
return new Promise((resolve, reject) => {
chrome.tabs.executeScript(tab.id || tab, {
code: 'document.__webextContentScriptLoaded',
runAt: 'document_start'
}, hasScriptAlready => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
} else {
resolve(Boolean(hasScriptAlready[0]));
}
});
});
}

if (typeof module === 'object') {
module.exports = pingContentScript;
}
});

var pingContentScript = interopDefault(webextContentScriptPing);

async function p(fn, ...args) {
return new Promise((resolve, reject) => fn(...args, r => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
} else {
resolve(r);
}
}));
}

async function addToTab(tab, contentScripts) {
if (typeof tab !== 'object' && typeof tab !== 'number') {
throw new TypeError('Specify a Tab or tabId');
}

if (!contentScripts) {
// Get all scripts from manifest.json
contentScripts = chrome.runtime.getManifest().content_scripts;
} else if (!Array.isArray(contentScripts)) {
// Single script object, make it an array
contentScripts = [contentScripts];
}

try {
const tabId = tab.id || tab;
if (!await pingContentScript(tabId)) {
const injections = [];
for (const group of contentScripts) {
const allFrames = group.all_frames;
const runAt = group.run_at;
for (const file of group.css) {
injections.push(p(chrome.tabs.insertCSS, tabId, {file, allFrames, runAt}));
}
for (const file of group.js) {
injections.push(p(chrome.tabs.executeScript, tabId, {file, allFrames, runAt}));
}
}
return Promise.all(injections);
}
} catch (err) {
// Probably the domain isn't permitted.
// It's easier to catch this than do 2 queries
}
}

function addToFutureTabs(scripts) {
chrome.tabs.onUpdated.addListener((tabId, {status}) => {
if (status === 'loading') {
addToTab(tabId, scripts);
}
});
}

var index = {
addToTab,
addToFutureTabs
};

exports.addToTab = addToTab;
exports.addToFutureTabs = addToFutureTabs;
exports['default'] = index;

Object.defineProperty(exports, '__esModule', { value: true });

})));