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.You are not allowed to attach a file to this page.