Setting tag myplc-5.3-5
[myplc.git] / bin / plc-orphan-accounts.py
1 #!/usr/bin/env plcsh
2 #
3 # searches and displays any local orphan account (not attached to a site)
4 # remote accounts with identical emails are displayed as well
5
6 import sys
7 import time
8 import readline
9 from optparse import OptionParser
10
11 logdir="/var/log/accounts"
12
13 def run_in_log (options):
14     monthstring=time.strftime("%Y-%m")
15     if not os.path.isdir(logdir):
16         os.mkdir(logdir)
17     logname="%s/orphans-%s.log"%(logdir,monthstring)
18     sys.stdout=open(logname,'a')
19     sys.stderr=sys.stdout
20     run(options)
21     sys.stderr.close()
22     sys.stdout.close()
23
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
28     return 1
29
30 def get_orphans ():
31     orphans = [p for p in GetPersons({'peer_id':None,'-SORT':'email'}) if not p['site_ids'] ]
32     orphans.sort(sort_email)
33     return orphans
34
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',
40     else: print 'DIS',
41     print p['email']
42
43 date_keys=['date_created','last_updated']
44 def details_person (p):
45     keys=p.keys()
46     keys.sort()
47     for key in keys:
48         print key,'->',
49         value=p[key]
50         if key in date_keys:    print time.asctime(time.gmtime(value))
51         else:                   print value
52
53 def get_related(email):
54     return GetPersons ({'email':email,'~peer_id':None})
55
56 def header (message):
57     print '--------------------'
58     print GetPeerName(),
59     print time.asctime(time.gmtime())
60     print 'Listing orphan accounts and any similar remote'
61     print '--------------------'
62
63 def delete_local (person,default_bool,options):
64     
65     # just in case
66     if person['peer_id'] != None:
67         print 'ERROR: cannot delete non-local person',person['email']
68         return
69
70     prompt = 'want to delete '+person['email']
71     if default_bool:    prompt += ' v(erbose)/[y]/n ? '
72     else:               prompt += ' v(erbose)y/[n] ? '
73
74     done=False
75
76     while not done:
77         done=True
78         try:
79             answer = raw_input(prompt).strip()
80         except EOFError :
81             print 'bailing out'
82             sys.exit(1)
83
84         if answer=='':
85             do_delete=default_bool
86         elif answer.lower()[0]=='y':
87             do_delete=True
88         elif answer.lower()[0]=='n':
89             do_delete=False
90         elif answer.lower()[0]=='v':
91             details_person(person)
92             done=False
93         else:
94             done=False
95     id=person['person_id']
96     email=person['email']
97     if options.dry_run:
98         if do_delete:                   print 'Would delete',id,'->',email
99         else:                           print 'Would preserve',id,'->',email
100     elif do_delete:
101         print 'Deleting',id,'->',email,
102         if DeletePerson(id) == 1:       print 'OK',id,'deleted'
103         else:                           print 'Deletion failed'
104
105 def main_orphans (options):
106     orphans = get_orphans()
107     header ('Listing  %d  local accounts with no site - and similar remote accounts'%len(orphans))
108     index=0
109     for local in orphans:
110         index+=1
111         list_person ("%3d"%index,local)
112         for related in get_related(local['email']):
113             list_person("dup",related)
114         if options.delete:
115             delete_default = not local['enabled']
116             delete_local(local,delete_default,options)
117     
118 def main_duplicates(options):
119
120     header ('Listing all duplicate accounts')
121     locals = GetPersons({'peer_id':None,'-SORT':'email'})
122     locals.sort(sort_email)
123     index=0
124     for local in locals:
125         remotes=GetPersons({'email':local['email'],'~peer_id':None})
126         if remotes:
127             index+=1
128             list_person('%3d'%index,local)
129             for remote in remotes:
130                 list_person('dup',remote)
131             if options.delete:
132                 delete_default = not local['enabled']
133                 delete_local(local,delete_default,options)
134
135 def run (options):
136     main_orphans(options)
137     main_duplicates(options)
138
139 def main():
140
141     usage="%prog [ -- options]"
142
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")
150
151     (options,args) = parser.parse_args()
152     if len(args)!=0:
153         parser.error("Unexpected arguments",args)
154
155     if options.dry_run: options.delete=True
156     
157     if options.log:
158         options.delete=False
159         run_in_log(options)
160     else:
161         run(options)
162     
163 if __name__ == '__main__':
164     main()