discourse/spec/jobs
Keegan George f4bd916c88
FEATURE: Log in with a one-time email code (#40804)
Previously, the only passwordless way to log in by email was a one-click
magic link, enabled with `enable_local_logins_via_email`.

This change adds `enable_local_logins_via_code`, which switches that
flow to send a short one-time code instead of a link: when enabled, the
login page offers "Email me a one-time login code" in place of the link
option, and entering the emailed code logs the user in (including
through any configured second factor). A code only ever logs an
*existing* user in, and the request endpoint responds identically
whether or not the email matches an account, so it can't be used to
probe for accounts.

Signing up with a one-time code builds on this and is in #40909.

<details>
<summary>Screenshots</summary>

**Desktop**

| Step | Foundation · Light | Foundation · Dark | Horizon · Light |
Horizon · Dark |
|---|---|---|---|---|
| Password form (default) | <img width="1400" height="1200"
alt="desktop-foundation-light-code-login-password-form"
src="https://github.com/user-attachments/assets/aa6758f0-9402-4229-8ad8-962d9773b7bd"
/> | <img width="1400" height="1200"
alt="desktop-foundation-dark-code-login-password-form"
src="https://github.com/user-attachments/assets/e4283e80-5973-48ba-8b24-e4a154fd04ea"
/> | <img width="1400" height="1200"
alt="desktop-horizon-light-code-login-password-form"
src="https://github.com/user-attachments/assets/8b58915c-f040-40cf-aa28-50e763032ba1"
/> | <img width="1400" height="1200"
alt="desktop-horizon-dark-code-login-password-form"
src="https://github.com/user-attachments/assets/4de1c283-1021-4ac1-b4e1-9e5e14a1a883"
/> |
| Email entry | <img width="1400" height="1200"
alt="desktop-foundation-light-code-login-email-step"
src="https://github.com/user-attachments/assets/9ecd42cd-b7a4-4eaa-b7a4-f3de2418d7df"
/> | <img width="1400" height="1200"
alt="desktop-foundation-dark-code-login-email-step"
src="https://github.com/user-attachments/assets/6e2d106c-6fdd-498b-a470-85b5dafab2c7"
/> | <img width="1400" height="1200"
alt="desktop-horizon-light-code-login-email-step"
src="https://github.com/user-attachments/assets/adfc7f9b-2651-43e1-a2ab-b37d1ff3e34f"
/> | <img width="1400" height="1200"
alt="desktop-horizon-dark-code-login-email-step"
src="https://github.com/user-attachments/assets/4e6872e1-ce77-462d-a04f-2c81fa5e61ed"
/> |
| Code entry | <img width="1400" height="1200"
alt="desktop-foundation-light-code-login-code-step"
src="https://github.com/user-attachments/assets/b9b53768-e095-489a-bb62-d23e8b018d28"
/> | <img width="1400" height="1200"
alt="desktop-foundation-dark-code-login-code-step"
src="https://github.com/user-attachments/assets/933e41fb-ea1b-434e-87b7-ffca6d651628"
/> | <img width="1400" height="1200"
alt="desktop-horizon-light-code-login-code-step"
src="https://github.com/user-attachments/assets/936967cf-b657-4d9f-80e2-c44226b681c3"
/> | <img width="1400" height="1200"
alt="desktop-horizon-dark-code-login-code-step"
src="https://github.com/user-attachments/assets/2bf4530c-e6ba-4561-963e-36a494288c3c"
/> |
| Invalid code | <img width="1400" height="1200"
alt="desktop-foundation-light-code-login-wrong-code"
src="https://github.com/user-attachments/assets/ddaf1ae4-66ec-499b-859c-c169ce544f3d"
/> | <img width="1400" height="1200"
alt="desktop-foundation-dark-code-login-wrong-code"
src="https://github.com/user-attachments/assets/f6a57236-f498-4a98-ac80-aee3f7a1e1a5"
/> | <img width="1400" height="1200"
alt="desktop-horizon-light-code-login-wrong-code"
src="https://github.com/user-attachments/assets/e8622433-d693-4faf-b2aa-f71c910c3b52"
/> | <img width="1400" height="1200"
alt="desktop-horizon-dark-code-login-wrong-code"
src="https://github.com/user-attachments/assets/0221c9ba-5003-4160-9ef9-281045f2f318"
/> |

**Mobile**

| Step | Foundation · Light | Foundation · Dark | Horizon · Light |
Horizon · Dark |
|---|---|---|---|---|
| Password form (default) | <img width="1170" height="3600"
alt="mobile-foundation-light-code-login-password-form"
src="https://github.com/user-attachments/assets/6e25f7b4-915f-4f55-8b27-9f51ec4ec1ea"
/> | <img width="1170" height="3600"
alt="mobile-foundation-dark-code-login-password-form"
src="https://github.com/user-attachments/assets/0e1b0009-8b70-454f-8167-01c7a8ce0664"
/> | <img width="1170" height="3600"
alt="mobile-horizon-light-code-login-password-form"
src="https://github.com/user-attachments/assets/79949635-a8f5-4fc5-aa2f-22edb77f7b2d"
/> | <img width="1170" height="3600"
alt="mobile-horizon-dark-code-login-password-form"
src="https://github.com/user-attachments/assets/1f7e962d-5e0b-4e22-bb54-0b27b870696f"
/> |
| Email entry | <img width="1170" height="3600"
alt="mobile-foundation-light-code-login-email-step"
src="https://github.com/user-attachments/assets/5577aad2-dd30-4424-af7a-af5f33458c8c"
/> | <img width="1170" height="3600"
alt="mobile-foundation-dark-code-login-email-step"
src="https://github.com/user-attachments/assets/571b5bf2-0b07-46ec-ba3a-b80bc1078643"
/> | <img width="1170" height="3600"
alt="mobile-horizon-light-code-login-email-step"
src="https://github.com/user-attachments/assets/3beb6702-e7df-434b-98d6-23203c6bee98"
/> | <img width="1170" height="3600"
alt="mobile-horizon-dark-code-login-email-step"
src="https://github.com/user-attachments/assets/17b33dc8-c133-4f07-8817-1f1f7c6cf8ff"
/> |
| Code entry | <img width="1170" height="3600"
alt="mobile-foundation-light-code-login-code-step"
src="https://github.com/user-attachments/assets/91beeec5-87eb-4169-a53d-53164dd7dd2a"
/> | <img width="1170" height="3600"
alt="mobile-foundation-dark-code-login-code-step"
src="https://github.com/user-attachments/assets/8d8de095-7050-4006-bc72-6a82f7c17513"
/> | <img width="1170" height="3600"
alt="mobile-horizon-light-code-login-code-step"
src="https://github.com/user-attachments/assets/f874a1c6-2e9f-4c0c-b500-850c44067489"
/> | <img width="1170" height="3600"
alt="mobile-horizon-dark-code-login-code-step"
src="https://github.com/user-attachments/assets/4957797c-00e9-45b8-8504-8baba15cde06"
/> |
| Invalid code | <img width="1170" height="3600"
alt="mobile-foundation-light-code-login-wrong-code"
src="https://github.com/user-attachments/assets/76124aa6-fd77-467a-b1bb-60e85e354612"
/> | <img width="1170" height="3600"
alt="mobile-foundation-dark-code-login-wrong-code"
src="https://github.com/user-attachments/assets/c0f8d7db-9a7e-4803-928c-91a504bf8391"
/> | <img width="1170" height="3600"
alt="mobile-horizon-light-code-login-wrong-code"
src="https://github.com/user-attachments/assets/77b97702-8ee7-4244-906e-6fddb5e22cae"
/> | <img width="1170" height="3600"
alt="mobile-horizon-dark-code-login-wrong-code"
src="https://github.com/user-attachments/assets/e034b400-6430-4441-9b2a-c0f1b0bb49c6"
/> |
</details>
2026-06-17 12:34:48 -07:00
..
regular FEATURE: Log in with a one-time email code (#40804) 2026-06-17 12:34:48 -07:00
scheduled FIX: Do not send notifications for upcoming changes not displayed (#40933) 2026-06-17 09:10:49 +10:00
about_stats_spec.rb DEV: Enable Style/RedundantBegin rubocop rule (#40096) 2026-05-19 18:44:54 +02:00
activation_reminder_emails_spec.rb
auto_queue_handler_spec.rb DEV: Convert min_trust_to_flag_posts setting to groups (#24864) 2023-12-13 17:18:42 +08:00
automatic_group_membership_spec.rb
backfill_sidebar_site_settings_spec.rb
bookmark_reminder_notifications_spec.rb DEV: Enable Style/RedundantBegin rubocop rule (#40096) 2026-05-19 18:44:54 +02:00
bulk_grant_trust_level_spec.rb PERF: Add Users to Group Pt. 1 (#38737) 2026-03-26 09:11:22 -05:00
bulk_invite_spec.rb DEV: Update bulk-invite logs and PM template (#27057) 2024-05-17 12:21:21 -06:00
bump_topic_spec.rb DEV: Fix various rubocop lints (#24749) 2023-12-06 23:25:00 +01:00
call_discourse_hub_spec.rb FIX: Handle boolean values in version check response (#38786) 2026-03-23 15:39:38 +00:00
change_display_name_spec.rb FIX: Preserve display name in quotes when using the rich text editor (#38078) 2026-02-26 21:04:07 +01:00
check_new_features_spec.rb UX: suppress new feature notifications on brand new sites (#40135) 2026-05-19 09:38:57 +10:00
check_translation_overrides_spec.rb DEV: Refresh translation override status when updating (#31233) 2025-02-07 14:12:28 +08:00
clean_dismissed_topic_users_spec.rb DEV: Update rubocop-discourse to 3.13 and autofix issues (#35073) 2025-10-06 16:11:01 +02:00
clean_up_associated_accounts_spec.rb
clean_up_browser_pageview_events_spec.rb FIX: Delete BrowserPageviewEventScore rows during cleanup (#40390) 2026-05-29 12:25:35 +08:00
clean_up_crawler_stats_spec.rb
clean_up_email_change_requests_spec.rb
clean_up_email_logs_spec.rb DEV: add shortcut fab!(:variable, :fabricator) to specs (#33577) 2025-07-11 11:16:34 -03:00
clean_up_inactive_users_spec.rb
clean_up_post_reply_keys_spec.rb
clean_up_tags_spec.rb DEV: fix a large amount of typos (#37428) 2026-02-02 16:31:58 +11:00
clean_up_unused_staged_users_spec.rb
clean_up_unused_user_api_key_clients_spec.rb Require permitted scopes when registering a client (#29718) 2024-11-19 15:28:04 -05:00
clean_up_unused_user_api_keys_spec.rb DEV: add shortcut fab!(:variable, :fabricator) to specs (#33577) 2025-07-11 11:16:34 -03:00
clean_up_uploads_spec.rb DEV: Enable Style/RedundantBegin rubocop rule (#40096) 2026-05-19 18:44:54 +02:00
clean_up_user_api_keys_max_life_spec.rb DEV: Update rubocop-discourse to 3.13 and autofix issues (#35073) 2025-10-06 16:11:01 +02:00
clean_up_user_export_topics_spec.rb DEV: Allow fab! without block (#24314) 2023-11-09 16:47:59 -06:00
cleanup_problem_check_trackers_spec.rb DEV: Clean up trackers with outdated targets (#35978) 2026-01-14 12:54:16 +01:00
cleanup_redelivering_web_hook_events_spec.rb FEATURE: Add Mechanism to redeliver all failed webhook events (#27609) 2024-07-08 15:43:16 -05:00
close_topic_spec.rb FIX: Gate MessageBus groups when closing topic (#40913) 2026-06-15 15:27:07 -05:00
correct_missing_dualstack_urls_spec.rb DEV: Use Discourse::SYSTEM_USER_ID in fixtures/009_users (#24743) 2023-12-07 09:04:45 +10:00
crawl_topic_link_spec.rb DEV: Clean up scope resolution operators in plugins (#34979) 2025-09-30 14:36:34 +02:00
create_linked_topic_spec.rb DEV: add shortcut fab!(:variable, :fabricator) to specs (#33577) 2025-07-11 11:16:34 -03:00
create_missing_avatars_spec.rb
create_recent_post_search_indexes_spec.rb DEV: Fix random typos (#24756) 2023-12-06 22:25:26 +01:00
create_user_reviewable_spec.rb
delete_replies_spec.rb FIX: DeleteReplies should use the guardian instead of checking for staff (#35443) 2025-10-16 18:26:41 +02:00
delete_topic_spec.rb DEV: Fix various rubocop lints (#24749) 2023-12-06 23:25:00 +01:00
delete_user_posts_spec.rb FIX: return nil correctly for nil check (#37460) 2026-02-02 15:43:56 -08:00
deliver_push_notification_spec.rb DEV: Centralize push notification delivery into a single job (#39207) 2026-04-14 11:55:45 -03:00
detect_crawler_pageviews_spec.rb DEV: Add anonymous pageview crawler scoring job (#39954) 2026-05-14 12:46:08 +08:00
download_avatar_from_url_spec.rb DEV: Allow fab! without block (#24314) 2023-11-09 16:47:59 -06:00
download_backup_email_spec.rb FEATURE: better email subject lines (#36040) 2026-04-24 15:14:10 +04:00
download_profile_background_from_url_spec.rb DEV: Allow fab! without block (#24314) 2023-11-09 16:47:59 -06:00
emit_web_hook_event_spec.rb DEV: always load the excon gem 2026-01-15 17:13:11 -05:00
enqueue_digest_emails_spec.rb FIX: send activity summaries based on "last seen" (#27035) 2024-05-22 10:23:03 +02:00
enqueue_suspect_users_spec.rb FIX: Exclude suspended users from suspect users review queue (#37796) 2026-02-16 10:46:52 +08:00
ensure_db_consistency_spec.rb FIX: we introduced a Jobs::UserEmail which broke consistency checks (#30409) 2024-12-22 21:33:47 +11:00
ensure_s3_uploads_existence_multisite_spec.rb FIX: Jobs::EnsureS3UploadsExistence broken for multisite (#27401) 2024-06-10 16:26:39 +08:00
ensure_s3_uploads_existence_spec.rb DEV: Deprecate the assignment of nil to site settings (#36093) 2025-12-01 15:04:23 +08:00
export_csv_file_spec.rb FIX: Reject DiscourseConnect SSO payloads when secret is blank (#40830) 2026-06-12 15:17:16 +03:00
export_user_archive_spec.rb FIX: Escape markdown characters in upload filenames (#39133) 2026-04-14 10:37:41 +02:00
feature_topic_users_spec.rb DEV: Allow fab! without block (#24314) 2023-11-09 16:47:59 -06:00
fix_out_of_sync_user_uploaded_avatar_spec.rb
fix_primary_emails_for_staged_users_spec.rb
fix_s3_etags_spec.rb
fix_user_usernames_and_groups_names_clash_spec.rb
grant_anniversary_badges_spec.rb
grant_new_user_of_the_month_badges_spec.rb
ignored_users_summary_spec.rb
index_user_fields_for_search_spec.rb FIX: Move user reindexing into a job (#26753) 2024-04-25 20:58:34 +08:00
invalidate_inactive_admins_spec.rb
invite_email_spec.rb DEV: Tighten protections when disabling allow_email_invites (#37453) 2026-02-02 11:40:04 -05:00
jobs_base_spec.rb DEV: Enable Rails/FilePath rubocop rule (#40097) 2026-05-19 19:07:54 +02:00
jobs_scheduled_spec.rb DEV: Support a perform_when_readonly option for Jobs::Scheduled (#30478) 2024-12-27 09:42:40 +08:00
jobs_spec.rb FIX: Redo Sidekiq monitoring to restart stuck sidekiq processes (#30198) 2024-12-18 12:48:50 +08:00
maintain_browser_pageview_rollups_spec.rb FIX: Backfill normalized referrer for historical browser pageviews (#40357) 2026-06-09 09:04:57 +08:00
mass_award_badge_spec.rb DEV: Allow fab! without block (#24314) 2023-11-09 16:47:59 -06:00
notify_category_change_spec.rb DEV: add shortcut fab!(:variable, :fabricator) to specs (#33577) 2025-07-11 11:16:34 -03:00
notify_mailing_list_subscribers_spec.rb DEV: add shortcut fab!(:variable, :fabricator) to specs (#33577) 2025-07-11 11:16:34 -03:00
notify_moved_posts_spec.rb DEV: add shortcut fab!(:variable, :fabricator) to specs (#33577) 2025-07-11 11:16:34 -03:00
notify_reviewable_spec.rb FIX: Resolve all of a deleted spammer's reviewables (#40780) 2026-06-15 13:34:15 +08:00
notify_tag_change_spec.rb FIX: Allow "watching first post" notification to fire when tags edit notifications are disabled (#37935) 2026-02-20 16:59:53 +08:00
old_keys_reminder_spec.rb DEV: Update rubocop-discourse to 3.13 and autofix issues (#35073) 2025-10-06 16:11:01 +02:00
open_topic_spec.rb FIX: Gate MessageBus groups when closing topic (#40913) 2026-06-15 15:27:07 -05:00
pending_queued_posts_reminder_spec.rb
pending_reviewables_reminder_spec.rb DEV: Convert min_trust_to_flag_posts setting to groups (#24864) 2023-12-13 17:18:42 +08:00
pending_users_reminder_spec.rb Revert "FEATURE: discourse-workflows (#39704)" (#40366) 2026-05-28 13:59:42 +01:00
periodical_updates_spec.rb DEV: ensure rebaking works even when some users have inconsistent data (#30261) 2024-12-16 19:48:25 +08:00
poll_mailbox_spec.rb FIX: Allow only sanitized strings in admin notices (#39796) 2026-05-06 13:40:20 -04:00
post_update_topic_tracking_state_spec.rb FIX: PM unread count shows (1) but message list is empty (#38733) 2026-03-20 09:50:38 +01:00
post_uploads_recovery_spec.rb
process_bulk_invite_emails_spec.rb
process_email_spec.rb
process_localized_cooked_spec.rb FEATURE: Localize local oneboxes (#40493) 2026-06-08 11:49:55 +08:00
process_post_spec.rb FIX: Sync category description when post content changes outside PostRevisor (#39184) 2026-05-11 16:13:23 +02:00
process_shelved_notifications_spec.rb DEV: Update rubocop-discourse to 3.13 and autofix issues (#35073) 2025-10-06 16:11:01 +02:00
publish_topic_to_category_spec.rb FIX: TL4 PM participants can schedule system publication of private messages (#39872) 2026-05-12 14:50:04 +10:00
pull_hotlinked_images_spec.rb DEV: fix a large amount of typos (#37428) 2026-02-02 16:31:58 +11:00
pull_user_profile_hotlinked_images_spec.rb DEV: Allow fab! without block (#24314) 2023-11-09 16:47:59 -06:00
purge_expired_ignored_users_spec.rb
push_notification_spec.rb DEV: Centralize push notification delivery into a single job (#39207) 2026-04-14 11:55:45 -03:00
rebake_custom_emoji_posts_spec.rb
redeliver_web_hook_events_spec.rb FIX: Match webhook-related messagebus audience to controller audience (#40693) 2026-06-09 18:22:26 +01:00
refresh_users_reviewable_counts_spec.rb FEATURE: Support designating multiple groups as mods on category (#28655) 2024-09-04 04:38:46 +03:00
reindex_search_spec.rb FEATURE: Add full-text search for chat messages (#34704) 2025-10-22 11:30:35 +02:00
remove_banner_spec.rb DEV: Allow fab! without block (#24314) 2023-11-09 16:47:59 -06:00
reviewable_priorities_spec.rb DEV: add shortcut fab!(:variable, :fabricator) to specs (#33577) 2025-07-11 11:16:34 -03:00
run_problem_check_spec.rb FIX: Fix scheduled targeted problem checks (#35696) 2025-11-10 10:09:14 +08:00
run_problem_checks_spec.rb FIX: Fix scheduled targeted problem checks (#35696) 2025-11-10 10:09:14 +08:00
send_push_notification_spec.rb DEV: Centralize push notification delivery into a single job (#39207) 2026-04-14 11:55:45 -03:00
send_system_message_spec.rb DEV: Allow fab! without block (#24314) 2023-11-09 16:47:59 -06:00
suspicious_login_spec.rb DEV: add shortcut fab!(:variable, :fabricator) to specs (#33577) 2025-07-11 11:16:34 -03:00
sync_access_control_for_uploads_spec.rb DEV: Add setting to tag s3 objects enabling tag based access control policies (#32988) 2025-06-16 13:26:18 +08:00
sync_topic_user_bookmarked_spec.rb DEV: Allow fab! without block (#24314) 2023-11-09 16:47:59 -06:00
tl3_promotions_spec.rb DEV: Add tl3_custom_promotions plugin modifier to tl3_promotions.rb (#29834) 2024-11-22 15:28:43 -05:00
toggle_topic_closed_spec.rb DEV: rename topic_id to timerable_id for BaseTimer (#34667) 2025-09-17 13:19:17 +08:00
topic_timer_enqueuer_spec.rb DEV: Update rubocop-discourse to 3.13 and autofix issues (#35073) 2025-10-06 16:11:01 +02:00
truncate_user_flag_stats_spec.rb DEV: Convert min_trust_to_flag_posts setting to groups (#24864) 2023-12-13 17:18:42 +08:00
unsilence_users_spec.rb
update_animated_uploads_spec.rb
update_gravatar_spec.rb DEV: Allow fab! without block (#24314) 2023-11-09 16:47:59 -06:00
update_topic_hot_scores_spec.rb DEV: Clean up scope resolution operators in plugins (#34979) 2025-09-30 14:36:34 +02:00
update_username_spec.rb FIX: Sync category description when post content changes outside PostRevisor (#39184) 2026-05-11 16:13:23 +02:00
user_email_spec.rb DEV: add shortcut fab!(:variable, :fabricator) to specs (#33577) 2025-07-11 11:16:34 -03:00