From 0e9d3165a7f1c4a908c63d1ece1a59e83f011f57 Mon Sep 17 00:00:00 2001 From: jay-hodgson Date: Mon, 28 Oct 2024 13:55:54 -0700 Subject: [PATCH 1/9] SWC-7132 --- .../src/components/ChangePasswordPage.tsx | 10 ++-------- .../src/components/Authentication/Login.test.tsx | 2 +- .../synapse-react-client/src/utils/hooks/useLogin.ts | 11 ++--------- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/apps/SageAccountWeb/src/components/ChangePasswordPage.tsx b/apps/SageAccountWeb/src/components/ChangePasswordPage.tsx index d0fd6b81e8..4ddf5fe41b 100644 --- a/apps/SageAccountWeb/src/components/ChangePasswordPage.tsx +++ b/apps/SageAccountWeb/src/components/ChangePasswordPage.tsx @@ -3,16 +3,10 @@ import { LeftRightPanel } from './LeftRightPanel' import { SourceAppLogo } from './SourceApp' import { SetPasswordInstructions } from './ResetPassword' import { ChangePassword } from 'synapse-react-client' -import { useLocation } from 'react-router-dom' export const ChangePasswordPage = () => { - const { search } = useLocation() - const urlSearchParams = new URLSearchParams(search) - const errorCode = urlSearchParams.get('errorCode') ?? '' - const instructions = - errorCode == 'PASSWORD_RESET_VIA_EMAIL_REQUIRED' - ? 'Your current password does not meet Synapse security requirements' - : 'Set a new password' + // previously, if the errorCode was PASSWORD_RESET_VIA_EMAIL_REQUIRED then this page would tell the user that their current password does not meet Synapse security requirements. But this is not necessarily true. + const instructions = 'Set a new password' return ( <> { ) expect(callback).not.toHaveBeenCalled() expect(window.location.assign).toHaveBeenCalledWith( - 'http://localhost:3000/changePassword?errorCode=PASSWORD_RESET_VIA_EMAIL_REQUIRED', + 'http://localhost:3000/changePassword', ) }) }) diff --git a/packages/synapse-react-client/src/utils/hooks/useLogin.ts b/packages/synapse-react-client/src/utils/hooks/useLogin.ts index c96e9c88ef..c497f8f2e4 100644 --- a/packages/synapse-react-client/src/utils/hooks/useLogin.ts +++ b/packages/synapse-react-client/src/utils/hooks/useLogin.ts @@ -71,15 +71,8 @@ export default function useLogin(opts: UseLoginOptions): UseLoginReturn { const [twoFaErrorResponse, setTwoFaErrorResponse] = useState< TwoFactorAuthErrorResponse | undefined >() - const changePasswordSearchParams = new URLSearchParams() - changePasswordSearchParams.set( - 'errorCode', - ErrorResponseCode.PASSWORD_RESET_VIA_EMAIL_REQUIRED, - ) - const changePasswordUrl = useOneSageURL( - '/changePassword', - changePasswordSearchParams, - ) + + const changePasswordUrl = useOneSageURL('/changePassword') /** * Update state variable if optional prop changes */ From 22c3dff459b7b374b66fd636fb846cd77700e34c Mon Sep 17 00:00:00 2001 From: jay-hodgson Date: Mon, 28 Oct 2024 14:16:59 -0700 Subject: [PATCH 2/9] comment out ELITE portal computation tools e2e test for now --- apps/portals-e2e/src/configs/exploreConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/portals-e2e/src/configs/exploreConfig.ts b/apps/portals-e2e/src/configs/exploreConfig.ts index e1fb3ad7dd..e8b675d98c 100644 --- a/apps/portals-e2e/src/configs/exploreConfig.ts +++ b/apps/portals-e2e/src/configs/exploreConfig.ts @@ -52,7 +52,7 @@ const exploreConfig: ExploreConfig = { 'Projects', 'Studies', 'Publications', - 'Computational Tools', + // 'Computational Tools', // empty - known data curation issue ], people_charts: ['People'], }, From 0642204d3a5820837d341baff1611e6938c9e9e5 Mon Sep 17 00:00:00 2001 From: jay-hodgson Date: Mon, 28 Oct 2024 15:00:29 -0700 Subject: [PATCH 3/9] only show the Synapse specific dialog (refering to Data) if redirecting to a /Synapse route --- .../src/components/RedirectDialog.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/synapse-portal-framework/src/components/RedirectDialog.tsx b/apps/synapse-portal-framework/src/components/RedirectDialog.tsx index 2a6b32f689..bd3ba4baa2 100644 --- a/apps/synapse-portal-framework/src/components/RedirectDialog.tsx +++ b/apps/synapse-portal-framework/src/components/RedirectDialog.tsx @@ -43,7 +43,11 @@ export const synapseRedirectInstructions = ( const isSynapseURL = (url: string) => { if (!url) return false - return new URL(url).hostname.toLowerCase() === 'www.synapse.org' + const parsedURL = new URL(url) + return ( + parsedURL.hostname.toLowerCase() === 'www.synapse.org' && + parsedURL.pathname.startsWith('/Synapse') + ) } const getInitialCountdownSeconds = (redirectURL: string) => { @@ -106,7 +110,7 @@ const RedirectDialog = (props: RedirectDialogProps) => { className="RedirectDialog" PaperProps={{ sx: { padding: 0 } }} > - +
Date: Tue, 29 Oct 2024 11:28:45 -0700 Subject: [PATCH 4/9] PORTALS-3299: proposed solution for oauth sign in app when prompt is set to login --- apps/synapse-oauth-signin/package.json | 1 + .../src/AppInitializer.tsx | 8 +++++++- .../src/utils/AppUtils/AppUtils.ts | 19 +++++++++++++++++-- .../src/utils/SynapseConstants.ts | 3 +++ pnpm-lock.yaml | 3 +++ 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/apps/synapse-oauth-signin/package.json b/apps/synapse-oauth-signin/package.json index 52a9234775..66bf79ee75 100644 --- a/apps/synapse-oauth-signin/package.json +++ b/apps/synapse-oauth-signin/package.json @@ -22,6 +22,7 @@ "react-dom": "^18.2.0", "react-router-dom": "^5.3.4", "sass": "^1.71.1", + "universal-cookie": "^4.0.4", "synapse-react-client": "workspace:*" }, "devDependencies": { diff --git a/apps/synapse-oauth-signin/src/AppInitializer.tsx b/apps/synapse-oauth-signin/src/AppInitializer.tsx index 440e12ac1a..0ed78ae70c 100644 --- a/apps/synapse-oauth-signin/src/AppInitializer.tsx +++ b/apps/synapse-oauth-signin/src/AppInitializer.tsx @@ -6,12 +6,18 @@ import { SynapseConstants, } from 'synapse-react-client' import { handleErrorRedirect } from './URLUtils' +import UniversalCookies from 'universal-cookie' +const cookies = new UniversalCookies() function AppInitializer( props: React.PropsWithChildren>, ) { + const accountSitePrompted = cookies.get( + SynapseConstants.ACCOUNT_SITE_PROMPTED_FOR_LOGIN_COOKIE_KEY, + ) // short-lived cookie const urlSearchParams = new URLSearchParams(window.location.search) - const prompt = urlSearchParams.get('prompt') + const prompt = + accountSitePrompted == 'true' ? 'none' : urlSearchParams.get('prompt') let maxAge = undefined // check max age when re-establishing the session, not to auto-consent. diff --git a/packages/synapse-react-client/src/utils/AppUtils/AppUtils.ts b/packages/synapse-react-client/src/utils/AppUtils/AppUtils.ts index 56b58ec571..9bcf92ee6b 100644 --- a/packages/synapse-react-client/src/utils/AppUtils/AppUtils.ts +++ b/packages/synapse-react-client/src/utils/AppUtils/AppUtils.ts @@ -1,5 +1,8 @@ import { useHistory } from 'react-router-dom' -import { LAST_PLACE_LOCALSTORAGE_KEY } from '../SynapseConstants' +import { + ACCOUNT_SITE_PROMPTED_FOR_LOGIN_COOKIE_KEY, + LAST_PLACE_LOCALSTORAGE_KEY, +} from '../SynapseConstants' import { useEffect, useState } from 'react' import UniversalCookies from 'universal-cookie' @@ -33,10 +36,22 @@ export function storeRedirectURLForOneSageLoginAndGotoURL(href: string) { } export function processRedirectURLInOneSage() { + // PORTALS-3299 : Indicate that we have completed the login workflow (cookie expires in a minute) to break out of a cycle + const expireDate = new Date() + expireDate.setMinutes(expireDate.getMinutes() + 1) + const hostname = window.location.hostname.toLowerCase() + cookies.set(ACCOUNT_SITE_PROMPTED_FOR_LOGIN_COOKIE_KEY, 'true', { + path: '/', + expires: expireDate, + domain: hostname.endsWith('.synapse.org') ? 'synapse.org' : undefined, + }) + if (cookies.get(ONE_SAGE_REDIRECT_COOKIE_KEY)) { const href = cookies.get(ONE_SAGE_REDIRECT_COOKIE_KEY) cookies.remove(ONE_SAGE_REDIRECT_COOKIE_KEY) - window.location.assign(href) + setTimeout(() => { + window.location.assign(href) + }, 10) return true } //else diff --git a/packages/synapse-react-client/src/utils/SynapseConstants.ts b/packages/synapse-react-client/src/utils/SynapseConstants.ts index df749f3d4d..c42c8ecabd 100644 --- a/packages/synapse-react-client/src/utils/SynapseConstants.ts +++ b/packages/synapse-react-client/src/utils/SynapseConstants.ts @@ -186,6 +186,9 @@ export const ACCESS_TOKEN_COOKIE_KEY = 'org.sagebionetworks.security.user.login.token' export const LAST_PLACE_LOCALSTORAGE_KEY = 'last_place_url' +export const ACCOUNT_SITE_PROMPTED_FOR_LOGIN_COOKIE_KEY = + 'org.sagebionetworks.account.promptedforlogin' + /* Persistent localStorage keys on SWC logout */ export const PERSISTENT_LOCAL_STORAGE_KEYS = [ ...ORIENTATION_BANNER_KEYS, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c11a908268..9ecdcd38f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -854,6 +854,9 @@ importers: synapse-react-client: specifier: workspace:* version: link:../../packages/synapse-react-client + universal-cookie: + specifier: ^4.0.4 + version: 4.0.4 devDependencies: '@sage-bionetworks/synapse-types': specifier: workspace:* From ec7906b4dcd4ff5d25f596e1dc0324b496ec958b Mon Sep 17 00:00:00 2001 From: Jay Hodgson Date: Tue, 29 Oct 2024 11:51:17 -0700 Subject: [PATCH 5/9] Update apps/synapse-oauth-signin/src/AppInitializer.tsx Co-authored-by: Nick Grosenbacher --- apps/synapse-oauth-signin/src/AppInitializer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/synapse-oauth-signin/src/AppInitializer.tsx b/apps/synapse-oauth-signin/src/AppInitializer.tsx index 0ed78ae70c..d31ec8e305 100644 --- a/apps/synapse-oauth-signin/src/AppInitializer.tsx +++ b/apps/synapse-oauth-signin/src/AppInitializer.tsx @@ -14,7 +14,7 @@ function AppInitializer( ) { const accountSitePrompted = cookies.get( SynapseConstants.ACCOUNT_SITE_PROMPTED_FOR_LOGIN_COOKIE_KEY, - ) // short-lived cookie + ) == 'true' // short-lived cookie const urlSearchParams = new URLSearchParams(window.location.search) const prompt = accountSitePrompted == 'true' ? 'none' : urlSearchParams.get('prompt') From db78ab3c8173b79bde206935d9d5e9f239ab7c33 Mon Sep 17 00:00:00 2001 From: Jay Hodgson Date: Tue, 29 Oct 2024 11:51:30 -0700 Subject: [PATCH 6/9] Update apps/synapse-oauth-signin/src/AppInitializer.tsx Co-authored-by: Nick Grosenbacher --- apps/synapse-oauth-signin/src/AppInitializer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/synapse-oauth-signin/src/AppInitializer.tsx b/apps/synapse-oauth-signin/src/AppInitializer.tsx index d31ec8e305..0ff574fb74 100644 --- a/apps/synapse-oauth-signin/src/AppInitializer.tsx +++ b/apps/synapse-oauth-signin/src/AppInitializer.tsx @@ -17,7 +17,7 @@ function AppInitializer( ) == 'true' // short-lived cookie const urlSearchParams = new URLSearchParams(window.location.search) const prompt = - accountSitePrompted == 'true' ? 'none' : urlSearchParams.get('prompt') + accountSitePrompted ? 'none' : urlSearchParams.get('prompt') let maxAge = undefined // check max age when re-establishing the session, not to auto-consent. From 904338b0649573408bda3168c88045f3c4fecc93 Mon Sep 17 00:00:00 2001 From: jay-hodgson Date: Tue, 29 Oct 2024 11:54:24 -0700 Subject: [PATCH 7/9] from code review --- packages/synapse-react-client/src/utils/AppUtils/AppUtils.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/synapse-react-client/src/utils/AppUtils/AppUtils.ts b/packages/synapse-react-client/src/utils/AppUtils/AppUtils.ts index 9bcf92ee6b..f7b5f9a301 100644 --- a/packages/synapse-react-client/src/utils/AppUtils/AppUtils.ts +++ b/packages/synapse-react-client/src/utils/AppUtils/AppUtils.ts @@ -49,9 +49,7 @@ export function processRedirectURLInOneSage() { if (cookies.get(ONE_SAGE_REDIRECT_COOKIE_KEY)) { const href = cookies.get(ONE_SAGE_REDIRECT_COOKIE_KEY) cookies.remove(ONE_SAGE_REDIRECT_COOKIE_KEY) - setTimeout(() => { - window.location.assign(href) - }, 10) + window.location.assign(href) return true } //else From 3098c9d82554ee30f60f9195f0876fcc683e4380 Mon Sep 17 00:00:00 2001 From: jay-hodgson Date: Tue, 29 Oct 2024 12:36:39 -0700 Subject: [PATCH 8/9] PORTALS-3299: only respect maxAge if we did not just log in --- apps/synapse-oauth-signin/src/AppInitializer.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/synapse-oauth-signin/src/AppInitializer.tsx b/apps/synapse-oauth-signin/src/AppInitializer.tsx index 0ff574fb74..8b7adff464 100644 --- a/apps/synapse-oauth-signin/src/AppInitializer.tsx +++ b/apps/synapse-oauth-signin/src/AppInitializer.tsx @@ -12,18 +12,17 @@ const cookies = new UniversalCookies() function AppInitializer( props: React.PropsWithChildren>, ) { - const accountSitePrompted = cookies.get( - SynapseConstants.ACCOUNT_SITE_PROMPTED_FOR_LOGIN_COOKIE_KEY, - ) == 'true' // short-lived cookie + const accountSitePrompted = + cookies.get(SynapseConstants.ACCOUNT_SITE_PROMPTED_FOR_LOGIN_COOKIE_KEY) == + 'true' // short-lived cookie const urlSearchParams = new URLSearchParams(window.location.search) - const prompt = - accountSitePrompted ? 'none' : urlSearchParams.get('prompt') + const prompt = accountSitePrompted ? 'none' : urlSearchParams.get('prompt') let maxAge = undefined // check max age when re-establishing the session, not to auto-consent. const maxAgeURLParam = urlSearchParams.get('max_age') // SWC-5597: if max_age is defined, then return if the user last authenticated more than max_age seconds ago - if (maxAgeURLParam && parseInt(maxAgeURLParam)) { + if (!accountSitePrompted && maxAgeURLParam && parseInt(maxAgeURLParam)) { maxAge = parseInt(maxAgeURLParam) } From b552992892530799adb5a3a9fd87495009aebf96 Mon Sep 17 00:00:00 2001 From: Nick Grosenbacher Date: Tue, 29 Oct 2024 17:06:20 -0400 Subject: [PATCH 9/9] SWC-7084 --- .../TableColumnSchemaEditor/TableColumnSchemaEditorUtils.test.ts | 1 + .../TableColumnSchemaEditor/TableColumnSchemaEditorUtils.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/synapse-react-client/src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.test.ts b/packages/synapse-react-client/src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.test.ts index 24a9fe58ed..960d2cc7fc 100644 --- a/packages/synapse-react-client/src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.test.ts +++ b/packages/synapse-react-client/src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.test.ts @@ -126,6 +126,7 @@ describe('TableColumnSchemaEditorUtils', () => { ColumnTypeEnum.BOOLEAN_LIST, ColumnTypeEnum.DATE_LIST, ColumnTypeEnum.INTEGER_LIST, + ColumnTypeEnum.ENTITYID_LIST, ] Object.values(ColumnTypeEnum).forEach((key: ColumnType) => { diff --git a/packages/synapse-react-client/src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.ts b/packages/synapse-react-client/src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.ts index 951c0eb095..46a27cc892 100644 --- a/packages/synapse-react-client/src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.ts +++ b/packages/synapse-react-client/src/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.ts @@ -145,6 +145,7 @@ export function canHaveMaxListLength( case ColumnTypeEnum.BOOLEAN_LIST: case ColumnTypeEnum.DATE_LIST: case ColumnTypeEnum.INTEGER_LIST: + case ColumnTypeEnum.ENTITYID_LIST: return true default: // all others are false