* Rename dropdown primitives to OL-prefixed components
* Migrate all consumers to OL-prefixed dropdown components
* Migrate subscription dropdown shells to OL components
* Update pdf-preview story to OL-prefixed dropdown components
* Migrate navbar and spelling dropdowns to OL components
* Move dropdown primitives to ol/ol-dropdown-menu, remove BS5 import aliases
* Rename dropdown prop types to OL-prefixed, clean up BS5 import aliases
* Widen OLDropdownItem/Toggle/Menu props to include AriaAttributes and data-*
GitOrigin-RevId: 0babce46867849b3f176bac8cf1652dc76fd34da
* github-sync: only swallow permanent revocation failures during unlink
404 (token gone) and 422 (token issued under a mismatched client_id,
the confirmed cause of #35108) are treated as safe to proceed past;
any other revocation error now aborts the unlink instead of silently
deleting the local credential row, so a token that might still be
live isn't orphaned by a transient GitHub failure.
* web: surface genuine github-sync unlink failures instead of a 500
When GithubSyncApiHandler.unlink rejects for a reason other than the
permanent 404/422 cases now handled by github-sync, show an error
notification on the settings page instead of crashing the request,
mirroring the existing projectSyncSuccessMessage session-flash pattern.
* github-sync: detect expired credentials in user status check
getStatus now validates a stored token against GitHub (GET /user)
before reporting it as linked. A GithubInvalidCredentialsError (401)
now surfaces as expired: true alongside enabled: true, distinguishing
a dead token from a genuinely working link. Any other validation
failure fails open and reports enabled: true as before.
* web: propagate github-sync expired status through to the client
Thread the new expired field from github-sync's status endpoint
through GithubSyncController.getUserStatus and the settings-page
injectUserSettings middleware, and extend the corresponding
TypeScript types on both the app and frontend side.
* web: show a re-link path on the settings widget when github credentials expire
The widget now checks expired status: it shows an error indicator
with a "connection expired" message and renders the Link action
instead of a dead-end Unlink button, since relinking upserts a fresh
token regardless of the stale row.
* web: keep unlink available for expired github credentials
Some users just want to remove an expired connection rather than
relink it. Keep Unlink as the primary action regardless of expired
status, and surface the relink path as an inline link next to the
expired message instead of replacing the primary action.
* web: correct the github unlink confirmation warning
Unlinking never touches a project's githubSyncProjectStates row,
regardless of whether the credential was healthy or expired -
verified by tracing unlinkAccount/deleteUser and confirming no other
code path deletes project sync state on account unlink. Sync pauses
until relink, but no project loses its GitHub connection, so the
warning text was simply wrong; corrected rather than adding a
separate expired-specific message.
* web: add Storybook story for expired github-sync credentials
Covers the new expired state alongside the existing NoFeature,
Unlinked, Linked and Error stories for the settings widget.
* simplify: collapse duplicated branches and extract session-flash helper
- Merge the near-identical 404/422 checks in _revokeToken into one
status-set check.
- Use optional chaining instead of null-guard ternaries in
GithubSyncMiddleware.
- Extract popSessionValue() in UserPagesController to de-duplicate the
read-then-delete session flash-message pattern, now used 3 times.
* review-self: close test coverage gaps found in self-review
- AuthenticationController: cover 401/403 revocation responses and a
plain network error with no .response, alongside existing 404/422/500.
- GithubSyncController: assert projectSyncErrorMessage stays unset on
the unlink success path.
- UserPagesController: cover projectSyncErrorMessage set-then-cleared
and absent-stays-undefined cases.
- Add GithubSyncMiddleware.test.mjs (previously untested): not-logged-in,
successful status fetch, and callback-error branches.
- Cypress: cover cancelling the unlink confirmation modal while expired.
- Storybook: add ErrorWhileUnlinked story for the disabled-Link +
error-indicator combination.
* review-self: fix audit-log ordering, cache getStatus validation safely
- GithubSyncApiHandler: write the link-github/unlink-github audit log
entry only after the corresponding github-sync API call succeeds,
instead of before (resolves the discrepancy tracked in issue 3354).
- UserController/UserManager: cache getStatus's live token-validation
result for 5 minutes to cut down on redundant GitHub API calls,
with an optimistic-lock write (matched against the encrypted token
that was actually validated) so a relink can never be overwritten by
a stale in-flight validation of the old token.
- github-integration-linking-widget: dedupe the relink href against
the linkPath already passed to IntegrationLinkingWidget.
* web: surface expired github credentials proactively in the sync modal
The modal previously only showed the reauthorize prompt after a real
GitHub API call failed with 401 mid-action. It now also checks the
expired field already returned by the status endpoint and shows the
same prompt immediately on open, before ever rendering the export
form against a token known to be dead. Extracted the existing
reauthorize markup into GithubCredentialsExpired so both call sites
share it.
* github-sync: avoid double-fetching the credential doc in getStatus
getStatus called UserManager.getUser, then getAuthToken which
internally fetched the same document again. Add getAuthTokenFromUser
to decrypt from an already-fetched doc and use it in getStatus,
removing the redundant Mongo query and the now-unreachable
GithubUserNotLinkedError handling (the user doc's existence was
already confirmed by the first fetch).
* github-sync: make expired-token handling reactive, drop proactive getStatus validation
Reverts getStatus in the github-sync service to a pure DB check — no live
GitHub API call, no 5-minute cache, no token_expired/token_validated_at
fields. The expired state is already surfaced reactively: the unmerged-commits
fetch on modal open returns 401 when the token is dead (handled by the existing
case 401 branch), and ExportToGithub handles 401 from the orgs call. The
proactive check added complexity (caching, optimistic-lock writes) without a
meaningful UX gain over the reactive paths.
Removes the expired indicator from the settings widget and the proactive
GithubCredentialsExpired screen from the modal's pre-flight check. The
github_sync_expired locale key is removed as it is no longer referenced.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* github-sync: show reauthorize prompt when push/pull fails with expired credentials
When a merge (push or pull) returns 401, GithubSyncMergeAction now renders
GithubCredentialsExpired with the Reauthorize button instead of the raw
"GithubInvalidCredentialsError" string that was previously falling through
to the default error branch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* github-sync: wrap all async controller handlers with expressify
Without expressify, an unhandled throw from an async route handler
(e.g. a token decryption failure in the github-sync service producing a
non-4xx error that _reportError re-throws) becomes an unhandled rejection.
Express never sends a response and the modal is left stuck on loading.
expressify catches the error and passes it to next(), so Express's error
handler sends a 500 and the frontend can surface it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* removing redundant tests
* removing getAuthTokenFromUser function
* removing redundant key
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
GitOrigin-RevId: 0d9a314bf70bea9e6037593f2a6f8b8d1f2c6e71
* Merge intermediate component wrappers into OL-prefixed components
* Replace all intermediate wrapper consumers with OL-prefixed components directly
* Fix jsx/js files still importing deleted shim components
* Remove duplicate OLNotification imports left by first pass
* Rename OLTagIcon to TagIcon, remove OL prefix
* Rename OLDropdownMenuItem to DropdownMenuItem, remove OL prefix
* Remove OLNotification, use Notification directly
* Move Notification to the main shared component folder
* Update tag-icon import path out of ol/
* Move TagIcon to the main shared component folder
* Update dropdown-menu-item import path out of ol/
* Move DropdownMenuItem to the main shared component folder
* Fix dropdown-menu-item import path to dropdown/ subfolder
* Remove BS5 alias prefixes from shared components
* Restore notification-list wrapper in Notification component
* Add translation for loading button
* Remove redundant import aliasing
* Resolve conflicts
* Restore notification container `notification-list`
GitOrigin-RevId: 24a5af18599a3e02ac6fd61c09cf5a49ef6e0020
* update doc links to point to docs.overleaf.com instead of the old learn wiki
* fix broken link to LaTeX positioning wiki article in figure modal help
* point figure positioning help link to the docs.overleaf.com page
* point figure/table label help links to specific anchors on the captioning-and-referencing-figures doc page
* point figure modal error-help link to the graphicx-loading doc page
* normalize target/rel on docs.overleaf.com links opened in a new tab
* open figure modal and SSO help links in a new tab now that they point off-site
* add eslint rule enforcing rel=noopener noreferrer on docs.overleaf.com links
* extend require-rel-for-docs-links to also check OLButton
* add lint script catching missing rel on docs.overleaf.com links in pug templates
* fix require-rel-for-docs-links autofix crash on valueless rel attribute
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* add regression test for require-rel-for-docs-links valueless-rel autofix
* revert `target=_blank` on figure modal and SSO help links
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
GitOrigin-RevId: b6111341e1080fd7e4b42f6a1a18c27ea0fd7d8c
* 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
* [web] Replace `pro` with `commons` wording on institutional subscriptions
Replaces the wording in several places:
- subscription settings
- email tags
- features tooltip
- institution portal
GitOrigin-RevId: 1b9a0e51245ed8a41865300d9e9d555bc05e6c17
* feat: add granular controls for other features
* feat: add filtering to notifications that were missing them
* refactor: rm duplicate thread fetches
* fix: reduce permissions to fit spec (all === new comments/tracked changes, replies === only if also a participant)
* fix: include mentions in types
GitOrigin-RevId: b4a09ef59e5cf4de2e07d5b9a13c31fc1cf81a31
* display global disabled state
* show loading indicator while project notification preferences load
GitOrigin-RevId: d7e905aaa3fc7b15b54bf99caeabf60c1e5d8050
* merging ide-redesign/components/file-tree into features/file-tree
* moving ide-redesign/contexts/settings-modal-context to features/settings/contexts
* use-collapsible-file-tree.tsx → features/file-tree/hooks
* use-focus-on-setting.tsx → features/settings/hooks
* use-project-notification-preferences.ts → features/settings/hooks
* use-rail-overflow.tsx→ features/ide-react/hooks
* deleting use-switch-enable-new-editor-state.ts
* use-toolbar-menu-editor-commands.tsx → features/source-editor/hooks
* npm run extract-translations
* modifying the test to target correct buttons and removing a test for old component
* adding a test back and modifying it
* changing the test
GitOrigin-RevId: baa1e9a992c88b84313eea82161354d4958cf1ef
* Merge all .prettierignore files into top-level config
* Merge all .prettierrc files into top-level config
* Replace service-specific glob patterns in package.json format scripts with `prettier .`
* Add template files with Jinja2, Go template, envsubst, and Handlebars syntax to .prettierignore
* Ignore GitHub templates
* Ignore PUG templates to format them separately with `format:pug`
* Encourage double quotes for YAML, YML files
* Move prettier for PUG source format script to the root
* Move prettier for styles source format script to the root
* Remove prettier for jenkins files from web
* Remove prettier source format script from all services
* Make .prettierrc more readable
* Update format scripts by file type
* Organise `.prettierignore`
* Add `--cache` flag to prettier scripts for faster runs
* Format all files with prettier
* Format all or format services
* Remove `format`/`format:fix` scripts from services since now it runs from root `package.json`
* Avoid conlficts with yamllint configuration
* Remove `--cache` flag from prettier scripts
* Update all service Makefiles to use root-level prettier configuration
* Update all Jenkinsfile to use root-level prettier configuration
* Ignore auto-generated files by build_scripts
* Update package-lock.json
* Update root Makefile format targets
* Update SP Jenkinsfile format target
* Update E2E Makefile format script
* Udpate `format_js` to work in both local and CI env
* Add docker-mailtrap to .prettierignore
docker-mailtrap is a third-party git-ignored directory used for testing
* Added Docker env detection to prevent nested Docker spawning
* Ignore handlebars templates
* Add cryptographic files and test output to `.prettierignore`
* Add terraform modules to `.gitignore`
* Remove prettier-plugin-groovy
* Use npx directly instead of Docker for local formatting for faster formatting
* Auto-generate Makefiles
* Revert "Remove prettier-plugin-groovy"
This reverts commit 194a33589a2e1e4d2225d10c67e9f025e4222025.
* Mount monorepo root in RUN_LINT_FORMAT for prettier config access
* Prettier ignores all `node_modules` by default regardless of location
* Show only changed files in format output
* Ignore LICENSE files
* Enable prettier on rendered build_scripts outputs
* Ignoring all the template folders by prettier
* Remove the public/minjs entry since it does not exist
* Remove all non-existent paths
* Sync `.prettierignore` with ignored files by `.gitignore` and `.dockerignore` files
* Revert "Auto-generate Makefiles"
This reverts commit c0233e490de1bc95fe437219d65e0b66e0331ec9.
* Revert "Use npx directly instead of Docker for local formatting for faster formatting"
This reverts commit 1d2b2cf1a6c6974c76885852a90dd55e84167e41.
* Ignore dashboard JSON files
* Ignore files generated by bin/update_build_scripts
* Remove unsupported file types from `.prettierignore`
* Ignore test fixture generated files
* Ignore README file types by prettier
* Ignore generate snapshots by prettier
* Allow to format generated bin/update_build_scripts by prettier
* Ensure build script outputs prettier-compatible tsconfig.json
* Fix build script output to match prettier formatting
- Fix Jinja2 whitespace in docker-compose templates
- Change YAML quotes from single to double
* Don't read cryptographic files by prettier
* Ignore google verification files by prettier
* Revert npx prettier formatting
* Ignore domain verification files
* Show only changed files in format output
* Make `.github` prettier
* Allow all files to be formatted in jobs by prettier
* Allow server-ce/server-pro files to be formatted by prettier
* Ignore more folders in clsi, filestory, git-bridge by prettier
* Update build script with `RUN_LINTING_CI_MONOREPO`
* Ignore docker-mailtrap and downloads in server-ce by prettier
* Restore prettier configs and prettierignore for V1 since it has its own prettier (an older version)
* Source format
GitOrigin-RevId: 637adc3cc422d1f20c86d6ebc8ec514d60758287
* changing to pug conditional format for admin page conditional render
* feat: update notifications settings page and open BE route
feat: adding new page for notification prefs on user settings, along with updating saving prefs for global preferences
adding error handling and disabling when request is inflight
formatting and adding split test for viewing notification ettings
fix: updating to levels of preferences, and removing global type for preferences as we will now share the same backing settings between global and project preferences
feat: add global mute to user settings for notifications
making params in preferences schema optional
feat: update global settings to only set mute, and remove optional settings
fix: store userId as objectId, and filter based on global mute setting
GitOrigin-RevId: 947a95dc02d12b4a2d8e3cc29bd04c23af2aef25
* Remove focused style from the stepper
* Reduce spacing between password input and password policy
* Make input validation icon larger
* Make animated-tick.svg faster
* Move notification to below h1
* Move notification to below h1
* Fix: Warning: Invalid DOM property `autocomplete`. Did you mean `autoComplete`?
* Wrap form-text in a span so it's displayed correctly and not altered by flex
* Remove "Please request a new password reset email and follow the link." text after the email is entered
* Remove (unnecessary?) flex property on .ciam-form-text-icon
* Rename `messageTextNode` to `messageTextSpan`
* Revert changes to input-validator.ts
GitOrigin-RevId: ad83c92a59b9dbc872cf4e49362b0baec9fb5b93
* no grey hyphen when the input is empty
* show email in bold
* Fix tests
* Add test to verify email display in confirmation code input
* Format
GitOrigin-RevId: ade4a670b9dc80b99f64cc3273407a98428521b8
* Make CIAM copies of Pug files
passwordResetCiam.pug
setPasswordCiam.pug
* Update controller with split test assignment
* Use CIAM layout in passwordResetCiam.pug
* Style passwordResetCiam according to designs
* Use CIAM layout in setPasswordCiam.pug
* Style setPasswordCiam according to designs
* Use settings value in registration screen for must_be_at_least_n_characters
* Retrieve email input with a script
* Replace mb-4 by --ds-spacing-800
* Add eye icon to toggle password visibility
* Avoid double dots after some translated strings
* Use `ciamCustomFormDangerMessage`
* Use `ciamErrorNotification`
* Use `ciamButtonContentLoading`
* Replace remaining "mb" classes
* Move new password errors to the top of the form
* Fix CIAM mixins path after rebase
* Use `ciamCustomFormDangerMessage`
* Add `data-ol-spinner-inflight` to buttons
* Replace classname ciam-notification by notification-ds
Remove borders from CIAM notifications
Fix font size
* Revert "Use settings value in registration screen for must_be_at_least_n_characters"
This reverts commit a0af95c11e171097750ad7ee871f6baf89d5c0cb.
(It's Friday afternoon so I don't want to update unrelated stuff :D)
* Update: check_your_inbox
* Remove `.ciam-card` min-height.
Unnecessary thanks to `.confirm-email-success-form`'s min-height: 400px;
* Use phosphor icons
* Style `formMessagesNewStyle` with DS notifications within CIAM pages
Alternatively, we could extend/duplicate `showMessagesNewStyle` with a CIAM variant
* Revert "Style `formMessagesNewStyle` with DS notifications within CIAM pages"
This reverts commit ed382dc1e8cdf5b916c1527f4da0a825167e9675.
* Fix styling of dynamically-created DS notifications
* Set password length info to secondary color
* Move `ciamSamlErrorNotLoggedIn` to saas-authentication module
Prevents errors in CE:
Error: ENOENT: no such file or directory, open '/overleaf/services/web/modules/saas-authentication/app/views/_mixins.pug'
at /overleaf/services/web/app/views/_mixins/ciam_mixins.pug line 3
---------
Co-authored-by: Tim Down <158919+timdown@users.noreply.github.com>
GitOrigin-RevId: afe58f18ecee92460ab628a285b6edb48a5c678d
* removing placeholders and adding labels
* adding a test
* adding a test back
* deleting comment
* Target the label of department and role
---------
Co-authored-by: Rebeka <o.dekany@gmail.com>
GitOrigin-RevId: 890c2f836a17c360a577bd71280805e3e5408dd6
* Move `main#main-content.content.content-alt` into a React component (`ContentLayout`)
* Create the CIAM variant of `RegistrationConfirmEmailForm`
* `bin/run web npm run extract-translations`
* Use `CiamLayout` in the Storybook demo
* Add `SplitTestProvider` in tests
* Fix Storybook: Wrap `RegistrationConfirmEmailForm` Story in `onboarding-confirm-email`
* Refactor SCSS files:
- only imports in all.scss
- split .storybook-layout and .storybook-enabled
- extract ciam-spacing.scss
GitOrigin-RevId: f4a214a0978423a1621dd8f60bf459af7b8f877e