diff --git a/Dockerfile b/Dockerfile index fa6b34e10..c8b752d54 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,8 +25,6 @@ RUN rm /usr/share/nginx/html/* COPY --from=builder /opt/threema-web/release/threema-web-* /usr/share/nginx/html/ COPY docker/entrypoint.sh /usr/local/bin/ -ENV SALTYRTC_HOST="" \ - SALTYRTC_PORT=443 \ - SALTYRTC_SERVER_KEY="b1337fc8402f7db8ea639e05ed05d65463e24809792f91eca29e88101b4a2171" +EXPOSE 80 CMD ["/bin/sh", "/usr/local/bin/entrypoint.sh"] diff --git a/README.md b/README.md index c4a2526a4..71197d769 100644 --- a/README.md +++ b/README.md @@ -124,9 +124,10 @@ You can also install a pre-push hook to do the linting: ## Configuration -The configuration of Threema Web can be tweaked in `src/config.ts`: +The configuration of Threema Web can be tweaked in `src/config.ts` and +`src/userconfig.js`: -**General** +**General (Config)** - `SELF_HOSTED`: Set this to `true` if this instance of Threema Web isn't being hosted on `web.threema.ch`. @@ -135,7 +136,7 @@ The configuration of Threema Web can be tweaked in `src/config.ts`: previous protocol version. If set to something different than `null`, a message will be shown to the user if reconnecting fails. -**SaltyRTC** +**SaltyRTC (Userconfig)** - `SALTYRTC_HOST`: Set this to the hostname of the SaltyRTC server that you want to use. If supplied, the substring `{prefix}` will be replaced by the @@ -146,16 +147,24 @@ The configuration of Threema Web can be tweaked in `src/config.ts`: this value to `null` if your server does not provide a public permanent key, or if you don't want to verify it. -**ICE** +**ICE (Userconfig)** - `ICE_SERVERS`: Configuration object for the WebRTC STUN and ICE servers. Each URL may contain the substring `{prefix}`, which will be replaced by a random byte represented as a lowercase hexadecimal value. -**Push** +**Push (Userconfig)** - `PUSH_URL`: The server URL used to deliver push notifications to the app. +**Fonts (Userconfig)** + +Note: If you want to use the Lab Grotesque font in your self-hosted instance +(with SELF_HOSTED=true), you need to obtain a license for it and update the +font URL below. Otherwise, Threema Web will fall back to Roboto. + +- `FONT_CSS_URL`: URL to the Lab Grotesque font. + ## Self Hosting diff --git a/dist/package.sh b/dist/package.sh index e9e00dcb9..0dd52bcc5 100755 --- a/dist/package.sh +++ b/dist/package.sh @@ -45,8 +45,8 @@ mkdir -p $DIR/{partials,directives,components,node_modules,partials/messenger.re echo "+ Copy code..." cp -R index.html $DIR/ -cp -R dist/generated/*.bundle.js $DIR/ -cp -R dist/generated/*.bundle.js.map $DIR/ +cp -R dist/generated/*.js $DIR/ +cp -R dist/generated/*.js.map $DIR/ cp -R dist/generated/*.wasm $DIR/ cp -R public/* $DIR/ cp -R troubleshoot/* $DIR/troubleshoot/ diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 916bd9515..5530c2c94 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -2,13 +2,22 @@ set -euo pipefail # Patch config file -echo "Patching config file..." +echo "Patching userconfig file..." cd /usr/share/nginx/html/ -if [ ! -z "$SALTYRTC_HOST" ]; then - sed -i -E "s/SALTYRTC_HOST:\s*null,/SALTYRTC_HOST:'${SALTYRTC_HOST}',/g" *.bundle.js +if [[ ! -f userconfig.js ]]; then + echo "Error: Userconfig not found" + exit 1 +fi +echo '// Overrides by entrypoint.sh' >> userconfig.js +if [ ! -z "${SALTYRTC_HOST:-}" ]; then + echo "window.UserConfig.SALTYRTC_HOST = '${SALTYRTC_HOST}';" >> userconfig.js +fi +if [ ! -z "${SALTYRTC_PORT:-}" ]; then + echo "window.UserConfig.SALTYRTC_PORT = ${SALTYRTC_PORT};" >> userconfig.js +fi +if [ ! -z "${SALTYRTC_SERVER_KEY:-}" ]; then + echo "window.UserConfig.SALTYRTC_SERVER_KEY = '${SALTYRTC_SERVER_KEY}';" >> userconfig.js fi -sed -i -E "s/SALTYRTC_PORT:\s*[^,]*,/SALTYRTC_PORT:${SALTYRTC_PORT},/g" *.bundle.js -sed -i -E "s/SALTYRTC_SERVER_KEY:\s*\"[^\"]*\",/SALTYRTC_SERVER_KEY:\"${SALTYRTC_SERVER_KEY}\",/g" *.bundle.js # Add nginx mime type for wasm # See https://trac.nginx.org/nginx/ticket/1606 diff --git a/docs/docker.md b/docs/docker.md index 2239779f8..adc4486e8 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -21,7 +21,8 @@ mechanisms in your web server. ## Config Variables -- `SALTYRTC_HOST`: The SaltyRTC signaling server hostname (default `null`) +- `SALTYRTC_HOST`: The SaltyRTC signaling server hostname + (default `saltyrtc-{prefix}.threema.ch`) - `SALTYRTC_PORT`: The SaltyRTC signaling server port (default `443`) - `SALTYRTC_SERVER_KEY`: The SaltyRTC signaling server public key (default `"b1337fc8402f7db8ea639e05ed05d65463e24809792f91eca29e88101b4a2171"`) diff --git a/index.html b/index.html index 3b43419d1..10e3bd604 100644 --- a/index.html +++ b/index.html @@ -167,6 +167,7 @@

+ diff --git a/package-lock.json b/package-lock.json index 0a85a0a80..66b453093 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1616,7 +1616,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1625,14 +1624,12 @@ "@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" }, "@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -2254,8 +2251,7 @@ "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" }, "arrify": { "version": "1.0.1", @@ -3150,6 +3146,37 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, + "copy-webpack-plugin": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz", + "integrity": "sha512-rxnR7PaGigJzhqETHGmAcxKnLZSR5u1Y3/bcIv/1FnqXedcL/E2ewK7ZCNrArJKCiSv8yVXhTqetJh8inDvfsA==", + "requires": { + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^11.0.3", + "normalize-path": "^3.0.0", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "requires": { + "is-glob": "^4.0.3" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + } + } + }, "core-js": { "version": "3.18.3", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.3.tgz", @@ -3413,7 +3440,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, "requires": { "path-type": "^4.0.0" } @@ -3811,7 +3837,6 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -3824,7 +3849,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -3833,7 +3857,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -3841,14 +3864,12 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, "requires": { "braces": "^3.0.1", "picomatch": "^2.2.3" @@ -3857,14 +3878,12 @@ "picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -3885,7 +3904,6 @@ "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, "requires": { "reusify": "^1.0.4" } @@ -4190,7 +4208,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -4209,7 +4226,6 @@ "version": "11.0.4", "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -4546,8 +4562,7 @@ "ignore": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" }, "immediate": { "version": "3.0.6", @@ -4691,8 +4706,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { "version": "1.0.0", @@ -4706,7 +4720,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -5387,8 +5400,7 @@ "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "messageformat": { "version": "2.3.0", @@ -5707,8 +5719,7 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "normalize-url": { "version": "6.1.0", @@ -5946,8 +5957,7 @@ "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, "pathval": { "version": "1.1.1", @@ -6062,8 +6072,7 @@ "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, "quick-lru": { "version": "4.0.1", @@ -6429,8 +6438,7 @@ "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, "rfdc": { "version": "1.3.0", @@ -6442,7 +6450,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "requires": { "queue-microtask": "^1.2.2" } @@ -6694,8 +6701,7 @@ "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, "socket.io": { "version": "4.3.1", diff --git a/package.json b/package.json index 3359ecf08..e3b7f1889 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "angularjs-scroll-glue": "=2.1.0", "autolinker": "^3.14.3", "babel-loader": "^8.2.3", + "copy-webpack-plugin": "^9.1.0", "core-js": "^3.18.3", "croppie": "^2.6.5", "emojibase-regex": "^4.1.1", diff --git a/src/config.ts b/src/config.ts index bdd46b1e8..c2fa62110 100644 --- a/src/config.ts +++ b/src/config.ts @@ -3,6 +3,7 @@ * * The various options are explained in the `README.md` file. */ + // tslint:disable:max-line-length export default { // Version @@ -18,32 +19,6 @@ export default { PREV_PROTOCOL_LAST_VERSION: '1.8.2', GIT_BRANCH: 'master', - // SaltyRTC - SALTYRTC_HOST: 'saltyrtc-{prefix}.threema.ch', - SALTYRTC_PORT: 443, - SALTYRTC_SERVER_KEY: 'b1337fc8402f7db8ea639e05ed05d65463e24809792f91eca29e88101b4a2171', - - // ICE - ICE_SERVERS: [{ - urls: [ - 'turn:ds-turn-{prefix}.threema.ch:443?transport=udp', - 'turn:ds-turn-{prefix}.threema.ch:443?transport=tcp', - 'turns:ds-turn-{prefix}.threema.ch:443', - ], - username: 'threema-angular', - credential: 'Uv0LcCq3kyx6EiRwQW5jVigkhzbp70CjN2CJqzmRxG3UGIdJHSJV6tpo7Gj7YnGB', - }], - - // Push - PUSH_URL: 'https://push-web.threema.ch/push', - - // Fonts - // Note: If you want to use the Lab Grotesque font in your self-hosted - // instance (with SELF_HOSTED=true), you need to obtain a license for - // it and update the font URL below. Otherwise, Threema Web will - // fall back to Roboto. - FONT_CSS_URL: null, - // Padding length (in characters) of the log tag // Note: The padding will be stripped by the report log. LOG_TAG_PADDING: 20, diff --git a/src/controllers/header.ts b/src/controllers/header.ts index b1b0a4424..2b0ae3ff8 100644 --- a/src/controllers/header.ts +++ b/src/controllers/header.ts @@ -21,10 +21,13 @@ export class HeaderController { // Config private config: threema.Config; + private userConfig: threema.UserConfig; public static $inject = ['CONFIG']; constructor(config: threema.Config) { this.config = config; + // tslint:disable-next-line: no-string-literal + this.userConfig = window['UserConfig']; } /** @@ -33,17 +36,17 @@ export class HeaderController { public useThreemaFont(): boolean { // In the officially hosted version, the Threema font is loaded from static.threema.ch. // In a self-hosted version, a custom font URL needs to be provided. - return !this.config.SELF_HOSTED || this.config.FONT_CSS_URL !== null; + return !this.config.SELF_HOSTED || this.userConfig.FONT_CSS_URL !== null; } /** * Return the URL to the Threema font (Lab Grotesque). */ public fontUrl(): string { - if (this.config.FONT_CSS_URL === null) { + if (this.userConfig.FONT_CSS_URL === null) { return 'https://static.threema.ch/fonts/labgrotesque.css'; } else { - return this.config.FONT_CSS_URL; + return this.userConfig.FONT_CSS_URL; } } } diff --git a/src/controllers/troubleshooting.ts b/src/controllers/troubleshooting.ts index 145b4a7ba..eb9dc7d11 100644 --- a/src/controllers/troubleshooting.ts +++ b/src/controllers/troubleshooting.ts @@ -192,8 +192,10 @@ export class TroubleshootingController extends DialogController { // Sanitise usernames and credentials from ICE servers in config const config = copyShallow(this.config) as threema.Config; + // tslint:disable-next-line: no-string-literal + const userConfig = copyShallow(window['UserConfig']) as threema.UserConfig; if (sanitize) { - config.ICE_SERVERS = config.ICE_SERVERS.map((server: RTCIceServer) => { + userConfig.ICE_SERVERS = userConfig.ICE_SERVERS.map((server: RTCIceServer) => { server = copyShallow(server) as RTCIceServer; for (const key of ['username', 'credential', 'credentialType']) { if (server[key] !== undefined) { @@ -207,6 +209,7 @@ export class TroubleshootingController extends DialogController { // Create container for meta data and log records const container = { config: config, + userConfig: userConfig, browser: browser.description(), log: this.logService.memory.getRecords(), }; diff --git a/src/services/push.ts b/src/services/push.ts index ab11f8df5..c6a29e91a 100644 --- a/src/services/push.ts +++ b/src/services/push.ts @@ -247,8 +247,6 @@ export class PushSession { } export class PushService { - public static readonly $inject = ['CONFIG', 'PROTOCOL_VERSION', 'LogService']; - public static readonly ARG_TYPE = 'type'; public static readonly ARG_TOKEN = 'token'; public static readonly ARG_SESSION = 'session'; @@ -268,9 +266,12 @@ export class PushService { private _pushToken: string = null; private _pushType = threema.PushTokenType.Fcm; + public static readonly $inject = ['CONFIG', 'PROTOCOL_VERSION', 'LogService']; constructor(CONFIG: threema.Config, PROTOCOL_VERSION: number, logService: LogService) { this.config = CONFIG; - this.url = CONFIG.PUSH_URL; + // tslint:disable-next-line: no-string-literal + const userConfig: threema.UserConfig = window['UserConfig']; + this.url = userConfig.PUSH_URL; this.version = PROTOCOL_VERSION; this.logService = logService; this.log = logService.getLogger(`Push-S`, 'color: #fff; background-color: #9900ff'); diff --git a/src/services/webclient.ts b/src/services/webclient.ts index b88c1e171..5ea8b8f30 100644 --- a/src/services/webclient.ts +++ b/src/services/webclient.ts @@ -262,6 +262,7 @@ export class WebClientService { // Other private config: threema.Config; + private userConfig: threema.UserConfig; private container: threema.Container.Factory; private typingInstance: threema.Container.Typing; private drafts: threema.Container.Drafts; @@ -349,6 +350,8 @@ export class WebClientService { // Configuration object this.config = CONFIG; + // tslint:disable-next-line: no-string-literal + this.userConfig = window['UserConfig']; // Logging this.log = logService.getLogger('WebClient-S', 'color: #fff; background-color: #0066cc'); @@ -441,8 +444,8 @@ export class WebClientService { return this.qrCodeService.buildQrCodePayload( this.salty.permanentKeyBytes, this.salty.authTokenBytes, - hexToU8a(this.config.SALTYRTC_SERVER_KEY), - this.saltyRtcHost, this.config.SALTYRTC_PORT, + hexToU8a(this.userConfig.SALTYRTC_SERVER_KEY), + this.saltyRtcHost, this.userConfig.SALTYRTC_PORT, persistent); } @@ -533,13 +536,13 @@ export class WebClientService { } // Determine SaltyRTC host, replace the inner prefix (if any) - this.saltyRtcHost = this.config.SALTYRTC_HOST.replace('{prefix}', keyStore.publicKeyHex.substr(0, 2)); + this.saltyRtcHost = this.userConfig.SALTYRTC_HOST.replace('{prefix}', keyStore.publicKeyHex.substr(0, 2)); // Create SaltyRTC client let builder = new saltyrtcClient.SaltyRTCBuilder() - .connectTo(this.saltyRtcHost, this.config.SALTYRTC_PORT) + .connectTo(this.saltyRtcHost, this.userConfig.SALTYRTC_PORT) .withLoggingLevel(this.config.SALTYRTC_LOG_LEVEL) - .withServerKey(this.config.SALTYRTC_SERVER_KEY) + .withServerKey(this.userConfig.SALTYRTC_SERVER_KEY) .withKeyStore(keyStore) .usingTasks(tasks) .withPingInterval(30); @@ -895,7 +898,7 @@ export class WebClientService { // Determine ICE servers and replace random prefix (if any) const prefix = u8aToHex(nacl.randomBytes(1)); - const iceServers = this.config.ICE_SERVERS.map((server) => { + const iceServers = this.userConfig.ICE_SERVERS.map((server) => { server = copyShallow(server) as RTCIceServer; const urls = Array.isArray(server.urls) ? server.urls : [server.urls]; server.urls = urls.map((url) => url.replace('{prefix}', prefix)); diff --git a/src/threema.d.ts b/src/threema.d.ts index d1dcdd8b7..11e047ed1 100644 --- a/src/threema.d.ts +++ b/src/threema.d.ts @@ -663,20 +663,6 @@ declare namespace threema { PREV_PROTOCOL_LAST_VERSION: string | null; GIT_BRANCH: string; - // SaltyRTC - SALTYRTC_HOST: string; - SALTYRTC_PORT: number; - SALTYRTC_SERVER_KEY: string | null; - - // ICE - ICE_SERVERS: RTCIceServer[]; - - // Push - PUSH_URL: string; - - // Fonts - FONT_CSS_URL: string; - // Logging/debugging LOG_TAG_PADDING: number, CONSOLE_LOG_LEVEL: LogLevel; @@ -693,6 +679,22 @@ declare namespace threema { IN_MEMORY_SESSION_PASSWORD: boolean; } + interface UserConfig { + // SaltyRTC + SALTYRTC_HOST: string; + SALTYRTC_PORT: number; + SALTYRTC_SERVER_KEY: string | null; + + // ICE + ICE_SERVERS: RTCIceServer[]; + + // Push + PUSH_URL: string; + + // Fonts + FONT_CSS_URL: string; + } + interface InitialConversationData { draft: string; initialText: string; diff --git a/src/userconfig.js b/src/userconfig.js new file mode 100644 index 000000000..9f3c6d6f5 --- /dev/null +++ b/src/userconfig.js @@ -0,0 +1,33 @@ +/** + * Threema Web configuration. + * + * The various options are explained in the `README.md` file. + */ + +window.UserConfig = { + // SaltyRTC + SALTYRTC_HOST: 'saltyrtc-{prefix}.threema.ch', + SALTYRTC_PORT: 443, + SALTYRTC_SERVER_KEY: 'b1337fc8402f7db8ea639e05ed05d65463e24809792f91eca29e88101b4a2171', + + // ICE + ICE_SERVERS: [{ + urls: [ + 'turn:ds-turn-{prefix}.threema.ch:443?transport=udp', + 'turn:ds-turn-{prefix}.threema.ch:443?transport=tcp', + 'turns:ds-turn-{prefix}.threema.ch:443', + ], + username: 'threema-angular', + credential: 'Uv0LcCq3kyx6EiRwQW5jVigkhzbp70CjN2CJqzmRxG3UGIdJHSJV6tpo7Gj7YnGB', + }], + + // Push + PUSH_URL: 'https://push-web.threema.ch/push', + + // Fonts + // Note: If you want to use the Lab Grotesque font in your self-hosted + // instance (with SELF_HOSTED=true), you need to obtain a license for + // it and update the font URL below. Otherwise, Threema Web will + // fall back to Roboto. + FONT_CSS_URL: null, +}; diff --git a/troubleshoot/log.html b/troubleshoot/log.html index 9b83e955f..495258611 100644 --- a/troubleshoot/log.html +++ b/troubleshoot/log.html @@ -78,7 +78,7 @@ display: inline-block; } - #config { + .config { background-color: #fafafa; border: 1px solid #e0e0e0; padding: 8px; @@ -180,7 +180,12 @@

Browser:

Config

-

+            

+        
+ +
+

Userconfig

+

         

Log

diff --git a/troubleshoot/log.js b/troubleshoot/log.js index 9e03b00a3..6581919b9 100644 --- a/troubleshoot/log.js +++ b/troubleshoot/log.js @@ -10,6 +10,7 @@ const elements = { container: document.querySelector('#container'), browser: document.querySelector('#browser'), config: document.querySelector('#config'), + userConfig: document.querySelector('#userconfig'), log: document.querySelector('#log'), }; @@ -125,6 +126,7 @@ function showLog(data) { // Display meta data elements.browser.textContent = container.browser; elements.config.textContent = JSON.stringify(container.config, null, 2); + elements.userConfig.textContent = JSON.stringify(container.userConfig, null, 2); // Display log records elements.log.innerHTML = ''; diff --git a/webpack.common.js b/webpack.common.js index 8e4e1732e..3bf0488e6 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,5 +1,6 @@ const path = require('path'); const webpack = require('webpack'); +const CopyPlugin = require("copy-webpack-plugin"); const babelOptions = { presets: [ @@ -49,6 +50,17 @@ module.exports = { resolve: { extensions: ['.js', '.ts', '.wasm'], }, + plugins: [ + new CopyPlugin({ + patterns: [ + { + from: 'src/userconfig.js', + to: path.resolve(__dirname, 'dist', 'generated'), + info: { minimized: true /* Do not minimize / uglify */ }, + }, + ], + }), + ], output: { path: path.resolve(__dirname, 'dist', 'generated'), filename: '[name].bundle.js',