Repository: fedora-infra/bodhi

Issue:
bodhi-client doesn't gracefully handle Ctrl+C when asking for an auth token
This was reported [here](https://bugzilla.redhat.com/show_bug.cgi?id=2102585):

```
$ fedora-easy-karma 
Logging into Bodhi...
Authenticating... Please open your browser to:
https://id.fedoraproject.org/openidc/Authorization?...
Paste here the code that you got after logging in:      # Hit Ctrl+C
Traceback (most recent call last):
  File "/usr/bin/fedora-easy-karma", line 811, in <module>
    fek = FedoraEasyKarma()
  File "/usr/bin/fedora-easy-karma", line 470, in __init__
    self.bc.ensure_auth()
  File "/usr/lib/python3.10/site-packages/bodhi/client/bindings.py", line 236, in ensure_auth
    self.oidc.ensure_auth()
  File "/usr/lib/python3.10/site-packages/bodhi/client/oidcclient.py", line 185, in ensure_auth
    self.login()
  File "/usr/lib/python3.10/site-packages/bodhi/client/oidcclient.py", line 135, in login
    value = click.prompt(
  File "/usr/lib/python3.10/site-packages/click/termui.py", line 166, in prompt
    value = prompt_func(prompt)
  File "/usr/lib/python3.10/site-packages/click/termui.py", line 149, in prompt_func
    raise Abort() from None
click.exceptions.Abort
```

The `oidcclient.py` should probably handle `click.exceptions.Abort` exception and either raise some custom bodhi-client exception or at least a generic `RuntimeError` with some description. I don't want to import `click` just to handle the error. The original `KeyboardInterrupt` seems consumed, so I can't catch that one either.

bodhi-client-6.0.1-1.fc36.noarch


Discussion:

Resolving patch:
diff --git a/bodhi-client/bodhi/client/oidcclient.py b/bodhi-client/bodhi/client/oidcclient.py
--- a/bodhi-client/bodhi/client/oidcclient.py
+++ b/bodhi-client/bodhi/client/oidcclient.py
@@ -169,8 +169,10 @@ def login_with_browser(self, uri):
                         ),
                         hide_input=True,
                     )
-                except KeyboardInterrupt:
-                    raise click.ClickException("Cancelled.")
+                except click.exceptions.Abort:
+                    # Raise a generic exception for friendliness to outside scripts
+                    # that don't want to import click
+                    raise SystemExit("Cancelled.")
                 try:
                     self.auth_callback(f"?{value}")
                 except OAuthError as e:


Test patch:
diff --git a/bodhi-client/tests/test_oidcclient.py b/bodhi-client/tests/test_oidcclient.py
--- a/bodhi-client/tests/test_oidcclient.py
+++ b/bodhi-client/tests/test_oidcclient.py
@@ -3,6 +3,7 @@
 
 from authlib.integrations.base_client.errors import OAuthError
 from click import ClickException
+from click.exceptions import Abort
 import pytest
 import requests
 
@@ -250,7 +251,7 @@ def test_oidcclient_login_no_oob_failure(mocker, client):
 def test_oidcclient_login_interrupted(mocker, client):
     oauth2client = mocker.Mock()
     client.client = oauth2client
-    mocker.patch("bodhi.client.oidcclient.click.prompt", side_effect=KeyboardInterrupt)
+    mocker.patch("bodhi.client.oidcclient.click.prompt", side_effect=Abort)
     # Enable OOB
     client.metadata = {
         "token_endpoint": "http://id.example.com/token",
@@ -258,7 +259,7 @@ def test_oidcclient_login_interrupted(mocker, client):
         "response_modes_supported": ["oob"]
     }
     oauth2client.create_authorization_url.return_value = ("auth-url", "state")
-    with pytest.raises(ClickException) as exc:
+    with pytest.raises(SystemExit) as exc:
         client.login()
     oauth2client.fetch_token.assert_not_called()
     assert str(exc.value) == "Cancelled."