Skip to content

Wire every settings option through the auth pipeline#8

Open
manzoorwanijk wants to merge 4 commits into
trunkfrom
rsm-3233-wire-settings-options
Open

Wire every settings option through the auth pipeline#8
manzoorwanijk wants to merge 4 commits into
trunkfrom
rsm-3233-wire-settings-options

Conversation

@manzoorwanijk
Copy link
Copy Markdown
Member

Summary

Fixes RSM-3233.

The B3 settings UI (#5) exposed the full schema, but three options were declared and never consumed by the runtime. This PR wires them up and adds a few related UX cleanups discovered during the sweep.

Options now consumed

  • email_modecreate_user_from_claims always passed an empty user_email. Now reads Settings::get_email_mode(): placeholder synthesizes tg_<sub>@users.noreply.<host>; none (default) keeps it empty.
  • button_label — the shortcode, login_form auto-print, and the Block all hardcoded "Sign in with Telegram". Now read Settings::get_button_label() as the default.
  • post_login_redirect — only the per-request tx->redirect_to was honoured. Now used as a fallback after the per-request value, still routed through wp_safe_redirect so cross-host targets are downgraded.

Related UX cleanups

  • Block inspector shows the saved settings as placeholder text in the label / redirect inputs, so freshly inserted blocks visibly inherit the site-wide values. Empty block attributes continue to fall back at render time.
  • wp-login.php button gets a wrapping <p> plus a small login_enqueue_scripts stylesheet so it has breathing room between the password field and the submit row. SVG icon now has vertical-align: middle so it sits centered against the label everywhere it renders (shortcode, block, login form).
  • Profile-page "Connect Telegram" button switches from button-primary to button-secondary to avoid competing visually with the WordPress save-changes button.
  • Settings-page email-mode description now spells out how the placeholder mode actually works (the tg_<id>@users.noreply.<your-site> shape + the bounce caveat) instead of just saying "choose how to handle the missing value".

Public UI gated on configuration

The settings page is always reachable so admins can configure the plugin, but the public-facing entry points are now hooked only when both credentials resolve (constants or DB). When unconfigured:

  • No "Sign in with Telegram" button on wp-login.php.
  • The [telegram_auth_button] shortcode renders nothing.
  • The block isn't registered (doesn't appear in the inserter).
  • The user profile "Connect Telegram" section is hidden.

Always-on regardless: settings schema + REST, OIDC endpoints (they fail closed when unconfigured), the avatar provider for already-linked users, the users-list Phone column.

Test plan

Automated (all green locally):

  • composer phpunit — 128 tests, 242 assertions.
  • composer phpcs — clean.
  • npm run lint:js / npm run lint:css / npm run typecheck / npm test / npm run build.

Manual:

  • With no credentials in DB or constants: confirm wp-login.php has no Telegram button, the shortcode renders empty, the block doesn't appear in the inserter, and the user profile shows no Telegram section.
  • Add credentials in DB or as constants, reload: all four surfaces reappear.
  • Settings → Telegram Auth → set email_mode to Placeholder email, sign in as a fresh Telegram user, confirm the created WP user has tg_<sub>@users.noreply.<host> in user_email.
  • Settings → set email_mode to No email, repeat — user_email is empty.
  • Settings → set a custom Sign-in button label and a Default post-login redirect. Reload wp-login.php: the button uses the new label. Click sign-in, complete the flow without a per-request redirect_to, confirm landing on the configured URL. Repeat with a per-request redirect_to, confirm it wins.
  • Insert a Telegram Login Button block fresh: the inspector inputs display the saved settings as placeholder text. Type to override; clear the field to fall back to the inherited value at render time.
  • Visit the user profile screen: the "Connect Telegram" button is button-secondary, not primary.

🤖 Generated with Claude Code

Sweep for RSM-3233. The settings UI (B3) exposed the full schema but
three options were declared and never consumed by the runtime:

- email_mode: create_user_from_claims always passed '' for user_email.
  Now reads Settings::get_email_mode(); 'placeholder' synthesizes
  tg_<sub>@users.noreply.<host>, 'none' (default) keeps it empty.
- button_label: shortcode, login_form auto-print, and the Block all
  hardcoded "Sign in with Telegram". Now read
  Settings::get_button_label() as the default.
- post_login_redirect: only the per-request tx->redirect_to was
  honoured. Now used as a fallback after the per-request value (still
  via wp_safe_redirect, so cross-host targets are downgraded).

While we're here:

- Block inspector inputs show the saved settings as placeholders so
  freshly inserted blocks visibly inherit the site-wide values. Empty
  block attributes continue to fall back at render time.
- wp-login.php button gets a wrapping <p> and a small inline
  stylesheet enqueued via login_enqueue_scripts so it has breathing
  room around the password field instead of sitting flush.
- Profile-page "Connect Telegram" button switches from
  button-primary to button-secondary to avoid competing visually
  with the WordPress save-changes button.

Tests: PHPUnit covers each new accessor (button_label fallbacks,
email_mode validation + default, post_login_redirect read) and the
two user-creation branches (placeholder vs empty email).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@manzoorwanijk manzoorwanijk marked this pull request as ready for review May 15, 2026 13:29
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 15, 2026

🔍 WordPress Plugin Check Report

⚠️ Status: Passed with warnings

📊 Report

🎯 Total Issues ❌ Errors ⚠️ Warnings
24 0 24

⚠️ Warnings (24)

📁 composer.json (1 warning)
📍 Line 🔖 Check 💬 Message
0 missing_composer_json_file The "/vendor" directory using composer exists, but "composer.json" file is missing.
📁 build/build.php (5 warnings)
📍 Line 🔖 Check 💬 Message
13 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$modules_file".
19 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$scripts_file".
25 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$styles_file".
31 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$routes_file".
37 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$pages_file".
📁 build/routes.php (12 warnings)
📍 Line 🔖 Check 💬 Message
14 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$routes_file".
19 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$routes".
22 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$routes_by_page".
23 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$route".
24 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$page_slug".
26 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$routes_by_page".
28 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$routes_by_page".
32 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$page_slug".
32 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$page_routes".
33 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$page_slug_underscore".
34 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$global_name".
35 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound Global variables defined by a theme/plugin should start with the theme/plugin prefix. Found: "$$global_name".
📁 build/pages/telegram-auth/page-wp-admin.php (1 warning)
📍 Line 🔖 Check 💬 Message
141 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound Hook names invoked by a theme/plugin should start with the theme/plugin prefix. Found: "telegram-auth-wp-admin_init".
📁 build/pages/telegram-auth/page.php (5 warnings)
📍 Line 🔖 Check 💬 Message
141 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound Hook names invoked by a theme/plugin should start with the theme/plugin prefix. Found: "telegram-auth_init".
263 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound Hook names invoked by a theme/plugin should start with the theme/plugin prefix. Found: "admin_head-{$hook_suffix}".
270 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound Hook names invoked by a theme/plugin should start with the theme/plugin prefix. Found: "admin_head".
284 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound Hook names invoked by a theme/plugin should start with the theme/plugin prefix. Found: "admin_footer".
298 WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound Hook names invoked by a theme/plugin should start with the theme/plugin prefix. Found: "admin_footer-{$hook_suffix}".

🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

- Bootstrap registers Login_Button, Login_Button_Block, and
  Profile_Section unconditionally again. Already-saved shortcode and
  block instances stay reachable across credential rotations; the
  render paths now no-op when Settings::is_configured() is false.
- Login_Button_Block::render also treats an empty-string redirectTo
  attribute (not just missing) as a fall-back to the site-wide
  post_login_redirect setting, matching the label-side logic and the
  "Leave blank to inherit" copy in the inspector.
- Profile_Section now hides the whole "Telegram Auth" section when
  the plugin isn't configured AND the user isn't already linked.
  Linked users still see their status + the Disconnect button, even
  after credentials get removed, so they can clean up the link.
- Block editor reads inherited defaults from a
  `window.telegramAuthBlockDefaults` global emitted on
  `enqueue_block_editor_assets`. Drops the apiFetch round-trip and
  the empty-cache-on-failure footgun (`/wp/v2/settings` requires
  manage_options, which editors don't necessarily have).
- Login_Button + Login_Button_Block tests now stub credentials so
  the new is_configured() gate in the render paths doesn't short-
  circuit them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@manzoorwanijk manzoorwanijk force-pushed the rsm-3233-wire-settings-options branch from a02a77b to 6dfb40f Compare May 15, 2026 13:57
manzoorwanijk and others added 2 commits May 15, 2026 19:45
- jetpack-wp-build-polyfills 0.1.6 → 0.1.8 (upstream dep bumps;
  no behavior change for us).
- @wordpress/boot's asset.php now declares @wordpress/lazy-editor as
  a dynamic-import dep, but neither Core nor the polyfills package
  ships it yet. Register an empty data-URI stub on the settings page
  so WP 6.9.1+'s WP_Script_Modules::register doesn't fire a
  "doing it wrong" notice when polyfills enqueue boot. Hooked at
  wp_default_scripts priority 15 (after Core's default priority-10
  registration, before polyfills' priority-20 registration) so a
  real lazy-editor shipped by a future Core/Gutenberg wins via the
  first-registration-wins rule. Scoped to the settings page so the
  stub never shadows lazy-editor on surfaces that actually consume
  it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two related changes to how the plugin handles the OIDC phone_number
claim:

1. The write now routes through add_user_meta() with
   $unique = true instead of update_user_meta(). That's the WP
   idiom for "write only if absent" — when a user already has a
   billing_phone (set by WooCommerce, BuddyPress, theme, or the user
   themselves), WP returns false without touching the row. Defense
   in depth even though create_user_from_claims is structurally
   "new user only" today.

2. We now also attempt the write when an existing user signs in,
   not just on first-account-creation. update_profile_from_claims
   calls the same helper, so a user who linked before granting the
   phone scope (or who simply hadn't set billing_phone yet) gets it
   populated on their next sign-in — but never has an existing
   value overwritten, thanks to the unique flag.

The two existing billing_phone tests are updated to track
add_user_meta calls (instead of update_user_meta) and to assert
$unique = true is being passed; the "does not backfill for existing
users" test is renamed to its new positive form.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant