84
86
properties and calls a hook function when any of them are
87
def __init__(self, proxy_object=None, *args, **kwargs):
89
def __init__(self, proxy_object=None, properties=None, **kwargs):
88
90
self.proxy = proxy_object # Mandos Client proxy object
90
self.properties = dict()
91
self.properties = dict() if properties is None else properties
91
92
self.property_changed_match = (
92
93
self.proxy.connect_to_signal("PropertyChanged",
93
self.property_changed,
94
self._property_changed,
97
self.properties.update(
98
self.proxy.GetAll(client_interface,
99
dbus_interface = dbus.PROPERTIES_IFACE))
101
#XXX This breaks good super behaviour
102
# 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)
105
110
def property_changed(self, property=None, value=None):
106
111
"""This is called whenever we get a PropertyChanged signal
109
114
# Update properties dict with new value
110
115
self.properties[property] = value
112
def delete(self, *args, **kwargs):
113
118
self.property_changed_match.remove()
114
super(MandosClientPropertyCache, self).__init__(
118
121
class MandosClientWidget(urwid.FlowWidget, MandosClientPropertyCache):
122
125
def __init__(self, server_proxy_object=None, update_hook=None,
123
delete_hook=None, logger=None, *args, **kwargs):
126
delete_hook=None, logger=None, **kwargs):
124
127
# Called on update
125
128
self.update_hook = update_hook
126
129
# Called on delete
131
134
self.logger = logger
133
136
self._update_timer_callback_tag = None
134
self._update_timer_callback_lock = 0
136
138
# The widget shown normally
137
139
self._text_widget = urwid.Text("")
138
140
# The widget shown when we have focus
139
141
self._focus_text_widget = urwid.Text("")
140
super(MandosClientWidget, self).__init__(
141
update_hook=update_hook, delete_hook=delete_hook,
142
super(MandosClientWidget, self).__init__(**kwargs)
144
144
self.opened = False
146
last_checked_ok = isoformat_to_datetime(self.properties
149
if self.properties ["LastCheckerStatus"] != 0:
150
self.using_timer(True)
152
if self.need_approval:
153
self.using_timer(True)
155
146
self.match_objects = (
156
147
self.proxy.connect_to_signal("CheckerCompleted",
157
148
self.checker_completed,
176
167
#self.logger('Created client {0}'
177
168
# .format(self.properties["Name"]))
179
def property_changed(self, property=None, value=None):
180
super(self, MandosClientWidget).property_changed(property,
182
if property == "ApprovalPending":
183
using_timer(bool(value))
184
if property == "LastCheckerStatus":
185
using_timer(value != 0)
186
#self.logger('Checker for client {0} (command "{1}") was '
187
# ' successful'.format(self.properties["Name"],
190
170
def using_timer(self, flag):
191
171
"""Call this method with True or False when timer should be
192
172
activated or deactivated.
194
old = self._update_timer_callback_lock
196
self._update_timer_callback_lock += 1
198
self._update_timer_callback_lock -= 1
199
if old == 0 and self._update_timer_callback_lock:
174
if flag and self._update_timer_callback_tag is None:
200
175
# Will update the shown timer value every second
201
176
self._update_timer_callback_tag = (gobject.timeout_add
203
178
self.update_timer))
204
elif old and self._update_timer_callback_lock == 0:
179
elif not (flag or self._update_timer_callback_tag is None):
205
180
gobject.source_remove(self._update_timer_callback_tag)
206
181
self._update_timer_callback_tag = None
249
224
message = 'Client {0} will get its secret in {1} seconds'
250
225
self.logger(message.format(self.properties["Name"],
252
self.using_timer(True)
254
228
def rejected(self, reason):
255
229
self.logger('Client {0} was rejected; reason: {1}'
281
255
"bold-underline-blink":
282
256
"bold-underline-blink-standout",
285
259
# Rebuild focus and non-focus widgets using current properties
287
261
# Base part of a client. Name!
288
262
base = '{name}: '.format(name=self.properties["Name"])
289
263
if not self.properties["Enabled"]:
290
264
message = "DISABLED"
265
self.using_timer(False)
291
266
elif self.properties["ApprovalPending"]:
292
267
timeout = datetime.timedelta(milliseconds
293
268
= self.properties
295
270
last_approval_request = isoformat_to_datetime(
296
271
self.properties["LastApprovalRequest"])
297
272
if last_approval_request is not None:
298
timer = timeout - (datetime.datetime.utcnow()
299
- last_approval_request)
273
timer = max(timeout - (datetime.datetime.utcnow()
274
- last_approval_request),
275
datetime.timedelta())
301
277
timer = datetime.timedelta()
302
278
if self.properties["ApprovedByDefault"]:
305
281
message = "Denial in {0}. (a)pprove?"
306
282
message = message.format(unicode(timer).rsplit(".", 1)[0])
283
self.using_timer(True)
307
284
elif self.properties["LastCheckerStatus"] != 0:
308
285
# When checker has failed, show timer until client expires
309
286
expires = self.properties["Expires"]
313
290
expires = (datetime.datetime.strptime
314
291
(expires, '%Y-%m-%dT%H:%M:%S.%f'))
315
timer = expires - datetime.datetime.utcnow()
292
timer = max(expires - datetime.datetime.utcnow(),
293
datetime.timedelta())
316
294
message = ('A checker has failed! Time until client'
317
295
' gets disabled: {0}'
318
296
.format(unicode(timer).rsplit(".", 1)[0]))
297
self.using_timer(True)
320
299
message = "enabled"
300
self.using_timer(False)
321
301
self._text = "{0}{1}".format(base, message)
323
303
if not urwid.supports_unicode():
324
304
self._text = self._text.encode("ascii", "replace")
325
305
textlist = [("normal", self._text)]
343
323
return True # Keep calling this
345
def delete(self, *args, **kwargs):
325
def delete(self, **kwargs):
346
326
if self._update_timer_callback_tag is not None:
347
327
gobject.source_remove(self._update_timer_callback_tag)
348
328
self._update_timer_callback_tag = None
351
331
self.match_objects = ()
352
332
if self.delete_hook is not None:
353
333
self.delete_hook(self)
354
return super(MandosClientWidget, self).delete(*args, **kwargs)
334
return super(MandosClientWidget, self).delete(**kwargs)
356
336
def render(self, maxcolrow, focus=False):
357
337
"""Render differently if we have focus.
402
def property_changed(self, property=None, value=None,
382
def property_changed(self, property=None, **kwargs):
404
383
"""Call self.update() if old value is not new value.
405
384
This overrides the method from MandosClientPropertyCache"""
406
385
property_name = unicode(property)
407
386
old_value = self.properties.get(property_name)
408
387
super(MandosClientWidget, self).property_changed(
409
property=property, value=value, *args, **kwargs)
388
property=property, **kwargs)
410
389
if self.properties.get(property_name) != old_value:
416
395
"down" key presses, thus not allowing any containing widgets to
417
396
use them as an excuse to shift focus away from this widget.
419
def keypress(self, maxcolrow, key):
420
ret = super(ConstrainedListBox, self).keypress(maxcolrow, key)
398
def keypress(self, *args, **kwargs):
399
ret = super(ConstrainedListBox, self).keypress(*args, **kwargs)
421
400
if ret in ("up", "down"):