Attachment 'mail-verification.patch'

Download

   1 Description: Add support for requiring new accounts to be verified by email
   2 Origin: http://moinmo.in/MoinMoinPatch/VerifyAccountCreationByEmail
   3 Author: Steve McIntyre
   4 Last-Update: 2013-09-04
   5 
   6 Index: moin/MoinMoin/action/newaccount.py
   7 ===================================================================
   8 --- moin.orig/MoinMoin/action/newaccount.py	2013-09-03 23:52:51.279579526 +0000
   9 +++ moin/MoinMoin/action/newaccount.py	2013-09-03 23:53:28.143762319 +0000
  10 @@ -12,7 +12,29 @@
  11  from MoinMoin.security.textcha import TextCha
  12  from MoinMoin.security.sec_recaptcha import ReCaptcha
  13  from MoinMoin.auth import MoinAuth
  14 +from MoinMoin.mail import sendmail
  15 +import subprocess
  16  
  17 +def _send_verification_mail(request, user):
  18 +    _ = request.getText
  19 +    querystr = {'action': 'verifyaccount',
  20 +                'i': user.id,
  21 +                'v': user.account_verification}
  22 +    page = Page(request, "FrontPage")
  23 +    pagelink = "%(link)s" % {'link': request.getQualifiedURL(page.url(request, querystr))}
  24 +    subject = _('[%(sitename)s] account verification check for new user %(username)s') % {
  25 +            'sitename': request.page.cfg.sitename or request.url_root,
  26 +            'username': user.name,
  27 +        }
  28 +
  29 +    text = "Please verify your account by visiting this URL:\n\n  %(link)s\n\n" % {
  30 +        'link': pagelink}
  31 +
  32 +    mailok, msg = sendmail.sendmail(request, user.email, subject, text, request.cfg.mail_from)
  33 +    if mailok:
  34 +        return (1, _("Verification message sent to %(email)s" % {'email': user.email}))
  35 +    else:
  36 +        return (mailok, msg)
  37  
  38  def _create_user(request):
  39      _ = request.getText
  40 @@ -46,8 +68,18 @@
  41  space between words. Group page name is not allowed.""", wiki=True) % wikiutil.escape(theuser.name)
  42  
  43      # Name required to be unique. Check if name belong to another user.
  44 -    if user.getUserId(request, theuser.name):
  45 -        return _("This user name already belongs to somebody else.")
  46 +    userid = user.getUserId(request, theuser.name)
  47 +    if userid:
  48 +        if request.cfg.require_email_verification and theuser.account_verification:
  49 +            resendlink = request.page.url(request, querystr={
  50 +                'action': 'newaccount',
  51 +                'i': userid,
  52 +                'resend': '1'})
  53 +            return _('This user name already belongs to somebody else. If this is a new account'
  54 +                     ' and you need another verification link, try <a href="%s">'
  55 +                     'sending another one</a>. ' % resendlink)
  56 +        else:
  57 +            return _("This user name already belongs to somebody else.")
  58  
  59      # try to get the password and pw repeat
  60      password = form.get('password1', '')
  61 @@ -76,18 +108,41 @@
  62      email = wikiutil.clean_input(form.get('email', ''))
  63      theuser.email = email.strip()
  64      if not theuser.email and 'email' not in request.cfg.user_form_remove:
  65 -        return _("Please provide your email address. If you lose your"
  66 -                 " login information, you can get it by email.")
  67 +        if request.cfg.require_email_verification:
  68 +            return _("Please provide your email address. You will need it"
  69 +                     " to be able to confirm your registration.")
  70 +        else:
  71 +            return _("Please provide your email address. If you lose your"
  72 +                     " login information, you can get it by email.")
  73  
  74      # Email should be unique - see also MoinMoin/script/accounts/moin_usercheck.py
  75      if theuser.email and request.cfg.user_email_unique:
  76 -        if user.get_by_email_address(request, theuser.email):
  77 -            return _("This email already belongs to somebody else.")
  78 +        emailuser = user.get_by_email_address(request, theuser.email)
  79 +        if emailuser:
  80 +            if request.cfg.require_email_verification and theuser.account_verification:
  81 +                resendlink = request.page.url(request, querystr={
  82 +                    'action': 'newaccount',
  83 +                    'i': emailuser.id,
  84 +                    'resend': '1'})
  85 +                return _('This email already belongs to somebody else. If this is a new account'
  86 +                         ' and you need another verification link, try <a href="%s">'
  87 +                         'sending another one</a>. ' % resendlink)
  88 +            else:
  89 +                return _("This email already belongs to somebody else.")
  90 +
  91 +    # Send verification links if desired
  92 +    if request.cfg.require_email_verification:        
  93 +        mailok, msg = _send_verification_mail(request, theuser)
  94 +        if mailok:
  95 +            result = _("User account created! Use the link in your email (%s) to verify your account"
  96 +                       " then you will be able to use this account to login..." % theuser.email)
  97 +        else:
  98 +            request.theme.add_msg(_("Unable to send verification mail, %s. Account creation aborted." % msg), "error")
  99 +    else:
 100 +        result = _("User account created! You can use this account to login now...")
 101  
 102      # save data
 103      theuser.save()
 104 -
 105 -    result = _("User account created! You can use this account to login now...")
 106      return result
 107  
 108  
 109 @@ -185,9 +240,20 @@
 110  
 111      submitted = form.has_key('create')
 112  
 113 +    uid = request.values.get('i', None)
 114 +    resend = request.values.get('resend', None)
 115 +
 116      if submitted: # user pressed create button
 117          request.theme.add_msg(_create_user(request), "dialog")
 118          return page.send_page()
 119 +    if resend and uid:
 120 +        theuser = user.User(request, id=uid)
 121 +        mailok, msg = _send_verification_mail(request, theuser)
 122 +        if mailok:
 123 +            request.theme.add_msg(_("Verification message re-sent to %s" % theuser.email), "dialog")
 124 +        else:
 125 +            request.theme.add_msg(_("Unable to re-send verification message, %s" % msg), "dialog")
 126 +        return page.send_page()
 127      else: # show create form
 128          request.theme.send_title(_("Create Account"), pagename=pagename)
 129  
 130 Index: moin/MoinMoin/action/verifyaccount.py
 131 ===================================================================
 132 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
 133 +++ moin/MoinMoin/action/verifyaccount.py	2013-09-03 23:52:51.275579511 +0000
 134 @@ -0,0 +1,64 @@
 135 +# -*- coding: iso-8859-1 -*-
 136 +"""
 137 +    MoinMoin - verify account action
 138 +
 139 +    @copyright: 2012 Steve McIntyre
 140 +    @license: GNU GPL, see COPYING for details.
 141 +"""
 142 +
 143 +from MoinMoin import user, wikiutil
 144 +from MoinMoin.Page import Page
 145 +from MoinMoin.widget import html
 146 +from MoinMoin.auth import MoinAuth
 147 +
 148 +def execute(pagename, request):
 149 +    found = False
 150 +    for auth in request.cfg.auth:
 151 +        if isinstance(auth, MoinAuth):
 152 +            found = True
 153 +            break
 154 +
 155 +    if not found:
 156 +        # we will not have linked, so forbid access
 157 +        request.makeForbidden(403, 'No MoinAuth in auth list')
 158 +        return
 159 +
 160 +    page = Page(request, "FrontPage")
 161 +    _ = request.getText
 162 +
 163 +    if not request.cfg.require_email_verification:
 164 +        result = _("Verification not configured!")
 165 +        request.theme.add_msg(result, "error")
 166 +        return page.send_page()
 167 +
 168 +    uid = request.values.get('i', None)
 169 +    verify = request.values.get('v', None)
 170 +
 171 +    # Grab user profile
 172 +    theuser = user.User(request, id=uid)
 173 +
 174 +    # Compare the verification code
 175 +    if not theuser.valid:
 176 +        result = _("Unable to verify user account i=%s v=%s") % (uid, verify)
 177 +        request.theme.add_msg(result, "error")
 178 +        return page.send_page()
 179 +
 180 +    if not theuser.account_verification:
 181 +        result = _("User account has already been verified!")
 182 +        request.theme.add_msg(result, "error")
 183 +        return page.send_page()
 184 +
 185 +    if theuser.account_verification != verify:
 186 +        result = _("Unable to verify user account i=%s v=%s") % (uid, verify)
 187 +        request.theme.add_msg(result, "error")
 188 +        return page.send_page()
 189 +
 190 +    # All looks sane. Mark verification as done, save data
 191 +    theuser.account_verification = ""
 192 +    theuser.save()
 193 +
 194 +    loginlink = request.page.url(request, querystr={'action': 'login'})
 195 +    result = _('User account verified! You can use this account to <a href="%s">login</a> now...' % loginlink)
 196 +    request.theme.add_msg(result, "dialog")
 197 +    return page.send_page()
 198 +
 199 Index: moin/MoinMoin/auth/__init__.py
 200 ===================================================================
 201 --- moin.orig/MoinMoin/auth/__init__.py	2013-09-03 23:52:51.279579526 +0000
 202 +++ moin/MoinMoin/auth/__init__.py	2013-09-03 23:52:51.275579511 +0000
 203 @@ -242,8 +242,15 @@
 204          if username and not password:
 205              return ContinueLogin(user_obj, _('Missing password. Please enter user name and password.'))
 206  
 207 -        u = user.User(request, name=username, password=password, auth_method=self.name)
 208 +        u = user.User(request, name=username, password=password, auth_method=self.name)            
 209          if u.valid:
 210 +            try:
 211 +                verification = u.account_verification
 212 +            except:
 213 +                verification = False
 214 +            if request.cfg.require_email_verification and verification:
 215 +                logging.debug("%s: could not authenticate user %r (not verified yet)" % (self.name, username))
 216 +                return ContinueLogin(user_obj, _("User account not verified yet."))
 217              logging.debug("%s: successfully authenticated user %r (valid)" % (self.name, u.name))
 218              return ContinueLogin(u)
 219          else:
 220 Index: moin/MoinMoin/config/multiconfig.py
 221 ===================================================================
 222 --- moin.orig/MoinMoin/config/multiconfig.py	2013-09-03 23:52:51.279579526 +0000
 223 +++ moin/MoinMoin/config/multiconfig.py	2013-09-03 23:53:49.335867416 +0000
 224 @@ -1083,6 +1083,8 @@
 225  
 226      ('userprefs_disabled', [],
 227       "Disable the listed user preferences plugins."),
 228 +    ('require_email_verification', False ,
 229 +     "Require verification of new user accounts."),
 230    )),
 231    # ==========================================================================
 232    'various': ('Various', None, (
 233 Index: moin/MoinMoin/user.py
 234 ===================================================================
 235 --- moin.orig/MoinMoin/user.py	2013-09-03 23:52:51.279579526 +0000
 236 +++ moin/MoinMoin/user.py	2013-09-03 23:52:51.279579526 +0000
 237 @@ -22,6 +22,7 @@
 238  
 239  import os, time, codecs, base64
 240  import md5crypt
 241 +import uuid
 242  
 243  try:
 244      import crypt
 245 @@ -410,6 +411,12 @@
 246              self.id = self.make_id()
 247              if password is not None:
 248                  self.enc_password = encodePassword(self._cfg, password)
 249 +            self.account_creation_date = str(time.time())
 250 +            self.account_creation_host = self._request.remote_addr
 251 +            if self._cfg.require_email_verification:
 252 +                self.account_verification = uuid.uuid4()
 253 +            else:
 254 +                self.account_verification = ""
 255  
 256          # "may" so we can say "if user.may.read(pagename):"
 257          if self._cfg.SecurityPolicy:

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2013-09-05 17:03:37, 10.7 KB) [[attachment:mail-verification.patch]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.