From fa6a4abbd9e9e23f4f2ea9125bfd25c8fd068a42 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Fri, 14 Jan 2022 12:59:31 +0100 Subject: [PATCH] feat: add known webui addresses to CORS conf License: MIT Signed-off-by: Henrique Dias --- src/daemon/config.js | 54 ++++++++++++++++++++++++++----- test/e2e/launch.e2e.test.js | 63 ++++++++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 8 deletions(-) diff --git a/src/daemon/config.js b/src/daemon/config.js index 613ab72d8..0aadb1f08 100644 --- a/src/daemon/config.js +++ b/src/daemon/config.js @@ -57,15 +57,29 @@ function applyDefaults (ipfsd) { writeConfigFile(ipfsd, config) } +function getGatewayPort (config) { + let gatewayUrl = null + + if (Array.isArray(config.Addresses.Gateway)) { + gatewayUrl = config.Addresses.Gateway.find(v => v.includes('127.0.0.1')) + } else { + gatewayUrl = config.Addresses.Gateway + } + + const gw = parseCfgMultiaddr(gatewayUrl) + return gw.nodeAddress().port +} + // Apply one-time updates to the config of IPFS node. // This is the place where we execute fixes and performance tweaks for existing users. function migrateConfig (ipfsd) { // Bump revision number when new migration rule is added - const REVISION = 1 + const REVISION = 2 const REVISION_KEY = 'daemonConfigRevision' + const CURRENT_REVISION = store.get(REVISION_KEY, 0) // Migration is applied only once per revision - if (store.get(REVISION_KEY) >= REVISION) return + if (CURRENT_REVISION >= REVISION) return // Read config let config = null @@ -78,11 +92,37 @@ function migrateConfig (ipfsd) { return } - // Cleanup https://github.com/ipfs-shipyard/ipfs-desktop/issues/1631 - if (config.Discovery && config.Discovery.MDNS && config.Discovery.MDNS.enabled) { - config.Discovery.MDNS.Enabled = config.Discovery.MDNS.Enabled || true - delete config.Discovery.MDNS.enabled - changed = true + if (CURRENT_REVISION <= 0) { + // Cleanup https://github.com/ipfs-shipyard/ipfs-desktop/issues/1631 + if (config.Discovery && config.Discovery.MDNS && config.Discovery.MDNS.enabled) { + config.Discovery.MDNS.Enabled = config.Discovery.MDNS.Enabled || true + delete config.Discovery.MDNS.enabled + changed = true + } + } + + if (CURRENT_REVISION <= 1) { + const api = config.API || {} + const httpHeaders = api.HTTPHeaders || {} + const accessControlAllowOrigin = httpHeaders['Access-Control-Allow-Origin'] || [] + + const addURL = url => { + if (!accessControlAllowOrigin.includes(url)) { + accessControlAllowOrigin.push(url) + return true + } + return false + } + + const addedWebUI = addURL('https://webui.ipfs.io') + const addedGw = addURL(`http://webui.ipfs.io.ipns.localhost:${getGatewayPort(config)}`) + + if (addedWebUI || addedGw) { + httpHeaders['Access-Control-Allow-Origin'] = accessControlAllowOrigin + api.HTTPHeaders = httpHeaders + config.API = api + changed = true + } } // TODO: update config.Swarm.ConnMgr.* diff --git a/test/e2e/launch.e2e.test.js b/test/e2e/launch.e2e.test.js index b19db4899..a94d155b1 100644 --- a/test/e2e/launch.e2e.test.js +++ b/test/e2e/launch.e2e.test.js @@ -78,7 +78,7 @@ test.describe.serial('Application launch', async () => { expect(peerId).toBe(expectedId) }) - test('applies config migration to existing config', async () => { + test('applies config migration (MDNS.enabled)', async () => { // create preexisting, initialized repo and config const { repoPath, configPath, peerId: expectedId } = await makeRepository({ start: false }) @@ -99,6 +99,67 @@ test.describe.serial('Application launch', async () => { expect(config.Discovery.MDNS.Enabled).toBeTruthy() }) + test('applies config migration (Web UI CORS 1)', async function () { + // create preexisting, initialized repo and config + const { repoPath, configPath, peerId: expectedId } = await makeRepository({ start: false }) + + const initConfig = fs.readJsonSync(configPath) + initConfig.API.HTTPHeaders['Access-Control-Allow-Origin'] = ['https://127.0.0.1:4040'] + fs.writeJsonSync(configPath, initConfig, { spaces: 2 }) + + const { app } = await startApp({ repoPath }) + const { peerId } = await daemonReady(app) + expect(peerId).toBe(expectedId) + + const config = fs.readJsonSync(configPath) + // ensure app has migrated config + expect(config.API.HTTPHeaders['Access-Control-Allow-Origin']).toEqual([ + 'https://127.0.0.1:4040', + 'https://webui.ipfs.io', + 'http://webui.ipfs.io.ipns.localhost:0' // ipfsd 'test' profile uses '/ip4/127.0.0.1/tcp/0' + ]) + }) + + test('applies config migration (Web UI CORS 2)', async function () { + // create preexisting, initialized repo and config + const { repoPath, configPath, peerId: expectedId } = await makeRepository({ start: false }) + + const initConfig = fs.readJsonSync(configPath) + initConfig.API.HTTPHeaders['Access-Control-Allow-Origin'] = [] + fs.writeJsonSync(configPath, initConfig, { spaces: 2 }) + + const { app } = await startApp({ repoPath }) + const { peerId } = await daemonReady(app) + expect(peerId).toBe(expectedId) + + const config = fs.readJsonSync(configPath) + // ensure app has migrated config + expect(config.API.HTTPHeaders['Access-Control-Allow-Origin']).toEqual([ + 'https://webui.ipfs.io', + 'http://webui.ipfs.io.ipns.localhost:0' // ipfsd 'test' profile uses '/ip4/127.0.0.1/tcp/0' + ]) + }) + + test('applies config migration (Web UI CORS 3)', async function () { + // create preexisting, initialized repo and config + const { repoPath, configPath, peerId: expectedId } = await makeRepository({ start: false }) + + const initConfig = fs.readJsonSync(configPath) + delete initConfig.API.HTTPHeaders + fs.writeJsonSync(configPath, initConfig, { spaces: 2 }) + + const { app } = await startApp({ repoPath }) + const { peerId } = await daemonReady(app) + expect(peerId).toBe(expectedId) + + const config = fs.readJsonSync(configPath) + // ensure app has migrated config + expect(config.API.HTTPHeaders['Access-Control-Allow-Origin']).toEqual([ + 'https://webui.ipfs.io', + 'http://webui.ipfs.io.ipns.localhost:0' // ipfsd 'test' profile uses '/ip4/127.0.0.1/tcp/0' + ]) + }) + test('starts with repository with "IPFS_PATH/api" file and no daemon running', async () => { // create "remote" repo const { ipfsd } = await makeRepository({ start: true })