Skip to content

Commit

Permalink
feat: send the email update verification token to the new email
Browse files Browse the repository at this point in the history
KK-1071 KK-1093 KK-1092.
Earlier the flow had a flaw: it sent the verification token to the old email.
It should send it to the new email instead.
  • Loading branch information
nikomakela committed Feb 14, 2024
1 parent 019b2ef commit 2aea1e2
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 97 deletions.
54 changes: 32 additions & 22 deletions src/domain/api/generatedTypes/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ export type Mutation = {
importTicketSystemPasswords: Maybe<ImportTicketSystemPasswordsMutationPayload>;
publishEvent: Maybe<PublishEventMutationPayload>;
publishEventGroup: Maybe<PublishEventGroupMutationPayload>;
requestEmailUpdateToken: Maybe<RequestEmailUpdateTokenMutation>;
requestEmailUpdateToken: Maybe<RequestEmailUpdateTokenMutationPayload>;
sendMessage: Maybe<SendMessageMutationPayload>;
setEnrolmentAttendance: Maybe<SetEnrolmentAttendanceMutationPayload>;
/** This is the first mutation one needs to execute to start using the service. After that this mutation cannot be used anymore. */
Expand Down Expand Up @@ -1036,6 +1036,10 @@ export type MutationPublishEventGroupArgs = {
input: PublishEventGroupMutationInput;
};

export type MutationRequestEmailUpdateTokenArgs = {
input: RequestEmailUpdateTokenMutationInput;
};

export type MutationSendMessageArgs = {
input: SendMessageMutationInput;
};
Expand Down Expand Up @@ -1459,8 +1463,14 @@ export enum RelationshipTypeEnum {
Parent = 'PARENT',
}

export type RequestEmailUpdateTokenMutation = {
__typename?: 'RequestEmailUpdateTokenMutation';
export type RequestEmailUpdateTokenMutationInput = {
clientMutationId?: InputMaybe<Scalars['String']['input']>;
email: Scalars['String']['input'];
};

export type RequestEmailUpdateTokenMutationPayload = {
__typename?: 'RequestEmailUpdateTokenMutationPayload';
clientMutationId: Maybe<Scalars['String']['output']>;
email: Maybe<Scalars['String']['output']>;
emailUpdateTokenRequested: Maybe<Scalars['Boolean']['output']>;
};
Expand Down Expand Up @@ -3543,14 +3553,14 @@ export type LanguageQuery = {
} | null;
};

export type RequestEmailUpdateVerificationTokenMutationVariables = Exact<{
[key: string]: never;
export type RequestEmailUpdateTokenMutationVariables = Exact<{
input: RequestEmailUpdateTokenMutationInput;
}>;

export type RequestEmailUpdateVerificationTokenMutation = {
export type RequestEmailUpdateTokenMutation = {
__typename?: 'Mutation';
requestEmailUpdateToken: {
__typename?: 'RequestEmailUpdateTokenMutation';
__typename?: 'RequestEmailUpdateTokenMutationPayload';
email: string | null;
emailUpdateTokenRequested: boolean | null;
} | null;
Expand Down Expand Up @@ -5310,26 +5320,26 @@ export type LanguageQueryQueryResult = Apollo.QueryResult<
LanguageQuery,
LanguageQueryVariables
>;
export const RequestEmailUpdateVerificationTokenMutationDocument = gql`
mutation RequestEmailUpdateVerificationTokenMutation {
requestEmailUpdateToken {
export const RequestEmailUpdateTokenDocument = gql`
mutation RequestEmailUpdateToken(
$input: RequestEmailUpdateTokenMutationInput!
) {
requestEmailUpdateToken(input: $input) {
email
emailUpdateTokenRequested
}
}
`;
export type RequestEmailUpdateVerificationTokenMutationMutationFn =
Apollo.MutationFunction<
RequestEmailUpdateVerificationTokenMutation,
RequestEmailUpdateVerificationTokenMutationVariables
>;
export type RequestEmailUpdateVerificationTokenMutationMutationResult =
Apollo.MutationResult<RequestEmailUpdateVerificationTokenMutation>;
export type RequestEmailUpdateVerificationTokenMutationMutationOptions =
Apollo.BaseMutationOptions<
RequestEmailUpdateVerificationTokenMutation,
RequestEmailUpdateVerificationTokenMutationVariables
>;
export type RequestEmailUpdateTokenMutationFn = Apollo.MutationFunction<
RequestEmailUpdateTokenMutation,
RequestEmailUpdateTokenMutationVariables
>;
export type RequestEmailUpdateTokenMutationResult =
Apollo.MutationResult<RequestEmailUpdateTokenMutation>;
export type RequestEmailUpdateTokenMutationOptions = Apollo.BaseMutationOptions<
RequestEmailUpdateTokenMutation,
RequestEmailUpdateTokenMutationVariables
>;
export const UpdateMyEmailMutationDocument = gql`
mutation UpdateMyEmailMutation($input: UpdateMyEmailMutationInput!) {
updateMyEmail(input: $input) {
Expand Down
105 changes: 57 additions & 48 deletions src/domain/profile/modal/EditMyEmailForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,29 +101,36 @@ export default function EditMyEmailForm({
validate={validate}
validationSchema={emailChangeSchema}
>
{({ isSubmitting }: FormikProps<UpdateMyEmailMutationInput>) => (
<Form>
<FormikTextInput
className={styles.formField}
id="email"
name="email"
disabled={!isChangingEmail}
label={t('registration.form.guardian.email.input.label')}
/>
{!isChangingEmail && (
<Button
className={styles.emailChangeButton}
variant="supplementary"
onClick={() => {
setIsChangingEmail(true);
}}
>
{t('registration.form.guardian.email.change.button')}
</Button>
)}
{isChangingEmail && (
<>
<div className={styles.emailVerificationTokenFieldWrapper}>
{({ isSubmitting, values }: FormikProps<UpdateMyEmailMutationInput>) => {
const hasEmailChanged = values.email !== originalEmail;
const shouldLockActions = isSubmitting || !hasEmailChanged;
return (
<Form>
<FormikTextInput
className={styles.formField}
id="email"
name="email"
disabled={!isChangingEmail}
label={t('registration.form.guardian.email.input.label')}
/>
{!isChangingEmail && (
<Button
className={styles.emailChangeButton}
variant="supplementary"
onClick={() => {
setIsChangingEmail(true);
}}
>
{t('registration.form.guardian.email.change.button')}
</Button>
)}

{isChangingEmail && (
<>
<RequestVerificationTokenButton
email={values.email}
disabled={shouldLockActions}
/>
<FormikTextInput
className={styles.formField}
id="verificationToken"
Expand All @@ -138,34 +145,36 @@ export default function EditMyEmailForm({
'registration.form.guardian.email.verificationToken.input.helper'
)}
autoComplete="off"
disabled={shouldLockActions}
/>
<RequestVerificationTokenButton />
</div>

<div className={styles.buttonsWrapper}>
<Button
onClick={() => setIsChangingEmail(false)}
variant="secondary"
type="button"
className={styles.cancelButton}
>
{t('common.modal.cancel.text')}
</Button>
<div className={styles.buttonsWrapper}>
<Button
onClick={() => setIsChangingEmail(false)}
variant="secondary"
type="button"
className={styles.cancelButton}
>
{t('common.modal.cancel.text')}
</Button>

<Button
type="submit"
className={styles.submitButton}
disabled={isSubmitting}
>
{t('common.modal.save.textWithSubject', {
subject: t('registration.form.guardian.email.input.label'),
})}
</Button>
</div>
</>
)}
</Form>
)}
<Button
type="submit"
className={styles.submitButton}
disabled={shouldLockActions}
>
{t('common.modal.save.textWithSubject', {
subject: t(
'registration.form.guardian.email.input.label'
),
})}
</Button>
</div>
</>
)}
</Form>
);
}}
</Formik>
);
}
29 changes: 20 additions & 9 deletions src/domain/profile/modal/RequestVerificationTokenButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@ import requestEmailUpdateTokenMutation from '../mutations/requestEmailUpdateToke
import LoadingSpinner from '../../../common/components/spinner/LoadingSpinner';
import useCoolDown from './useCoolDown';

export default function RequestVerificationTokenButton() {
type RequestVerificationTokenButtonProps = {
email: string;
disabled?: boolean;
};

export default function RequestVerificationTokenButton({
email,
disabled = false,
}: RequestVerificationTokenButtonProps) {
const { t } = useTranslation();
const [requestUpdateEmailVerificationToken, { loading }] =
useMutation<RequestEmailUpdateTokenMutation>(
Expand All @@ -22,11 +30,17 @@ export default function RequestVerificationTokenButton() {
false
);

const isDisabled = Boolean(loading || coolDownSeconds);
const isDisabled = Boolean(disabled || loading || coolDownSeconds);

const handleOnClick = async () => {
try {
await requestUpdateEmailVerificationToken();
await requestUpdateEmailVerificationToken({
variables: {
input: {
email,
},
},
});
resetCoolDown();
toast.success(
t(
Expand All @@ -44,16 +58,13 @@ export default function RequestVerificationTokenButton() {
return (
<LoadingSpinner isLoading={loading}>
<Button
variant="supplementary"
variant="primary"
onClick={handleOnClick}
className={styles.requestVerificationTokenButton}
disabled={isDisabled}
>
{coolDownSeconds
? coolDownSeconds
: t(
'registration.form.guardian.email.verificationToken.request.button'
)}
{t('registration.form.guardian.email.verificationToken.request.button')}
{!!coolDownSeconds && ` (${coolDownSeconds})`}
</Button>
</LoadingSpinner>
);
Expand Down
18 changes: 2 additions & 16 deletions src/domain/profile/modal/editProfileModal.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
}
}

.emailChangeButton,
.requestVerificationTokenButton {
.emailChangeButton {
height: auto;
min-height: unset !important;
margin-left: 0 !important;
Expand All @@ -27,20 +26,7 @@
}

.requestVerificationTokenButton {
margin-top: 20px !important;
padding: var(--spacing-s) !important;
height: fit-content;
font-size: large;
}

.emailVerificationTokenFieldWrapper {
display: grid;
grid-template-columns: 8fr 2fr;
grid-gap: $baseMargin;

button {
width: 100%;
}
margin-bottom: var(--spacing-s) !important;
}

.separator {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { gql } from '@apollo/client';

const requestEmailUpdateTokenMutation = gql`
mutation RequestEmailUpdateVerificationTokenMutation {
requestEmailUpdateToken {
mutation RequestEmailUpdateToken(
$input: RequestEmailUpdateTokenMutationInput!
) {
requestEmailUpdateToken(input: $input) {
email
emailUpdateTokenRequested
}
Expand Down

0 comments on commit 2aea1e2

Please sign in to comment.