diff --git a/Logic/Osm/OsmConnection.ts b/Logic/Osm/OsmConnection.ts index e74fb1c97f..1bba8d7d52 100644 --- a/Logic/Osm/OsmConnection.ts +++ b/Logic/Osm/OsmConnection.ts @@ -7,6 +7,7 @@ import {ElementStorage} from "../ElementStorage"; import Svg from "../../Svg"; import LayoutConfig from "../../Customizations/JSON/LayoutConfig"; import Img from "../../UI/Base/Img"; +import {Utils} from "../../Utils"; export default class UserDetails { @@ -22,28 +23,49 @@ export default class UserDetails { export class OsmConnection { + public static readonly _oauth_configs = { + "osm": { + oauth_consumer_key: 'hivV7ec2o49Two8g9h8Is1VIiVOgxQ1iYexCbvem', + oauth_secret: 'wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI', + url: "https://openstreetmap.org" + }, + "osm-test": { + oauth_consumer_key: 'Zgr7EoKb93uwPv2EOFkIlf3n9NLwj5wbyfjZMhz2', + oauth_secret: '3am1i1sykHDMZ66SGq4wI2Z7cJMKgzneCHp3nctn', + url: "https://master.apis.dev.openstreetmap.org" + } + + + } public auth; public userDetails: UIEventSource; _dryRun: boolean; - public preferencesHandler: OsmPreferences; public changesetHandler: ChangesetHandler; - private _onLoggedIn: ((userDetails: UserDetails) => void)[] = []; private readonly _iframeMode: Boolean | boolean; private readonly _singlePage: boolean; + private readonly _oauth_config: { + oauth_consumer_key: string, + oauth_secret: string, + url: string + }; constructor(dryRun: boolean, oauth_token: UIEventSource, // Used to keep multiple changesets open and to write to the correct changeset layoutName: string, - singlePage: boolean = true) { + singlePage: boolean = true, + osmConfiguration: "osm" | "osm-test" = 'osm' + ) { this._singlePage = singlePage; - this._iframeMode = window !== window.top; + this._oauth_config = OsmConnection._oauth_configs[osmConfiguration] ?? OsmConnection._oauth_configs.osm; + console.debug("Using backend", this._oauth_config.url) + this._iframeMode = Utils.runningFromConsole ? false : window !== window.top; this.userDetails = new UIEventSource(new UserDetails(), "userDetails"); this.userDetails.data.dryRun = dryRun; this._dryRun = dryRun; - + this.updateAuthObject(); this.preferencesHandler = new OsmPreferences(this.auth, this); @@ -67,37 +89,6 @@ export class OsmConnection { console.log("Not authenticated"); } } - - private updateAuthObject(){ - let pwaStandAloneMode = false; - try { - if (window.matchMedia('(display-mode: standalone)').matches || window.matchMedia('(display-mode: fullscreen)').matches) { - pwaStandAloneMode = true; - } - } catch (e) { - console.warn("Detecting standalone mode failed", e, ". Assuming in browser and not worrying furhter") - } - if (this._iframeMode || pwaStandAloneMode || !this._singlePage) { - // In standalone mode, we DON'T use single page login, as 'redirecting' opens a new window anyway... - // Same for an iframe... - this.auth = new osmAuth({ - oauth_consumer_key: 'hivV7ec2o49Two8g9h8Is1VIiVOgxQ1iYexCbvem', - oauth_secret: 'wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI', - singlepage: false, - auto: true, - }); - } else { - - this.auth = new osmAuth({ - oauth_consumer_key: 'hivV7ec2o49Two8g9h8Is1VIiVOgxQ1iYexCbvem', - oauth_secret: 'wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI', - singlepage: true, - landing: window.location.href, - auto: true, - }); - } - } - public UploadChangeset( layout: LayoutConfig, @@ -144,7 +135,7 @@ export class OsmConnection { // Not authorized - our token probably got revoked // Reset all the tokens const tokens = [ - "https://www.openstreetmap.orgoauth_request_token_secret", + "https://www.openstreetmap.orgoauth_request_token_secret", "https://www.openstreetmap.orgoauth_token", "https://www.openstreetmap.orgoauth_token_secret"] tokens.forEach(token => localStorage.removeItem(token)) @@ -196,6 +187,33 @@ export class OsmConnection { }); } + private updateAuthObject() { + let pwaStandAloneMode = false; + try { + if (Utils.runningFromConsole) { + pwaStandAloneMode = true + } else if (window.matchMedia('(display-mode: standalone)').matches || window.matchMedia('(display-mode: fullscreen)').matches) { + pwaStandAloneMode = true; + } + } catch (e) { + console.warn("Detecting standalone mode failed", e, ". Assuming in browser and not worrying furhter") + } + const standalone = this._iframeMode || pwaStandAloneMode || !this._singlePage; + + // In standalone mode, we DON'T use single page login, as 'redirecting' opens a new window anyway... + // Same for an iframe... + + + this.auth = new osmAuth({ + oauth_consumer_key: this._oauth_config.oauth_consumer_key, + oauth_secret: this._oauth_config.oauth_secret, + url: this._oauth_config.url, + landing: standalone ? undefined : window.location.href, + singlepage: !standalone, + auto: true, + + }); + } private CheckForMessagesContinuously() { const self = this; diff --git a/Logic/Osm/OsmPreferences.ts b/Logic/Osm/OsmPreferences.ts index 29bf456d77..e802b8abb0 100644 --- a/Logic/Osm/OsmPreferences.ts +++ b/Logic/Osm/OsmPreferences.ts @@ -96,10 +96,13 @@ export class OsmPreferences { } public GetPreference(key: string, prefix: string = "mapcomplete-"): UIEventSource { + console.warn(key) key = prefix + key; + key = key.replace(/[:\\\/"' {}.%]/g, '') if (key.length >= 255) { throw "Preferences: key length to big"; } + console.warn(key) if (this.preferenceSources[key] !== undefined) { return this.preferenceSources[key]; } diff --git a/State.ts b/State.ts index 25053f497c..2a17a48ad9 100644 --- a/State.ts +++ b/State.ts @@ -98,6 +98,7 @@ export default class State { public readonly featureSwitchIsTesting: UIEventSource; public readonly featureSwitchIsDebugging: UIEventSource; public readonly featureSwitchShowAllQuestions: UIEventSource; + public readonly featureSwitchApiURL: UIEventSource; /** @@ -201,7 +202,6 @@ export default class State { this.featureSwitchShowAllQuestions = featSw("fs-all-questions", (layoutToUse) => layoutToUse?.enableShowAllQuestions ?? false, "Always show all questions"); - this.featureSwitchIsTesting = QueryParameters.GetQueryParameter("test", "false", "If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org") .map(str => str === "true", [], b => "" + b); @@ -209,6 +209,10 @@ export default class State { this.featureSwitchIsDebugging = QueryParameters.GetQueryParameter("debug","false", "If true, shows some extra debugging help such as all the available tags on every object") .map(str => str === "true", [], b => "" + b) + + this.featureSwitchApiURL = QueryParameters.GetQueryParameter("backend","https://openstreetmap.org", + "The OSM backend to use - can be used to redirect mapcomplete to a testing backend or e.g. openHistoricalMap") + } @@ -217,7 +221,9 @@ export default class State { QueryParameters.GetQueryParameter("oauth_token", undefined, "Used to complete the login"), layoutToUse?.id, - true + true, + // @ts-ignore + this.featureSwitchApiURL.data ); diff --git a/test.ts b/test.ts index ddf4def815..0b0b2f0626 100644 --- a/test.ts +++ b/test.ts @@ -1,3 +1,4 @@ import ValidatedTextField from "./UI/Input/ValidatedTextField"; +import TestAll from "./test/TestAll"; -ValidatedTextField.InputForType("phone").AttachTo("maindiv") \ No newline at end of file +new TestAll().testAll(); \ No newline at end of file diff --git a/test/OsmConnection.spec.ts b/test/OsmConnection.spec.ts new file mode 100644 index 0000000000..ffcb4840ca --- /dev/null +++ b/test/OsmConnection.spec.ts @@ -0,0 +1,46 @@ +import T from "./TestHelper"; +import UserDetails, {OsmConnection} from "../Logic/Osm/OsmConnection"; +import {UIEventSource} from "../Logic/UIEventSource"; +import ScriptUtils from "../scripts/ScriptUtils"; + + +export default class OsmConnectionSpec extends T { + + /* + This token gives access to the TESTING-instance of OSM. No real harm can be done with it, so it can be commited to the repo + */ + private static _osm_token = "LJFmv2nUicSNmBNsFeyCHx5KKx6Aiesx8pXPbX4n" + + constructor() { + super("OsmConnectionSpec-test", [ + ["login on dev", + () => { + const osmConn = new OsmConnection(false, + new UIEventSource(undefined), + "Unit test", + true, + "osm-test" + ) + + osmConn.userDetails.map((userdetails : UserDetails) => { + if(userdetails.loggedIn){ + console.log("Logged in with the testing account. Writing some random data to test preferences") + const data = Math.random().toString() + osmConn.GetPreference("test").setData(data) + + osmConn.GetPreference("https://raw.githubusercontent.com/AgusQui/MapCompleteRailway/main/railway") + .setData(data) + + } + }); + + ScriptUtils.sleep(1000) + + } + ] + + + ]); + } + +} \ No newline at end of file diff --git a/test/TestAll.ts b/test/TestAll.ts index 79e66af182..f7c79cf989 100644 --- a/test/TestAll.ts +++ b/test/TestAll.ts @@ -9,7 +9,26 @@ import TagQuestionSpec from "./TagQuestion.spec"; import ImageSearcherSpec from "./ImageSearcher.spec"; import ThemeSpec from "./Theme.spec"; import UtilsSpec from "./Utils.spec"; +import OsmConnectionSpec from "./OsmConnection.spec"; +import T from "./TestHelper"; +import {FixedUiElement} from "../UI/Base/FixedUiElement"; +import Combine from "../UI/Base/Combine"; +export default class TestAll { + private needsBrowserTests: T[] = [new OsmConnectionSpec()] + + public testAll(): void { + Utils.runningFromConsole = false + for (const test of this.needsBrowserTests.concat(allTests)) { + if (test.failures.length > 0) { + new Combine([new FixedUiElement("TEST FAILED: " + test.name).SetStyle("background: red"), + ...test.failures]) + .AttachTo("maindiv") + throw "Some test failed" + } + } + } +} const allTests = [ new TagSpec(), @@ -20,8 +39,9 @@ const allTests = [ new ThemeSpec(), new UtilsSpec()] + for (const test of allTests) { - if(test.failures.length > 0){ + if (test.failures.length > 0) { throw "Some test failed" } } \ No newline at end of file diff --git a/test/TestHelper.ts b/test/TestHelper.ts index f846fe0e9f..265eeb11ad 100644 --- a/test/TestHelper.ts +++ b/test/TestHelper.ts @@ -1,8 +1,10 @@ export default class T { - public readonly failures = [] + public readonly failures : string[] = [] + public readonly name : string; constructor(testsuite: string, tests: [string, () => void][]) { + this.name = testsuite for (const [name, test] of tests) { try { test();