Skip to content
This repository was 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
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
@@ -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",
6 changes: 5 additions & 1 deletion src/components/Redirection.tsx
Original file line number Diff line number Diff line change
@@ -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;
13 changes: 10 additions & 3 deletions src/components/SignIn.tsx
Original file line number Diff line number Diff line change
@@ -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';
@@ -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('');
@@ -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);
@@ -114,6 +120,7 @@ const SignIn: FC = () => {
email: lowercaseEmail,
password,
captcha: token,
url: redirect.url,
}));
if (result && result.resource) {
window.location.href = result.resource;
7 changes: 5 additions & 2 deletions src/components/SignUp.tsx
Original file line number Diff line number Diff line change
@@ -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';
@@ -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>('');
@@ -98,6 +100,7 @@ const SignUp = () => {
name: name.trim(),
email: lowercaseEmail,
captcha: token,
url: redirect.url,
}));
setSuccessView(true);
}
15 changes: 12 additions & 3 deletions src/components/SuccessContent.tsx
Original file line number Diff line number Diff line change
@@ -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;
@@ -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 = () => {
2 changes: 1 addition & 1 deletion src/hooks/mobile.tsx
Original file line number Diff line number Diff line change
@@ -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 {
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';

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;
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
@@ -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
@@ -3167,7 +3167,7 @@ __metadata:
uuid: 9.0.0
peerDependencies:
react: ^17.0.0
checksum: d6789d5a0ef00b5febbabdf92cbb5904ffbc1359ee9fcd80c6e9be30e7008b4ae114cbb5ae543e49d2a58a838201d6f834d27c8582859bcc21a47ff42c49abb3
checksum: 81c2eb3fb9f471d88fc6ecd039574b648aa1fa06fb600f986bd13cdba529244f8dc301b6e2e01884bcadbbb14fad9529818fb53cea7f6d8d667c5862c1f50a50
languageName: node
linkType: hard

@@ -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"
@@ -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"
@@ -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
@@ -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"