[gnome-keysign: 1/4] receive: show error when certifying fails




commit 68745b555a9ee41cd50cef6c96df86307ad861ca
Author: Tobias Mueller <muelli cryptobitch de>
Date:   Sat Feb 13 20:13:06 2021 +0100

    receive: show error when certifying fails
    
    I can trigger this easily when aborting the passphrase dialog.
    Unfortunately, all we get to know from gpg is "keysig 83886179".

 keysign/gpgmeh.py     |   5 ++-
 keysign/keyconfirm.py |  23 +++++++++-
 keysign/receive.py    |  95 +++++++++++++++++++++-------------------
 keysign/receive.ui    | 118 ++++++++++++++++++++++++++++++++++++++++++--------
 4 files changed, 177 insertions(+), 64 deletions(-)
---
diff --git a/keysign/gpgmeh.py b/keysign/gpgmeh.py
index 7cc6f42..61279aa 100755
--- a/keysign/gpgmeh.py
+++ b/keysign/gpgmeh.py
@@ -42,6 +42,9 @@ log = logging.getLogger(__name__)
 ## INTERNAL API
 ##
 
+class GPGRuntimeError(RuntimeError):
+    pass
+
 class GenEdit:
     _ignored_status = (gpg.constants.STATUS_EOF,
                        gpg.constants.STATUS_GOT_IT,
@@ -161,7 +164,7 @@ def sign_key(uid=0, sign_cmd=u"sign", expire=False, check=3,
             if error_cb:
                 error_cb(prompt)
             else:
-                raise RuntimeError("Error signing key: %s" % prompt)
+                raise GPGRuntimeError("Error signing key: %s" % prompt)
             status, prompt = yield None
         else:
             raise AssertionError("Unexpected state %r %r" % (status, prompt))
diff --git a/keysign/keyconfirm.py b/keysign/keyconfirm.py
index e0b9bcf..e346e58 100755
--- a/keysign/keyconfirm.py
+++ b/keysign/keyconfirm.py
@@ -134,9 +134,30 @@ class PreSignWidget(Gtk.VBox):
         # API. The infobar should probably be part of the caller's responsibility,
         # i.e. not part of this widget.
         self.infobar_success = builder.get_object('infobar_certifications_produced')
+        self.infobar_errors = builder.get_object('infobar_certifications_errors')
         self.infobar_save_as_button = builder.get_object('btn_local_import_save_as')
         self.infobar_import_button = builder.get_object('btn_local_import')
-
+        self.infobar_show_error_button = builder.get_object('btn_show_error_details')
+
+        ib_error_show = self.infobar_errors.show
+        def show(exception):
+            self.infobar_errors.exception = exception
+            ib_error_show()
+            def show_error(btn):
+                dialog = Gtk.MessageDialog(
+                    transient_for=self.get_toplevel(),
+                    flags=0,
+                    message_type=Gtk.MessageType.ERROR,
+                    buttons=Gtk.ButtonsType.CLOSE,
+                    text="Error certifying key"
+                )
+                dialog.format_secondary_text(
+                    str(exception) + "\n"
+                    "We don't know any more, sorry :(")
+                dialog.run()
+                dialog.destroy()
+            self.infobar_show_error_button.connect("clicked", show_error)
+        self.infobar_errors.show = show
 
     def on_confirm_button_clicked(self, buttonObject, *args):
         self.emit('sign-key-confirmed', self.key, *args)
diff --git a/keysign/receive.py b/keysign/receive.py
index 435d099..ec2e7f0 100755
--- a/keysign/receive.py
+++ b/keysign/receive.py
@@ -51,7 +51,7 @@ if  __name__ == "__main__" and __package__ is None:
 from .avahidiscovery import AvahiKeysignDiscoveryWithMac
 from .discover import Discover
 from .errors import NoBluezDbus, UnpoweredAdapter, NoAdapter
-from .gpgmeh import openpgpkey_from_data, local_sign_keydata
+from .gpgmeh import openpgpkey_from_data, local_sign_keydata, GPGRuntimeError
 from .i18n import _
 from .keyfprscan import KeyFprScanWidget
 from .keyconfirm import PreSignWidget
@@ -201,49 +201,56 @@ class ReceiveApp:
         self.log.debug ("Sign key confirmed! %r", key)
         # We need to prevent tmpfiles from going out of
         # scope too early so that they don't get deleted
-        tmpfiles_plaintext = list(sign_keydata_and_send(keydata))
-        self.log.debug("sign keydata result: %r", tmpfiles_plaintext)
-        # This is unzipping the list of tuples, e.g. [(1,2), (3,4)] becomes [(1,3), (2,4)]
-        self.tmpfiles, plaintexts = zip(*tmpfiles_plaintext)
-
-        keyPreSignWidget.infobar_success.show()
-
-        def import_clicked(button):
-            self.log.info("Import clicked")
-            local_sign_keydata(keydata)
-        keyPreSignWidget.infobar_import_button.connect("clicked", import_clicked)
-
-        def save_as_clicked(button):
-            self.log.info("Save as clicked")
-            dialog = Gtk.FileChooserDialog(_("Select file for saving"),
-                self.get_toplevel(),
-                Gtk.FileChooserAction.SAVE,
-                (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                 Gtk.STOCK_SAVE, Gtk.ResponseType.OK)
-            )
-            response = dialog.run()
-            if response == Gtk.ResponseType.OK:
-                filename = dialog.get_filename()
-                self.log.info("Saving file to: %r", filename)
-                with open(filename, 'wb') as f:
-                    for p in plaintexts:
-                        f.write(p)
-                    for sigfile in self.tmpfiles:
-                        pass
-                        # Hrm. Those are the encrypted files, I think.
-                        # We probably want to offer the plaintext versions, though
-                        #f.write(open(sigfile, 'r').read())
-            else:
-                self.log.info("Not saving file: %r", response)
-            dialog.destroy()
-
-        keyPreSignWidget.infobar_save_as_button.connect("clicked", save_as_clicked)
-
-        # After the user has signed, we switch back to the scanner,
-        # because currently, there is not much to do on the
-        # key confirmation page.
-        log.debug ("Signed the key: %r", self.tmpfiles)
-        # self.stack.set_visible_child_name("scanner")
+        try:
+            tmpfiles_plaintext = list(sign_keydata_and_send(keydata))
+        except GPGRuntimeError as e:
+            self.log.exception("Something went wrong with signing the key")
+            keyPreSignWidget.infobar_success.hide()
+            keyPreSignWidget.infobar_errors.show(e)
+        else:
+            self.log.debug("sign keydata result: %r", tmpfiles_plaintext)
+            # This is unzipping the list of tuples, e.g. [(1,2), (3,4)] becomes [(1,3), (2,4)]
+            self.tmpfiles, plaintexts = zip(*tmpfiles_plaintext)
+
+            keyPreSignWidget.infobar_errors.hide()
+            keyPreSignWidget.infobar_success.show()
+
+            def import_clicked(button):
+                self.log.info("Import clicked")
+                local_sign_keydata(keydata)
+            keyPreSignWidget.infobar_import_button.connect("clicked", import_clicked)
+
+            def save_as_clicked(button):
+                self.log.info("Save as clicked")
+                dialog = Gtk.FileChooserDialog(_("Select file for saving"),
+                    self.get_toplevel(),
+                    Gtk.FileChooserAction.SAVE,
+                    (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+                     Gtk.STOCK_SAVE, Gtk.ResponseType.OK)
+                )
+                response = dialog.run()
+                if response == Gtk.ResponseType.OK:
+                    filename = dialog.get_filename()
+                    self.log.info("Saving file to: %r", filename)
+                    with open(filename, 'wb') as f:
+                        for p in plaintexts:
+                            f.write(p)
+                        for sigfile in self.tmpfiles:
+                            pass
+                            # Hrm. Those are the encrypted files, I think.
+                            # We probably want to offer the plaintext versions, though
+                            #f.write(open(sigfile, 'r').read())
+                else:
+                    self.log.info("Not saving file: %r", response)
+                dialog.destroy()
+
+            keyPreSignWidget.infobar_save_as_button.connect("clicked", save_as_clicked)
+
+            # After the user has signed, we switch back to the scanner,
+            # because currently, there is not much to do on the
+            # key confirmation page.
+            log.debug ("Signed the key: %r", self.tmpfiles)
+            # self.stack.set_visible_child_name("scanner")
 
     def on_list_changed(self, discovery, number, userdata):
         """We show an infobar if we can only receive with Avahi and
diff --git a/keysign/receive.ui b/keysign/receive.ui
index 0213655..4e79437 100644
--- a/keysign/receive.ui
+++ b/keysign/receive.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.1 -->
+<!-- Generated with glade 3.22.2 -->
 <interface>
   <requires lib="gtk+" version="3.16"/>
   <object class="GtkImage" id="confirm-button-image">
@@ -328,6 +328,88 @@ For more information visit &lt;a href="https://wiki.gnome.org/Apps/Keysign/Doc/N
         <property name="margin_bottom">10</property>
         <property name="orientation">vertical</property>
         <property name="spacing">6</property>
+        <child>
+          <object class="GtkInfoBar" id="infobar_certifications_errors">
+            <property name="can_focus">False</property>
+            <property name="message_type">error</property>
+            <child internal-child="action_area">
+              <object class="GtkButtonBox">
+                <property name="can_focus">False</property>
+                <property name="spacing">6</property>
+                <property name="layout_style">end</property>
+                <child>
+                  <object class="GtkButton" id="btn_show_error_details">
+                    <property name="label">gtk-help</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">Show details about the error</property>
+                    <property name="use_stock">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child internal-child="content_area">
+              <object class="GtkBox">
+                <property name="can_focus">False</property>
+                <property name="spacing">16</property>
+                <child>
+                  <object class="GtkLabel" id="infobar_discover2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="label" translatable="yes">Error producing certifications ☹
+Something went wrong. Sometime, the passphrase was not correctly entered.
+You may try again by clicking the "confirm" button.</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
         <child>
           <object class="GtkInfoBar" id="infobar_certifications_produced">
             <property name="can_focus">False</property>
@@ -431,7 +513,7 @@ For more information visit &lt;a href="https://wiki.gnome.org/Apps/Keysign/Doc/P
           <packing>
             <property name="expand">False</property>
             <property name="fill">True</property>
-            <property name="position">0</property>
+            <property name="position">1</property>
           </packing>
         </child>
         <child>
@@ -439,21 +521,6 @@ For more information visit &lt;a href="https://wiki.gnome.org/Apps/Keysign/Doc/P
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="orientation">vertical</property>
-            <child>
-              <object class="GtkLabel" id="label70">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">To sign the key, confirm that you want to sign the 
following key.
-This will generate an email that must be sent in order to complete the signing process.</property>
-                <property name="wrap">True</property>
-                <property name="xalign">0</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
             <child>
               <object class="GtkBox">
                 <property name="visible">True</property>
@@ -577,11 +644,26 @@ Alpha Bar &lt;example example com&gt;</property>
                 <property name="position">1</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkLabel" id="label70">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">To sign the key, confirm that you want to sign the 
following key.
+This will generate an email that must be sent in order to complete the signing process.</property>
+                <property name="wrap">True</property>
+                <property name="xalign">0</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
           </object>
           <packing>
             <property name="expand">True</property>
             <property name="fill">True</property>
-            <property name="position">1</property>
+            <property name="position">2</property>
           </packing>
         </child>
         <child>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]