Files
Verso/services/web/frontend/js/shared/components/ds/ds-form-text.tsx
T
3140e46e68 [web] Replace token-link email verification with 6-digit code on SSO registration (ORCID) (#33889)
* Replace token-link email with 6-digit code on SSO registration

Unverified SSO emails previously received a long-lived token link
(90-day TTL) via UserEmailsConfirmationHandler. This replaces that
flow with the same 6-digit code verification used for password
registration, redirecting through /registration/confirm-email.

- SSOManager.registerSSO now always confirms email (caller must
  verify first); removes sendConfirmationEmail / _finishRegistration
- SSOController._signUp sends confirmation code and stores
  pendingSSORegistration in session when IdP email_verified is false
- New SSOConfirmEmailHandler completes registration after code check
  via completeSSOEmailConfirmation module hook
- OnboardingController confirm-email handlers accept
  pendingSSORegistration alongside pendingUserRegistration

confirmEmailFromToken (POST /user/emails/confirm) removal is deferred
to a follow-up PR to avoid breaking in-flight 90-day tokens.

Closes #28607

* Fix unverified-email edge cases; Add ORCID e2e tests;

* Rename `confirmEmail` parameter to `emailVerifiedByIdP` in _signUp function

* Remove `sendConfirmationEmail`

* Mock getUserByAnyEmail in tests

* Extract _finishSSORegistration helper to deduplicate the register →
set session flags → allocate referral → finishSaasLogin → finishLogin
sequence shared by both the direct and deferred (code-confirmed) paths.

* Stop duplicating session data in pendingSSORegistration

analyticsId, splitTests, and referal_* are already in the session at
confirmation time — no need to copy them into pendingSSORegistration.
Re-fetch splitTests fresh on completion instead.

* Simplify the code

* Remove dead confirmEmail template

No callers remain after sendConfirmationEmail was deleted. The token-link
flow (confirmEmailFromToken) only validates tokens, never sends email.

* Remove dead reconfirmEmail template

* Address comments from Copilot

* Clear stale pending registration when starting a new flow

* Add unit tests for completeSSOEmailConfirmation

* Add `verificationMethod` param

* Fix camelcase issues

* Extract _createSSOUser and _registerAndFinish helpers to deduplicate registration logic

* Remove obscure "registration_error"

* Prevent FormTextIcon from shrinking

* Enable "email_already_registered_sso" error

* Misc. improvements to confirm-email-form.tsx

* Remove `UserEmailsConfirmationHandler` mock

Co-authored-by: Olzhas Askar <olzhas.askar@overleaf.com>

* Add info on sso_email.pug page

---------

Co-authored-by: Olzhas Askar <olzhas.askar@overleaf.com>
GitOrigin-RevId: d0196ebc6d81ff61bcd27726d0b899b743d08d64
2026-06-05 08:06:34 +00:00

60 lines
1.3 KiB
TypeScript

import { Form, FormTextProps as BS5FormTextProps } from 'react-bootstrap'
import classnames from 'classnames'
import { MergeAndOverride } from '@ol-types/utils'
import { CheckCircle, WarningCircle } from '@phosphor-icons/react'
type TextType = 'success' | 'error'
export type FormTextProps = MergeAndOverride<
BS5FormTextProps,
{
type?: TextType
marginless?: boolean
}
>
const typeClasses = {
error: 'text-danger',
success: 'text-success',
} as const
export const getFormTextClass = (type?: TextType) =>
type && type in typeClasses
? typeClasses[type as keyof typeof typeClasses]
: undefined
function FormTextIcon({ type }: { type?: TextType }) {
switch (type) {
case 'success':
return <CheckCircle className="ciam-form-text-icon flex-shrink-0" />
case 'error':
return <WarningCircle className="ciam-form-text-icon flex-shrink-0" />
default:
return null
}
}
function DSFormText({
type,
marginless,
children,
className,
...rest
}: FormTextProps) {
return (
<Form.Text
className={classnames('form-text-ds', className, getFormTextClass(type), {
marginless,
})}
{...rest}
>
<span className="form-text-inner-ds">
<FormTextIcon type={type} />
<span>{children}</span>
</span>
</Form.Text>
)
}
export default DSFormText