Skip to content
This repository has been archived by the owner on Nov 21, 2024. It is now read-only.

feat: handle redirection url search param #222

Merged
merged 3 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@emotion/cache": "11.11.0",
"@emotion/react": "11.11.1",
"@emotion/styled": "11.11.0",
"@graasp/query-client": "1.4.3",
"@graasp/query-client": "1.6.0",
"@graasp/sdk": "1.3.0",
"@graasp/translations": "1.18.3",
"@graasp/ui": "3.3.2",
Expand Down
6 changes: 5 additions & 1 deletion src/components/Redirection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ import { RedirectionContent } from '@graasp/ui';

import { GRAASP_BUILDER_HOST } from '../config/env';
import { hooks } from '../config/queryClient';
import { useRedirection } from '../hooks/searchParams';

type Props = {
children: React.ReactElement;
};

const Redirection: FC<Props> = ({ children }) => {
const { data: member } = hooks.useCurrentMember();
const redirect = useRedirection();

if (member?.get('id')) {
redirectToSavedUrl(GRAASP_BUILDER_HOST);

return <RedirectionContent link={getUrlForRedirection() ?? ''} />;
return (
<RedirectionContent link={redirect.url ?? getUrlForRedirection() ?? ''} />
);
}

return children;
Expand Down
13 changes: 10 additions & 3 deletions src/components/SignIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import {
SIGN_IN_HEADER_ID,
} from '../config/selectors';
import { useRecaptcha } from '../context/RecaptchaContext';
import { useMobileLogin } from '../hooks/mobile';
import { useMobileAppLogin } from '../hooks/mobile';
import { useRedirection } from '../hooks/searchParams';
import { SIGN_IN_METHODS } from '../types/signInMethod';
import { emailValidator, passwordValidator } from '../utils/validation';
import EmailInput from './EmailInput';
Expand All @@ -44,8 +45,9 @@ const SignIn: FC = () => {
const { t } = useAuthTranslation();
const { executeCaptcha } = useRecaptcha();

const { isMobile, challenge } = useMobileLogin();
const { isMobile, challenge } = useMobileAppLogin();
const { search } = useLocation();
const redirect = useRedirection();

const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
Expand Down Expand Up @@ -80,7 +82,11 @@ const SignIn: FC = () => {
);
await (isMobile
? mobileSignIn({ email: lowercaseEmail, captcha: token, challenge })
: signIn({ email: lowercaseEmail, captcha: token }));
: signIn({
email: lowercaseEmail,
captcha: token,
url: redirect.url,
}));
setSuccessView(true);
} catch (e) {
console.error(e);
Expand Down Expand Up @@ -114,6 +120,7 @@ const SignIn: FC = () => {
email: lowercaseEmail,
password,
captcha: token,
url: redirect.url,
}));
if (result && result.resource) {
window.location.href = result.resource;
Expand Down
7 changes: 5 additions & 2 deletions src/components/SignUp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
SIGN_UP_HEADER_ID,
} from '../config/selectors';
import { useRecaptcha } from '../context/RecaptchaContext';
import { useMobileLogin } from '../hooks/mobile';
import { useMobileAppLogin } from '../hooks/mobile';
import { useRedirection } from '../hooks/searchParams';
import { emailValidator, nameValidator } from '../utils/validation';
import EmailInput from './EmailInput';
import FullscreenContainer from './FullscreenContainer';
Expand All @@ -33,7 +34,8 @@ const SignUp = () => {
const { t } = useAuthTranslation();
const { executeCaptcha } = useRecaptcha();

const { isMobile, challenge } = useMobileLogin();
const { isMobile, challenge } = useMobileAppLogin();
const redirect = useRedirection();

const [email, setEmail] = useState<string>('');
const [name, setName] = useState<string>('');
Expand Down Expand Up @@ -98,6 +100,7 @@ const SignUp = () => {
name: name.trim(),
email: lowercaseEmail,
captcha: token,
url: redirect.url,
}));
setSuccessView(true);
}
Expand Down
15 changes: 12 additions & 3 deletions src/components/SuccessContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ import { Container, Stack, Typography } from '@mui/material';

import { useAuthTranslation } from '../config/i18n';
import { mutations } from '../config/queryClient';
import { SUCCESS_CONTENT_ID } from '../config/selectors';
import { BACK_BUTTON_ID, RESEND_EMAIL_BUTTON_ID } from '../config/selectors';
import {
BACK_BUTTON_ID,
RESEND_EMAIL_BUTTON_ID,
SUCCESS_CONTENT_ID,
} from '../config/selectors';
import { useRecaptcha } from '../context/RecaptchaContext';
import { useRedirection } from '../hooks/searchParams';

type Props = {
title: string;
Expand All @@ -30,13 +34,18 @@ const SuccessContent = ({
const [isEmailSent, setIsEmailSent] = useState(false);

// used for resend email
const redirect = useRedirection();
const { mutate: signIn } = mutations.useSignIn();

// used for resend email
const handleResendEmail = async () => {
const lowercaseEmail = email.toLowerCase();
const token = await executeCaptcha(RecaptchaAction.SignIn);
signIn({ email: lowercaseEmail, captcha: token });
signIn({
email: lowercaseEmail,
captcha: token,
url: redirect.url,
});
};

const onClickResendEmail = () => {
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/mobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const enum MobileSearchParams {
* This is determined given the presence of the "m" query parameter, which is set to the nonce challenge value only if the page was loaded from mobile
* @returns { isMobile, challenge } a boolean that indicates if the login is for the mobile app, and the challenge nonce
*/
export const useMobileLogin = () => {
export const useMobileAppLogin = () => {
const [searchParams] = useSearchParams();
const challenge = searchParams.get(MobileSearchParams.CHALLENGE);
return {
Expand Down
31 changes: 31 additions & 0 deletions src/hooks/searchParams.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useSearchParams } from 'react-router-dom';
codeofmochi marked this conversation as resolved.
Show resolved Hide resolved

const enum SearchParams {
REDIRECTION = 'url',
}

/**
* Checks whether the redirection url search parameter is set, in which case the value should be passed to the back-end
* endpoints such that the final authentication (/auth) redirects to this URL (after e.g. password or e-mail)
*
* @returns { url } the redirection url to be passed with any authentication method
*/
export const useRedirection = () => {
const [searchParams] = useSearchParams();

let url: string | undefined;
try {
const urlParam = searchParams.get(SearchParams.REDIRECTION) ?? undefined;
codeofmochi marked this conversation as resolved.
Show resolved Hide resolved
url = urlParam ? decodeURIComponent(urlParam) : undefined;
} catch (error) {
/* eslint-disable-next-line no-console */
console.error(
'The redirection URL search parameter could not be parsed and has been ignored',
error,
);
}

return {
url,
};
};
51 changes: 44 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3152,12 +3152,12 @@ __metadata:
languageName: node
linkType: hard

"@graasp/query-client@npm:1.4.3":
version: 1.4.3
resolution: "@graasp/query-client@npm:1.4.3"
"@graasp/query-client@npm:1.6.0":
version: 1.6.0
resolution: "@graasp/query-client@npm:1.6.0"
dependencies:
"@graasp/sdk": 1.2.1
"@graasp/translations": 1.18.3
"@graasp/sdk": 1.4.0
"@graasp/translations": 1.19.0
axios: 0.27.2
crypto-js: 4.1.1
http-status-codes: 2.2.0
Expand All @@ -3167,7 +3167,7 @@ __metadata:
uuid: 9.0.0
peerDependencies:
react: ^17.0.0
checksum: d6789d5a0ef00b5febbabdf92cbb5904ffbc1359ee9fcd80c6e9be30e7008b4ae114cbb5ae543e49d2a58a838201d6f834d27c8582859bcc21a47ff42c49abb3
checksum: 81c2eb3fb9f471d88fc6ecd039574b648aa1fa06fb600f986bd13cdba529244f8dc301b6e2e01884bcadbbb14fad9529818fb53cea7f6d8d667c5862c1f50a50
languageName: node
linkType: hard

Expand Down Expand Up @@ -3209,6 +3209,25 @@ __metadata:
languageName: node
linkType: hard

"@graasp/sdk@npm:1.4.0":
version: 1.4.0
resolution: "@graasp/sdk@npm:1.4.0"
dependencies:
"@aws-sdk/client-s3": 3.370.0
"@fastify/secure-session": 6.1.0
"@graasp/etherpad-api": 2.1.1
fastify: 4.18.0
fluent-json-schema: 4.1.0
immutable: 4.3.2
js-cookie: 3.0.5
qs: 6.11.2
typeorm: 0.3.17
uuid: 9.0.0
validator: 13.11.0
checksum: 224ed990ed7b68fe4b463d2d1e24fc503c5f5434703cb818a54d22ee9aa8e9997c3a02768ceec082bea604853aa4804ac4d454c746e38089e3e327e0ffcd4c27
languageName: node
linkType: hard

"@graasp/translations@npm:1.18.3":
version: 1.18.3
resolution: "@graasp/translations@npm:1.18.3"
Expand All @@ -3218,6 +3237,15 @@ __metadata:
languageName: node
linkType: hard

"@graasp/translations@npm:1.19.0":
version: 1.19.0
resolution: "@graasp/translations@npm:1.19.0"
dependencies:
i18next: 23.4.6
checksum: b204158615ee2cb50c7aa9e993d52a4d8ec473c1d5c934f9926905eb7e019d46f900273dad896cf04911cf675d0b645e5b3b4c6f61f9ed58a0fa7aeda18fe734
languageName: node
linkType: hard

"@graasp/ui@npm:3.3.2":
version: 3.3.2
resolution: "@graasp/ui@npm:3.3.2"
Expand Down Expand Up @@ -8558,7 +8586,7 @@ __metadata:
"@emotion/cache": 11.11.0
"@emotion/react": 11.11.1
"@emotion/styled": 11.11.0
"@graasp/query-client": 1.4.3
"@graasp/query-client": 1.6.0
"@graasp/sdk": 1.3.0
"@graasp/translations": 1.18.3
"@graasp/ui": 3.3.2
Expand Down Expand Up @@ -8899,6 +8927,15 @@ __metadata:
languageName: node
linkType: hard

"i18next@npm:23.4.6":
version: 23.4.6
resolution: "i18next@npm:23.4.6"
dependencies:
"@babel/runtime": ^7.22.5
checksum: ffc63889e28b2bfce2c6e635bd686087290fe2e2f58e0a235525011bb74d541ff681895abe994b12546be6c92b66a7cc3002a13c26e587b4da8c89b15ef648db
languageName: node
linkType: hard

"iconv-lite@npm:^0.6.2":
version: 0.6.3
resolution: "iconv-lite@npm:0.6.3"
Expand Down