diff --git a/keyserver/src/database/migration-config.js b/keyserver/src/database/migration-config.js index 1eb5b79b7..f97db9500 100644 --- a/keyserver/src/database/migration-config.js +++ b/keyserver/src/database/migration-config.js @@ -1,190 +1,238 @@ // @flow import fs from 'fs'; import { policyTypes } from 'lib/facts/policies.js'; import { dbQuery, SQL } from '../database/database'; import { updateRolesAndPermissionsForAllThreads } from '../updaters/thread-permission-updaters'; const migrations: $ReadOnlyMap Promise> = new Map([ [ 0, async () => { await makeSureBaseRoutePathExists('facts/commapp_url.json'); await makeSureBaseRoutePathExists('facts/squadcal_url.json'); }, ], [ 1, async () => { try { await fs.promises.unlink('facts/url.json'); } catch {} }, ], [ 2, async () => { await fixBaseRoutePathForLocalhost('facts/commapp_url.json'); await fixBaseRoutePathForLocalhost('facts/squadcal_url.json'); }, ], [3, updateRolesAndPermissionsForAllThreads], [ 4, async () => { await dbQuery(SQL`ALTER TABLE uploads ADD INDEX container (container)`); }, ], [ 5, async () => { await dbQuery(SQL` ALTER TABLE cookies ADD device_id varchar(255) DEFAULT NULL, ADD public_key varchar(255) DEFAULT NULL, ADD social_proof varchar(255) DEFAULT NULL; `); }, ], [ 7, async () => { await dbQuery( SQL` ALTER TABLE users DROP COLUMN IF EXISTS public_key, MODIFY hash char(60) COLLATE utf8mb4_bin DEFAULT NULL; ALTER TABLE sessions DROP COLUMN IF EXISTS public_key; `, { multipleStatements: true }, ); }, ], [ 8, async () => { await dbQuery( SQL` ALTER TABLE users ADD COLUMN IF NOT EXISTS ethereum_address char(42) DEFAULT NULL; `, ); }, ], [ 9, async () => { await dbQuery( SQL` ALTER TABLE messages ADD COLUMN IF NOT EXISTS target_message bigint(20) DEFAULT NULL; ALTER TABLE messages ADD INDEX target_message (target_message); `, { multipleStatements: true }, ); }, ], [ 10, async () => { await dbQuery(SQL` CREATE TABLE IF NOT EXISTS policy_acknowledgments ( user bigint(20) NOT NULL, policy varchar(255) NOT NULL, date bigint(20) NOT NULL, confirmed tinyint(1) UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (user, policy) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `); }, ], [ 11, async () => { const time = Date.now(); await dbQuery(SQL` INSERT IGNORE INTO policy_acknowledgments (policy, user, date, confirmed) SELECT ${policyTypes.tosAndPrivacyPolicy}, id, ${time}, 1 FROM users `); }, ], [ 12, async () => { await dbQuery(SQL` CREATE TABLE IF NOT EXISTS siwe_nonces ( nonce char(17) NOT NULL, creation_time bigint(20) NOT NULL, PRIMARY KEY (nonce) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `); }, ], + [ + 13, + async () => { + await Promise.all([ + writeSquadCalRoute('facts/squadcal_url.json'), + moveToNonApacheConfig('facts/commapp_url.json', '/comm/'), + moveToNonApacheConfig('facts/landing_url.json', '/commlanding/'), + ]); + }, + ], ]); const newDatabaseVersion: number = Math.max(...migrations.keys()); +async function writeJSONToFile(data: any, filePath: string): Promise { + console.warn(`updating ${filePath} to ${JSON.stringify(data)}`); + const fileHandle = await fs.promises.open(filePath, 'w'); + await fileHandle.writeFile(JSON.stringify(data, null, ' '), 'utf8'); + await fileHandle.close(); +} + async function makeSureBaseRoutePathExists(filePath: string): Promise { let readFile, json; try { readFile = await fs.promises.open(filePath, 'r'); const contents = await readFile.readFile('utf8'); json = JSON.parse(contents); } catch { return; } finally { if (readFile) { await readFile.close(); } } if (json.baseRoutePath) { return; } let baseRoutePath; if (json.baseDomain === 'http://localhost') { baseRoutePath = json.basePath; } else if (filePath.endsWith('commapp_url.json')) { baseRoutePath = '/commweb/'; } else { baseRoutePath = '/'; } const newJSON = { ...json, baseRoutePath }; console.warn(`updating ${filePath} to ${JSON.stringify(newJSON)}`); - const writeFile = await fs.promises.open(filePath, 'w'); - await writeFile.writeFile(JSON.stringify(newJSON, null, ' '), 'utf8'); - await writeFile.close(); + await writeJSONToFile(newJSON, filePath); } async function fixBaseRoutePathForLocalhost(filePath: string): Promise { let readFile, json; try { readFile = await fs.promises.open(filePath, 'r'); const contents = await readFile.readFile('utf8'); json = JSON.parse(contents); } catch { return; } finally { if (readFile) { await readFile.close(); } } if (json.baseDomain !== 'http://localhost') { return; } const baseRoutePath = '/'; json = { ...json, baseRoutePath }; console.warn(`updating ${filePath} to ${JSON.stringify(json)}`); - const writeFile = await fs.promises.open(filePath, 'w'); - await writeFile.writeFile(JSON.stringify(json, null, ' '), 'utf8'); - await writeFile.close(); + await writeJSONToFile(json, filePath); +} + +async function moveToNonApacheConfig( + filePath: string, + routePath: string, +): Promise { + if (process.env.COMM_DATABASE_HOST) { + return; + } + // Since the non-Apache config is so opinionated, just write expected config + const newJSON = { + baseDomain: 'http://localhost:3000', + basePath: routePath, + baseRoutePath: routePath, + https: false, + proxy: 'none', + }; + + await writeJSONToFile(newJSON, filePath); +} + +async function writeSquadCalRoute(filePath: string): Promise { + if (process.env.COMM_DATABASE_HOST) { + return; + } + // Since the non-Apache config is so opinionated, just write expected config + const newJSON = { + baseDomain: 'http://localhost:3000', + basePath: '/comm/', + baseRoutePath: '/', + https: false, + proxy: 'apache', + }; + + await writeJSONToFile(newJSON, filePath); } export { migrations, newDatabaseVersion }; diff --git a/native/utils/url-utils.js b/native/utils/url-utils.js index 103c8d470..9a9464056 100644 --- a/native/utils/url-utils.js +++ b/native/utils/url-utils.js @@ -1,76 +1,76 @@ // @flow import invariant from 'invariant'; import { Platform } from 'react-native'; import DeviceInfo from 'react-native-device-info'; import { natDevHostname, checkForMissingNatDevHostname } from './dev-hostname'; const localhostHostname = 'localhost'; const localhostHostnameFromAndroidEmulator = '10.0.2.2'; const productionNodeServerURL = 'https://squadcal.org'; const productionLandingURL = 'https://comm.app'; const devIsEmulator: boolean = __DEV__ && DeviceInfo.isEmulatorSync(); function getDevServerHostname(): string { if (!devIsEmulator) { checkForMissingNatDevHostname(); return natDevHostname; } else if (Platform.OS === 'android') { return localhostHostnameFromAndroidEmulator; } else if (Platform.OS === 'ios') { return localhostHostname; } invariant(false, `unsupported platform: ${Platform.OS}`); } function getDevNodeServerURLFromHostname(hostname: string): string { - return `http://${hostname}/comm`; + return `http://${hostname}:3000/comm`; } function getDevLandingURLFromHostname(hostname: string): string { - return `http://${hostname}/commlanding`; + return `http://${hostname}:3000/commlanding`; } function getDevNodeServerURL(): string { invariant(__DEV__, 'getDevNodeServerURL called from production'); const hostname = getDevServerHostname(); return getDevNodeServerURLFromHostname(hostname); } function getDevLandingURL(): string { invariant(__DEV__, 'getDevLandingURL called from production'); const hostname = getDevServerHostname(); return getDevLandingURLFromHostname(hostname); } const nodeServerOptions = [productionNodeServerURL]; if (Platform.OS === 'android') { nodeServerOptions.push( getDevNodeServerURLFromHostname(localhostHostnameFromAndroidEmulator), ); } else { nodeServerOptions.push(getDevNodeServerURLFromHostname(localhostHostname)); } const defaultURLPrefix: string = __DEV__ ? getDevNodeServerURL() : productionNodeServerURL; const defaultLandingURLPrefix: string = __DEV__ ? getDevLandingURL() : productionLandingURL; const natNodeServer: string = getDevNodeServerURLFromHostname(natDevHostname); const setCustomServer = 'SET_CUSTOM_SERVER'; export { defaultURLPrefix, defaultLandingURLPrefix, getDevServerHostname, nodeServerOptions, natNodeServer, setCustomServer, };