=== modified file 'DBUS-API' --- DBUS-API 2012-01-15 20:27:28 +0000 +++ DBUS-API 2014-08-10 14:13:02 +0000 @@ -150,9 +150,6 @@ milliseconds, depending on ApprovedByDefault. Approve() can now usefully be called on this client object. -*** PropertyChanged(s: Property, v: Value) - The Property on this client has changed to Value. - *** Rejected(s: Reason) This client was not given its secret for a specified Reason. === modified file 'TODO' --- TODO 2014-08-09 23:37:07 +0000 +++ TODO 2014-08-10 14:13:02 +0000 @@ -68,9 +68,6 @@ ** TODO Use python-tlslite? ** TODO D-Bus AddClient() method on server object ** TODO Use org.freedesktop.DBus.Method.NoReply annotation on async methods. :2: -** TODO Emit [[http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties][org.freedesktop.DBus.Properties.PropertiesChanged]] signal :2: - TODO Deprecate se.recompile.Mandos.Client.PropertyChanged - annotate! - TODO Can use "invalidates" annotation to also emit on changed secret. ** TODO Support [[http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager][org.freedesktop.DBus.ObjectManager]] interface on server object :2: Deprecate methods GetAllClients(), GetAllClientsWithProperties() and signals ClientAdded and ClientRemoved. @@ -78,7 +75,7 @@ ** TODO CheckerCompleted method, deprecate CheckedOK ** TODO Secret Service API? http://standards.freedesktop.org/secret-service/ -** TODO Remove D-Bus interfaces with old domain name :2: +** TODO Remove D-Bus interfaces with old domain name :2: ** TODO Remove old string_to_delta format :2: ** TODO http://0pointer.de/blog/projects/stateless.html *** tmpfiles snippet to create /var/lib/mandos with right user+perms === modified file 'mandos' --- mandos 2014-08-09 13:18:46 +0000 +++ mandos 2014-08-10 14:13:02 +0000 @@ -813,11 +813,11 @@ """Decorator to annotate D-Bus methods, signals or properties Usage: + @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true", + "org.freedesktop.DBus.Property." + "EmitsChangedSignal": "false"}) @dbus_service_property("org.example.Interface", signature="b", access="r") - @dbus_annotations({{"org.freedesktop.DBus.Deprecated": "true", - "org.freedesktop.DBus.Property." - "EmitsChangedSignal": "false"}) def Property_dbus_property(self): return dbus.Boolean(False) """ @@ -946,6 +946,14 @@ value.variant_level+1) return dbus.Dictionary(properties, signature="sv") + @dbus.service.signal(dbus.PROPERTIES_IFACE, signature="sa{sv}as") + def PropertiesChanged(self, interface_name, changed_properties, + invalidated_properties): + """Standard D-Bus PropertiesChanged() signal, see D-Bus + standard. + """ + pass + @dbus.service.method(dbus.INTROSPECTABLE_IFACE, out_signature="s", path_keyword='object_path', @@ -1218,6 +1226,8 @@ runtime_expansions = (Client.runtime_expansions + ("dbus_object_path",)) + _interface = "se.recompile.Mandos.Client" + # dbus.service.Object doesn't use super(), so we can't either. def __init__(self, bus = None, *args, **kwargs): @@ -1235,7 +1245,8 @@ def notifychangeproperty(transform_func, dbus_name, type_func=lambda x: x, - variant_level=1): + variant_level=1, invalidate_only=False, + _interface=_interface): """ Modify a variable so that it's a property which announces its changes to DBus. @@ -1252,11 +1263,21 @@ if (not hasattr(self, attrname) or type_func(getattr(self, attrname, None)) != type_func(value)): - dbus_value = transform_func(type_func(value), - variant_level - =variant_level) - self.PropertyChanged(dbus.String(dbus_name), - dbus_value) + if invalidate_only: + self.PropertiesChanged(_interface, + dbus.Dictionary(), + dbus.Array + ((dbus_name,))) + else: + dbus_value = transform_func(type_func(value), + variant_level + =variant_level) + self.PropertyChanged(dbus.String(dbus_name), + dbus_value) + self.PropertiesChanged(_interface, + dbus.Dictionary({ + dbus.String(dbus_name): + dbus_value }), dbus.Array()) setattr(self, attrname, value) return property(lambda self: getattr(self, attrname), setter) @@ -1300,6 +1321,8 @@ lambda td: td.total_seconds() * 1000) checker_command = notifychangeproperty(dbus.String, "Checker") + secret = notifychangeproperty(dbus.ByteArray, "Secret", + invalidate_only=True) del notifychangeproperty @@ -1352,15 +1375,9 @@ self.send_changedstate() ## D-Bus methods, signals & properties - _interface = "se.recompile.Mandos.Client" ## Interfaces - @dbus_interface_annotations(_interface) - def _foo(self): - return { "org.freedesktop.DBus.Property.EmitsChangedSignal": - "false"} - ## Signals # CheckerCompleted - signal @@ -1376,6 +1393,7 @@ pass # PropertyChanged - signal + @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"}) @dbus.service.signal(_interface, signature="sv") def PropertyChanged(self, property, value): "D-Bus signal" @@ -2709,8 +2727,8 @@ def GetAllClientsWithProperties(self): "D-Bus method" return dbus.Dictionary( - ((c.dbus_object_path, c.GetAll("")) - for c in tcp_server.clients.itervalues()), + { c.dbus_object_path: c.GetAll("") + for c in tcp_server.clients.itervalues() }, signature="oa{sv}") @dbus.service.method(_interface, in_signature="o") === modified file 'mandos-monitor' --- mandos-monitor 2014-08-06 20:56:55 +0000 +++ mandos-monitor 2014-08-10 14:13:02 +0000 @@ -87,9 +87,9 @@ self.proxy = proxy_object # Mandos Client proxy object self.properties = dict() if properties is None else properties self.property_changed_match = ( - self.proxy.connect_to_signal("PropertyChanged", - self._property_changed, - client_interface, + self.proxy.connect_to_signal("PropertiesChanged", + self.properties_changed, + dbus.PROPERTIES_IFACE, byte_arrays=True)) if properties is None: @@ -100,16 +100,12 @@ super(MandosClientPropertyCache, self).__init__(**kwargs) - def _property_changed(self, property, value): - """Helper which takes positional arguments""" - return self.property_changed(property=property, value=value) - - def property_changed(self, property=None, value=None): - """This is called whenever we get a PropertyChanged signal - It updates the changed property in the "properties" dict. + def properties_changed(self, interface, properties, invalidated): + """This is called whenever we get a PropertiesChanged signal + It updates the changed properties in the "properties" dict. """ # Update properties dict with new value - self.properties[property] = value + self.properties.update(properties) def delete(self): self.property_changed_match.remove() @@ -377,14 +373,15 @@ else: return key - def property_changed(self, property=None, **kwargs): - """Call self.update() if old value is not new value. + def properties_changed(self, interface, properties, invalidated): + """Call self.update() if any properties changed. This overrides the method from MandosClientPropertyCache""" - property_name = str(property) - old_value = self.properties.get(property_name) - super(MandosClientWidget, self).property_changed( - property=property, **kwargs) - if self.properties.get(property_name) != old_value: + old_values = { key: self.properties.get(key) + for key in properties.keys() } + super(MandosClientWidget, self).properties_changed( + interface, properties, invalidated) + if any(old_values[key] != self.properties.get(key) + for key in old_values): self.update()