changeset 5915:19e8a1c50bda

moin account resetpw - added options --all-users and --notify --all-users is to reset the password of all (even disabled) users (use some random and secret password for this). Note: if -q (quiet) flag is not given, it will show some progress indication with the current count / total count and uid. --notify can be used to notify the user of the account via e-mail and send a password reset link. when used with --all-users, all users that have an e-mail address and are not disabled will be notified by e-mail (caution: depending on your wiki's user count, this can generate a huge count of e-mails and take quite a while to be processed). refactored the code to use exceptions, move some code to user module
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Tue, 08 Jan 2013 00:07:30 +0100
parents d5669dcdc16b
children 881d9053592a
files MoinMoin/script/account/resetpw.py MoinMoin/user.py
diffstat 2 files changed, 64 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/script/account/resetpw.py	Sat Dec 29 22:05:05 2012 +0100
+++ b/MoinMoin/script/account/resetpw.py	Tue Jan 08 00:07:30 2013 +0100
@@ -2,12 +2,14 @@
 """
 MoinMoin - disable a user account
 
-@copyright: 2006 MoinMoin:ThomasWaldmann,
+@copyright: 2006-2013 MoinMoin:ThomasWaldmann,
             2008 MoinMoin:JohannesBerg
 @license: GNU GPL, see COPYING for details.
 """
 
-from MoinMoin.script import MoinScript
+from MoinMoin.script import MoinScript, log
+from MoinMoin.user import getUserList, set_password, Fault
+
 
 class PluginScript(MoinScript):
     """\
@@ -40,14 +42,25 @@
             "--name", metavar="NAME", dest="uname",
             help="Reset password for the user with user name NAME."
         )
+        self.parser.add_option(
+            "-a", "--all-users", dest="all_users", action="store_true",
+            help="Reset password for ALL users."
+        )
+        self.parser.add_option(
+            "--notify", dest="notify", action="store_true",
+            help="Notify user(s), send them an E-Mail with a password reset link."
+        )
+        self.parser.add_option(
+            "-v", "--verbose", dest="verbose", action="store_true",
+            help="Verbose operation."
+        )
 
     def mainloop(self):
-        # we don't expect non-option arguments
         if len(self.args) != 1:
             self.parser.error("no new password given")
         newpass = self.args[0]
 
-        flags_given = self.options.uid or self.options.uname
+        flags_given = self.options.uid or self.options.uname or self.options.all_users
         if not flags_given:
             self.parser.print_help()
             import sys
@@ -56,15 +69,25 @@
         self.init_request()
         request = self.request
 
-        from MoinMoin import user
         if self.options.uid:
-            u = user.User(request, self.options.uid)
+            try:
+                set_password(request, newpass, uid=self.options.uid,
+                             notify=self.options.notify)
+            except Fault, err:
+                print str(err)
         elif self.options.uname:
-            u = user.User(request, None, self.options.uname)
-
-        if not u.exists():
-            print 'This user "%s" does not exists!' % u.name
-            return
-
-        u.enc_password = user.encodePassword(newpass)
-        u.save()
+            try:
+                set_password(request, newpass, uname=self.options.uname,
+                             notify=self.options.notify)
+            except Fault, err:
+                print str(err)
+        elif self.options.all_users:
+            uids = sorted(getUserList(request))
+            total = len(uids)
+            for nr, uid in enumerate(uids, start=1):
+                log("%05d / %05d - processing uid %s" % (nr, total, uid))
+                try:
+                    set_password(request, newpass, uid=uid,
+                                 notify=self.options.notify)
+                except Fault, err:
+                    print str(err)
--- a/MoinMoin/user.py	Sat Dec 29 22:05:05 2012 +0100
+++ b/MoinMoin/user.py	Tue Jan 08 00:07:30 2013 +0100
@@ -15,7 +15,7 @@
       * storage code
 
     @copyright: 2000-2004 Juergen Hermann <jh@web.de>,
-                2003-2007 MoinMoin:ThomasWaldmann,
+                2003-2013 MoinMoin:ThomasWaldmann,
                 2010 Michael Foetsch <foetsch@yahoo.com>
     @license: GNU GPL, see COPYING for details.
 """
@@ -167,6 +167,32 @@
     return '{SSHA}' + base64.encodestring(hash.digest() + salt).rstrip()
 
 
+class Fault(Exception):
+    """something went wrong"""
+
+class NoSuchUser(Fault):
+    """raised if no such user exists"""
+
+class MailFailed(Fault):
+    """raised if e-mail sending failed"""
+
+
+def set_password(request, newpass, u=None, uid=None, uname=None, notify=False):
+    if uid:
+        u = User(request, uid)
+    elif uname:
+        u = User(request, None, uname)
+    if u and u.exists():
+        u.enc_password = encodePassword(newpass)
+        u.save()
+        if notify and not u.disabled and u.email:
+            mailok, msg = u.mailAccountData()
+            if not mailok:
+                raise MailFailed(msg)
+    else:
+        raise NoSuchUser('User does not exist (name: %r id: %r)!' % (u.name, u.id))
+
+
 def normalizeName(name):
     """ Make normalized user name