Fix 2FA: always-visible code entry, Enter key submits, pipe code to icloudctl auth stdin
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
3aa5737c5e
commit
ee39e39e02
1 file changed
+37
-24
+37
-24
@@ -1150,27 +1150,41 @@ class AuthPage(Gtk.Box):
|
||||
card.pack_start(self.status_label, False, False, 0)
|
||||
self.pack_start(card, False, False, 0)
|
||||
|
||||
# 2FA section (hidden until needed)
|
||||
self.tfa_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
|
||||
self.tfa_box.get_style_context().add_class("card")
|
||||
self.tfa_box.set_no_show_all(True)
|
||||
# 2FA section — always visible so user can enter code any time
|
||||
tfa_card = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
|
||||
tfa_card.get_style_context().add_class("card")
|
||||
tfa_card.set_margin_top(4)
|
||||
|
||||
tfa_lbl = Gtk.Label()
|
||||
tfa_lbl.set_markup("<b>Two-Factor Code</b>")
|
||||
tfa_lbl.set_markup("<b>Two-Factor Authentication</b>")
|
||||
tfa_lbl.set_halign(Gtk.Align.START)
|
||||
tfa_sub = Gtk.Label(label="If Apple sent a code to your device, enter it here.")
|
||||
tfa_sub.set_halign(Gtk.Align.START)
|
||||
|
||||
code_row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
|
||||
self.tfa_entry = Gtk.Entry()
|
||||
self.tfa_entry.set_placeholder_text("Enter 6-digit code from your device")
|
||||
self.tfa_entry.set_placeholder_text("6-digit code")
|
||||
self.tfa_entry.set_max_length(6)
|
||||
self.tfa_entry.set_input_purpose(Gtk.InputPurpose.DIGITS)
|
||||
self.tfa_entry.set_hexpand(True)
|
||||
self.tfa_entry.connect("activate", self._on_tfa) # Enter key submits
|
||||
|
||||
btn_tfa = Gtk.Button(label="Verify Code")
|
||||
btn_tfa.get_style_context().add_class("action-btn")
|
||||
btn_tfa.get_style_context().add_class("btn-primary")
|
||||
btn_tfa.connect("clicked", self._on_tfa)
|
||||
|
||||
self.tfa_box.pack_start(tfa_lbl, False, False, 0)
|
||||
self.tfa_box.pack_start(self.tfa_entry, False, False, 0)
|
||||
self.tfa_box.pack_start(btn_tfa, False, False, 0)
|
||||
self.pack_start(self.tfa_box, False, False, 0)
|
||||
code_row.pack_start(self.tfa_entry, True, True, 0)
|
||||
code_row.pack_start(btn_tfa, False, False, 0)
|
||||
|
||||
self.tfa_status = Gtk.Label(label="")
|
||||
self.tfa_status.set_halign(Gtk.Align.START)
|
||||
|
||||
tfa_card.pack_start(tfa_lbl, False, False, 0)
|
||||
tfa_card.pack_start(tfa_sub, False, False, 0)
|
||||
tfa_card.pack_start(code_row, False, False, 0)
|
||||
tfa_card.pack_start(self.tfa_status, False, False, 0)
|
||||
self.pack_start(tfa_card, False, False, 0)
|
||||
|
||||
def _on_auth(self, _):
|
||||
args = ["auth"]
|
||||
@@ -1186,21 +1200,23 @@ class AuthPage(Gtk.Box):
|
||||
threading.Thread(target=_worker, daemon=True).start()
|
||||
|
||||
def _auth_result(self, rc, output):
|
||||
if "two-factor" in output.lower() or "verification" in output.lower():
|
||||
if "two-factor" in output.lower() or "verification" in output.lower() or "2fa" in output.lower():
|
||||
self.status_label.set_markup(
|
||||
'<span fgcolor="#e6a020">2FA required - enter code from your Apple device.</span>'
|
||||
'<span fgcolor="#e6a020">A code was sent to your Apple device — enter it below.</span>'
|
||||
)
|
||||
self.tfa_box.show()
|
||||
self.tfa_entry.grab_focus()
|
||||
elif rc == 0:
|
||||
self.status_label.set_markup('<span fgcolor="#68b723">Authentication successful!</span>')
|
||||
else:
|
||||
msg = GLib.markup_escape_text(output[:200])
|
||||
self.status_label.set_markup(f'<span fgcolor="#c6262e">Error: {msg}</span>')
|
||||
msg = GLib.markup_escape_text(output[:300])
|
||||
self.status_label.set_markup(f'<span fgcolor="#c6262e">{msg}</span>')
|
||||
|
||||
def _on_tfa(self, _):
|
||||
code = self.tfa_entry.get_text().strip()
|
||||
if not code:
|
||||
if len(code) < 6:
|
||||
self.tfa_status.set_markup('<span fgcolor="#c6262e">Please enter the full 6-digit code.</span>')
|
||||
return
|
||||
self.tfa_status.set_markup('<span fgcolor="#64a6e0">Verifying…</span>')
|
||||
|
||||
def _worker():
|
||||
rc, out, err = icloudctl("auth", input_data=code + "\n")
|
||||
@@ -1208,15 +1224,12 @@ class AuthPage(Gtk.Box):
|
||||
threading.Thread(target=_worker, daemon=True).start()
|
||||
|
||||
def _tfa_result(self, rc, output):
|
||||
if rc == 0:
|
||||
self.status_label.set_markup(
|
||||
'<span fgcolor="#68b723">Verification complete! You can now start the service.</span>'
|
||||
)
|
||||
self.tfa_box.hide()
|
||||
if rc == 0 or "authenticated" in output.lower() or "success" in output.lower():
|
||||
self.tfa_status.set_markup('<span fgcolor="#68b723">Verified! You can now start the service.</span>')
|
||||
self.tfa_entry.set_text("")
|
||||
else:
|
||||
self.status_label.set_markup(
|
||||
'<span fgcolor="#c6262e">Verification failed. Try again.</span>'
|
||||
)
|
||||
msg = GLib.markup_escape_text(output[:200]) if output.strip() else f"exit code {rc}"
|
||||
self.tfa_status.set_markup(f'<span fgcolor="#c6262e">Failed: {msg}</span>')
|
||||
|
||||
|
||||
# ── Main window ────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in new issue
Block a user