From d10e37c98e2b2e8020bbeebfba8d1661bf501380 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 13 Feb 2024 07:46:48 -0600 Subject: [PATCH 1/2] Svelte runtime env config --- Dockerfile | 6 ++ build/app-docker-entrypoint.sh | 4 ++ build/docker-entrypoint.sh | 6 +- build/update-config-next.sh | 65 +++++++++++++++++++ src/Exceptionless.Web/ClientApp/.env | 10 +-- src/Exceptionless.Web/ClientApp/src/app.html | 1 + .../ClientApp/src/hooks.client.ts | 6 +- .../ClientApp/src/lib/api/auth.ts | 18 ++--- .../(app)/account/security/+page.svelte | 4 +- .../src/routes/(auth)/login/+page.svelte | 4 +- .../ClientApp/static/runtime-env.js | 19 ++++++ 11 files changed, 122 insertions(+), 21 deletions(-) create mode 100644 build/update-config-next.sh create mode 100644 src/Exceptionless.Web/ClientApp/static/runtime-env.js diff --git a/Dockerfile b/Dockerfile index fc17c14ccb..aed38c8b5f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -82,6 +82,7 @@ WORKDIR /app COPY --from=app-publish /app/src/Exceptionless.Web/out ./ COPY ./build/app-docker-entrypoint.sh ./ COPY ./build/update-config.sh /usr/local/bin/update-config +COPY ./build/update-config-next.sh /usr/local/bin/update-config-next ENV EX_ConnectionStrings__Storage=provider=folder;path=/app/storage \ EX_RunJobsInProcess=true \ @@ -90,6 +91,7 @@ ENV EX_ConnectionStrings__Storage=provider=folder;path=/app/storage \ RUN chmod +x /app/app-docker-entrypoint.sh RUN chmod +x /usr/local/bin/update-config +RUN chmod +x /usr/local/bin/update-config-next EXPOSE 8080 @@ -104,6 +106,7 @@ COPY --from=job-publish /app/src/Exceptionless.Job/out ./ COPY --from=app-publish /app/src/Exceptionless.Web/out ./ COPY ./build/docker-entrypoint.sh ./ COPY ./build/update-config.sh /usr/local/bin/update-config +COPY ./build/update-config-next.sh /usr/local/bin/update-config-next COPY ./build/supervisord.conf /etc/ USER root @@ -136,6 +139,7 @@ ENV discovery.type=single-node \ RUN chmod +x /app/docker-entrypoint.sh && \ chmod +x /usr/local/bin/update-config && \ + chmod +x /usr/local/bin/update-config-next && \ chown -R elasticsearch:elasticsearch /app && \ mkdir -p /var/log/supervisor >/dev/null 2>&1 && \ chown -R elasticsearch:elasticsearch /var/log/supervisor @@ -160,6 +164,7 @@ COPY --from=job-publish /app/src/Exceptionless.Job/out ./ COPY --from=app-publish /app/src/Exceptionless.Web/out ./ COPY ./build/docker-entrypoint.sh ./ COPY ./build/update-config.sh /usr/local/bin/update-config +COPY ./build/update-config-next.sh /usr/local/bin/update-config-next COPY ./build/supervisord.conf /etc/ USER root @@ -192,6 +197,7 @@ ENV discovery.type=single-node \ RUN chmod +x /app/docker-entrypoint.sh && \ chmod +x /usr/local/bin/update-config && \ + chmod +x /usr/local/bin/update-config-next && \ chown -R elasticsearch:elasticsearch /app && \ mkdir -p /var/log/supervisor >/dev/null 2>&1 && \ chown -R elasticsearch:elasticsearch /var/log/supervisor diff --git a/build/app-docker-entrypoint.sh b/build/app-docker-entrypoint.sh index dea9316785..bed328c7a7 100644 --- a/build/app-docker-entrypoint.sh +++ b/build/app-docker-entrypoint.sh @@ -4,4 +4,8 @@ pushd /app/wwwroot update-config popd +pushd /app/wwwroot/next +update-config-next +popd + eval "dotnet Exceptionless.Web.dll $@" diff --git a/build/docker-entrypoint.sh b/build/docker-entrypoint.sh index 073a9b3958..f893511874 100755 --- a/build/docker-entrypoint.sh +++ b/build/docker-entrypoint.sh @@ -24,10 +24,14 @@ else update-config popd + pushd /app/wwwroot/next + update-config-next + popd + supervisord -c /etc/supervisord.conf while [ ! -f /var/log/supervisor/elasticsearch.log ]; do sleep 1; done while [ ! -f /var/log/supervisor/exceptionless.log ]; do sleep 1; done tail -f /var/log/supervisor/*.log -fi \ No newline at end of file +fi diff --git a/build/update-config-next.sh b/build/update-config-next.sh new file mode 100644 index 0000000000..31da4775d3 --- /dev/null +++ b/build/update-config-next.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +ApiUrl="${EX_ApiUrl:-}" +EnableSsl="${EX_EnableSsl:-false}" +EnableAccountCreation="${EX_EnableAccountCreation:-true}" + +OAuth="${EX_ConnectionStrings__OAuth:-}" +IFS=';' read -a oauthParts <<< "$OAuth" +for part in ${oauthParts[@]} +do + key="$( cut -d '=' -f 1 <<< $part )"; echo "key: $key" + value="$( cut -d '=' -f 2- <<< $part )"; echo "value: $value" + + if [ "$key" == "FacebookId" ]; then + FacebookAppId=$value + fi + if [ "$key" == "GitHubId" ]; then + GitHubAppId=$value + fi + if [ "$key" == "GoogleId" ]; then + GoogleAppId=$value + fi + if [ "$key" == "IntercomId" ]; then + IntercomAppId=$value + fi + if [ "$key" == "MicrosoftId" ]; then + MicrosoftAppId=$value + fi + if [ "$key" == "SlackId" ]; then + SlackAppId=$value + fi +done + +config_header="(function (window) { + 'use strict'; + + window.__env = {" + +config=" + PUBLIC_BASE_URL: '$ApiUrl' || window.location.origin, + PUBLIC_USE_SSL: $EnableSsl, + PUBLIC_ENABLE_ACCOUNT_CREATION: $EnableAccountCreation, + PUBLIC_SYSTEM_NOTIFICATION_MESSAGE: '$EX_NotificationMessage', + PUBLIC_EXCEPTIONLESS_API_KEY: '$EX_ExceptionlessApiKey', + PUBLIC_EXCEPTIONLESS_SERVER_URL: '$EX_ExceptionlessServerUrl', + PUBLIC_STRIPE_PUBLISHABLE_KEY: '$EX_StripePublishableApiKey', + PUBLIC_FACEBOOK_APPID: '$FacebookAppId', + PUBLIC_GITHUB_APPID: '$GitHubAppId', + PUBLIC_GOOGLE_APPID: '$GoogleAppId', + PUBLIC_MICROSOFT_APPID: '$MicrosoftAppId', + PUBLIC_INTERCOM_APPID: '$IntercomAppId', + PUBLIC_SLACK_APPID: '$SlackAppId'" + +config_footer=" + }; +}());" + +echo "Exceptionless UI Config" +echo "$config" + +checksum=`echo -n $config | md5sum | cut -c 1-32` +echo "$config_header$config$config_footer" > "runtime-env.$checksum.js" + +CONTENT=$(cat index.html) +echo "$CONTENT" | sed -E "s/runtime-env\..+\.js/runtime-env.$checksum.js/" > index.html diff --git a/src/Exceptionless.Web/ClientApp/.env b/src/Exceptionless.Web/ClientApp/.env index fc4b10c20e..8d9b339d36 100644 --- a/src/Exceptionless.Web/ClientApp/.env +++ b/src/Exceptionless.Web/ClientApp/.env @@ -1,11 +1,13 @@ +PUBLIC_BASE_URL= +PUBLIC_USE_SSL=false +PUBLIC_ENABLE_ACCOUNT_CREATION=true +PUBLIC_SYSTEM_NOTIFICATION_MESSAGE= PUBLIC_EXCEPTIONLESS_API_KEY= PUBLIC_EXCEPTIONLESS_SERVER_URL= +PUBLIC_STRIPE_PUBLISHABLE_KEY= PUBLIC_FACEBOOK_APPID= PUBLIC_GITHUB_APPID= PUBLIC_GOOGLE_APPID= -PUBLIC_INTERCOM_APPID= PUBLIC_LIVE_APPID= +PUBLIC_INTERCOM_APPID= PUBLIC_SLACK_APPID= -PUBLIC_STRIPE_PUBLISHABLE_KEY= -PUBLIC_SYSTEM_NOTIFICATION_MESSAGE= -PUBLIC_ENABLE_ACCOUNT_CREATION=true diff --git a/src/Exceptionless.Web/ClientApp/src/app.html b/src/Exceptionless.Web/ClientApp/src/app.html index ecd5efc035..7b622f4d8d 100644 --- a/src/Exceptionless.Web/ClientApp/src/app.html +++ b/src/Exceptionless.Web/ClientApp/src/app.html @@ -7,6 +7,7 @@ %sveltekit.head% +
%sveltekit.body%
diff --git a/src/Exceptionless.Web/ClientApp/src/hooks.client.ts b/src/Exceptionless.Web/ClientApp/src/hooks.client.ts index e3fbb6e9f0..200395e876 100644 --- a/src/Exceptionless.Web/ClientApp/src/hooks.client.ts +++ b/src/Exceptionless.Web/ClientApp/src/hooks.client.ts @@ -1,10 +1,10 @@ -import { PUBLIC_EXCEPTIONLESS_API_KEY, PUBLIC_EXCEPTIONLESS_SERVER_URL } from '$env/static/public'; +import { env } from '$env/dynamic/public'; import { Exceptionless, toError } from '@exceptionless/browser'; await Exceptionless.startup((c) => { - c.apiKey = PUBLIC_EXCEPTIONLESS_API_KEY; - c.serverUrl = PUBLIC_EXCEPTIONLESS_SERVER_URL || window.location.origin; + c.apiKey = env.PUBLIC_EXCEPTIONLESS_API_KEY; + c.serverUrl = env.PUBLIC_EXCEPTIONLESS_SERVER_URL || window.location.origin; c.defaultTags.push('UI', 'Svelte'); c.settings['@@log:*'] = 'debug'; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/api/auth.ts b/src/Exceptionless.Web/ClientApp/src/lib/api/auth.ts index 65dc9b0818..683eccb713 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/api/auth.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/api/auth.ts @@ -1,6 +1,6 @@ import { goto } from '$app/navigation'; import { page } from '$app/stores'; -import { PUBLIC_ENABLE_ACCOUNT_CREATION, PUBLIC_FACEBOOK_APPID, PUBLIC_GITHUB_APPID, PUBLIC_GOOGLE_APPID, PUBLIC_LIVE_APPID } from '$env/static/public'; +import { env } from '$env/dynamic/public'; import { persisted } from 'svelte-local-storage-store'; import { derived, get } from 'svelte/store'; @@ -11,12 +11,12 @@ export const accessToken = persisted('satellizer_token', null, { serializer: { parse: (s) => s, stringify: (s) => s as string } }); export const isAuthenticated = derived(accessToken, ($accessToken) => $accessToken !== null); -export const enableAccountCreation = PUBLIC_ENABLE_ACCOUNT_CREATION === 'true'; -export const facebookClientId = PUBLIC_FACEBOOK_APPID; -export const gitHubClientId = PUBLIC_GITHUB_APPID; -export const googleClientId = PUBLIC_GOOGLE_APPID; -export const liveClientId = PUBLIC_LIVE_APPID; -export const enableOAuthLogin = facebookClientId || gitHubClientId || googleClientId || liveClientId; +export const enableAccountCreation = env.PUBLIC_ENABLE_ACCOUNT_CREATION === 'true'; +export const facebookClientId = env.PUBLIC_FACEBOOK_APPID; +export const gitHubClientId = env.PUBLIC_GITHUB_APPID; +export const googleClientId = env.PUBLIC_GOOGLE_APPID; +export const microsoftClientId = env.PUBLIC_MICROSOFT_APPID; +export const enableOAuthLogin = facebookClientId || gitHubClientId || googleClientId || microsoftClientId; export async function login(email: string, password: string) { const data: Login = { email, password }; @@ -46,13 +46,13 @@ export async function logout() { } export async function liveLogin(redirectUrl?: string) { - if (!liveClientId) { + if (!microsoftClientId) { throw new Error('Live client id not set'); } await oauthLogin({ provider: 'live', - clientId: liveClientId, + clientId: microsoftClientId, authUrl: 'https://login.live.com/oauth20_authorize.srf', scope: 'wl.emails', extraParams: { diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/security/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/security/+page.svelte index 9e3d72b6f2..8ab6b32086 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/security/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/security/+page.svelte @@ -13,7 +13,7 @@ enableOAuthLogin, facebookClientId, gitHubClientId, - liveClientId + microsoftClientId } from '$api/auth'; import ErrorMessage from '$comp/ErrorMessage.svelte'; @@ -112,7 +112,7 @@
    - {#if !liveClientId} + {#if !microsoftClientId}
  • diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(auth)/login/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(auth)/login/+page.svelte index d43431c76e..7cbfddd7e2 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(auth)/login/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(auth)/login/+page.svelte @@ -20,7 +20,7 @@ enableOAuthLogin, facebookClientId, gitHubClientId, - liveClientId + microsoftClientId } from '$api/auth'; import { FetchClient, ProblemDetails } from '$lib/api/FetchClient'; import { Login } from '$lib/models/api'; @@ -93,7 +93,7 @@
    - {#if liveClientId} + {#if microsoftClientId} diff --git a/src/Exceptionless.Web/ClientApp/static/runtime-env.js b/src/Exceptionless.Web/ClientApp/static/runtime-env.js new file mode 100644 index 0000000000..2f5ddd78fd --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/static/runtime-env.js @@ -0,0 +1,19 @@ +(function (window) { + 'use strict'; + + window.__env = { + PUBLIC_BASE_URL: '', + PUBLIC_USE_SSL: false, + PUBLIC_ENABLE_ACCOUNT_CREATION: true, + PUBLIC_SYSTEM_NOTIFICATION_MESSAGE: '', + PUBLIC_EXCEPTIONLESS_API_KEY: '', + PUBLIC_EXCEPTIONLESS_SERVER_URL: '', + PUBLIC_STRIPE_PUBLISHABLE_KEY: '', + PUBLIC_FACEBOOK_APPID: '', + PUBLIC_GITHUB_APPID: '', + PUBLIC_GOOGLE_APPID: '', + PUBLIC_MICROSOFT_APPID: '', + PUBLIC_INTERCOM_APPID: '', + PUBLIC_SLACK_APPID: '' + }; +}(this)); From bba1a08d4ec04b6cbedc7a2f99879b8cab52da43 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 13 Feb 2024 08:19:12 -0600 Subject: [PATCH 2/2] Updated config --- build/update-config-next.sh | 2 +- .../ClientApp/src/hooks.client.ts | 15 ++++++++++++++- .../ClientApp/static/runtime-env.js | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/build/update-config-next.sh b/build/update-config-next.sh index 31da4775d3..61e347f489 100644 --- a/build/update-config-next.sh +++ b/build/update-config-next.sh @@ -53,7 +53,7 @@ config=" config_footer=" }; -}());" +})(this);" echo "Exceptionless UI Config" echo "$config" diff --git a/src/Exceptionless.Web/ClientApp/src/hooks.client.ts b/src/Exceptionless.Web/ClientApp/src/hooks.client.ts index 200395e876..3dbcdd31c3 100644 --- a/src/Exceptionless.Web/ClientApp/src/hooks.client.ts +++ b/src/Exceptionless.Web/ClientApp/src/hooks.client.ts @@ -1,6 +1,19 @@ +import { Exceptionless, toError } from '@exceptionless/browser'; + import { env } from '$env/dynamic/public'; +const { __env = {} } = globalThis as unknown as { __env: typeof env }; -import { Exceptionless, toError } from '@exceptionless/browser'; +// if we are in production, we will use the environment variables that were injected via docker configuration. +if (__env && import.meta.env.PROD) { + Object.assign(env, __env); +} + +// If the PUBLIC_BASE_URL is set in local storage, we will use that instead of the one from the environment variables. +// This allows you to target other environments from your browser. +const PUBLIC_BASE_URL = localStorage?.getItem('PUBLIC_BASE_URL'); +if (PUBLIC_BASE_URL) { + env.PUBLIC_BASE_URL = PUBLIC_BASE_URL; +} await Exceptionless.startup((c) => { c.apiKey = env.PUBLIC_EXCEPTIONLESS_API_KEY; diff --git a/src/Exceptionless.Web/ClientApp/static/runtime-env.js b/src/Exceptionless.Web/ClientApp/static/runtime-env.js index 2f5ddd78fd..09fc3d668b 100644 --- a/src/Exceptionless.Web/ClientApp/static/runtime-env.js +++ b/src/Exceptionless.Web/ClientApp/static/runtime-env.js @@ -16,4 +16,4 @@ PUBLIC_INTERCOM_APPID: '', PUBLIC_SLACK_APPID: '' }; -}(this)); +})(this);