MoinMoin.security package

Submodules

MoinMoin.security.textcha module

MoinMoin - Text CAPTCHAs

This is just asking some (admin configured) questions and checking if the answer is as expected. It is up to the wiki admin to setup questions that a bot can not easily answer, but humans can. It is recommended to setup SITE SPECIFIC questions and not to share the questions with other sites (if everyone asks the same questions / expects the same answers, spammers could adapt to that).

TODO:

  • roundtrip the question in some other way, make sure a q/a pair in the POST is for the q in the GET before
  • make some nice CSS
  • make similar changes to GUI editor
class MoinMoin.security.textcha.TextCha(form)[source]

Bases: object

Text CAPTCHA support

amend_form()[source]

Amend the form by doing the following:

  • set the question if textcha is enabled, or
  • make the fields optional if it isn’t.
init_qa(question=None)[source]

Initialize the question / answer.

Parameters:question – If given, the given question will be used. If None, a new question will be generated.
is_enabled()[source]

check if textchas are enabled.

They can be disabled for all languages if you use textchas = None or = {}, also they can be disabled for some specific language, like:

textchas = {
    'en': {
        'some question': 'some answer',
        # ...
    },
    'de': {}, # having no questions for 'de' means disabling textchas for 'de'
    # ...
}
class MoinMoin.security.textcha.TextChaValid(**kw)[source]

Bases: flatland.validation.base.Validator

Validator for TextChas

textcha_incorrect_msg = l'The entered TextCha was incorrect.'
textcha_invalid_msg = l'The TextCha question is invalid or has expired. Please try again.'
validate(element, state)[source]
class MoinMoin.security.textcha.TextChaizedForm(value=Unspecified, **kw)[source]

Bases: flatland.schema.declarative.Form

a form providing TextCha support

field_schema = [<class 'flatland.schema.declarative.String'>, <class 'flatland.schema.declarative.String'>]

MoinMoin.security.ticket module

MoinMoin - Tickets

Tickets are usually used in forms to make sure that form submissions are in response to a form the same user got from moin.

MoinMoin.security.ticket.checkTicket(ticket, **kw)[source]

Check validity of a previously created ticket.

Parameters:
  • ticket – a str as created by createTicket
  • kw – see createTicket kw
MoinMoin.security.ticket.createTicket(tm=None, **kw)[source]

Create a ticket using a configured secret

Parameters:
  • tm – unix timestamp (optional, uses current time if not given)
  • kw – key/value stuff put into ticket, must be same for ticket creation and ticket check

Module contents

MoinMoin - Wiki Security Interface and Access Control Lists

class MoinMoin.security.ACLStringIterator(rights, aclstring)[source]

Bases: object

Iterator for acl string

Parse acl string and return the next entry on each call to next. Implements the Iterator protocol.

Usage:

iter = ACLStringIterator(rights_valid, 'user name:right')
for modifier, entries, rights in iter:
    # process data
next()[source]

Return the next values from the acl string

When the iterator is finished and you try to call next, it raises a StopIteration. The iterator finishes as soon as the string is fully parsed or can not be parsed any more.

Return type:3 tuple - (modifier, [entry, ..], [right, ..])
Returns:values for one item in an acl string
class MoinMoin.security.AccessControlList(lines=[], default='', valid=None)[source]

Bases: MoinMoin.util.pysupport.AutoNe

Access Control List - controls who may do what.

Syntax of an ACL string:

[+|-]User[,User,...]:[right[,right,...]] [[+|-]SomeGroup:...] ... ... [[+|-]Known:...] [[+|-]All:...]

“User” is a user name and triggers only if the user matches. Any name can be used in acl lines, including names with spaces using exotic languages.

“SomeGroup” is a group name. The group defines its members somehow, e.g. on a wiki page of this name as first level list with the group members’ names.

“Known” is a special group containing all valid / known users.

“All” is a special group containing all users (Known and Anonymous users).

“right” may be an arbitrary word like read, write or admin. Only valid words are accepted, others are ignored (see valid param). It is allowed to specify no rights, which means that no rights are given.

How ACL is processed

When some user is trying to access some ACL-protected resource, the ACLs will be processed in the order they are found. The first matching ACL will tell if the user has access to that resource or not.

For example, the following ACL tells that SomeUser is able to read and write the resources protected by that ACL, while any member of SomeGroup (besides SomeUser, if part of that group) may also admin that, and every other user is able to read it.

SomeUser:read,write SomeGroup:read,write,admin All:read

In this example, SomeUser can read and write but can not admin items. Rights that are NOT specified on the right list are automatically set to NO.

Using Prefixes

To make the system more flexible, there are also two modifiers: the prefixes “+” and “-”.

+SomeUser:read -OtherUser:write

The acl line above will grant SomeUser read right, and deny OtherUser write right, but will NOT block automatically all other rights for these users. For example, if SomeUser asks to write, the above acl line does not define if he can or can not write. He will be able to write if the acls checked before or afterwards allow this (see configuration options).

Using prefixes, this acl line:

SomeUser:read,write SomeGroup:read,write,admin All:read

Can be written as:

-SomeUser:admin SomeGroup:read,write,admin All:read

Or even:

+All:read -SomeUser:admin SomeGroup:read,write,admin

Note that you probably would not want to use the second and third examples in ACL entries of some item. They are very useful in the wiki configuration though.

has_acl()[source]

Checks whether we have a real acl here.

may(name, dowhat)[source]

May <name> <dowhat>? Returns boolean answer.

Note: this just checks THIS ACL, the before/default/after ACL must
be handled elsewhere, if needed.
special_users = ['All', 'Known', 'Trusted']
class MoinMoin.security.DefaultSecurityPolicy(user)[source]

Bases: object

Basic interface for user permissions and system policy.

If you want to define your own policy, inherit from DefaultSecurityPolicy, so that when new permissions are defined later, you will inherit their default behaviour.

Then assign your new class (not an instance!) to “SecurityPolicy” in the wiki configuration.

When subclassing this class, you must extend the class methods, not replace them, or you might break the ACLs in the wiki.

Correct subclassing looks like this:

class MySecPol(DefaultSecurityPolicy):
    def read(self, itemname):
        # Your special security rule
        if something:
            return False

        # Do not just return True or you break (ignore) ACLs!
        # This call will return correct permissions by checking ACLs:
        return super(MySecPol, self).read(itemname)
read(itemname)[source]

read permission is special as we have 2 kinds of read capabilities:

  • READ - gives permission to read, unconditionally
  • PUBREAD - gives permission to read, when published
MoinMoin.security.require_permission(permission)[source]

view decorator to require a specific permission

if the permission is not granted, abort with 403