ApproveChanges

Changeset

21:7e7687892a5e
2011-10-16 Paul Boddie raw files shortlog changelog graph Added user approval when approving their changes. Removed the obsolete secret key acquisition function in the library since page signing has not been done for several revisions.
ApproveChangesSupport.py (file) actions/ApproveChanges.py (file) docs/COPYING.txt (file) to-do/approve-user.txt (file)
     1.1 --- a/ApproveChangesSupport.py	Sun Oct 16 17:57:55 2011 +0200
     1.2 +++ b/ApproveChangesSupport.py	Sun Oct 16 19:18:44 2011 +0200
     1.3 @@ -12,17 +12,21 @@
     1.4      default "PageReviewersGroup").
     1.5  
     1.6      @copyright: 2011 by Paul Boddie <paul@boddie.org.uk>
     1.7 +                2003-2007 MoinMoin:ThomasWaldmann,
     1.8 +                2003 by Gustavo Niemeyer
     1.9      @license: GNU GPL (v2 or later), see COPYING.txt for details.
    1.10  """
    1.11  
    1.12  from MoinMoin import user
    1.13  from MoinMoin.Page import Page
    1.14 +from MoinMoin.PageEditor import PageEditor
    1.15  from MoinMoin.wikiutil import escape
    1.16  import re
    1.17  
    1.18  __version__ = "0.1"
    1.19  
    1.20  space_pattern = re.compile("(\s+)")
    1.21 +group_member_pattern = re.compile(ur'^ \* +(?:\[\[)?(?P<member>.+?)(?:\]\])? *$', re.MULTILINE | re.UNICODE)
    1.22  
    1.23  def get_queued_changes_page(request):
    1.24      return getattr(request.cfg, "queued_changes_page", "ApprovalQueue")
    1.25 @@ -36,9 +40,6 @@
    1.26  def get_queued_changes_user(request):
    1.27      return getattr(request.cfg, "queued_changes_user", "ApprovalQueueUser")
    1.28  
    1.29 -def get_secret_key(request):
    1.30 -    return request.cfg.secrets["wikiutil/tickets"]
    1.31 -
    1.32  def is_reviewer(request):
    1.33      return request.user.valid and (
    1.34          has_member(request, get_approved_editors_group(request), request.user.name) or \
    1.35 @@ -46,9 +47,12 @@
    1.36  
    1.37  def is_approved(request):
    1.38      return request.user.valid and (
    1.39 -        has_member(request, get_approved_editors_group(request), request.user.name) or \
    1.40 +        user_is_approved(request, request.user.name) or \
    1.41          request.user.isSuperUser())
    1.42  
    1.43 +def user_is_approved(request, username):
    1.44 +    return has_member(request, get_approved_editors_group(request), username)
    1.45 +
    1.46  def is_queued_changes_user(request):
    1.47      return request.user.valid and request.user.name == get_queued_changes_user(request)
    1.48  
    1.49 @@ -168,6 +172,36 @@
    1.50  
    1.51      return "\n".join(new_body), found
    1.52  
    1.53 +def add_to_group_page(request, username, groupname):
    1.54 +
    1.55 +    """
    1.56 +    Using the 'request', add 'username' to 'groupname', changing the group page.
    1.57 +    This is not the same as adding a member to the group, but it will have the
    1.58 +    same effect when the group is rescanned.
    1.59 +    """
    1.60 +
    1.61 +    _ = request.getText
    1.62 +
    1.63 +    page = PageEditor(request, groupname)
    1.64 +    body = page.get_raw_body()
    1.65 +    match = None
    1.66 +
    1.67 +    # Find the last matching span.
    1.68 +
    1.69 +    for match in group_member_pattern.finditer(body):
    1.70 +        start, end = match.span()
    1.71 +
    1.72 +    # Add a group member to the body.
    1.73 +
    1.74 +    entry = ("\n * %s" % username)
    1.75 +
    1.76 +    if match:
    1.77 +        body = body[:end] + entry + body[end:]
    1.78 +    else:
    1.79 +        body += entry
    1.80 +
    1.81 +    page.saveText(body, 0, comment=_("Added %s to the approved editors group.") % username)
    1.82 +
    1.83  # Utility classes and associated functions.
    1.84  # NOTE: These are a subset of EventAggregatorSupport.
    1.85  
     2.1 --- a/actions/ApproveChanges.py	Sun Oct 16 17:57:55 2011 +0200
     2.2 +++ b/actions/ApproveChanges.py	Sun Oct 16 19:18:44 2011 +0200
     2.3 @@ -71,7 +71,12 @@
     2.4          current_rev = target_page.current_rev()
     2.5          parent_rev = int(directives.get("parent-revision", current_rev))
     2.6  
     2.7 +        # Get the user who submitted the changes.
     2.8 +
     2.9 +        username = directives.get("unapproved-user")
    2.10 +
    2.11          d = {
    2.12 +            "approval_label"        : escape(_("Make %s an approved user") % username),
    2.13              "buttons_html"          : buttons_html,
    2.14              "prompt"                : escape(_("Approve the displayed page version?")),
    2.15              "rev"                   : escattr(rev),
    2.16 @@ -92,6 +97,12 @@
    2.17          <td><em>%(notice)s</em></td>
    2.18      </tr>''' % d
    2.19  
    2.20 +        if username and not user_is_approved(request, username):
    2.21 +            html += '''
    2.22 +    <tr>
    2.23 +        <td><input name="approve" type="checkbox" value="true" /> %(approval_label)s</td>
    2.24 +    </tr>''' % d
    2.25 +
    2.26          html += '''
    2.27      <tr>
    2.28          <td class="buttons">
    2.29 @@ -112,6 +123,7 @@
    2.30  
    2.31          _ = self._
    2.32          request = self.request
    2.33 +        form = get_form(request)
    2.34  
    2.35          # Make sure that only suitably privileged users can perform this action.
    2.36  
    2.37 @@ -144,6 +156,15 @@
    2.38          current_rev = target_page.current_rev()
    2.39          parent_rev = int(directives.get("parent-revision", current_rev))
    2.40  
    2.41 +        # Get the user who submitted the changes.
    2.42 +
    2.43 +        username = directives.get("unapproved-user")
    2.44 +
    2.45 +        # Approve the user if requested, regardless of what happens below.
    2.46 +
    2.47 +        if username and form.get("approve", ["false"])[0] == "true":
    2.48 +            add_to_group_page(request, username, get_approved_editors_group(request))
    2.49 +
    2.50          # Where the parent revision differs from the current revision of the
    2.51          # page, attempt to merge the changes.
    2.52  
    2.53 @@ -187,7 +208,6 @@
    2.54  
    2.55              # Switch user if a specific user was recorded.
    2.56  
    2.57 -            username = directives.get("unapproved-user")
    2.58              if username:
    2.59                  new_user = get_user(request, username)
    2.60              else:
     3.1 --- a/docs/COPYING.txt	Sun Oct 16 17:57:55 2011 +0200
     3.2 +++ b/docs/COPYING.txt	Sun Oct 16 19:18:44 2011 +0200
     3.3 @@ -3,6 +3,12 @@
     3.4  
     3.5  Copyright (C) 2011 Paul Boddie <paul@boddie.org.uk>
     3.6  
     3.7 +Group page parsing and manipulation involves code from the MoinMoin.wikidicts
     3.8 +module:
     3.9 +
    3.10 +Copyright (C) 2003-2007 MoinMoin:ThomasWaldmann
    3.11 +Copyright (C) 2003 by Gustavo Niemeyer
    3.12 +
    3.13  This software is free software; you can redistribute it and/or
    3.14  modify it under the terms of the GNU General Public License as
    3.15  published by the Free Software Foundation; either version 2 of
     4.1 --- a/to-do/approve-user.txt	Sun Oct 16 17:57:55 2011 +0200
     4.2 +++ b/to-do/approve-user.txt	Sun Oct 16 19:18:44 2011 +0200
     4.3 @@ -1,3 +1,8 @@
     4.4 -Permit the approval of users when approving their edits. The user will be added
     4.5 +Some testing around the immediate effect of approving users needs to be done.
     4.6 +The MoinMoin 1.8.x API allows users to be added to groups for immediate effect,
     4.7 +but the API in 1.9.x is more complicated. This may well affect mod_wsgi and
     4.8 +other "persistent server" deployments, not CGI.
     4.9 +
    4.10 +(Permit the approval of users when approving their edits. The user will be added
    4.11  to the ApprovedGroup if the reviewer indicates that they should henceforth be
    4.12 -considered as a trusted user in the Wiki.
    4.13 +considered as a trusted user in the Wiki.)