Attachment 'userform_moin1-5-4-1_patched.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - UserPreferences Form and User Browser
4
5 @copyright: 2001-2004 by Jürgen Hermann <jh@web.de>
6 @license: GNU GPL, see COPYING for details.
7 """
8
9 import string, time, re
10 from MoinMoin import user, util, wikiutil
11 from MoinMoin.util import web, mail, timefuncs
12 from MoinMoin.widget import html
13
14 _debug = 0
15
16 #############################################################################
17 ### Form POST Handling
18 #############################################################################
19
20 def savedata(request):
21 """ Handle POST request of the user preferences form.
22
23 Return error msg or None.
24 """
25 return UserSettingsHandler(request).handleData()
26
27
28 class UserSettingsHandler:
29
30 def __init__(self, request):
31 """ Initialize user settings form. """
32 self.request = request
33 self._ = request.getText
34 self.cfg = request.cfg
35
36 def decodePageList(self, key):
37 """ Decode list of pages from form input
38
39 Each line is a page name, empty lines ignored.
40
41 Items can use '_' as spaces, needed by [name_with_spaces label]
42 format used in quicklinks. We do not touch those names here, the
43 underscores are handled later by the theme code.
44
45 @param key: the form key to get
46 @rtype: list of unicode strings
47 @return: list of normalized names
48 """
49 text = self.request.form.get(key, [''])[0]
50 text = text.replace('\r', '')
51 items = []
52 for item in text.split('\n'):
53 item = item.strip()
54 if not item:
55 continue
56 # Normalize names - except [name_with_spaces label]
57 # Commented out to allow URLs
58 #if not (item.startswith('[') and item.endswith(']')):
59 # item = self.request.normalizePagename(item)
60 items.append(item)
61 return items
62
63 def handleData(self):
64 _ = self._
65 form = self.request.form
66
67 if form.has_key('cancel'):
68 return
69
70 if form.has_key('account_sendmail'):
71 if not self.cfg.mail_enabled:
72 return _("""This wiki is not enabled for mail processing.
73 Contact the owner of the wiki, who can enable email.""")
74 try:
75 email = form['email'][0].lower()
76 except KeyError:
77 return _("Please provide a valid email address!")
78
79 users = user.getUserList(self.request)
80 for uid in users:
81 theuser = user.User(self.request, uid)
82 if theuser.valid and theuser.email.lower() == email:
83 msg = theuser.mailAccountData()
84 return wikiutil.escape(msg)
85
86 return _("Found no account matching the given email address '%(email)s'!") % {'email': wikiutil.escape(email)}
87
88 if (form.has_key('create') or
89 form.has_key('create_only') or
90 form.has_key('create_and_mail')):
91 if self.request.request_method != 'POST':
92 return _("Use UserPreferences to change your settings or create an account.")
93 # Create user profile
94 if form.has_key('create'):
95 theuser = self.request.get_user_from_form()
96 else:
97 theuser = user.User(self.request, auth_method="request:152")
98
99 # Require non-empty name
100 try:
101 theuser.name = form['name'][0]
102 except KeyError:
103 return _("Empty user name. Please enter a user name.")
104
105 # Don't allow users with invalid names
106 if not user.isValidName(self.request, theuser.name):
107 return _("""Invalid user name {{{'%s'}}}.
108 Name may contain any Unicode alpha numeric character, with optional one
109 space between words. Group page name is not allowed.""") % wikiutil.escape(theuser.name)
110
111 # Is this an existing user trying to change information or a new user?
112 # Name required to be unique. Check if name belong to another user.
113 newuser = 1
114 if user.getUserId(self.request, theuser.name):
115 if theuser.name != self.request.user.name:
116 return _("This user name already belongs to somebody else.")
117 else:
118 newuser = 0
119
120 # try to get the password and pw repeat
121 password = form.get('password', [''])[0]
122 password2 = form.get('password2',[''])[0]
123
124 # Check if password is given and matches with password repeat
125 if password != password2:
126 return _("Passwords don't match!")
127 if not password and newuser:
128 return _("Please specify a password!")
129 # Encode password
130 if password and not password.startswith('{SHA}'):
131 try:
132 theuser.enc_password = user.encodePassword(password)
133 except UnicodeError, err:
134 # Should never happen
135 return "Can't encode password: %s" % str(err)
136
137 # try to get the (required) email
138 email = form.get('email', [''])[0]
139 theuser.email = email.strip()
140 if not theuser.email:
141 return _("Please provide your email address. If you lose your"
142 " login information, you can get it by email.")
143
144 # Email should be unique - see also MoinMoin/script/accounts/moin_usercheck.py
145 if theuser.email and self.request.cfg.user_email_unique:
146 users = user.getUserList(self.request)
147 for uid in users:
148 if uid == theuser.id:
149 continue
150 thisuser = user.User(self.request, uid)
151 if thisuser.email == theuser.email and not thisuser.disabled:
152 return _("This email already belongs to somebody else.")
153
154 # save data
155 theuser.save()
156 if form.has_key('create_and_mail'):
157 result1 = _("User account created.") # ToDo: Add translation for this!!
158 result2 = theuser.mailAccountData(form.get('password', [''])[0],True)
159 result = "%s %s" % (result1, _(result2)) # This assumes that all msg from mailAccountData have translations
160 else:
161 result = _("User account created! You can use this account to login now...")
162
163 if _debug:
164 result = result + util.dumpFormData(form)
165 return result
166
167
168 # Select user profile (su user) - only works with cookie auth active.
169 if form.has_key('select_user'):
170 if (wikiutil.checkTicket(self.request.form['ticket'][0]) and
171 self.request.request_method == 'POST' and
172 self.request.user.isSuperUser()):
173 su_user = form.get('selected_user', [''])[0]
174 uid = user.getUserId(self.request, su_user)
175 theuser = user.User(self.request, uid)
176 theuser.disabled = None
177 theuser.save()
178 from MoinMoin import auth
179 auth.setCookie(self.request, theuser)
180 self.request.user = theuser
181 return _("Use UserPreferences to change settings of the selected user account")
182 else:
183 return _("Use UserPreferences to change your settings or create an account.")
184
185 if form.has_key('save'): # Save user profile
186 if self.request.request_method != 'POST':
187 return _("Use UserPreferences to change your settings or create an account.")
188 theuser = self.request.get_user_from_form()
189
190 if not 'name' in theuser.auth_attribs:
191 # Require non-empty name
192 theuser.name = form.get('name', [theuser.name])[0]
193 if not theuser.name:
194 return _("Empty user name. Please enter a user name.")
195
196 # Don't allow users with invalid names
197 if not user.isValidName(self.request, theuser.name):
198 return _("""Invalid user name {{{'%s'}}}.
199 Name may contain any Unicode alpha numeric character, with optional one
200 space between words. Group page name is not allowed.""") % wikiutil.escape(theuser.name)
201
202 # Is this an existing user trying to change information or a new user?
203 # Name required to be unique. Check if name belong to another user.
204 newuser = 1
205 if user.getUserId(self.request, theuser.name):
206 if theuser.name != self.request.user.name:
207 return _("This user name already belongs to somebody else.")
208 else:
209 newuser = 0
210
211 if not 'password' in theuser.auth_attribs:
212 # try to get the password and pw repeat
213 password = form.get('password', [''])[0]
214 password2 = form.get('password2',[''])[0]
215
216 # Check if password is given and matches with password repeat
217 if password != password2:
218 return _("Passwords don't match!")
219 if not password and newuser:
220 return _("Please specify a password!")
221 # Encode password
222 if password and not password.startswith('{SHA}'):
223 try:
224 theuser.enc_password = user.encodePassword(password)
225 except UnicodeError, err:
226 # Should never happen
227 return "Can't encode password: %s" % str(err)
228
229 if not 'email' in theuser.auth_attribs:
230 # try to get the email
231 email = form.get('email', [theuser.email])[0]
232 theuser.email = email.strip()
233
234 # Require email
235 if not theuser.email:
236 return _("Please provide your email address. If you lose your"
237 " login information, you can get it by email.")
238
239 # Email should be unique - see also MoinMoin/script/accounts/moin_usercheck.py
240 if theuser.email and self.request.cfg.user_email_unique:
241 users = user.getUserList(self.request)
242 for uid in users:
243 if uid == theuser.id:
244 continue
245 thisuser = user.User(self.request, uid, auth_method='userform:283')
246 if thisuser.email == theuser.email:
247 return _("This email already belongs to somebody else.")
248
249 if not 'aliasname' in theuser.auth_attribs:
250 # aliasname
251 theuser.aliasname = form.get('aliasname', [''])[0]
252
253 # editor size
254 theuser.edit_rows = util.web.getIntegerInput(self.request, 'edit_rows', theuser.edit_rows, 10, 60)
255
256 # try to get the editor
257 theuser.editor_default = form.get('editor_default', [self.cfg.editor_default])[0]
258 theuser.editor_ui = form.get('editor_ui', [self.cfg.editor_ui])[0]
259
260 # time zone
261 theuser.tz_offset = util.web.getIntegerInput(self.request, 'tz_offset', theuser.tz_offset, -84600, 84600)
262
263 # datetime format
264 try:
265 dt_d_combined = UserSettings._date_formats.get(form['datetime_fmt'][0], '')
266 theuser.datetime_fmt, theuser.date_fmt = dt_d_combined.split(' & ')
267 except (KeyError, ValueError):
268 theuser.datetime_fmt = '' # default
269 theuser.date_fmt = '' # default
270
271 # try to get the (optional) theme
272 theme_name = form.get('theme_name', [self.cfg.theme_default])[0]
273 if theme_name != theuser.theme_name:
274 # if the theme has changed, load the new theme
275 # so the user has a direct feedback
276 # WARNING: this should be refactored (i.e. theme load
277 # after userform handling), cause currently the
278 # already loaded theme is just replaced (works cause
279 # nothing has been emitted yet)
280 theuser.theme_name = theme_name
281 if self.request.loadTheme(theuser.theme_name) > 0:
282 theme_name = wikiutil.escape(theme_name)
283 return _("The theme '%(theme_name)s' could not be loaded!") % locals()
284
285 # try to get the (optional) preferred language
286 theuser.language = form.get('language', [''])[0]
287
288 # I want to handle all inputs from user_form_fields, but
289 # don't want to handle the cases that have already been coded
290 # above.
291 # This is a horribly fragile kludge that's begging to break.
292 # Something that might work better would be to define a
293 # handler for each form field, instead of stuffing them all in
294 # one long and inextensible method. That would allow for
295 # plugins to provide methods to validate their fields as well.
296 already_handled = ['name', 'password', 'password2', 'email',
297 'aliasname', 'edit_rows', 'editor_default',
298 'editor_ui', 'tz_offset', 'datetime_fmt',
299 'theme_name', 'language']
300 for field in self.cfg.user_form_fields:
301 key = field[0]
302 if ((key in self.cfg.user_form_disable)
303 or (key in already_handled)):
304 continue
305 default = self.cfg.user_form_defaults[key]
306 value = form.get(key, [default])[0]
307 setattr(theuser, key, value)
308
309 # checkbox options
310 if not newuser:
311 for key, label in self.cfg.user_checkbox_fields:
312 if key not in self.cfg.user_checkbox_disable and key not in self.cfg.user_checkbox_remove:
313 value = form.get(key, ["0"])[0]
314 try:
315 value = int(value)
316 except ValueError:
317 pass
318 else:
319 setattr(theuser, key, value)
320
321 # quicklinks for navibar
322 theuser.quicklinks = self.decodePageList('quicklinks')
323
324 # subscription for page change notification
325 theuser.subscribed_pages = self.decodePageList('subscribed_pages')
326
327 # save data
328 theuser.save()
329 self.request.user = theuser
330
331 result = _("User preferences saved!")
332 if _debug:
333 result = result + util.dumpFormData(form)
334 return result
335
336
337 #############################################################################
338 ### Form Generation
339 #############################################################################
340
341 class UserSettings:
342 """ User login and settings management. """
343
344 _date_formats = { # datetime_fmt & date_fmt
345 'iso': '%Y-%m-%d %H:%M:%S & %Y-%m-%d',
346 'us': '%m/%d/%Y %I:%M:%S %p & %m/%d/%Y',
347 'euro': '%d.%m.%Y %H:%M:%S & %d.%m.%Y',
348 'rfc': '%a %b %d %H:%M:%S %Y & %a %b %d %Y',
349 }
350
351 def __init__(self, request):
352 """ Initialize user settings form.
353 """
354 self.request = request
355 self._ = request.getText
356 self.cfg = request.cfg
357
358 def _tz_select(self):
359 """ Create time zone selection. """
360 tz = 0
361 if self.request.user.valid:
362 tz = int(self.request.user.tz_offset)
363
364 options = []
365 now = time.time()
366 for halfhour in range(-47, 48):
367 offset = halfhour * 1800
368 t = now + offset
369
370 options.append((
371 str(offset),
372 '%s [%s%s:%s]' % (
373 time.strftime(self.cfg.datetime_fmt, timefuncs.tmtuple(t)),
374 "+-"[offset < 0],
375 string.zfill("%d" % (abs(offset) / 3600), 2),
376 string.zfill("%d" % (abs(offset) % 3600 / 60), 2),
377 ),
378 ))
379
380 return util.web.makeSelection('tz_offset', options, str(tz))
381
382
383 def _dtfmt_select(self):
384 """ Create date format selection. """
385 _ = self._
386 try:
387 dt_d_combined = '%s & %s' % (self.request.user.datetime_fmt, self.request.user.date_fmt)
388 selected = [
389 k for k, v in self._date_formats.items()
390 if v == dt_d_combined][0]
391 except IndexError:
392 selected = ''
393 options = [('', _('Default'))] + self._date_formats.items()
394
395 return util.web.makeSelection('datetime_fmt', options, selected)
396
397
398 def _lang_select(self):
399 """ Create language selection. """
400 from MoinMoin import i18n
401 from MoinMoin.i18n import NAME
402 _ = self._
403 cur_lang = self.request.user.valid and self.request.user.language or ''
404 langs = i18n.wikiLanguages().items()
405 langs.sort(lambda x,y,NAME=NAME: cmp(x[1][NAME], y[1][NAME]))
406 options = [('', _('<Browser setting>', formatted=False))]
407 for lang in langs:
408 name = lang[1][NAME]
409 options.append((lang[0], name))
410
411 return util.web.makeSelection('language', options, cur_lang)
412
413 def _user_select(self):
414 options = []
415 users = user.getUserList(self.request)
416 for uid in users:
417 name = user.User(self.request, id=uid).name # + '_' + uid # for debugging
418 options.append((name, name))
419 options.sort()
420
421 size = min(5, len(options))
422 current_user = self.request.user.name
423 return util.web.makeSelection('selected_user', options, current_user, size=size)
424
425 def _theme_select(self):
426 """ Create theme selection. """
427 cur_theme = self.request.user.valid and self.request.user.theme_name or self.cfg.theme_default
428 options = [("<default>", "<%s>" % self._("Default"))]
429 for theme in wikiutil.getPlugins('theme', self.request.cfg):
430 options.append((theme, theme))
431
432 return util.web.makeSelection('theme_name', options, cur_theme)
433
434 def _editor_default_select(self):
435 """ Create editor selection. """
436 editor_default = self.request.user.valid and self.request.user.editor_default or self.cfg.editor_default
437 options = [("<default>", "<%s>" % self._("Default"))]
438 for editor in ['text','gui',]:
439 options.append((editor, editor))
440 return util.web.makeSelection('editor_default', options, editor_default)
441
442 def _editor_ui_select(self):
443 """ Create editor selection. """
444 editor_ui = self.request.user.valid and self.request.user.editor_ui or self.cfg.editor_ui
445 options = [("<default>", "<%s>" % self._("Default")),
446 ("theonepreferred", self._("the one preferred")),
447 ("freechoice", self._("free choice")),
448 ]
449 return util.web.makeSelection('editor_ui', options, editor_ui)
450
451 def make_form(self):
452 """ Create the FORM, and the TABLE with the input fields
453 """
454 sn = self.request.getScriptname()
455 pi = self.request.getPathinfo()
456 action = u"%s%s" % (sn, pi)
457 self._form = html.FORM(action=action)
458 self._table = html.TABLE(border="0")
459
460 # Use the user interface language and direction
461 lang_attr = self.request.theme.ui_lang_attr()
462 self._form.append(html.Raw('<div class="userpref"%s>' % lang_attr))
463
464 self._form.append(html.INPUT(type="hidden", name="action", value="userform"))
465 self._form.append(self._table)
466 self._form.append(html.Raw("</div>"))
467
468
469 def make_row(self, label, cell, **kw):
470 """ Create a row in the form table.
471 """
472 self._table.append(html.TR().extend([
473 html.TD(**kw).extend([html.B().append(label), ' ']),
474 html.TD().extend(cell),
475 ]))
476
477
478 def asHTML(self, create_only=False):
479 """ Create the complete HTML form code. """
480 _ = self._
481 self.make_form()
482
483 if self.request.user.isSuperUser() and create_only == False:
484 ticket = wikiutil.createTicket()
485 self.make_row(_('Select User'), [self._user_select()])
486 self._form.append(html.INPUT(type="hidden", name="ticket", value="%s" % ticket))
487 buttons = [("select_user", _('Select User'))]
488 button_cell = []
489 for name, label in buttons:
490 button_cell.extend([
491 html.INPUT(type="submit", name=name, value=label),
492 ' ',
493 ])
494 self.make_row('', button_cell)
495
496 if self.request.user.valid and not create_only:
497 buttons = [('save', _('Save')), ('cancel', _('Cancel')), ]
498 uf_remove = self.cfg.user_form_remove
499 uf_disable = self.cfg.user_form_disable
500 for attr in self.request.user.auth_attribs:
501 if attr == 'password':
502 uf_remove.append(attr)
503 uf_remove.append('password2')
504 else:
505 uf_disable.append(attr)
506 for key, label, type, length, textafter in self.cfg.user_form_fields:
507 default = self.cfg.user_form_defaults[key]
508 if not key in uf_remove:
509 if key in uf_disable:
510 self.make_row(_(label),
511 [ html.INPUT(type=type, size=length, name=key, disabled="disabled",
512 value=getattr(self.request.user, key)), ' ', _(textafter), ])
513 else:
514 self.make_row(_(label),
515 [ html.INPUT(type=type, size=length, name=key, value=getattr(self.request.user, key)), ' ', _(textafter), ])
516
517 if not self.cfg.theme_force and not "theme_name" in self.cfg.user_form_remove:
518 self.make_row(_('Preferred theme'), [self._theme_select()])
519
520 if not self.cfg.editor_force:
521 if not "editor_default" in self.cfg.user_form_remove:
522 self.make_row(_('Editor Preference'), [self._editor_default_select()])
523 if not "editor_ui" in self.cfg.user_form_remove:
524 self.make_row(_('Editor shown on UI'), [self._editor_ui_select()])
525
526 if not "tz_offset" in self.cfg.user_form_remove:
527 self.make_row(_('Time zone'), [
528 _('Your time is'), ' ',
529 self._tz_select(),
530 html.BR(),
531 _('Server time is'), ' ',
532 time.strftime(self.cfg.datetime_fmt, timefuncs.tmtuple()),
533 ' (UTC)',
534 ])
535
536 if not "datetime_fmt" in self.cfg.user_form_remove:
537 self.make_row(_('Date format'), [self._dtfmt_select()])
538
539 if not "language" in self.cfg.user_form_remove:
540 self.make_row(_('Preferred language'), [self._lang_select()])
541
542 # boolean user options
543 bool_options = []
544 checkbox_fields = self.cfg.user_checkbox_fields
545 _ = self.request.getText
546 checkbox_fields.sort(lambda a, b: cmp(a[1](_), b[1](_)))
547 for key, label in checkbox_fields:
548 if not key in self.cfg.user_checkbox_remove:
549 bool_options.extend([
550 html.INPUT(type="checkbox", name=key, value="1",
551 checked=getattr(self.request.user, key, 0),
552 disabled=key in self.cfg.user_checkbox_disable and True or None),
553 ' ', label(_), html.BR(),
554 ])
555 self.make_row(_('General options'), bool_options, valign="top")
556
557 self.make_row(_('Quick links'), [
558 html.TEXTAREA(name="quicklinks", rows="6", cols="50")
559 .append('\n'.join(self.request.user.getQuickLinks())),
560 ], valign="top")
561
562 # subscribed pages
563 if self.cfg.mail_enabled:
564 # Get list of subscribe pages, DO NOT sort! it should
565 # stay in the order the user entered it in his input
566 # box.
567 notifylist = self.request.user.getSubscriptionList()
568
569 warning = []
570 if not self.request.user.email:
571 warning = [
572 html.BR(),
573 html.SMALL(Class="warning").append(
574 _("This list does not work, unless you have"
575 " entered a valid email address!")
576 )]
577
578 self.make_row(
579 html.Raw(_('Subscribed wiki pages (one regex per line)')),
580 [html.TEXTAREA(name="subscribed_pages", rows="6", cols="50").append(
581 '\n'.join(notifylist)),
582 ] + warning,
583 valign="top"
584 )
585 else: # not logged in
586 # Login / register interface
587 buttons = [
588 # IMPORTANT: login should be first to be the default
589 # button when a user hits ENTER.
590 #('login', _('Login')), # we now have a Login macro
591 ('create', _('Create Profile')),
592 ('cancel', _('Cancel')),
593 ]
594 if create_only == False:
595 for key, label, type, length, textafter in self.cfg.user_form_fields:
596 if key in ('name', 'password', 'password2', 'email'):
597 self.make_row(_(label),
598 [ html.INPUT(type=type, size=length, name=key,
599 value=''),
600 ' ', _(textafter), ])
601 else:
602 # We are in invitation mode; create some dummy password
603 from random import choice
604 letters = "abcdefghijklmnopqrstuvwxyz"
605 letters += "0123456789"
606 pwd = ''
607 for i in range(6):
608 pwd += choice(letters)
609
610 for key, label, type, length, textafter in self.cfg.user_form_fields:
611 if key in ('name', 'password', 'password2', 'email'):
612
613 if key == 'password' or key == 'password2':
614 self.make_row(_(label),
615 [ html.INPUT(type=type, size=length, name=key,
616 value='%s' % pwd),
617 ' ', _(textafter), ])
618 else:
619 self.make_row(_(label),
620 [ html.INPUT(type=type, size=length, name=key,
621 value=''),
622 ' ', _(textafter), ])
623
624
625 if self.cfg.mail_enabled:
626 buttons.append(("account_sendmail", _('Mail me my account data')))
627
628 if create_only:
629 # We don't want to have a create profile button in invitation mode
630 #buttons = [("create_only", _('Create Profile'))]
631 buttons = []
632 if self.cfg.mail_enabled:
633 buttons.append(("create_and_mail", "%s + %s" %
634 (_('Create Profile'), _('Email'))))
635
636 buttons.append(('cancel', _('Cancel')))
637
638 # Add buttons
639 button_cell = []
640 for name, label in buttons:
641 if not name in self.cfg.user_form_remove:
642 button_cell.extend([
643 html.INPUT(type="submit", name=name, value=label),
644 ' ',
645 ])
646 self.make_row('', button_cell)
647
648 return unicode(self._form)
649
650
651 def getUserForm(request, create_only=False):
652 """ Return HTML code for the user settings. """
653 return UserSettings(request).asHTML(create_only=create_only)
654
655
656 class Login:
657 """ User login. """
658
659 def __init__(self, request):
660 """ Initialize user settings form.
661 """
662 self.request = request
663 self._ = request.getText
664 self.cfg = request.cfg
665
666 def make_row(self, label, cell, **kw):
667 """ Create a row in the form table.
668 """
669 self._table.append(html.TR().extend([
670 html.TD(**kw).extend([html.B().append(label), ' ']),
671 html.TD().extend(cell),
672 ]))
673
674
675 def asHTML(self):
676 """ Create the complete HTML form code. """
677 _ = self._
678 request = self.request
679 sn = request.getScriptname()
680 pi = request.getPathinfo()
681 action = u"%s%s" % (sn, pi)
682 userprefslink = wikiutil.getSysPage(request, "UserPreferences").link_to(request)
683 hint = _("To create an account or recover a lost password, see the %(userprefslink)s page.") % {
684 'userprefslink': userprefslink}
685 self._form = html.FORM(action=action)
686 self._table = html.TABLE(border="0")
687
688 # Use the user interface language and direction
689 lang_attr = request.theme.ui_lang_attr()
690 self._form.append(html.Raw('<div class="userprefs"%s>' % lang_attr))
691
692 self._form.append(html.INPUT(type="hidden", name="action", value="login"))
693 self._form.append(self._table)
694 self._form.append(html.P().append(hint))
695 self._form.append(html.Raw("</div>"))
696
697 self.make_row(_('Name'), [
698 html.INPUT(
699 type="text", size="32", name="name",
700 ),
701 ])
702
703 self.make_row(_('Password'), [
704 html.INPUT(
705 type="password", size="32", name="password",
706 ),
707 ])
708
709 self.make_row('', [
710 html.INPUT(
711 type="submit", name='login', value=_('Login')
712 ),
713 ])
714
715 return unicode(self._form)
716
717 def getLogin(request):
718 """ Return HTML code for the login. """
719 return Login(request).asHTML()
720
721 #############################################################################
722 ### User account administration
723 #############################################################################
724
725 def do_user_browser(request):
726 """ Browser for SystemAdmin macro. """
727 from MoinMoin.util.dataset import TupleDataset, Column
728 from MoinMoin.Page import Page
729 _ = request.getText
730
731 data = TupleDataset()
732 data.columns = [
733 #Column('id', label=('ID'), align='right'),
734 Column('name', label=('Username')),
735 Column('email', label=('Email')),
736 Column('action', label=_('Action')),
737 ]
738
739 # Iterate over users
740 for uid in user.getUserList(request):
741 account = user.User(request, uid)
742
743 userhomepage = Page(request, account.name)
744 if userhomepage.exists():
745 namelink = userhomepage.link_to(request)
746 else:
747 namelink = account.name
748
749 data.addRow((
750 #request.formatter.code(1) + uid + request.formatter.code(0),
751 request.formatter.rawHTML(namelink),
752 (request.formatter.url(1, 'mailto:' + account.email, css='mailto', do_escape=0) +
753 request.formatter.text(account.email) +
754 request.formatter.url(0)),
755 request.page.link_to(request, text=_('Mail me my account data'),
756 querystr= {"action":"userform",
757 "email": account.email,
758 "account_sendmail": "1",
759 "sysadm": "users",})
760 ))
761
762 if data:
763 from MoinMoin.widget.browser import DataBrowserWidget
764
765 browser = DataBrowserWidget(request)
766 browser.setData(data)
767 return browser.toHTML()
768
769 # No data
770 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.