diff --git a/src/extension/actions.js b/src/extension/actions.js index 98a244f8..81cee0af 100644 --- a/src/extension/actions.js +++ b/src/extension/actions.js @@ -110,7 +110,7 @@ export async function showSidekickNotification(tabId, data, callback) { * @param {string} origin * @returns {boolean} true - trusted / false - untrusted */ -function isGetAuthInfoTrustedOrigin(origin) { +function isTrustedOrigin(origin) { const TRUSTED_ORIGINS = [ ADMIN_ORIGIN, 'https://labs.aem.live', @@ -138,10 +138,10 @@ function isGetAuthInfoTrustedOrigin(origin) { * Returns the organizations the user is currently authenticated for. * @returns {Promise} The organizations */ -async function getAuthInfo(message, sender) { +async function getAuthInfo(_, sender) { const { origin } = new URL(sender.url); - if (!isGetAuthInfoTrustedOrigin(origin)) { + if (!isTrustedOrigin(origin)) { return []; // don't give out any information } @@ -151,6 +151,24 @@ async function getAuthInfo(message, sender) { .map(({ owner }) => owner); } +/** + * Returns the configured sites. + * @returns {Promise} The sites + */ +async function getSites(_, sender) { + const { origin } = new URL(sender.url); + + if (!isTrustedOrigin(origin)) { + return []; // don't give out any information + } + + return (await getConfig('sync', 'projects') || []) + .map((handle) => { + const [org, site] = handle.split('/'); + return { org, site }; + }); +} + /** * Adds or removes a project based on the tab's URL * @param {chrome.tabs.Tab} tab The tab @@ -306,4 +324,5 @@ export const internalActions = { export const externalActions = { updateAuthToken, getAuthInfo, + getSites, }; diff --git a/test/actions.test.js b/test/actions.test.js index bcb47092..538ae802 100644 --- a/test/actions.test.js +++ b/test/actions.test.js @@ -156,6 +156,55 @@ describe('Test actions', () => { expect(resp).to.deep.equal([]); }); + it('external: getSites', async () => { + const getStub = sandbox.stub(chrome.storage.sync, 'get'); + const projects = [ + 'foo/bar', + 'foo1/baz', + 'foo2/baz', + ]; + const expectedOutput = [ + { org: 'foo', site: 'bar' }, + { org: 'foo1', site: 'baz' }, + { org: 'foo2', site: 'baz' }, + ]; + + let resp; + + // without projects + getStub.resolves({}); + resp = await externalActions.getSites({}, mockTab('https://tools.aem.live')); + expect(resp).to.deep.equal([]); + + // with auth info + getStub.resolves({ + projects, + }); + + // trusted actors + resp = await externalActions.getSites({}, mockTab('https://tools.aem.live/foo')); + expect(resp).to.deep.equal(expectedOutput); + + resp = await externalActions.getSites({}, mockTab('https://labs.aem.live/foo')); + expect(resp).to.deep.equal(expectedOutput); + + resp = await externalActions.getSites({}, mockTab('https://feature--helix-labs-website--adobe.aem.page/feature')); + expect(resp).to.deep.equal(expectedOutput); + + // untrusted actors + resp = await externalActions.getSites({}, mockTab('https://evil.live')); + expect(resp).to.deep.equal([]); + + resp = await externalActions.getSites({}, mockTab('https://main--site--owner.aem.live')); + expect(resp).to.deep.equal([]); + + resp = await externalActions.getSites({}, mockTab('https://tools.aem.live.evil.com')); + expect(resp).to.deep.equal([]); + + resp = await externalActions.getSites({}, mockTab('https://main--helix-tools-website--adobe-evl.aem.live')); + expect(resp).to.deep.equal([]); + }); + it('internal: addRemoveProject', async () => { const set = sandbox.spy(chrome.storage.sync, 'set'); const remove = sandbox.spy(chrome.storage.sync, 'remove');