Fix auth: keep Sign In button locked, pipe code into waiting auth process stdin
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
9e6cdeb9c3
commit
02c3e9639e
1 file changed
+60
-21
+60
-21
@@ -1188,32 +1188,59 @@ class AuthPage(Gtk.Box):
|
|||||||
|
|
||||||
def _on_auth(self, btn):
|
def _on_auth(self, btn):
|
||||||
btn.set_sensitive(False)
|
btn.set_sensitive(False)
|
||||||
btn.set_label("Signing in…")
|
btn.set_label("Waiting for Apple…")
|
||||||
args = ["auth"]
|
self._auth_btn = btn
|
||||||
|
cmd = [ICLOUDCTL, "auth"]
|
||||||
if self.sms_check.get_active():
|
if self.sms_check.get_active():
|
||||||
args.append("--force-sms")
|
cmd.append("--force-sms")
|
||||||
if self.debug_check.get_active():
|
if self.debug_check.get_active():
|
||||||
args.append("--debug")
|
cmd.append("--debug")
|
||||||
self.status_label.set_markup('<span fgcolor="#64a6e0">Connecting to Apple — a code will be sent to your device…</span>')
|
self.status_label.set_markup('<span fgcolor="#64a6e0">Connecting to Apple — a code will appear on your device…</span>')
|
||||||
|
|
||||||
def _worker():
|
try:
|
||||||
rc, out, err = icloudctl(*args)
|
self._auth_proc = subprocess.Popen(
|
||||||
GLib.idle_add(self._auth_result, rc, out + err, btn)
|
cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
||||||
threading.Thread(target=_worker, daemon=True).start()
|
stderr=subprocess.STDOUT, text=True, bufsize=1
|
||||||
|
|
||||||
def _auth_result(self, rc, output, btn):
|
|
||||||
btn.set_sensitive(True)
|
|
||||||
btn.set_label("Sign in with Apple ID")
|
|
||||||
if "two-factor" in output.lower() or "verification" in output.lower() or "2fa" in output.lower() or "enter" in output.lower():
|
|
||||||
self.status_label.set_markup(
|
|
||||||
'<span fgcolor="#e6a020">Code sent — enter it in the box below.</span>'
|
|
||||||
)
|
)
|
||||||
self.tfa_entry.grab_focus()
|
except Exception as e:
|
||||||
elif rc == 0:
|
btn.set_sensitive(True)
|
||||||
|
btn.set_label("Sign in with Apple ID")
|
||||||
|
self.status_label.set_markup(f'<span fgcolor="#c6262e">Failed to start: {e}</span>')
|
||||||
|
return
|
||||||
|
|
||||||
|
proc = self._auth_proc
|
||||||
|
output_lines = []
|
||||||
|
|
||||||
|
def _reader():
|
||||||
|
for line in proc.stdout:
|
||||||
|
output_lines.append(line)
|
||||||
|
low = line.lower()
|
||||||
|
if "code" in low or "enter" in low or "sent" in low or "2fa" in low:
|
||||||
|
GLib.idle_add(self._prompt_for_code)
|
||||||
|
proc.wait()
|
||||||
|
out = "".join(output_lines)
|
||||||
|
GLib.idle_add(self._auth_proc_done, proc.returncode, out)
|
||||||
|
|
||||||
|
threading.Thread(target=_reader, daemon=True).start()
|
||||||
|
|
||||||
|
def _prompt_for_code(self):
|
||||||
|
self.status_label.set_markup('<span fgcolor="#e6a020">Code sent — enter it below and click Verify.</span>')
|
||||||
|
self.tfa_entry.grab_focus()
|
||||||
|
|
||||||
|
def _auth_proc_done(self, rc, output):
|
||||||
|
if rc == 0 and "authenticated" in output.lower():
|
||||||
|
self._unlock_auth_btn()
|
||||||
self.status_label.set_markup('<span fgcolor="#68b723">Authentication successful!</span>')
|
self.status_label.set_markup('<span fgcolor="#68b723">Authentication successful!</span>')
|
||||||
else:
|
elif rc != 0:
|
||||||
msg = GLib.markup_escape_text(output[:300])
|
self._unlock_auth_btn()
|
||||||
self.status_label.set_markup(f'<span fgcolor="#c6262e">{msg}</span>')
|
msg = GLib.markup_escape_text(output[-300:].strip())
|
||||||
|
self.status_label.set_markup(f'<span fgcolor="#c6262e">{msg or f"Exited {rc}"}</span>')
|
||||||
|
# rc==0 but still waiting for code → leave button locked until _on_tfa completes
|
||||||
|
|
||||||
|
def _unlock_auth_btn(self):
|
||||||
|
if hasattr(self, "_auth_btn"):
|
||||||
|
self._auth_btn.set_sensitive(True)
|
||||||
|
self._auth_btn.set_label("Sign in with Apple ID")
|
||||||
|
|
||||||
def _on_tfa(self, _):
|
def _on_tfa(self, _):
|
||||||
code = self.tfa_entry.get_text().strip()
|
code = self.tfa_entry.get_text().strip()
|
||||||
@@ -1222,12 +1249,24 @@ class AuthPage(Gtk.Box):
|
|||||||
return
|
return
|
||||||
self.tfa_status.set_markup('<span fgcolor="#64a6e0">Verifying…</span>')
|
self.tfa_status.set_markup('<span fgcolor="#64a6e0">Verifying…</span>')
|
||||||
|
|
||||||
|
proc = getattr(self, "_auth_proc", None)
|
||||||
|
if proc and proc.poll() is None:
|
||||||
|
# Feed the code into the waiting auth process
|
||||||
|
try:
|
||||||
|
proc.stdin.write(code + "\n")
|
||||||
|
proc.stdin.flush()
|
||||||
|
except Exception as e:
|
||||||
|
self.tfa_status.set_markup(f'<span fgcolor="#c6262e">Error: {e}</span>')
|
||||||
|
return
|
||||||
|
|
||||||
|
# auth process already finished — run a fresh auth with code piped in
|
||||||
def _worker():
|
def _worker():
|
||||||
rc, out, err = icloudctl("auth", input_data=code + "\n")
|
rc, out, err = icloudctl("auth", input_data=code + "\n")
|
||||||
GLib.idle_add(self._tfa_result, rc, out + err)
|
GLib.idle_add(self._tfa_result, rc, out + err)
|
||||||
threading.Thread(target=_worker, daemon=True).start()
|
threading.Thread(target=_worker, daemon=True).start()
|
||||||
|
|
||||||
def _tfa_result(self, rc, output):
|
def _tfa_result(self, rc, output):
|
||||||
|
self._unlock_auth_btn()
|
||||||
if rc == 0 or "authenticated" in output.lower() or "success" in output.lower():
|
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_status.set_markup('<span fgcolor="#68b723">Verified! You can now start the service.</span>')
|
||||||
self.tfa_entry.set_text("")
|
self.tfa_entry.set_text("")
|
||||||
|
|||||||
Reference in new issue
Block a user