diff --git a/src/account/components/AccountLogin.js b/src/account/components/AccountLogin.js
index 06971e28b8..024628051c 100644
--- a/src/account/components/AccountLogin.js
+++ b/src/account/components/AccountLogin.js
@@ -14,10 +14,10 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
-import React from 'react';
+import React, { useEffect } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
-import { Navigate, useSearchParams } from 'react-router-dom';
+import { useNavigate, useSearchParams } from 'react-router-dom';
import { fetchAuthURLs } from 'terraso-client-shared/account/accountSlice';
import { useFetchData } from 'terraso-client-shared/store/utils';
import AppleIcon from '@mui/icons-material/Apple';
@@ -45,28 +45,42 @@ const GoogleIcon = props => {
};
const appendReferrer = (url, referrer) => {
- return referrer ? `${url}&state=account?referrer=${referrer}` : url;
+ return referrer
+ ? `${url}&state=account?referrerBase64=${btoa(referrer)}`
+ : url;
};
const AccountForm = () => {
const { t } = useTranslation();
const { trackEvent } = useAnalytics();
+ const navigate = useNavigate();
const [searchParams] = useSearchParams();
const { fetching, urls } = useSelector(state => state.account.login);
const hasToken = useSelector(state => state.account.hasToken);
const referrer = searchParams.get('referrer');
+ const referrerBase64 = searchParams.get('referrerBase64');
useDocumentTitle(t('account.login_document_title'));
useDocumentDescription(t('account.login_document_description'));
useFetchData(fetchAuthURLs);
+ useEffect(() => {
+ if (!hasToken) {
+ return;
+ }
+ const url = referrerBase64 ? atob(referrerBase64) : referrer;
+ navigate(url ? decodeURIComponent(url) : '/', {
+ replace: true,
+ });
+ }, [hasToken, navigate, referrer, referrerBase64]);
+
if (fetching) {
return ;
}
if (hasToken) {
- return ;
+ return null;
}
return (
diff --git a/src/account/components/AccountLogin.test.js b/src/account/components/AccountLogin.test.js
index a329db953a..9b27bf39af 100644
--- a/src/account/components/AccountLogin.test.js
+++ b/src/account/components/AccountLogin.test.js
@@ -16,7 +16,7 @@
*/
import { render, screen } from 'tests/utils';
import React from 'react';
-import { useSearchParams } from 'react-router-dom';
+import { useNavigate, useSearchParams } from 'react-router-dom';
import * as accountService from 'terraso-client-shared/account/accountService';
import AccountLogin from 'account/components/AccountLogin';
@@ -26,10 +26,12 @@ jest.mock('terraso-client-shared/account/accountService');
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useSearchParams: jest.fn(),
+ useNavigate: jest.fn(),
}));
beforeEach(() => {
useSearchParams.mockReturnValue([new URLSearchParams(), () => {}]);
+ useNavigate.mockReturnValue(jest.fn());
});
test('AccountLogin: Display error', async () => {
@@ -61,7 +63,8 @@ test('AccountLogin: Display buttons', async () => {
test('AccountLogin: Add referrer', async () => {
const searchParams = new URLSearchParams();
- searchParams.set('referrer', 'groups?sort=-name');
+ const referrer = encodeURIComponent('groups?sort=-name&other=1');
+ searchParams.set('referrer', referrer);
useSearchParams.mockReturnValue([searchParams]);
accountService.getAuthURLs.mockReturnValue(
Promise.resolve({
@@ -71,17 +74,76 @@ test('AccountLogin: Add referrer', async () => {
);
await render();
expect(screen.getByText('Continue with Google')).toBeInTheDocument();
+ const state = `account?referrerBase64=${btoa(referrer)}`;
expect(screen.getByText('Continue with Google')).toHaveAttribute(
'href',
- 'google.url&state=groups?sort=-name'
+ `google.url&state=${state}`
);
expect(screen.getByText('Continue with Apple')).toBeInTheDocument();
expect(screen.getByText('Continue with Apple')).toHaveAttribute(
'href',
- 'apple.url&state=groups?sort=-name'
+ `apple.url&state=${state}`
);
});
+test('AccountLogin: Navigate to referrer if logged in', async () => {
+ accountService.getAuthURLs.mockReturnValue(
+ Promise.resolve({
+ google: 'google.url',
+ apple: 'apple.url',
+ })
+ );
+ const navigate = jest.fn();
+ useNavigate.mockReturnValue(navigate);
+ const searchParams = new URLSearchParams();
+ const referrer = encodeURIComponent('groups?sort=-name&other=1');
+ searchParams.set('referrer', referrer);
+ useSearchParams.mockReturnValue([searchParams]);
+ await render(, {
+ account: {
+ hasToken: true,
+ login: {},
+ currentUser: {
+ data: {
+ email: 'test@test.com',
+ },
+ },
+ },
+ });
+ expect(navigate).toHaveBeenCalledWith('groups?sort=-name&other=1', {
+ replace: true,
+ });
+});
+
+test('AccountLogin: Navigate to referrer base 64 if logged in', async () => {
+ accountService.getAuthURLs.mockReturnValue(
+ Promise.resolve({
+ google: 'google.url',
+ apple: 'apple.url',
+ })
+ );
+ const navigate = jest.fn();
+ useNavigate.mockReturnValue(navigate);
+ const searchParams = new URLSearchParams();
+ const referrer = encodeURIComponent('groups?sort=-name&other=1');
+ searchParams.set('referrerBase64', btoa(referrer));
+ useSearchParams.mockReturnValue([searchParams]);
+ await render(, {
+ account: {
+ hasToken: true,
+ login: {},
+ currentUser: {
+ data: {
+ email: 'test@test.com',
+ },
+ },
+ },
+ });
+ expect(navigate).toHaveBeenCalledWith('groups?sort=-name&other=1', {
+ replace: true,
+ });
+});
+
test('AccountLogin: Display locale picker', async () => {
accountService.getAuthURLs.mockReturnValue(
Promise.resolve({
diff --git a/src/account/components/RequireAuth.js b/src/account/components/RequireAuth.js
index 22400a7431..bcea17cd44 100644
--- a/src/account/components/RequireAuth.js
+++ b/src/account/components/RequireAuth.js
@@ -48,7 +48,9 @@ const RequireAuth = ({ children }) => {
const referrer = generateReferrerPath(location);
- const to = referrer ? `/account?referrer=${referrer}` : '/account';
+ const to = referrer
+ ? `/account?referrer=${encodeURIComponent(referrer)}`
+ : '/account';
return ;
};
diff --git a/src/account/components/RequireAuth.test.js b/src/account/components/RequireAuth.test.js
index 1593bb07f5..c4f1c9fee6 100644
--- a/src/account/components/RequireAuth.test.js
+++ b/src/account/components/RequireAuth.test.js
@@ -85,10 +85,24 @@ test('Auth: test redirect', async () => {
expect(terrasoApi.requestGraphQL).toHaveBeenCalledTimes(2);
expect(screen.getByText('To: /account')).toBeInTheDocument();
});
-test('Auth: test redirect referrer', async () => {
+
+const REDIRECT_PATHNAME = '/groups';
+const REDIRECT_SEARCH = '?sort=-name&other=1';
+const REFERRER_PATH = `/account?referrer=${encodeURIComponent(
+ `${REDIRECT_PATHNAME}${REDIRECT_SEARCH}`
+)}`;
+const REFERRER_URL = new URL(`http://127.0.0.1${REFERRER_PATH}`);
+
+test('Auth: Test url parsing for referrer', async () => {
+ expect(REFERRER_URL.searchParams.get('referrer')).toBe(
+ '/groups?sort=-name&other=1'
+ );
+});
+
+test('Auth: Test redirect referrer', async () => {
useLocation.mockReturnValue({
- pathname: '/groups',
- search: '?sort=-name',
+ pathname: REDIRECT_PATHNAME,
+ search: REDIRECT_SEARCH,
});
await render(
@@ -97,9 +111,10 @@ test('Auth: test redirect referrer', async () => {
);
expect(
- screen.getByText('To: /account?referrer=groups?sort=-name')
+ screen.getByText('To: /account?referrer=groups%3Fsort%3D-name%26other%3D1')
).toBeInTheDocument();
});
+
test('Auth: test refresh tokens', async () => {
useParams.mockReturnValue({
slug: 'slug-1',
diff --git a/src/navigation/navigationUtils.js b/src/navigation/navigationUtils.js
index 45c364a8c6..10d9e6d32a 100644
--- a/src/navigation/navigationUtils.js
+++ b/src/navigation/navigationUtils.js
@@ -22,8 +22,5 @@ export const generateReferrerPath = location => {
const referrer = [path.substring(1), queryParams]
.filter(part => part)
.join('');
- if (!referrer) {
- return null;
- }
- return btoa(`/${referrer}`);
+ return referrer;
};