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