summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbwarsaw2001-05-31 16:28:31 +0000
committerbwarsaw2001-05-31 16:28:31 +0000
commitffc9e2b8aa5563aae75d7ee80bf8015811df9f32 (patch)
treedebd72627f160d995db9114a1ed172c2bb5d4b48
parentf2d7e20d245aab514ff4efbb0d73bacf5dafcf1a (diff)
downloadmailman-ffc9e2b8aa5563aae75d7ee80bf8015811df9f32.tar.gz
mailman-ffc9e2b8aa5563aae75d7ee80bf8015811df9f32.tar.zst
mailman-ffc9e2b8aa5563aae75d7ee80bf8015811df9f32.zip
-rw-r--r--Mailman/Cgi/admin.py191
1 files changed, 104 insertions, 87 deletions
diff --git a/Mailman/Cgi/admin.py b/Mailman/Cgi/admin.py
index 62d1e1bb1..36bfd5ed1 100644
--- a/Mailman/Cgi/admin.py
+++ b/Mailman/Cgi/admin.py
@@ -80,17 +80,23 @@ def main():
syslog('error', 'Someone tried to access the admin interface for a '
'non-existent list: %s' % listname)
return
- #
# Now that we know what list has been requested, all subsequent admin
# pages are shown in that list's preferred language.
i18n.set_language(mlist.preferred_language)
# If the user is not authenticated, we're done.
cgidata = cgi.FieldStorage(keep_blank_values=1)
- try:
- Auth.authenticate(mlist, cgidata)
- except Auth.NotLoggedInError, e:
- Auth.loginpage(mlist, 'admin', e.message)
+
+ if not mlist.WebAuthenticate((mm_cfg.AuthListAdmin,
+ mm_cfg.AuthSiteAdmin),
+ cgidata.getvalue('adminpw', '')):
+ if cgidata.has_key('admlogin'):
+ # This is a re-authorization attempt
+ msg = Bold(FontSize('+1', _('Authorization failed.'))).Format()
+ else:
+ msg = ''
+ Auth.loginpage(mlist, 'admin', msg=msg)
return
+
# Which subcategory was requested? Default is `general'
if len(parts) == 1:
category = 'general'
@@ -100,7 +106,7 @@ def main():
category_suffix = category
# Is this a log-out request?
if category == 'logout':
- print mlist.ZapCookie('admin')
+ print mlist.ZapCookie(mm_cfg.AuthListAdmin)
Auth.loginpage(mlist, 'admin', frontpage=1)
return
# Sanity check
@@ -184,7 +190,7 @@ def main():
problem.'''))
# Glom up the results page and print it out
show_results(mlist, doc, category, category_suffix, cgidata)
- print doc.Format(bgcolor='#ffffff')
+ print doc.Format()
mlist.Save()
finally:
# Now be sure to unlock the list. It's okay if we get a signal here
@@ -211,8 +217,8 @@ def admin_overview(msg=''):
# The table that will hold everything
table = Table(border=0, width="100%")
table.AddRow([Center(Header(2, legend))])
- table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
- colspan=2, bgcolor="#99ccff")
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2,
+ bgcolor=mm_cfg.WEB_HEADERCOLOR)
# Skip any mailing list that isn't advertised.
advertised = []
listnames = Utils.list_names()
@@ -276,7 +282,7 @@ def admin_overview(msg=''):
doc.AddItem(table)
doc.AddItem('<hr>')
doc.AddItem(MailmanLogo())
- print doc.Format(bgcolor="#ffffff")
+ print doc.Format()
@@ -299,7 +305,7 @@ def option_help(mlist, varhelp):
path_info = os.environ.get('PATH_INFO')
bad = _('No valid variable details request not found: %(path_info)s')
add_error_message(doc, bad)
- print doc.Format(bgcolor='#fffff')
+ print doc.Format()
return
# Get the details about the variable
varname, kind, params, dependancies, description, elaboration = \
@@ -314,8 +320,8 @@ def option_help(mlist, varhelp):
header = Table(width='100%')
header.AddRow([Center(Header(3, legend))])
- header.AddCellInfo(max(header.GetCurrentRowIndex(), 0), 0,
- colspan=2, bgcolor="#99ccff")
+ header.AddCellInfo(header.GetCurrentRowIndex(), 0, colspan=2,
+ bgcolor=mm_cfg.WEB_HEADERCOLOR)
doc.SetTitle(_("Mailman %(varname)s List Option Help"))
doc.AddItem(header)
doc.AddItem("<b>%s</b> (%s): %s<p>" % (varname, category, description))
@@ -338,7 +344,7 @@ def option_help(mlist, varhelp):
_('return to the %(category)s options page.')))
doc.AddItem('</em>')
doc.AddItem(mlist.GetMailmanFooter())
- print doc.Format(bgcolor="#ffffff")
+ print doc.Format()
@@ -367,7 +373,7 @@ def show_results(mlist, doc, category, category_suffix, cgidata):
# The `other links' are stuff in the right column.
otherlinks = UnorderedList()
otherlinks.AddItem(Link(mlist.GetScriptURL('admindb'),
- _('Tend to pending administrative requests')))
+ _('Tend to pending moderator requests')))
otherlinks.AddItem(Link(mlist.GetScriptURL('listinfo'),
_('Go to the general list information page')))
otherlinks.AddItem(Link(mlist.GetScriptURL('edithtml'),
@@ -469,17 +475,15 @@ def show_variables(mlist, category, cgidata, doc, form):
break
table.AddRow([Center(Header(2, label))])
- table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
- colspan=2, bgcolor="#99ccff")
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2,
+ bgcolor=mm_cfg.WEB_HEADERCOLOR)
# Convenience
def column_header(table=table):
table.AddRow([Center(Bold(_('Description'))),
Center(Bold(_('Value')))])
- table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
- width='15%')
- table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 1,
- width='85%')
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0, width='15%')
+ table.AddCellInfo(table.GetCurrentRowIndex(), 1, width='85%')
did_col_header = 0
for item in options:
@@ -517,10 +521,10 @@ def add_options_table_item(mlist, category, table, item, detailsp=1):
descr = get_item_gui_description(mlist, category, varname, descr, detailsp)
val = get_item_gui_value(mlist, kind, varname, params)
table.AddRow([descr, val])
- table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 1,
- bgcolor="#cccccc")
- table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
- bgcolor="#cccccc")
+ table.AddCellInfo(table.GetCurrentRowIndex(), 1,
+ bgcolor=mm_cfg.WEB_ADMINITEM_COLOR)
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0,
+ bgcolor=mm_cfg.WEB_ADMINITEM_COLOR)
@@ -642,22 +646,22 @@ def membership_options(mlist, cgidata, doc, form):
# If we're in the list subcategory, show the membership list
if subcat == 'add':
header.AddRow([Center(Header(2, _('Mass Subscriptions')))])
- header.AddCellInfo(max(header.GetCurrentRowIndex(), 0), 0,
- colspan=2, bgcolor='#99ccff')
+ header.AddCellInfo(header.GetCurrentRowIndex(), 0, colspan=2,
+ bgcolor=mm_cfg.WEB_HEADERCOLOR)
container.AddItem(header)
mass_subscribe(mlist, container)
return container
if subcat == 'remove':
header.AddRow([Center(Header(2, _('Mass Removals')))])
- header.AddCellInfo(max(header.GetCurrentRowIndex(), 0), 0,
- colspan=2, bgcolor='#99ccff')
+ header.AddCellInfo(header.GetCurrentRowIndex(), 0, colspan=2,
+ bgcolor=mm_cfg.WEB_HEADERCOLOR)
container.AddItem(header)
mass_remove(mlist, container)
return container
# Otherwise...
header.AddRow([Center(Header(2, _('Membership List')))])
- header.AddCellInfo(max(header.GetCurrentRowIndex(), 0), 0,
- colspan=2, bgcolor='#99ccff')
+ header.AddCellInfo(header.GetCurrentRowIndex(), 0, colspan=2,
+ bgcolor=mm_cfg.WEB_HEADERCOLOR)
container.AddItem(header)
usertable = Table(width="90%", border='2')
# If there are more members than allowed by chunksize, then we split the
@@ -728,8 +732,9 @@ def membership_options(mlist, cgidata, doc, form):
else:
usertable.AddRow([Center(Italic(_('%(allcnt)s members total')))])
usertable.AddCellInfo(usertable.GetCurrentRowIndex(),
- usertable.GetCurrentCellIndex(),
- bgcolor="#cccccc", colspan=9)
+ usertable.GetCurrentCellIndex(),
+ colspan=9,
+ bgcolor=mm_cfg.WEB_ADMINITEM_COLOR)
# Add the alphabetical links
if bucket:
cells = []
@@ -745,8 +750,9 @@ def membership_options(mlist, cgidata, doc, form):
joiner = '&nbsp;'*2 + '\n'
usertable.AddRow([Center(joiner.join(cells))])
usertable.AddCellInfo(usertable.GetCurrentRowIndex(),
- usertable.GetCurrentCellIndex(),
- bgcolor="#cccccc", colspan=9)
+ usertable.GetCurrentCellIndex(),
+ colspan=9,
+ bgcolor=mm_cfg.WEB_ADMINITEM_COLOR)
usertable.AddRow([Center(h) for h in (_('member address<br>member name'),
_('subscr'), _('hide'), _('nomail'),
_('ack'), _('not metoo'),
@@ -754,7 +760,7 @@ def membership_options(mlist, cgidata, doc, form):
_('language'))])
rowindex = usertable.GetCurrentRowIndex()
for i in range(9):
- usertable.AddCellInfo(rowindex, i, bgcolor='#cccccc')
+ usertable.AddCellInfo(rowindex, i, bgcolor=mm_cfg.WEB_ADMINITEM_COLOR)
# Find the longest name in the list
if members:
longest = max([len(s) for s in members])
@@ -902,32 +908,48 @@ def mass_remove(mlist, container):
def password_inputs():
- change_pw_table = Table(bgcolor="#99cccc", border=0,
- cellspacing=0, cellpadding=2,
- valign="top")
- change_pw_table.AddRow(
- [Bold(Center(_('To Change The Administrator Password')))])
- change_pw_table.AddCellInfo(0, 0, align="left", colspan=2)
- old = Table(bgcolor="#99cccc", border=1,
- cellspacing=0, cellpadding=2, valign="top")
- old.AddRow([Label(_(' Enter current password:')),
- PasswordBox('adminpw', size=20)])
- new = Table(bgcolor="#99cccc", border=1,
- cellspacing=0, cellpadding=2, valign="top")
- new.AddRow([Label(_(' Enter new password:')),
- PasswordBox('newpw', size=20)])
- new.AddRow([Label(_("Confirm new password:")),
- PasswordBox('confirmpw', size=20)])
- change_pw_table.AddRow([old, new])
- change_pw_table.AddCellInfo(1, 0, align="left", valign="top")
- #change_pw_table.AddCellInfo(1, 1, align="left", valign="top")
- return change_pw_table
+ table = Table(cellspacing=3, cellpadding=4)
+ table.AddRow([Center(Header(2, _('Change list ownership passwords')))])
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2,
+ bgcolor=mm_cfg.WEB_HEADERCOLOR)
+ table.AddRow([_("""The <em>list administrators</em> are the people who have
+ultimate control over all parameters of this mailing list. They are able to
+change any list configuration variable available through these administration
+web pages.
+
+<p>The <em>list moderators</em> have more limited permissions; they are not
+able to change any list configuration variable, but they are allowed to tend
+to pending administration requests, including approving or rejecting held
+subscription requests, and disposing of held postings. Of course, the
+<em>list administrators</em> can also tend to pending requests.
+
+<p>In order to split the list ownership duties into administrators and
+moderators, you must set a separate moderator password in the fields below,
+and also provide the email addresses of the list moderators in the section
+above.""")])
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2)
+ # Set up the admin password table on the left
+ atable = Table(border=0, cellspacing=3, cellpadding=4,
+ bgcolor=mm_cfg.WEB_ADMINPW_COLOR)
+ atable.AddRow([Label(_('Enter new administrator password:')),
+ PasswordBox('newpw', size=20)])
+ atable.AddRow([Label(_('Confirm administator password:')),
+ PasswordBox('confirmpw', size=20)])
+ # Set up the moderator password table on the right
+ mtable = Table(border=0, cellspacing=3, cellpadding=4,
+ bgcolor=mm_cfg.WEB_ADMINPW_COLOR)
+ mtable.AddRow([Label(_('Enter new moderator password:')),
+ PasswordBox('newmodpw', size=20)])
+ mtable.AddRow([Label(_('Confirm moderator password:')),
+ PasswordBox('confirmmodpw', size=20)])
+ # Add these tables to the overall password table
+ table.AddRow([atable, mtable])
+ return table
def submit_button():
- submit = Table(bgcolor="#99ccff",
- border=0, cellspacing=0, cellpadding=2)
+ submit = Table(border=0, cellspacing=0, cellpadding=2)
submit.AddRow([Bold(SubmitButton('submit', _('Submit Your Changes')))])
submit.AddCellInfo(submit.GetCurrentRowIndex(), 0, align="middle")
return submit
@@ -991,36 +1013,31 @@ def get_valid_value(mlist, prop, my_type, val, dependant):
def change_options(mlist, category, cgidata, doc):
confirmed = 0
- if cgidata.has_key('newpw'):
- if cgidata.has_key('confirmpw'):
- if cgidata.has_key('adminpw') and cgidata['adminpw'].value:
- try:
- mlist.ConfirmAdminPassword(cgidata['adminpw'].value)
- confirmed = 1
- except Errors.MMBadPasswordError:
- add_error_message(doc,
- _('Incorrect administrator password'),
- tag='Error: ')
- if confirmed:
- new = cgidata['newpw'].value.strip()
- confirm = cgidata['confirmpw'].value.strip()
- if new == '' and confirm == '':
- add_error_message(
- doc,
- _('Empty admin passwords are not allowed'),
- tag='Error: ')
- elif new == confirm:
- mlist.password = sha.new(new).hexdigest()
- # Re-authenticate (to set new cookie)
- mlist.WebAuthenticate(password=new, cookie='admin')
- else:
- add_error_message(doc, _('Passwords did not match'),
- tag='Error: ')
+ # Handle changes to the list moderator password. Do this before checking
+ # the new admin password, since the latter will force a reauthentication.
+ new = cgidata.getvalue('newmodpw', '').strip()
+ confirm = cgidata.getvalue('confirmmodpw', '').strip()
+ if new or confirm:
+ if new == confirm:
+ mlist.mod_password = sha.new(new).hexdigest()
+ # No re-authentication necessary because the moderator's
+ # password doesn't get you into these pages.
else:
- add_error_message(doc,
- _('You must type in your new password twice'),
- tag='Error: ')
- #
+ add_error_message(
+ doc, _('Moderator passwords did not match'),
+ tag=_('Error: '))
+ # Handle changes to the list administator password
+ new = cgidata.getvalue('newpw', '').strip()
+ confirm = cgidata.getvalue('confirmpw', '').strip()
+ if new or confirm:
+ if new == confirm:
+ mlist.password = sha.new(new).hexdigest()
+ # Set new cookie
+ print mlist.MakeCookie(mm_cfg.AuthListAdmin)
+ else:
+ add_error_message(
+ doc, _('Administator passwords did not match'),
+ tag=_('Error: '))
# for some reason, the login page mangles important values for the list
# such as .real_name so we only process these changes if the category
# is not "members" and the request is not from the login page