83
86
properties and calls a hook function when any of them are
86
def __init__(self, proxy_object=None, *args, **kwargs):
89
def __init__(self, proxy_object=None, properties=None, **kwargs):
87
90
self.proxy = proxy_object # Mandos Client proxy object
89
self.properties = dict()
91
self.properties = dict() if properties is None else properties
90
92
self.property_changed_match = (
91
93
self.proxy.connect_to_signal("PropertyChanged",
92
self.property_changed,
94
self._property_changed,
96
self.properties.update(
97
self.proxy.GetAll(client_interface,
98
dbus_interface = dbus.PROPERTIES_IFACE))
100
#XXX This breaks good super behaviour
101
# super(MandosClientPropertyCache, self).__init__(
98
if properties is None:
99
self.properties.update(
100
self.proxy.GetAll(client_interface,
102
= dbus.PROPERTIES_IFACE))
104
super(MandosClientPropertyCache, self).__init__(**kwargs)
106
def _property_changed(self, property, value):
107
"""Helper which takes positional arguments"""
108
return self.property_changed(property=property, value=value)
104
110
def property_changed(self, property=None, value=None):
105
111
"""This is called whenever we get a PropertyChanged signal
132
136
self._update_timer_callback_tag = None
133
137
self._update_timer_callback_lock = 0
134
self.last_checker_failed = False
136
139
# The widget shown normally
137
140
self._text_widget = urwid.Text("")
138
141
# The widget shown when we have focus
139
142
self._focus_text_widget = urwid.Text("")
140
super(MandosClientWidget, self).__init__(
141
update_hook=update_hook, delete_hook=delete_hook,
143
super(MandosClientWidget, self).__init__(**kwargs)
144
145
self.opened = False
146
147
last_checked_ok = isoformat_to_datetime(self.properties
147
148
["LastCheckedOK"])
148
if last_checked_ok is None:
149
self.last_checker_failed = True
151
self.last_checker_failed = ((datetime.datetime.utcnow()
158
if self.last_checker_failed:
150
if self.properties ["LastCheckerStatus"] != 0:
159
151
self.using_timer(True)
161
153
if self.need_approval:
183
175
client_interface,
184
176
byte_arrays=True))
185
#self.logger('Created client %s' % (self.properties["Name"]))
177
#self.logger('Created client {0}'
178
# .format(self.properties["Name"]))
187
180
def property_changed(self, property=None, value=None):
188
181
super(self, MandosClientWidget).property_changed(property,
190
183
if property == "ApprovalPending":
191
184
using_timer(bool(value))
185
if property == "LastCheckerStatus":
186
using_timer(value != 0)
187
#self.logger('Checker for client {0} (command "{1}") was '
188
# ' successful'.format(self.properties["Name"],
193
191
def using_timer(self, flag):
194
192
"""Call this method with True or False when timer should be
195
193
activated or deactivated.
211
209
def checker_completed(self, exitstatus, condition, command):
212
210
if exitstatus == 0:
213
if self.last_checker_failed:
214
self.last_checker_failed = False
215
self.using_timer(False)
216
#self.logger('Checker for client %s (command "%s")'
218
# % (self.properties["Name"], command))
222
if not self.last_checker_failed:
223
self.last_checker_failed = True
224
self.using_timer(True)
225
214
if os.WIFEXITED(condition):
226
self.logger('Checker for client %s (command "%s")'
227
' failed with exit code %s'
228
% (self.properties["Name"], command,
229
os.WEXITSTATUS(condition)))
215
self.logger('Checker for client {0} (command "{1}")'
216
' failed with exit code {2}'
217
.format(self.properties["Name"], command,
218
os.WEXITSTATUS(condition)))
230
219
elif os.WIFSIGNALED(condition):
231
self.logger('Checker for client %s (command "%s")'
232
' was killed by signal %s'
233
% (self.properties["Name"], command,
234
os.WTERMSIG(condition)))
220
self.logger('Checker for client {0} (command "{1}") was'
221
' killed by signal {2}'
222
.format(self.properties["Name"], command,
223
os.WTERMSIG(condition)))
235
224
elif os.WCOREDUMP(condition):
236
self.logger('Checker for client %s (command "%s")'
225
self.logger('Checker for client {0} (command "{1}")'
238
% (self.properties["Name"], command))
227
.format(self.properties["Name"], command))
240
self.logger('Checker for client %s completed'
229
self.logger('Checker for client {0} completed'
231
.format(self.properties["Name"]))
244
234
def checker_started(self, command):
245
235
"""Server signals that a checker started. This could be useful
246
236
to log in the future. """
247
#self.logger('Client %s started checker "%s"'
248
# % (self.properties["Name"], unicode(command)))
237
#self.logger('Client {0} started checker "{1}"'
238
# .format(self.properties["Name"],
251
242
def got_secret(self):
252
self.last_checker_failed = False
253
self.logger('Client %s received its secret'
254
% self.properties["Name"])
243
self.logger('Client {0} received its secret'
244
.format(self.properties["Name"]))
256
246
def need_approval(self, timeout, default):
258
message = 'Client %s needs approval within %s seconds'
248
message = 'Client {0} needs approval within {1} seconds'
260
message = 'Client %s will get its secret in %s seconds'
262
% (self.properties["Name"], timeout/1000))
250
message = 'Client {0} will get its secret in {1} seconds'
251
self.logger(message.format(self.properties["Name"],
263
253
self.using_timer(True)
265
255
def rejected(self, reason):
266
self.logger('Client %s was rejected; reason: %s'
267
% (self.properties["Name"], reason))
256
self.logger('Client {0} was rejected; reason: {1}'
257
.format(self.properties["Name"], reason))
269
259
def selectable(self):
270
260
"""Make this a "selectable" widget.
313
302
timer = datetime.timedelta()
314
303
if self.properties["ApprovedByDefault"]:
315
message = "Approval in %s. (d)eny?"
304
message = "Approval in {0}. (d)eny?"
317
message = "Denial in %s. (a)pprove?"
318
message = message % unicode(timer).rsplit(".", 1)[0]
319
elif self.last_checker_failed:
320
# When checker has failed, print a timer until client expires
306
message = "Denial in {0}. (a)pprove?"
307
message = message.format(unicode(timer).rsplit(".", 1)[0])
308
elif self.properties["LastCheckerStatus"] != 0:
309
# When checker has failed, show timer until client expires
321
310
expires = self.properties["Expires"]
322
311
if expires == "":
323
312
timer = datetime.timedelta(0)
325
expires = datetime.datetime.strptime(expires,
326
'%Y-%m-%dT%H:%M:%S.%f')
314
expires = (datetime.datetime.strptime
315
(expires, '%Y-%m-%dT%H:%M:%S.%f'))
327
316
timer = expires - datetime.datetime.utcnow()
328
317
message = ('A checker has failed! Time until client'
330
% unicode(timer).rsplit(".", 1)[0])
318
' gets disabled: {0}'
319
.format(unicode(timer).rsplit(".", 1)[0]))
332
321
message = "enabled"
333
self._text = "%s%s" % (base, message)
322
self._text = "{0}{1}".format(base, message)
335
324
if not urwid.supports_unicode():
336
325
self._text = self._text.encode("ascii", "replace")
414
def property_changed(self, property=None, value=None,
403
def property_changed(self, property=None, **kwargs):
416
404
"""Call self.update() if old value is not new value.
417
405
This overrides the method from MandosClientPropertyCache"""
418
406
property_name = unicode(property)
419
407
old_value = self.properties.get(property_name)
420
408
super(MandosClientWidget, self).property_changed(
421
property=property, value=value, *args, **kwargs)
409
property=property, **kwargs)
422
410
if self.properties.get(property_name) != old_value:
428
416
"down" key presses, thus not allowing any containing widgets to
429
417
use them as an excuse to shift focus away from this widget.
431
def keypress(self, maxcolrow, key):
432
ret = super(ConstrainedListBox, self).keypress(maxcolrow, key)
419
def keypress(self, *args, **kwargs):
420
ret = super(ConstrainedListBox, self).keypress(*args, **kwargs)
433
421
if ret in ("up", "down"):
501
489
self.main_loop = gobject.MainLoop()
503
491
def client_not_found(self, fingerprint, address):
504
self.log_message(("Client with address %s and fingerprint %s"
505
" could not be found" % (address,
492
self.log_message("Client with address {0} and fingerprint"
493
" {1} could not be found"
494
.format(address, fingerprint))
508
496
def rebuild(self):
509
497
"""This rebuilds the User Interface.