fix resolv.conf issue on plc
[myplc.git] / plc-orphan-accounts.py
index fa8ee50..b8ce321 100755 (executable)
 #!/usr/bin/env plcsh
-
+#
+# $Id$
+#
 # searches and displays any local orphan account (not attached to a site)
 # remote accounts with identical emails are displayed as well
 
+import sys
 import time
+import readline
+from optparse import OptionParser
+
+logdir="/var/log/accounts"
+
+def run_in_log (options):
+    monthstring=time.strftime("%Y-%m")
+    if not os.path.isdir(logdir):
+        os.mkdir(logdir)
+    logname="%s/orphans-%s.log"%(logdir,monthstring)
+    sys.stdout=open(logname,'a')
+    sys.stderr=sys.stdout
+    run(options)
+    sys.stderr.close()
+    sys.stdout.close()
+
+# sort filters look broken
+def sort_email (p1,p2):
+    if p1['email'] == p2['email']: return 0
+    if p1['email'] < p2['email'] : return -1
+    return 1
 
 def get_orphans ():
-    return [p for p in GetPersons({'peer_id':None,'-SORT':'date_created'}) if not p['site_ids'] ]
+    orphans = [p for p in GetPersons({'peer_id':None,'-SORT':'email'}) if not p['site_ids'] ]
+    orphans.sort(sort_email)
+    return orphans
 
 def list_person (margin,p):
     print margin,'%6d'%p['person_id'], time.asctime(time.gmtime(p['date_created'])),
     if not p['peer_id']: print 'LOCAL',
     else: print 'pr=',p['peer_id'],
+    if p['enabled']: print 'ENB',
+    else: print 'DIS',
     print p['email']
 
+date_keys=['date_created','last_updated']
+def details_person (p):
+    keys=p.keys()
+    keys.sort()
+    for key in keys:
+        print key,'->',
+        value=p[key]
+        if key in date_keys:    print time.asctime(time.gmtime(value))
+        else:                   print value
+
 def get_related(email):
     return GetPersons ({'email':email,'~peer_id':None})
 
-def main ():
+def header (message):
+    print '--------------------'
+    print GetPeerName(),
+    print time.asctime(time.gmtime())
+    print 'Listing orphan accounts and any similar remote'
+    print '--------------------'
+
+def delete_local (person,default_bool,options):
     
+    # just in case
+    if person['peer_id'] != None:
+        print 'ERROR: cannot delete non-local person',person['email']
+        return
+
+    prompt = 'want to delete '+person['email']
+    if default_bool:    prompt += ' v(erbose)/[y]/n ? '
+    else:               prompt += ' v(erbose)y/[n] ? '
+
+    done=False
+
+    while not done:
+        done=True
+        try:
+            answer = raw_input(prompt).strip()
+        except EOFError :
+            print 'bailing out'
+            sys.exit(1)
+
+        if answer=='':
+            do_delete=default_bool
+        elif answer.lower()[0]=='y':
+            do_delete=True
+        elif answer.lower()[0]=='n':
+            do_delete=False
+        elif answer.lower()[0]=='v':
+            details_person(person)
+            done=False
+        else:
+            done=False
+    id=person['person_id']
+    email=person['email']
+    if options.dry_run:
+        if do_delete:                   print 'Would delete',id,'->',email
+        else:                           print 'Would preserve',id,'->',email
+    elif do_delete:
+        print 'Deleting',id,'->',email,
+        if DeletePerson(id) == 1:       print 'OK',id,'deleted'
+        else:                           print 'Deletion failed'
+
+def main_orphans (options):
     orphans = get_orphans()
-    print GetPeerName(),' ---  %d  --- '%len(orphans),'orphan accounts'
-    print time.asctime(time.gmtime())
-    print '---'
-    index=1
-    for p in orphans:
-        list_person ("%3d"%index,p)
-        for related in get_related(p['email']):
-            list_person("dup",related)
+    header ('Listing  %d  local accounts with no site - and similar remote accounts'%len(orphans))
+    index=0
+    for local in orphans:
         index+=1
+        list_person ("%3d"%index,local)
+        for related in get_related(local['email']):
+            list_person("dup",related)
+        if options.delete:
+            delete_default = not local['enabled']
+            delete_local(local,delete_default,options)
+    
+def main_duplicates(options):
+
+    header ('Listing all duplicate accounts')
+    locals = GetPersons({'peer_id':None,'-SORT':'email'})
+    locals.sort(sort_email)
+    index=0
+    for local in locals:
+        remotes=GetPersons({'email':local['email'],'~peer_id':None})
+        if remotes:
+            index+=1
+            list_person('%3d'%index,local)
+            for remote in remotes:
+                list_person('dup',remote)
+            if options.delete:
+                delete_default = not local['enabled']
+                delete_local(local,delete_default,options)
+
+def run (options):
+    main_orphans(options)
+    main_duplicates(options)
+
+def main():
+
+    usage="%prog [ -- options]"
+
+    parser = OptionParser(usage=usage)
+    parser.add_option("-l","--log", dest="log", action="store_true",default=False,
+                      help="write current status in /var/log/accounts")
+    parser.add_option("-d","--delete", dest="delete", action="store_true",default=False,
+                      help="interactively delete extraneous accounts")
+    parser.add_option("-n","--dry-run", dest="dry_run", action="store_true",default=False,
+                      help="go through the delete prompting but does not delete")
+
+    (options,args) = parser.parse_args()
+    if len(args)!=0:
+        parser.error("Unexpected arguments",args)
+
+    if options.dry_run: options.delete=True
+    
+    if options.log:
+        options.delete=False
+        run_in_log(options)
+    else:
+        run(options)
     
 if __name__ == '__main__':
     main()