Attachment 'userform.rs.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - User Account Maintenance
4
5 Copyright (c) 2000, 2001, 2002 by Jürgen Hermann <jh@web.de>
6 All rights reserved, see COPYING for details.
7
8 $Id: userform.py,v 1.54 2003/11/09 21:00:51 thomaswaldmann Exp $
9 ORS modifications:
10 13.01.04 RS auto-create homepage for new user
11
12 """
13
14 # Imports
15 import os, string, time, cgi, re, sha, Cookie
16 from MoinMoin import config, user, util, webapi, wikiutil
17 import MoinMoin.util.web
18 import MoinMoin.util.mail
19 import MoinMoin.util.datetime
20 from MoinMoin.widget import html
21 #RS auto-create homepage for new user
22 from MoinMoin.Page import Page
23 from MoinMoin.PageEditor import PageEditor
24 #RS end
25 _debug = 0
26
27
28 #############################################################################
29 ### Form POST Handling
30 #############################################################################
31
32 def savedata(pagename, request):
33 """ Handle POST request of the user preferences form.
34
35 Return error msg or None.
36 """
37 return UserSettingsHandler(request).handleData()
38
39
40 class UserSettingsHandler:
41
42 def __init__(self, request):
43 """ Initialize user settings form.
44 """
45 self.request = request
46 self._ = request.getText
47
48
49 def handleData(self):
50 _ = self._
51 form = self.request.form
52
53 if form.has_key('logout'):
54 # clear the cookie in the browser and locally
55 try:
56 cookie = Cookie.SimpleCookie(os.environ.get('HTTP_COOKIE', ''))
57 except Cookie.CookieError:
58 # ignore invalid cookies
59 cookie = None
60 else:
61 if cookie.has_key('MOIN_ID'):
62 uid = cookie['MOIN_ID'].value
63 webapi.setHttpHeader(self.request, 'Set-Cookie: MOIN_ID=%s; expires=Tuesday, 01-Jan-1999 12:00:00 GMT; Path=%s' % (
64 cookie['MOIN_ID'].value, webapi.getScriptname(),))
65 os.environ['HTTP_COOKIE'] = ''
66 self.request.auth_username = ''
67 self.request.user = user.User(self.request)
68 user.current = self.request.user
69 return _("<b>Cookie deleted. You are now logged out.</b>")
70
71 if form.has_key('login_sendmail'):
72 try:
73 email = form['login_email'].value
74 except KeyError:
75 return _("<b>Please provide a valid email address!</b>")
76
77 text = ''
78 users = user.getUserList()
79 for uid in users:
80 theuser = user.User(self.request, uid)
81 if theuser.valid and theuser.email == email:
82 text = "%s\n\nID: %s\nName: %s\nPassword: %s\nLogin URL: %s?action=userform&uid=%s" % (
83 text, theuser.id, theuser.name, theuser.enc_password, webapi.getBaseURL(), theuser.id)
84
85 if not text:
86 return _("<b>Found no account matching the given "
87 "email address '%(email)s'!</b>") % {'email': email}
88
89 mailok, msg = util.mail.sendmail(self.request, [email],
90 'Your wiki account data', text, mail_from=email)
91 return "<b>%s</b>" % cgi.escape(msg)
92
93 if form.has_key('login') or form.has_key('uid'):
94 # check for "uid" value that we use in the relogin URL
95 try:
96 uid = form['uid'].value
97 except KeyError:
98 uid = None
99
100 # try to get the user name
101 try:
102 name = form['username'].value.replace('\t', ' ').strip()
103 except KeyError:
104 name = ''
105
106 # try to get the password
107 password = form.getvalue('password','')
108
109 # load the user data and check for validness
110 theuser = user.User(self.request, uid, name=name, password=password)
111 if not theuser.valid:
112 return _("<b>Unknown user name or password.</b>")
113
114 # send the cookie
115 theuser.sendCookie(self.request)
116 self.request.user = theuser
117 user.current = theuser
118 else:
119 # save user's profile, first get user instance
120 theuser = user.User(self.request)
121
122 # try to get the name, if name is empty or missing, return an error msg
123 try:
124 theuser.name = form['username'].value.replace('\t', ' ').strip()
125 except KeyError:
126 return _("<b>Please enter a user name!</b>")
127
128 # Is this an existing user trying to change password, or a new user?
129 newuser = 1
130 if user.getUserId(theuser.name):
131 if theuser.name != user.current.name:
132 return _("<b>User name already exists!</b>")
133 else:
134 newuser = 0
135
136 # try to get the (optional) password and pw repeat
137 password = form.getvalue('password', '')
138 password2 = form.getvalue('password2','')
139
140 # Check if password and password repeat match
141 if password != password2:
142 return _("<b>Passwords don't match!</b>")
143 elif password and not password.startswith('{SHA}'):
144 theuser.enc_password = user.encodePassword(password)
145
146 # try to get the (optional) email
147 theuser.email = form.getvalue('email', '')
148
149 # editor size
150 theuser.edit_rows = util.web.getIntegerInput(self.request, 'edit_rows', theuser.edit_rows, 10, 60)
151 theuser.edit_cols = util.web.getIntegerInput(self.request, 'edit_cols', theuser.edit_cols, 30, 100)
152
153 # time zone
154 theuser.tz_offset = util.web.getIntegerInput(self.request, 'tz_offset', theuser.tz_offset, -84600, 84600)
155
156 # date format
157 try:
158 theuser.datetime_fmt = UserSettings._date_formats.get(form['datetime_fmt'].value, '')
159 except (KeyError, ValueError):
160 pass
161
162 # CSS URL
163 theuser.css_url = form.getvalue('css_url', '')
164 if theuser.css_url == config.css_url:
165 theuser.css_url = ''
166
167 # try to get the (optional) preferred language
168 theuser.language = form.getvalue('language', '')
169
170 # checkbox options
171 for key, label in user.User._checkbox_fields:
172 value = form.getvalue(key, 0)
173 try:
174 value = int(value)
175 except ValueError:
176 pass
177 else:
178 setattr(theuser, key, value)
179
180 # quicklinks for header
181 quicklinks = form.getvalue('quicklinks', '')
182 quicklinks = quicklinks.replace('\r', '')
183 quicklinks = quicklinks.split('\n')
184 quicklinks = map(string.strip, quicklinks)
185 quicklinks = filter(None, quicklinks)
186 quicklinks = map(wikiutil.quoteWikiname, quicklinks)
187 theuser.quicklinks = ','.join(quicklinks)
188
189 # subscription for page change notification
190 theuser.subscribed_pages = form.getvalue('subscribed_pages', '')
191 theuser.subscribed_pages = theuser.subscribed_pages.replace('\r', '')
192 theuser.subscribed_pages = theuser.subscribed_pages.replace('\n', ',')
193
194 # if we use ACLs, name and email are required to be unique
195 # further, name is required to be a WikiName (CamelCase!)
196 # see also MoinMoin/scripts/moin_usercheck.py
197 if config.acl_enabled:
198 theuser.name = theuser.name.replace(' ','') # strip spaces, we don't allow them anyway
199 if not re.match("(?:[%(u)s][%(l)s]+){2,}" % {'u': config.upperletters, 'l': config.lowerletters}, theuser.name):
200 return _("<b>Please enter your name like that: FirstnameLastname</b>")
201 if not theuser.email or not re.match(".+@.+\..{2,}", theuser.email):
202 return _("<b>Please provide your email address - without that you could not get your login data via email just in case you lose it.</b>")
203 users = user.getUserList()
204 for uid in users:
205 if uid == theuser.id:
206 continue
207 thisuser = user.User(self.request, uid)
208 if thisuser.name == theuser.name:
209 return _("<b>This user name already belongs to somebody else.</b>")
210 if theuser.email and thisuser.email == theuser.email:
211 return _("<b>This email already belongs to somebody else.</b>")
212 # save data and send cookie
213 theuser.save()
214 theuser.sendCookie(self.request)
215 self.request.user = theuser
216 user.current = theuser
217
218 result = _("<b>User preferences saved!</b>")
219 #RS auto-create homepage for new user
220 if newuser:
221 if wikiutil.getHomePage(self.request,theuser.name)==None:
222 homepagename=theuser.name
223 thetemplate=Page("HomepageTemplate")
224 if thetemplate.exists():
225 tempbody=thetemplate.get_raw_body()
226 newhomepage = PageEditor(homepagename, self.request)
227 ## newhomepage.sendEditor()
228 datestamp = '0'
229 newhomepage.saveText(tempbody, datestamp,
230 stripspaces=0, notify=0, comment='Homepage created for new user')
231 result = _("<b>User preferences saved and homepage created for %s!</b>" % homepagename)
232
233 #RS end
234 if _debug:
235 result = result + util.dumpFormData(form)
236 return result
237
238
239 #############################################################################
240 ### Form Generation
241 #############################################################################
242
243 class UserSettings:
244 """ User login and settings management.
245 """
246
247 _date_formats = {
248 'iso': '%Y-%m-%d %H:%M:%S',
249 'us': '%m/%d/%Y %I:%M:%S %p',
250 'euro': '%d.%m.%Y %H:%M:%S',
251 'rfc': '%a %b %d %H:%M:%S %Y',
252 }
253
254
255 def __init__(self, request):
256 """ Initialize user settings form.
257 """
258 self.request = request
259 self._ = request.getText
260
261
262 def _tz_select(self):
263 """ Create time zone selection.
264 """
265 tz = 0
266 if self.request.user.valid:
267 tz = int(self.request.user.tz_offset)
268
269 options = []
270 now = time.time()
271 for halfhour in range(-47, 48):
272 offset = halfhour * 1800
273 t = now + offset
274
275 options.append((
276 offset,
277 '%s [%s%s:%s]' % (
278 time.strftime(config.datetime_fmt, util.datetime.tmtuple(t)),
279 "+-"[offset < 0],
280 string.zfill("%d" % (abs(offset) / 3600), 2),
281 string.zfill("%d" % (abs(offset) % 3600 / 60), 2),
282 ),
283 ))
284
285 return util.web.makeSelection('tz_offset', options, tz)
286
287
288 def _dtfmt_select(self):
289 """ Create date format selection.
290 """
291 try:
292 selected = [
293 k for k, v in self._date_formats.items()
294 if v == self.request.user.datetime_fmt][0]
295 except IndexError:
296 selected = ''
297 options = [('', self._('Default'))] + self._date_formats.items()
298
299 return util.web.makeSelection('datetime_fmt', options, selected)
300
301
302 def _lang_select(self):
303 """ Create language selection.
304 """
305 from MoinMoin.i18n import languages, NAME, ENCODING
306
307 cur_lang = self.request.user.valid and self.request.user.language or ''
308 langs = languages.items()
309 langs.sort(lambda x,y,NAME=NAME: cmp(x[1][NAME], y[1][NAME]))
310
311 options = [('', self._('<Browser setting>'))]
312 for lang in langs:
313 if config.charset.upper() == 'UTF-8' or \
314 lang[0] in ['', 'en'] or \
315 lang[1][ENCODING] == config.charset:
316 options.append((lang[0], lang[1][NAME]))
317
318 return util.web.makeSelection('language', options, cur_lang)
319
320
321 def make_form(self):
322 """ Create the FORM, and the TABLE with the input fields
323 """
324 self._form = html.FORM(action=webapi.getScriptname()+webapi.getPathinfo())
325 self._table = html.TABLE(border=0)
326
327 self._form.append(html.INPUT(type="hidden", name="action", value="userform"))
328 self._form.append(self._table)
329
330
331 def make_row(self, label, cell, **kw):
332 """ Create a row in the form table.
333 """
334 self._table.append(html.TR().extend([
335 html.TD(**kw).extend([html.B().append(label), '\xA0']),
336 html.TD().extend(cell),
337 ]))
338
339
340 def asHTML(self):
341 """ Create the complete HTML form code.
342 """
343 self.make_form()
344
345 # check user data
346 if not self.request.user.css_url:
347 self.request.user.css_url = config.css_url
348
349 # different form elements depending on login state
350 html_uid = ''
351 if self.request.user.valid:
352 html_uid = '<tr><td><b>ID</b> </td><td>%s</td></tr>' % (self.request.user.id,)
353 buttons = [
354 ('save', self._(' Save ')),
355 ('logout', self._(' Logout ')),
356 ]
357 # url = "%s?action=userform&uid=%s" % (webapi.getBaseURL(), self.request.user.id)
358 # html_relogin = self._('To login from a different machine, use this URL: ') + \
359 # '<a href="%s">%s</a><br>' % (url, url)
360 else:
361 buttons = [
362 ("save", self._(' Create Profile ')),
363 ('login', self._(' Login ')),
364 ]
365 # html_relogin = ""
366
367 if config.mail_smarthost:
368 html_uid = """
369 <tr><td><b>%s</b> </td><td><input type="text" size="40" name="login_email"></td></tr>
370 <tr><td></td><td><input type="submit" name="login_sendmail" value="%s"></td></tr>
371 """ % (self._('Your email address'),
372 self._(' Mail me my account data '))
373
374 self._table.append(html.Raw(html_uid))
375
376 self.make_row(self._('Name'), [
377 html.INPUT(
378 type="text", size=32, name="username", value=self.request.user.name
379 ),
380 ' \xA0 ', self._('(Use FirstnameLastname)'),
381 ])
382
383 self.make_row(self._('Password'), [
384 html.INPUT(
385 type="password", size=32, name="password", value=self.request.user.enc_password
386 )
387 ])
388
389 self.make_row(self._('Password repeat'), [
390 html.INPUT(
391 type="password", size=32, name="password2", value=self.request.user.enc_password
392 ),
393 ' \xA0 ', self._('(Only when changing passwords)'),
394 ])
395
396 self.make_row(self._('Email'), [html.INPUT(
397 type="text", size=40, name="email", value=self.request.user.email
398 )])
399
400 self.make_row(self._('CSS URL'), [
401 html.INPUT(
402 type="text", size=40, name="css_url", value=self.request.user.css_url
403 ),
404 ' \xA0 ', self._('("None" for disabling CSS)'),
405 ])
406
407 self.make_row(self._('Editor size'), [
408 html.INPUT(type="text", size=3, maxlength=3,
409 name="edit_cols", value=self.request.user.edit_cols),
410 ' \xA0x\xA0 ',
411 html.INPUT(type="text", size=3, maxlength=3,
412 name="edit_rows", value=self.request.user.edit_rows),
413 ])
414
415 self.make_row(self._('Time zone'), [
416 self._('Your time is'), ' ',
417 self._tz_select(),
418 html.BR(),
419 self._('Server time is'), ' ',
420 time.strftime(config.datetime_fmt, util.datetime.tmtuple()),
421 ' (UTC)',
422 ])
423
424 self.make_row(self._('Date format'), [self._dtfmt_select()])
425
426 self.make_row(self._('Preferred language'), [self._lang_select()])
427
428 # boolean user options
429 bool_options = []
430 checkbox_fields = user.User._checkbox_fields
431 checkbox_fields.sort(lambda a, b: cmp(a[1](), b[1]()))
432 for key, label in checkbox_fields:
433 bool_options.extend([
434 html.INPUT(type="checkbox", name=key, value=1,
435 checked=getattr(self.request.user, key, 0)),
436 '\xA0', label(), html.BR(),
437 ])
438 self.make_row(self._('General options'), bool_options)
439
440 self.make_row(self._('Quick links'), valign="top", cell=[
441 html.TEXTAREA(name="quicklinks", rows=6, cols=50)
442 .append('\n'.join(self.request.user.getQuickLinks())),
443 ])
444
445 # subscribed pages
446 if config.mail_smarthost:
447 notifylist = self.request.user.getSubscriptionList()
448 notifylist.sort()
449
450 warning = []
451 if not self.request.user.email:
452 warning = [
453 html.BR(),
454 html.SMALL(Class="warning").append(
455 self._("This list does not work, unless you have"
456 " entered a valid email address!")
457 )]
458
459 self.make_row(
460 html.Raw(self._('Subscribed wiki pages<br>(one regex per line)')),
461 valign="top",
462 cell=[
463 html.TEXTAREA(name="subscribed_pages", rows=6, cols=50)
464 .append('\n'.join(notifylist)),
465 ] + warning
466 )
467
468 # add buttons
469 button_cell = []
470 for name, label in buttons:
471 button_cell.extend([
472 html.INPUT(type="submit", name=name, value=label),
473 ' \xA0 ',
474 ])
475 self.make_row('', button_cell)
476
477 return str(self._form)
478 # + html_relogin
479
480
481 def getUserForm(request):
482 """ Return HTML code for the user settings.
483 """
484 return UserSettings(request).asHTML()
485
486
487 #############################################################################
488 ### User account administration
489 #############################################################################
490
491 def do_user_browser(request):
492 """ Browser for SystemAdmin macro.
493 """
494 from MoinMoin.util.dataset import TupleDataset, Column
495 _ = request.getText
496
497 data = TupleDataset()
498 data.columns = [
499 Column('id', label=('ID'), align='right'),
500 Column('name', label=('Username')),
501 Column('email', label=('Email')),
502 Column('action', label=_('Action')),
503 ]
504
505 # iterate over users
506 for uid in user.getUserList():
507 account = user.User(request, uid)
508 data.addRow((
509 request.formatter.code(1) + uid + request.formatter.code(0),
510 request.formatter.text(account.name),
511 request.formatter.text(account.email),
512 '',
513 ))
514
515 if data:
516 from MoinMoin.widget.browser import DataBrowserWidget
517
518 browser = DataBrowserWidget(request)
519 browser.setData(data)
520 return browser.toHTML()
521
522 # no data
523 return ''
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.