chiark / gitweb /
New option to list a user's (or all) extant tokens.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 21 Mar 2006 14:09:01 +0000 (14:09 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Tue, 21 Mar 2006 14:17:55 +0000 (14:17 +0000)
.userv/rc
bin/cryptomail

index 9549421..84843a3 100644 (file)
--- a/.userv/rc
+++ b/.userv/rc
@@ -15,6 +15,11 @@ if glob service revoke
        execute bin/uwrap revoke
 fi
 
+if glob service list
+       no-suppress-args
+       execute bin/uwrap list
+fi
+
 if glob service help
        no-suppress-args
        execute bin/uwrap help
index 3a24d04..9559acc 100755 (executable)
@@ -392,6 +392,9 @@ def timecmp(x, y):
   else:
     return cmp(x, y)
 
+def token(c, id):
+  return M.base32_encode(c.encrypt(id)).strip('=').lower()
+
 def cmd_generate(argv):
   try:
     opts, argv = getopt(argv, 't:c:f:i:',
@@ -432,10 +435,8 @@ def cmd_generate(argv):
   a['addr'] = [addr]
   if user is not None:
     a['user'] = [user]
-  c = Crypto(k).encrypt(a.id)
   db.setexpire(a.id, expwhen)
-  print format.replace('%', M.base32_encode(Crypto(k).encrypt(a.id)).
-                       strip('=').lower())
+  print format.replace('%', token(Crypto(k), a.id))
   db.commit()
   kr.save()
 commands['generate'] = \
@@ -516,6 +517,21 @@ Check address token LOCAL.  On failure, report reason to stderr and exit
 111.  On success, write forwarding address to stdout and exit 0.  Expects
 the message on standard input, as a seekable file.""")
 
+ignore = {'user': 1, 'addr': 1}
+def show(db, a):
+  keys = a.keys()
+  keys.sort()
+  for k in keys:
+    if k in ignore:
+      continue
+    for v in a[k]:
+      print '\t%s: %s' % (k, v)
+  expwhen = db.expiry(a.id)
+  if expwhen:
+    print '\texpires: %s' % expwhen
+  else:
+    print '\tno-expiry'
+
 def cmd_info(argv):
   try:
     opts, argv = getopt(argv, '', [])
@@ -532,16 +548,8 @@ def cmd_info(argv):
       raise Reject, 'not your token'
     if 'addr' not in a:
       die('unknown token (expired?)')
-    keys = a.keys()
-    keys.sort()
-    for k in keys:
-      for v in a[k]:
-        print '%s: %s' % (k, v)
-    expwhen = db.expiry(id)
-    if expwhen:
-      print 'expires: %s'
-    else:
-      print 'no-expiry'
+    print 'addr: %s' % a['addr'][0]
+    show(db, a)
   except Reject, msg:
     die('invalid token')
 commands['info'] = \
@@ -574,6 +582,33 @@ commands['revoke'] = \
   (cmd_revoke, 'LOCAL', """
 Revoke the token LOCAL.""")
 
+def cmd_list(argv):
+  try:
+    opts, argv = getopt(argv, '', [])
+  except GetoptError:
+    return 1
+  if argv:
+    return 1
+  c = Crypto(C.KeyFile(keyfile, C.KOPEN_READ)[tag])
+  db = CMDB(dbfile)
+  if not user:
+    gen = db.select('SELECT DISTINCT id FROM attrset')
+  else:
+    gen = db.select('''SELECT DISTINCT attrset.id
+                               FROM attrset, attr ON attrset.attr = attr.id
+                               WHERE attr.key = 'user' AND attr.value = ?''',
+                    [user])
+  for id, in gen:
+    a = AttrMultiMap(db, id)    
+    print '%s %s%s' % \
+          (token(c, id),
+           a.get('addr', '<no-address>')[0],
+           (not user and ' [%s]' % a.get('user', ['<no-user>'])[0] or ''))
+    show(db, a)
+commands['list'] = \
+  (cmd_list, '', """
+List the user's tokens and information about them.""")
+
 def cmd_cleanup(argv):
   try:
     opts, argv = getopt(argv, '', [])