5 # searches and displays any local orphan account (not attached to a site)
6 # remote accounts with identical emails are displayed as well
11 from optparse import OptionParser
13 logdir="/var/log/accounts"
15 def run_in_log (options):
16 monthstring=time.strftime("%Y-%m")
17 if not os.path.isdir(logdir):
19 logname="%s/orphans-%s.log"%(logdir,monthstring)
20 sys.stdout=open(logname,'a')
26 # sort filters look broken
27 def sort_email (p1,p2):
28 if p1['email'] == p2['email']: return 0
29 if p1['email'] < p2['email'] : return -1
33 orphans = [p for p in GetPersons({'peer_id':None,'-SORT':'email'}) if not p['site_ids'] ]
34 orphans.sort(sort_email)
37 def list_person (margin,p):
38 print margin,'%6d'%p['person_id'], time.asctime(time.gmtime(p['date_created'])),
39 if not p['peer_id']: print 'LOCAL',
40 else: print 'pr=',p['peer_id'],
41 if p['enabled']: print 'ENB',
45 date_keys=['date_created','last_updated']
46 def details_person (p):
52 if key in date_keys: print time.asctime(time.gmtime(value))
55 def get_related(email):
56 return GetPersons ({'email':email,'~peer_id':None})
59 print '--------------------'
61 print time.asctime(time.gmtime())
62 print 'Listing orphan accounts and any similar remote'
63 print '--------------------'
65 def delete_local (person,default_bool,options):
68 if person['peer_id'] != None:
69 print 'ERROR: cannot delete non-local person',person['email']
72 prompt = 'want to delete '+person['email']
73 if default_bool: prompt += ' v(erbose)/[y]/n ? '
74 else: prompt += ' v(erbose)y/[n] ? '
81 answer = raw_input(prompt).strip()
87 do_delete=default_bool
88 elif answer.lower()[0]=='y':
90 elif answer.lower()[0]=='n':
92 elif answer.lower()[0]=='v':
93 details_person(person)
97 id=person['person_id']
100 if do_delete: print 'Would delete',id,'->',email
101 else: print 'Would preserve',id,'->',email
103 print 'Deleting',id,'->',email,
104 if DeletePerson(id) == 1: print 'OK',id,'deleted'
105 else: print 'Deletion failed'
107 def main_orphans (options):
108 orphans = get_orphans()
109 header ('Listing %d local accounts with no site - and similar remote accounts'%len(orphans))
111 for local in orphans:
113 list_person ("%3d"%index,local)
114 for related in get_related(local['email']):
115 list_person("dup",related)
117 delete_default = not local['enabled']
118 delete_local(local,delete_default,options)
120 def main_duplicates(options):
122 header ('Listing all duplicate accounts')
123 locals = GetPersons({'peer_id':None,'-SORT':'email'})
124 locals.sort(sort_email)
127 remotes=GetPersons({'email':local['email'],'~peer_id':None})
130 list_person('%3d'%index,local)
131 for remote in remotes:
132 list_person('dup',remote)
134 delete_default = not local['enabled']
135 delete_local(local,delete_default,options)
138 main_orphans(options)
139 main_duplicates(options)
143 usage="%prog [ -- options]"
145 parser = OptionParser(usage=usage)
146 parser.add_option("-l","--log", dest="log", action="store_true",default=False,
147 help="write current status in /var/log/accounts")
148 parser.add_option("-d","--delete", dest="delete", action="store_true",default=False,
149 help="interactively delete extraneous accounts")
150 parser.add_option("-n","--dry-run", dest="dry_run", action="store_true",default=False,
151 help="go through the delete prompting but does not delete")
153 (options,args) = parser.parse_args()
155 parser.error("Unexpected arguments",args)
157 if options.dry_run: options.delete=True
165 if __name__ == '__main__':