From 0af813ae975227d89c7fa385d10315fa44465d05 Mon Sep 17 00:00:00 2001 From: Salah Benmoussati <51402489+sbenmoussati@users.noreply.github.com> Date: Tue, 28 Mar 2023 15:10:18 +0200 Subject: [PATCH] SDA-4089 Browser login autoconnect (#1809) * RTC-13931 Disable D3D11 by default * SDA-4089 Browser login autolaunch * SDA-4089 Browser login autolaunch * SDA-4089 Browser login autolaunch * SDA-4089 Browser login autolaunch * SDA-4089 Browser login autolaunch * SDA-4089 Browser login autolaunch * SDA-4089 Browser login autolaunch * cleanup --- config/Symphony.config | 1 + installer/mac/postinstall.sh | 4 + installer/win/WixSharpInstaller/Symphony.cs | 4 +- installer/win/install_instructions_win.md | 28 ++- spec/__snapshots__/welcome.spec.ts.snap | 77 ++++--- spec/welcome.spec.ts | 29 +-- src/app/app-menu.ts | 1 + src/app/auto-update-handler.ts | 3 + src/app/config-handler.ts | 3 +- src/app/main-api-handler.ts | 19 +- src/app/protocol-handler.ts | 24 ++- src/app/stores/presence-status-store.ts | 2 +- src/app/window-handler.ts | 12 +- src/common/api-interface.ts | 5 +- src/locale/en-US.json | 5 +- src/locale/en.json | 5 +- src/locale/fr-FR.json | 1 + src/locale/fr.json | 1 + src/locale/ja-JP.json | 1 + src/locale/ja.json | 1 + src/renderer/components/welcome.tsx | 224 ++++++++++++++------ src/renderer/styles/theme.less | 6 +- src/renderer/styles/welcome.less | 137 +++++++++++- 23 files changed, 449 insertions(+), 144 deletions(-) diff --git a/config/Symphony.config b/config/Symphony.config index 85664e36..e2f612de 100644 --- a/config/Symphony.config +++ b/config/Symphony.config @@ -5,6 +5,7 @@ "isAutoUpdateEnabled": true, "autoUpdateCheckInterval": "30", "enableBrowserLogin": false, + "browserLoginAutoConnect": false, "overrideUserAgent": false, "minimizeOnClose" : "ENABLED", "launchOnStartup" : "ENABLED", diff --git a/installer/mac/postinstall.sh b/installer/mac/postinstall.sh index 72cae78e..33c88015 100755 --- a/installer/mac/postinstall.sh +++ b/installer/mac/postinstall.sh @@ -18,6 +18,7 @@ always_on_top=$(sed -n '5p' ${settingsFilePath}); bring_to_front=$(sed -n '6p' ${settingsFilePath}); dev_tools_enabled=$(sed -n '7p' ${settingsFilePath}); enable_browser_login=$(sed -n '8p' ${settingsFilePath}); +browser_login_autoconnect=$(sed -n '9p' ${settingsFilePath}); ## If any of the above values turn out to be empty, set default values ## if [ "$pod_url" = "" ]; then pod_url="https://my.symphony.com"; fi @@ -28,6 +29,8 @@ if [ "$always_on_top" = "" ] || [ "$always_on_top" = 'false' ]; then always_on_t if [ "$bring_to_front" = "" ] || [ "$bring_to_front" = 'false' ]; then bring_to_front='DISABLED'; else bring_to_front='ENABLED'; fi if [ "$dev_tools_enabled" = "" ]; then dev_tools_enabled=true; fi if [ "$enable_browser_login" = "" ]; then enable_browser_login=false; fi +if [ "$browser_login_autoconnect" = "" ]; then browser_login_autoconnect=false; fi + pod_url_escaped=$(sed 's#[&/\]#\\&#g' <<<"$pod_url") context_origin_url_escaped=$(sed 's#[&/\]#\\&#g' <<<"$context_origin_url") @@ -40,6 +43,7 @@ sed -i "" -E "s#\"launchOnStartup\" ?: ?\"([Ee][Nn][Aa][Bb][Ll][Ee][Dd]|[Dd][Ii] sed -i "" -E "s#\"bringToFront\" ?: ?\"([Ee][Nn][Aa][Bb][Ll][Ee][Dd]|[Dd][Ii][Ss][Aa][Bb][Ll][Ee][Dd])\"#\"bringToFront\":\ \"$bring_to_front\"#g" "${newPath}" sed -i "" -E "s#\"devToolsEnabled\" ?: ?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])#\"devToolsEnabled\":\ $dev_tools_enabled#g" "${newPath}" sed -i "" -E "s#\"enableBrowserLogin\" ?: ?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])#\"enableBrowserLogin\":\ $enable_browser_login#g" "${newPath}" +sed -i "" -E "s#\"browserLoginAutoConnect\" ?: ?([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])#\"browserLoginAutoConnect\":\ $browser_login_autoconnect#g" "${newPath}" ## Get Symphony Permissions from the temp file ## media=$(sed -n '1p' ${permissionsFilePath}); diff --git a/installer/win/WixSharpInstaller/Symphony.cs b/installer/win/WixSharpInstaller/Symphony.cs index 021e4d64..d653d68a 100644 --- a/installer/win/WixSharpInstaller/Symphony.cs +++ b/installer/win/WixSharpInstaller/Symphony.cs @@ -159,6 +159,7 @@ class Script new PublicProperty("USER_DATA_PATH", ""), new PublicProperty("OVERRIDE_USER_AGENT", "false"), new PublicProperty("ENABLE_BROWSER_LOGIN", "false"), + new PublicProperty("BROWSER_LOGIN_AUTOCONNECT", "false"), new PublicProperty("CHROME_FLAGS", ""), new Property("MSIINSTALLPERUSER", "1"), new Property("PROGRAMSFOLDER", System.Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%")) @@ -187,7 +188,7 @@ class Script new ElevatedManagedAction(CustomActions.UpdateConfig, Return.check, When.After, Step.InstallFiles, Condition.NOT_BeingRemoved ) { // The UpdateConfig action needs the built-in property INSTALLDIR as well as most of the custom properties - UsesProperties = "INSTALLDIR,POD_URL,CONTEXT_ORIGIN_URL,MINIMIZE_ON_CLOSE,ALWAYS_ON_TOP,AUTO_START,BRING_TO_FRONT,MEDIA,LOCATION,NOTIFICATIONS,MIDI_SYSEX,POINTER_LOCK,FULL_SCREEN,OPEN_EXTERNAL,CUSTOM_TITLE_BAR,DEV_TOOLS_ENABLED,AUTO_LAUNCH_PATH,USER_DATA_PATH,OVERRIDE_USER_AGENT,CHROME_FLAGS,ENABLE_BROWSER_LOGIN" + UsesProperties = "INSTALLDIR,POD_URL,CONTEXT_ORIGIN_URL,MINIMIZE_ON_CLOSE,ALWAYS_ON_TOP,AUTO_START,BRING_TO_FRONT,MEDIA,LOCATION,NOTIFICATIONS,MIDI_SYSEX,POINTER_LOCK,FULL_SCREEN,OPEN_EXTERNAL,CUSTOM_TITLE_BAR,DEV_TOOLS_ENABLED,AUTO_LAUNCH_PATH,USER_DATA_PATH,OVERRIDE_USER_AGENT,CHROME_FLAGS,ENABLE_BROWSER_LOGIN,BROWSER_LOGIN_AUTOCONNECT" }, // CleanRegistry @@ -362,6 +363,7 @@ public class CustomActions data = ReplaceBooleanProperty(data, "devToolsEnabled", session.Property("DEV_TOOLS_ENABLED")); data = ReplaceBooleanProperty(data, "overrideUserAgent", session.Property("OVERRIDE_USER_AGENT")); data = ReplaceBooleanProperty(data, "enableBrowserLogin", session.Property("ENABLE_BROWSER_LOGIN")); + data = ReplaceBooleanProperty(data, "browserLoginAutoConnect", session.Property("BROWSER_LOGIN_AUTOCONNECT")); // Write the contents back to the file System.IO.File.WriteAllText(filename, data); } diff --git a/installer/win/install_instructions_win.md b/installer/win/install_instructions_win.md index c2f75f2d..b1841789 100644 --- a/installer/win/install_instructions_win.md +++ b/installer/win/install_instructions_win.md @@ -535,15 +535,15 @@ Expected values: Expected values: * "true" - SDA will authenticate the user by relying on third-party browser + SDA will authenticate the user by relying on default browser * "false" SDA will authenticate the user in SDA -#### Example, install with user-agent override +#### Example, install with browser login enabled msiexec /i Symphony.msi ENABLE_BROWSER_LOGIN="true" -#### Example, install without user-agent override +#### Example, install without browser login enabled msiexec /i Symphony.msi ENABLE_BROWSER_LOGIN="false" @@ -554,3 +554,25 @@ or ------------------------------------------------------------------- +### BROWSER_LOGIN_AUTOCONNECT + +Acts in combination with ENABLE_BROWSER_LOGIN, if ENABLE_BROWSER_LOGIN is set to true. + +Expected values: + +* "true" + SDA will automatically authenticate the user by relying on default browser +* "false" + User will need to click on Login button to start browser login flow. + +#### Example, install with browser login autoconnect enabled + + msiexec /i Symphony.msi BROWSER_LOGIN_AUTOCONNECT="true" + +#### Example, install with browser login autoconnect disabled + + msiexec /i Symphony.msi BROWSER_LOGIN_AUTOCONNECT="false" + +or + + msiexec /i Symphony.msi diff --git a/spec/__snapshots__/welcome.spec.ts.snap b/spec/__snapshots__/welcome.spec.ts.snap index 91f5d8ad..98ac3111 100644 --- a/spec/__snapshots__/welcome.spec.ts.snap +++ b/spec/__snapshots__/welcome.spec.ts.snap @@ -99,35 +99,60 @@ exports[`welcome should render correctly 1`] = ` 1,000 institutions. -
-
- - Log in with your pod URL - +
+ + Log in with your pod URL + +
+
+ + Pod URL + +
+ +
-
+
+ +
+ + Automatically redirect to your web browser on launch -
- - -
+ )} +
+ )}
); @@ -110,7 +137,18 @@ export default class Welcome extends React.Component<{}, IState> { * Perform actions on component being mounted */ public componentDidMount(): void { - ipcRenderer.on('welcome', this.updateState); + ipcRenderer.on('welcome', (_event, data) => { + if ( + data.isPodConfigured && + data.browserLoginAutoConnect && + data.isBrowserLoginEnabled + ) { + this.browserLoginTimeoutId = setTimeout(() => { + this.login(); + }, BROWSER_LOGIN_AUTO_REDIRECT_TIMEOUT); + } + this.updateState(_event, data); + }); } /** @@ -125,12 +163,18 @@ export default class Welcome extends React.Component<{}, IState> { */ public login(): void { this.setState({ isLoading: true }); - const { url, isPodConfigured, isSeamlessLoginEnabled } = this.state; + const { + url, + isPodConfigured, + isBrowserLoginEnabled, + browserLoginAutoConnect, + } = this.state; ipcRenderer.send(apiName.symphonyApi, { - cmd: apiCmds.seamlessLogin, + cmd: apiCmds.browserLogin, newPodUrl: url, isPodConfigured, - isSeamlessLoginEnabled, + isBrowserLoginEnabled, + browserLoginAutoConnect, }); } @@ -159,13 +203,73 @@ export default class Welcome extends React.Component<{}, IState> { }); } + /** + * Update pod url from the text box + * @param event + */ + public updateBrowserLoginAutoConnect(event) { + const { urlValid } = this.state; + const browserLoginAutoConnect = event.target.checked; + if (!browserLoginAutoConnect) { + if (this.browserLoginTimeoutId) { + clearTimeout(this.browserLoginTimeoutId); + } + this.setState({ + browserLoginAutoConnect, + }); + } + + if (urlValid && browserLoginAutoConnect) { + this.setState({ + browserLoginAutoConnect, + isLoading: true, + }); + const { url, isPodConfigured, isBrowserLoginEnabled } = this.state; + ipcRenderer.send(apiName.symphonyApi, { + cmd: apiCmds.browserLogin, + newPodUrl: url, + isPodConfigured, + isBrowserLoginEnabled, + browserLoginAutoConnect, + }); + } + } + /** * Renders login button content */ private renderLoginButton() { - const { isLoading, isPodConfigured, urlValid } = this.state; - if (!isLoading) { - return ( + const { + isLoading, + isPodConfigured, + urlValid, + isBrowserLoginEnabled, + browserLoginAutoConnect, + } = this.state; + return ( + + {isBrowserLoginEnabled && ( +
+ +
+ + {i18n.t( + 'Automatically redirect to your web browser on launch', + WELCOME_NAMESPACE, + )()} + +
+
+ )} + - ); - } - return ( -
-
- - - -
-
+
); } diff --git a/src/renderer/styles/theme.less b/src/renderer/styles/theme.less index e95d7b28..05b11a93 100644 --- a/src/renderer/styles/theme.less +++ b/src/renderer/styles/theme.less @@ -7,11 +7,13 @@ // Color palette @electricity-ui-05: #e9f2f9; -@electricity-ui-50: #0277d6; -@electricity-ui-40: #2996fd; +@electricity-ui-20: #aad4f8; @electricity-ui-30: #6eb9fd; +@electricity-ui-40: #2996fd; +@electricity-ui-50: #0277d6; @electricity-ui-60: #27588e; +@graphite-10: #e3e5e7; @graphite-20: #cdcfd4; @graphite-05: #f1f1f3; @graphite-80: #27292c; diff --git a/src/renderer/styles/welcome.less b/src/renderer/styles/welcome.less index b6bed5c2..f1cc6852 100644 --- a/src/renderer/styles/welcome.less +++ b/src/renderer/styles/welcome.less @@ -220,10 +220,10 @@ body { text-decoration: none; line-height: 12px; background-color: @electricity-ui-50; - color: #ffffff; + color: @text-color-primary; cursor: pointer; text-transform: uppercase; - margin: 24px 0 4px 0; + margin: 16px 0 4px 0; &:focus { box-shadow: 0 0 10px rgba(61, 162, 253, 1); @@ -236,16 +236,61 @@ body { } &-redirect-info-text-container { - margin-top: 32px; + margin-top: 40px; + margin-bottom: 16px; span { font-weight: 400; - font-size: 12px; + font-size: 14px; line-height: 16px; text-align: center; color: @graphite-30; } } + + &-retry-button { + box-shadow: none; + border: none; + cursor: pointer; + padding: 0; + margin: 0 8px; + font-size: 14px; + text-align: center; + display: inline-block; + text-decoration: none; + background-color: transparent; + color: @electricity-ui-30; + } + + &-auto-connect-wrapper { + display: flex; + margin-top: 18px; + + .auto-connect-labels { + display: flex; + flex-direction: column; + .auto-connect-label { + font-size: 14px; + color: @graphite-10; + margin-bottom: 8px; + font-weight: 300; + } + .auto-connect-help-label { + font-size: 12px; + color: @graphite-30; + } + } + } + &-welcome-back { + font-size: 14px; + color: @graphite-05; + margin-top: 40px; + } + &-login-label { + font-size: 18px; + color: @graphite-05; + margin-top: 13px; + } } @keyframes fade-in-logo { @@ -313,15 +358,14 @@ body { .splash-screen--spinner-container { opacity: 0; animation: fade-in-spinner 1s ease-in 0s forwards; - margin-top: 2rem; text-align: center; } .splash-screen--spinner { display: inline-block; line-height: 1; - color: #0277d6; - width: 40px; - height: 40px; + color: @electricity-ui-50; + width: 20px; + height: 20px; animation: progress-circular-rotate 1.4s linear infinite; } .splash-screen--spinner-circle { @@ -330,3 +374,80 @@ body { stroke-dashoffset: 0px; stroke: currentColor; } + +.switch { + margin: auto; + margin-right: 8px; + position: relative; + display: inline-block; + width: 43px; + height: 8px; +} + +/* Hide default HTML checkbox */ +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +/* The slider */ +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + -webkit-transition: 0.4s; + transition: 0.4s; + background-color: @graphite-60; +} + +.slider:before { + position: absolute; + content: ''; + height: 14px; + width: 14px; + bottom: -5px; + -webkit-transition: 0.4s; + transition: 0.4s; + background-color: @graphite-80; + border: 2px solid @electricity-ui-40; + &:disabled { + background-color: #090a0b; + } +} + +input:checked + .slider:before { + -webkit-transform: translateX(20px); + -ms-transform: translateX(20px); + transform: translateX(20px); + background-color: @electricity-ui-40; +} + +input:not(:checked) + .slider { + &:hover { + &::before { + border-color: @electricity-ui-30; + } + } +} + +input:checked + .slider { + &:hover { + &::before { + background-color: @electricity-ui-30; + border-color: @electricity-ui-30; + } + } +} + +/* Rounded sliders */ +.slider.round { + border-radius: 34px; +} + +.slider.round:before { + border-radius: 50%; +}