<spanid="evennia-locks-lockhandler"></span><h1>evennia.locks.lockhandler<aclass="headerlink"href="#module-evennia.locks.lockhandler"title="Permalink to this headline">¶</a></h1>
<p>A <em>lock</em> defines access to a particular subsystem or property of
Evennia. For example, the “owner” property can be impmemented as a
lock. Or the disability to lift an object or to ban users.</p>
<p>A lock consists of three parts:</p>
<blockquote>
<div><ulclass="simple">
<li><p>access_type - this defines what kind of access this lock regulates. This
just a string.</p></li>
<li><p>function call - this is one or many calls to functions that will determine
if the lock is passed or not.</p></li>
<li><p>lock function(s). These are regular python functions with a special
set of allowed arguments. They should always return a boolean depending
on if they allow access or not.</p></li>
</ul>
</div></blockquote>
<p>A lock function is defined by existing in one of the modules
listed by settings.LOCK_FUNC_MODULES. It should also always
<p>The accessing object is the object wanting to gain access.
The accessed object is the object this lock resides on
args and kwargs will hold optional arguments and/or keyword arguments
to the function as a list and a dictionary respectively.</p>
<pclass="rubric">Example</p>
<dl>
<dt>perm(accessing_obj, accessed_obj, <ahref="#id5"><spanclass="problematic"id="id6">*</span></a>args, <ahref="#id7"><spanclass="problematic"id="id8">**</span></a>kwargs):</dt><dd><p>“Checking if the object has a particular, desired permission”
if args:</p>
<blockquote>
<div><p>desired_perm = args[0]
return desired_perm in accessing_obj.permissions.all()</p>
</div></blockquote>
<p>return False</p>
</dd>
</dl>
<p>Lock functions should most often be pretty general and ideally possible to
re-use and combine in various ways to build clever locks.</p>
<p>Lock definition (“Lock string”)</p>
<p>A lock definition is a string with a special syntax. It is added to
each object’s lockhandler, making that lock available from then on.</p>
<p>From then on, a command that wants to check for ‘edit’ access on this
object would do something like this:</p>
<blockquote>
<div><dlclass="simple">
<dt>if not target_obj.lockhandler.has_perm(caller, ‘edit’):</dt><dd><p>caller.msg(“Sorry, you cannot edit that.”)</p>
</dd>
</dl>
</div></blockquote>
<p>All objects also has a shortcut called ‘access’ that is recommended to
use instead:</p>
<blockquote>
<div><dlclass="simple">
<dt>if not target_obj.access(caller, ‘edit’):</dt><dd><p>caller.msg(“Sorry, you cannot edit that.”)</p>
</dd>
</dl>
</div></blockquote>
<p>Permissions</p>
<p>Permissions are just text strings stored in a comma-separated list on
typeclassed objects. The default perm() lock function uses them,
taking into account settings.PERMISSION_HIERARCHY. Also, the
restricted @perm command sets them, but otherwise they are identical
to any other identifier you can use.</p>
<dlclass="py class">
<dtid="evennia.locks.lockhandler.LockHandler">
<emclass="property">class </em><codeclass="sig-prename descclassname">evennia.locks.lockhandler.</code><codeclass="sig-name descname">LockHandler</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">obj</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler"title="Permalink to this definition">¶</a></dt>
<codeclass="sig-name descname">__init__</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">obj</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.__init__"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.__init__"title="Permalink to this definition">¶</a></dt>
<dd><p>Loads and pre-caches all relevant locks and their functions.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Parameters</dt>
<ddclass="field-odd"><ulclass="simple">
<li><p><strong>obj</strong> (<em>object</em>) – The object on which the lockhandler is</p></li>
<codeclass="sig-name descname">cache_lock_bypass</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">obj</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.cache_lock_bypass"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.cache_lock_bypass"title="Permalink to this definition">¶</a></dt>
<dd><p>We cache superuser bypass checks here for efficiency. This
needs to be re-run when an account is assigned to a character.
We need to grant access to superusers. We need to check both
directly on the object (accounts), through obj.account and using
the get_account() method (this sits on serversessions, in some
rare cases where a check is done before the login process has
yet been fully finalized)</p>
<dlclass="field-list simple">
<dtclass="field-odd">Parameters</dt>
<ddclass="field-odd"><p><strong>obj</strong> (<em>object</em>) – This is checked for the <strong>is_superuser</strong> property.</p>
<codeclass="sig-name descname">add</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">lockstring</span></em>, <emclass="sig-param"><spanclass="n">validate_only</span><spanclass="o">=</span><spanclass="default_value">False</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.add"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.add"title="Permalink to this definition">¶</a></dt>
<dd><p>Add a new lockstring to handler.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Parameters</dt>
<ddclass="field-odd"><ulclass="simple">
<li><p><strong>lockstring</strong> (<em>str</em><em> or </em><em>list</em>) – A string on the form
<codeclass="sig-name descname">validate</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">lockstring</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.validate"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.validate"title="Permalink to this definition">¶</a></dt>
<dd><p>Validate lockstring syntactically, without saving it.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Parameters</dt>
<ddclass="field-odd"><p><strong>lockstring</strong> (<em>str</em>) – Lockstring to validate.</p>
</dd>
<dtclass="field-even">Returns</dt>
<ddclass="field-even"><p><em>valid (bool)</em>– If validation passed or not.</p>
<codeclass="sig-name descname">replace</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">lockstring</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.replace"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.replace"title="Permalink to this definition">¶</a></dt>
<dd><p>Replaces the lockstring entirely.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Parameters</dt>
<ddclass="field-odd"><p><strong>lockstring</strong> (<em>str</em>) – The new lock definition.</p>
</dd>
<dtclass="field-even">Returns</dt>
<ddclass="field-even"><p><em>success (bool)</em>– False if an error occurred.</p>
</dd>
<dtclass="field-odd">Raises</dt>
<ddclass="field-odd"><p><aclass="reference internal"href="#evennia.locks.lockhandler.LockException"title="evennia.locks.lockhandler.LockException"><strong>LockException</strong></a>– If a critical error occurred.
<codeclass="sig-name descname">get</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">access_type</span><spanclass="o">=</span><spanclass="default_value">None</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.get"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.get"title="Permalink to this definition">¶</a></dt>
<dd><p>Get the full lockstring or the lockstring of a particular
<codeclass="sig-name descname">all</code><spanclass="sig-paren">(</span><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.all"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.all"title="Permalink to this definition">¶</a></dt>
<dd><p>Return all lockstrings</p>
<dlclass="field-list simple">
<dtclass="field-odd">Returns</dt>
<ddclass="field-odd"><p><em>lockstrings (list)</em>– All separate lockstrings</p>
<codeclass="sig-name descname">remove</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">access_type</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.remove"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.remove"title="Permalink to this definition">¶</a></dt>
<dd><p>Remove a particular lock from the handler</p>
<dlclass="field-list simple">
<dtclass="field-odd">Parameters</dt>
<ddclass="field-odd"><p><strong>access_type</strong> (<em>str</em>) – The type of lock to remove.</p>
<codeclass="sig-name descname">delete</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">access_type</span></em><spanclass="sig-paren">)</span><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.delete"title="Permalink to this definition">¶</a></dt>
<dd><p>Remove a particular lock from the handler</p>
<dlclass="field-list simple">
<dtclass="field-odd">Parameters</dt>
<ddclass="field-odd"><p><strong>access_type</strong> (<em>str</em>) – The type of lock to remove.</p>
<codeclass="sig-name descname">clear</code><spanclass="sig-paren">(</span><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.clear"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.clear"title="Permalink to this definition">¶</a></dt>
<codeclass="sig-name descname">reset</code><spanclass="sig-paren">(</span><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.reset"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.reset"title="Permalink to this definition">¶</a></dt>
<dd><p>Set the reset flag, so the the lock will be re-cached at next
checking. This is usually called by @reload.</p>
<codeclass="sig-name descname">append</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">access_type</span></em>, <emclass="sig-param"><spanclass="n">lockstring</span></em>, <emclass="sig-param"><spanclass="n">op</span><spanclass="o">=</span><spanclass="default_value">'or'</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.append"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.append"title="Permalink to this definition">¶</a></dt>
<dd><p>Append a lock definition to access_type if it doesn’t already exist.</p>
<codeclass="sig-name descname">check</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">accessing_obj</span></em>, <emclass="sig-param"><spanclass="n">access_type</span></em>, <emclass="sig-param"><spanclass="n">default</span><spanclass="o">=</span><spanclass="default_value">False</span></em>, <emclass="sig-param"><spanclass="n">no_superuser_bypass</span><spanclass="o">=</span><spanclass="default_value">False</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.check"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.check"title="Permalink to this definition">¶</a></dt>
<dd><p>Checks a lock of the correct type by passing execution off to
the lock function(s).</p>
<dlclass="field-list simple">
<dtclass="field-odd">Parameters</dt>
<ddclass="field-odd"><ulclass="simple">
<li><p><strong>accessing_obj</strong> (<em>object</em>) – The object seeking access.</p></li>
<li><p><strong>access_type</strong> (<em>str</em>) – The type of access wanted.</p></li>
<li><p><strong>default</strong> (<em>bool</em><em>, </em><em>optional</em>) – If no suitable lock type is
found, default to this result.</p></li>
<li><p><strong>no_superuser_bypass</strong> (<em>bool</em>) – Don’t use this unless you
really, really need to, it makes supersusers susceptible
to the lock check.</p></li>
</ul>
</dd>
</dl>
<pclass="rubric">Notes</p>
<p>A lock is executed in the follwoing way:</p>
<p>Parsing the lockstring, we (during cache) extract the valid
lock functions and store their function objects in the right
order along with their args/kwargs. These are now executed in
sequence, creating a list of True/False values. This is put
into the evalstring, which is a string of AND/OR/NOT entries
separated by placeholders where each function result should
go. We just put those results in and evaluate the string to
get a final, combined True/False value for the lockstring.</p>
<p>The important bit with this solution is that the full
lockstring is never blindly evaluated, and thus there (should
be) no way to sneak in malign code in it. Only “safe” lock
functions (as defined by your settings) are executed.</p>
<codeclass="sig-name descname">check_lockstring</code><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n">accessing_obj</span></em>, <emclass="sig-param"><spanclass="n">lockstring</span></em>, <emclass="sig-param"><spanclass="n">no_superuser_bypass</span><spanclass="o">=</span><spanclass="default_value">False</span></em>, <emclass="sig-param"><spanclass="n">default</span><spanclass="o">=</span><spanclass="default_value">False</span></em>, <emclass="sig-param"><spanclass="n">access_type</span><spanclass="o">=</span><spanclass="default_value">None</span></em><spanclass="sig-paren">)</span><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockHandler.check_lockstring"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockHandler.check_lockstring"title="Permalink to this definition">¶</a></dt>
<dd><p>Do a direct check against a lockstring (‘atype:func()..’),
without any intermediary storage on the accessed object.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Parameters</dt>
<ddclass="field-odd"><ulclass="simple">
<li><p><strong>accessing_obj</strong> (<em>object</em><em> or </em><em>None</em>) – The object seeking access.
Importantly, this can be left unset if the lock functions
don’t access it, no updating or storage of locks are made
against this object in this method.</p></li>
<li><p><strong>lockstring</strong> (<em>str</em>) – Lock string to check, on the form
<strong>“access_type:lock_definition”</strong> where the <strong>access_type</strong>
part can potentially be set to a dummy value to just check
a lock condition.</p></li>
<li><p><strong>no_superuser_bypass</strong> (<em>bool</em><em>, </em><em>optional</em>) – Force superusers to heed lock.</p></li>
<li><p><strong>default</strong> (<em>bool</em><em>, </em><em>optional</em>) – Fallback result to use if <strong>access_type</strong> is set
but no such <strong>access_type</strong> is found in the given <strong>lockstring</strong>.</p></li>
<li><p><strong>access_type</strong> (<em>str</em><em>, </em><em>bool</em>) – If set, only this access_type will be looked up
among the locks defined by <strong>lockstring</strong>.</p></li>
</ul>
</dd>
<dtclass="field-even">Returns</dt>
<ddclass="field-even"><p><em>access (bool)</em>– If check is passed or not.</p>
</dd>
</dl>
</dd></dl>
</dd></dl>
<dlclass="py exception">
<dtid="evennia.locks.lockhandler.LockException">
<emclass="property">exception </em><codeclass="sig-prename descclassname">evennia.locks.lockhandler.</code><codeclass="sig-name descname">LockException</code><aclass="reference internal"href="../_modules/evennia/locks/lockhandler.html#LockException"><spanclass="viewcode-link">[source]</span></a><aclass="headerlink"href="#evennia.locks.lockhandler.LockException"title="Permalink to this definition">¶</a></dt>