3 # searches and displays any local orphan account (not attached to a site)
4 # remote accounts with identical emails are displayed as well
9 from optparse import OptionParser
11 logdir="/var/log/accounts"
13 def run_in_log (options):
14 monthstring=time.strftime("%Y-%m")
15 if not os.path.isdir(logdir):
17 logname="%s/orphans-%s.log"%(logdir,monthstring)
18 sys.stdout=open(logname,'a')
24 # sort filters look broken
25 def sort_email (p1,p2):
26 if p1['email'] == p2['email']: return 0
27 if p1['email'] < p2['email'] : return -1
31 orphans = [p for p in GetPersons({'peer_id':None,'-SORT':'email'}) if not p['site_ids'] ]
32 orphans.sort(sort_email)
35 def list_person (margin,p):
36 print margin,'%6d'%p['person_id'], time.asctime(time.gmtime(p['date_created'])),
37 if not p['peer_id']: print 'LOCAL',
38 else: print 'pr=',p['peer_id'],
39 if p['enabled']: print 'ENB',
43 date_keys=['date_created','last_updated']
44 def details_person (p):
50 if key in date_keys: print time.asctime(time.gmtime(value))
53 def get_related(email):
54 return GetPersons ({'email':email,'~peer_id':None})
57 print '--------------------'
59 print time.asctime(time.gmtime())
60 print 'Listing orphan accounts and any similar remote'
61 print '--------------------'
63 def delete_local (person,default_bool,options):
66 if person['peer_id'] != None:
67 print 'ERROR: cannot delete non-local person',person['email']
70 prompt = 'want to delete '+person['email']
71 if default_bool: prompt += ' v(erbose)/[y]/n ? '
72 else: prompt += ' v(erbose)y/[n] ? '
79 answer = raw_input(prompt).strip()
85 do_delete=default_bool
86 elif answer.lower()[0]=='y':
88 elif answer.lower()[0]=='n':
90 elif answer.lower()[0]=='v':
91 details_person(person)
95 id=person['person_id']
98 if do_delete: print 'Would delete',id,'->',email
99 else: print 'Would preserve',id,'->',email
101 print 'Deleting',id,'->',email,
102 if DeletePerson(id) == 1: print 'OK',id,'deleted'
103 else: print 'Deletion failed'
105 def main_orphans (options):
106 orphans = get_orphans()
107 header ('Listing %d local accounts with no site - and similar remote accounts'%len(orphans))
109 for local in orphans:
111 list_person ("%3d"%index,local)
112 for related in get_related(local['email']):
113 list_person("dup",related)
115 delete_default = not local['enabled']
116 delete_local(local,delete_default,options)
118 def main_duplicates(options):
120 header ('Listing all duplicate accounts')
121 locals = GetPersons({'peer_id':None,'-SORT':'email'})
122 locals.sort(sort_email)
125 remotes=GetPersons({'email':local['email'],'~peer_id':None})
128 list_person('%3d'%index,local)
129 for remote in remotes:
130 list_person('dup',remote)
132 delete_default = not local['enabled']
133 delete_local(local,delete_default,options)
136 main_orphans(options)
137 main_duplicates(options)
141 usage="%prog [ -- options]"
143 parser = OptionParser(usage=usage)
144 parser.add_option("-l","--log", dest="log", action="store_true",default=False,
145 help="write current status in /var/log/accounts")
146 parser.add_option("-d","--delete", dest="delete", action="store_true",default=False,
147 help="interactively delete extraneous accounts")
148 parser.add_option("-n","--dry-run", dest="dry_run", action="store_true",default=False,
149 help="go through the delete prompting but does not delete")
151 (options,args) = parser.parse_args()
153 parser.error("Unexpected arguments",args)
155 if options.dry_run: options.delete=True
163 if __name__ == '__main__':