mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 22:06:30 +01:00
496 lines
No EOL
47 KiB
HTML
496 lines
No EOL
47 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
|
||
<title>Locks — Evennia 1.0-dev documentation</title>
|
||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
<script src="../_static/language_data.js"></script>
|
||
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
|
||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||
<link rel="index" title="Index" href="../genindex.html" />
|
||
<link rel="search" title="Search" href="../search.html" />
|
||
</head><body>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="General Index"
|
||
accesskey="I">index</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">Locks</a></li>
|
||
</ul>
|
||
<div class="develop">develop branch</div>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section class="tex2jax_ignore mathjax_ignore" id="locks">
|
||
<h1>Locks<a class="headerlink" href="#locks" title="Permalink to this headline">¶</a></h1>
|
||
<p>For most games it is a good idea to restrict what people can do. In Evennia such restrictions are
|
||
applied and checked by something called <em>locks</em>. All Evennia entities (<a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a>,
|
||
<a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc std std-doc">Scripts</span></a>, <a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>, <a class="reference internal" href="Help-System.html"><span class="doc std std-doc">Help System</span></a>,
|
||
<a class="reference internal" href="Msg.html"><span class="doc std std-doc">messages</span></a> and <a class="reference internal" href="Channels.html"><span class="doc std std-doc">channels</span></a>) are accessed through locks.</p>
|
||
<p>A lock can be thought of as an “access rule” restricting a particular use of an Evennia entity.
|
||
Whenever another entity wants that kind of access the lock will analyze that entity in different
|
||
ways to determine if access should be granted or not. Evennia implements a “lockdown” philosophy -
|
||
all entities are inaccessible unless you explicitly define a lock that allows some or full access.</p>
|
||
<p>Let’s take an example: An object has a lock on itself that restricts how people may “delete” that
|
||
object. Apart from knowing that it restricts deletion, the lock also knows that only players with
|
||
the specific ID of, say, <code class="docutils literal notranslate"><span class="pre">34</span></code> are allowed to delete it. So whenever a player tries to run <code class="docutils literal notranslate"><span class="pre">delete</span></code>
|
||
on the object, the <code class="docutils literal notranslate"><span class="pre">delete</span></code> command makes sure to check if this player is really allowed to do so.
|
||
It calls the lock, which in turn checks if the player’s id is <code class="docutils literal notranslate"><span class="pre">34</span></code>. Only then will it allow <code class="docutils literal notranslate"><span class="pre">delete</span></code>
|
||
to go on with its job.</p>
|
||
<section id="setting-and-checking-a-lock">
|
||
<h2>Setting and checking a lock<a class="headerlink" href="#setting-and-checking-a-lock" title="Permalink to this headline">¶</a></h2>
|
||
<p>The in-game command for setting locks on objects is <code class="docutils literal notranslate"><span class="pre">lock</span></code>:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > lock obj = <lockstring>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre"><lockstring></span></code> is a string of a certain form that defines the behaviour of the lock. We will go
|
||
into more detail on how <code class="docutils literal notranslate"><span class="pre"><lockstring></span></code> should look in the next section.</p>
|
||
<p>Code-wise, Evennia handles locks through what is usually called <code class="docutils literal notranslate"><span class="pre">locks</span></code> on all relevant entities.
|
||
This is a handler that allows you to add, delete and check locks.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">myobj</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="o"><</span><span class="n">lockstring</span><span class="o">></span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>One can call <code class="docutils literal notranslate"><span class="pre">locks.check()</span></code> to perform a lock check, but to hide the underlying implementation all
|
||
objects also have a convenience function called <code class="docutils literal notranslate"><span class="pre">access</span></code>. This should preferably be used. In the
|
||
example below, <code class="docutils literal notranslate"><span class="pre">accessing_obj</span></code> is the object requesting the ‘delete’ access whereas <code class="docutils literal notranslate"><span class="pre">obj</span></code> is the
|
||
object that might get deleted. This is how it would look (and does look) from inside the <code class="docutils literal notranslate"><span class="pre">delete</span></code>
|
||
command:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">accessing_obj</span><span class="p">,</span> <span class="s1">'delete'</span><span class="p">):</span>
|
||
<span class="n">accessing_obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Sorry, you may not delete that."</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="defining-locks">
|
||
<h2>Defining locks<a class="headerlink" href="#defining-locks" title="Permalink to this headline">¶</a></h2>
|
||
<p>Defining a lock (i.e. an access restriction) in Evennia is done by adding simple strings of lock
|
||
definitions to the object’s <code class="docutils literal notranslate"><span class="pre">locks</span></code> property using <code class="docutils literal notranslate"><span class="pre">obj.locks.add()</span></code>.</p>
|
||
<p>Here are some examples of lock strings (not including the quotes):</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">delete</span><span class="p">:</span><span class="nb">id</span><span class="p">(</span><span class="mi">34</span><span class="p">)</span> <span class="c1"># only allow obj #34 to delete</span>
|
||
<span class="n">edit</span><span class="p">:</span><span class="nb">all</span><span class="p">()</span> <span class="c1"># let everyone edit</span>
|
||
<span class="c1"># only those who are not "very_weak" or are Admins may pick this up</span>
|
||
<span class="n">get</span><span class="p">:</span> <span class="ow">not</span> <span class="n">attr</span><span class="p">(</span><span class="n">very_weak</span><span class="p">)</span> <span class="ow">or</span> <span class="n">perm</span><span class="p">(</span><span class="n">Admin</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Formally, a lockstring has the following syntax:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">access_type</span><span class="p">:</span> <span class="p">[</span><span class="n">NOT</span><span class="p">]</span> <span class="n">lockfunc1</span><span class="p">([</span><span class="n">arg1</span><span class="p">,</span><span class="o">..</span><span class="p">])</span> <span class="p">[</span><span class="n">AND</span><span class="o">|</span><span class="n">OR</span><span class="p">]</span> <span class="p">[</span><span class="n">NOT</span><span class="p">]</span> <span class="n">lockfunc2</span><span class="p">([</span><span class="n">arg1</span><span class="p">,</span><span class="o">...</span><span class="p">])</span> <span class="p">[</span><span class="o">...</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>where <code class="docutils literal notranslate"><span class="pre">[]</span></code> marks optional parts. <code class="docutils literal notranslate"><span class="pre">AND</span></code>, <code class="docutils literal notranslate"><span class="pre">OR</span></code> and <code class="docutils literal notranslate"><span class="pre">NOT</span></code> are not case sensitive and excess spaces are
|
||
ignored. <code class="docutils literal notranslate"><span class="pre">lockfunc1,</span> <span class="pre">lockfunc2</span></code> etc are special <em>lock functions</em> available to the lock system.</p>
|
||
<p>So, a lockstring consists of the type of restriction (the <code class="docutils literal notranslate"><span class="pre">access_type</span></code>), a colon (<code class="docutils literal notranslate"><span class="pre">:</span></code>) and then an
|
||
expression involving function calls that determine what is needed to pass the lock. Each function
|
||
returns either <code class="docutils literal notranslate"><span class="pre">True</span></code> or <code class="docutils literal notranslate"><span class="pre">False</span></code>. <code class="docutils literal notranslate"><span class="pre">AND</span></code>, <code class="docutils literal notranslate"><span class="pre">OR</span></code> and <code class="docutils literal notranslate"><span class="pre">NOT</span></code> work as they do normally in Python. If the
|
||
total result is <code class="docutils literal notranslate"><span class="pre">True</span></code>, the lock is passed.</p>
|
||
<p>You can create several lock types one after the other by separating them with a semicolon (<code class="docutils literal notranslate"><span class="pre">;</span></code>) in
|
||
the lockstring. The string below yields the same result as the previous example:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>delete:id(34);edit:all();get: not attr(very_weak) or perm(Admin)
|
||
</pre></div>
|
||
</div>
|
||
<section id="valid-access-types">
|
||
<h3>Valid access_types<a class="headerlink" href="#valid-access-types" title="Permalink to this headline">¶</a></h3>
|
||
<p>An <code class="docutils literal notranslate"><span class="pre">access_type</span></code>, the first part of a lockstring, defines what kind of capability a lock controls,
|
||
such as “delete” or “edit”. You may in principle name your <code class="docutils literal notranslate"><span class="pre">access_type</span></code> anything as long as it is
|
||
unique for the particular object. The name of the access types is not case-sensitive.</p>
|
||
<p>If you want to make sure the lock is used however, you should pick <code class="docutils literal notranslate"><span class="pre">access_type</span></code> names that you (or
|
||
the default command set) actually checks for, as in the example of <code class="docutils literal notranslate"><span class="pre">delete</span></code> above that uses the
|
||
‘delete’ <code class="docutils literal notranslate"><span class="pre">access_type</span></code>.</p>
|
||
<p>Below are the access_types checked by the default commandset.</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="Commands.html"><span class="doc std std-doc">Commands</span></a></p>
|
||
<ul>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">cmd</span></code> - this defines who may call this command at all.</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="Objects.html"><span class="doc std std-doc">Objects</span></a>:</p>
|
||
<ul>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">control</span></code> - who is the “owner” of the object. Can set locks, delete it etc. Defaults to the
|
||
creator of the object.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">call</span></code> - who may call Object-commands stored on this Object except for the Object itself. By
|
||
default, Objects share their Commands with anyone in the same location (e.g. so you can ‘press’ a
|
||
<code class="docutils literal notranslate"><span class="pre">Button</span></code> object in the room). For Characters and Mobs (who likely only use those Commands for
|
||
themselves and don’t want to share them) this should usually be turned off completely, using
|
||
something like <code class="docutils literal notranslate"><span class="pre">call:false()</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">examine</span></code> - who may examine this object’s properties.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">delete</span></code> - who may delete the object.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">edit</span></code> - who may edit properties and attributes of the object.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">view</span></code> - if the <code class="docutils literal notranslate"><span class="pre">look</span></code> command will display/list this object</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">get</span></code>- who may pick up the object and carry it around.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">puppet</span></code> - who may “become” this object and control it as their “character”.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">attrcreate</span></code> - who may create new attributes on the object (default True)</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="Objects.html#characters"><span class="std std-doc">Characters</span></a>:</p>
|
||
<ul>
|
||
<li><p>Same as for Objects</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="Objects.html#exits"><span class="std std-doc">Exits</span></a>:</p>
|
||
<ul>
|
||
<li><p>Same as for Objects</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">traverse</span></code> - who may pass the exit.</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="Accounts.html"><span class="doc std std-doc">Accounts</span></a>:</p>
|
||
<ul>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">examine</span></code> - who may examine the account’s properties.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">delete</span></code> - who may delete the account.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">edit</span></code> - who may edit the account’s attributes and properties.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">msg</span></code> - who may send messages to the account.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">boot</span></code> - who may boot the account.</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attributes</span></a>: (only checked by <code class="docutils literal notranslate"><span class="pre">obj.secure_attr</span></code>)</p>
|
||
<ul>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">attrread</span></code> - see/access attribute</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">attredit</span></code> - change/delete attribute</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="Channels.html"><span class="doc std std-doc">Channels</span></a>:</p>
|
||
<ul>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">control</span></code> - who is administrating the channel. This means the ability to delete the channel,
|
||
boot listeners etc.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">send</span></code> - who may send to the channel.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">listen</span></code> - who may subscribe and listen to the channel.</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="Help-System.html"><span class="doc std std-doc">HelpEntry</span></a>:</p>
|
||
<ul>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">examine</span></code> - who may view this help entry (usually everyone)</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">edit</span></code> - who may edit this help entry.</p></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<p>So to take an example, whenever an exit is to be traversed, a lock of the type <em>traverse</em> will be
|
||
checked. Defining a suitable lock type for an exit object would thus involve a lockstring <code class="docutils literal notranslate"><span class="pre">traverse:</span> <span class="pre"><lock</span> <span class="pre">functions></span></code>.</p>
|
||
</section>
|
||
<section id="custom-access-types">
|
||
<h3>Custom access_types<a class="headerlink" href="#custom-access-types" title="Permalink to this headline">¶</a></h3>
|
||
<p>As stated above, the <code class="docutils literal notranslate"><span class="pre">access_type</span></code> part of the lock is simply the ‘name’ or ‘type’ of the lock. The
|
||
text is an arbitrary string that must be unique for an object. If adding a lock with the same
|
||
<code class="docutils literal notranslate"><span class="pre">access_type</span></code> as one that already exists on the object, the new one override the old one.</p>
|
||
<p>For example, if you wanted to create a bulletin board system and wanted to restrict who can either
|
||
read a board or post to a board. You could then define locks such as:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">obj</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"read:perm(Player);post:perm(Admin)"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This will create a ‘read’ access type for Characters having the <code class="docutils literal notranslate"><span class="pre">Player</span></code> permission or above and a
|
||
‘post’ access type for those with <code class="docutils literal notranslate"><span class="pre">Admin</span></code> permissions or above (see below how the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> lock
|
||
function works). When it comes time to test these permissions, simply check like this (in this
|
||
example, the <code class="docutils literal notranslate"><span class="pre">obj</span></code> may be a board on the bulletin board system and <code class="docutils literal notranslate"><span class="pre">accessing_obj</span></code> is the player
|
||
trying to read the board):</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">accessing_obj</span><span class="p">,</span> <span class="s1">'read'</span><span class="p">):</span>
|
||
<span class="n">accessing_obj</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Sorry, you may not read that."</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="lock-functions">
|
||
<h3>Lock functions<a class="headerlink" href="#lock-functions" title="Permalink to this headline">¶</a></h3>
|
||
<p>A lock function is a normal Python function put in a place Evennia looks for such functions. The
|
||
modules Evennia looks at is the list <code class="docutils literal notranslate"><span class="pre">settings.LOCK_FUNC_MODULES</span></code>. <em>All functions</em> in any of those
|
||
modules will automatically be considered a valid lock function. The default ones are found in
|
||
<code class="docutils literal notranslate"><span class="pre">evennia/locks/lockfuncs.py</span></code> and you can start adding your own in <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/lockfuncs.py</span></code>.
|
||
You can append the setting to add more module paths. To replace a default lock function, just add
|
||
your own with the same name.</p>
|
||
<p>A lock function must always accept at least two arguments - the <em>accessing object</em> (this is the
|
||
object wanting to get access) and the <em>accessed object</em> (this is the object with the lock). Those
|
||
two are fed automatically as the first two arguments to the function when the lock is checked. Any
|
||
arguments explicitly given in the lock definition will appear as extra arguments.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># A simple example lock function. Called with e.g. `id(34)`. This is</span>
|
||
<span class="c1"># defined in, say mygame/server/conf/lockfuncs.py</span>
|
||
|
||
<span class="k">def</span> <span class="nf">id</span><span class="p">(</span><span class="n">accessing_obj</span><span class="p">,</span> <span class="n">accessed_obj</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">args</span><span class="p">:</span>
|
||
<span class="n">wanted_id</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="k">return</span> <span class="n">accessing_obj</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">wanted_id</span>
|
||
<span class="k">return</span> <span class="kc">False</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The above could for example be used in a lock function like this:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># we have `obj` and `owner_object` from before</span>
|
||
<span class="n">obj</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">f</span><span class="s2">"edit: id(</span><span class="si">{</span><span class="n">owner_object</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2">)"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>We could check if the “edit” lock is passed with something like this:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># as part of a Command's func() method, for example</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"edit"</span><span class="p">):</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"You don't have access to edit this!"</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In this example, everyone except the <code class="docutils literal notranslate"><span class="pre">caller</span></code> with the right <code class="docutils literal notranslate"><span class="pre">id</span></code> will get the error.</p>
|
||
<blockquote>
|
||
<div><p>(Using the <code class="docutils literal notranslate"><span class="pre">*</span></code> and <code class="docutils literal notranslate"><span class="pre">**</span></code> syntax causes Python to magically put all extra arguments into a list
|
||
<code class="docutils literal notranslate"><span class="pre">args</span></code> and all keyword arguments into a dictionary <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> respectively. If you are unfamiliar with
|
||
how <code class="docutils literal notranslate"><span class="pre">*args</span></code> and <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> work, see the Python manuals).</p>
|
||
</div></blockquote>
|
||
<p>Some useful default lockfuncs (see <code class="docutils literal notranslate"><span class="pre">src/locks/lockfuncs.py</span></code> for more):</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">true()/all()</span></code> - give access to everyone</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">false()/none()/superuser()</span></code> - give access to none. Superusers bypass the check entirely and are
|
||
thus the only ones who will pass this check.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">perm(perm)</span></code> - this tries to match a given <code class="docutils literal notranslate"><span class="pre">permission</span></code> property, on an Account firsthand, on a
|
||
Character second. See <a class="reference internal" href="Permissions.html"><span class="doc std std-doc">below</span></a>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">perm_above(perm)</span></code> - like <code class="docutils literal notranslate"><span class="pre">perm</span></code> but requires a “higher” permission level than the one given.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">id(num)/dbref(num)</span></code> - checks so the access_object has a certain dbref/id.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">attr(attrname)</span></code> - checks if a certain <a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attribute</span></a> exists on accessing_object.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">attr(attrname,</span> <span class="pre">value)</span></code> - checks so an attribute exists on accessing_object <em>and</em> has the given
|
||
value.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">attr_gt(attrname,</span> <span class="pre">value)</span></code> - checks so accessing_object has a value larger (<code class="docutils literal notranslate"><span class="pre">></span></code>) than the given
|
||
value.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">attr_ge,</span> <span class="pre">attr_lt,</span> <span class="pre">attr_le,</span> <span class="pre">attr_ne</span></code> - corresponding for <code class="docutils literal notranslate"><span class="pre">>=</span></code>, <code class="docutils literal notranslate"><span class="pre"><</span></code>, <code class="docutils literal notranslate"><span class="pre"><=</span></code> and <code class="docutils literal notranslate"><span class="pre">!=</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">holds(objid)</span></code> - checks so the accessing objects contains an object of given name or dbref.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">inside()</span></code> - checks so the accessing object is inside the accessed object (the inverse of
|
||
<code class="docutils literal notranslate"><span class="pre">holds()</span></code>).</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">pperm(perm)</span></code>, <code class="docutils literal notranslate"><span class="pre">pid(num)/pdbref(num)</span></code> - same as <code class="docutils literal notranslate"><span class="pre">perm</span></code>, <code class="docutils literal notranslate"><span class="pre">id/dbref</span></code> but always looks for
|
||
permissions and dbrefs of <em>Accounts</em>, not on Characters.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">serversetting(settingname,</span> <span class="pre">value)</span></code> - Only returns True if Evennia has a given setting or a
|
||
setting set to a given value.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="checking-simple-strings">
|
||
<h2>Checking simple strings<a class="headerlink" href="#checking-simple-strings" title="Permalink to this headline">¶</a></h2>
|
||
<p>Sometimes you don’t really need to look up a certain lock, you just want to check a lockstring. A
|
||
common use is inside Commands, in order to check if a user has a certain permission. The lockhandler
|
||
has a method <code class="docutils literal notranslate"><span class="pre">check_lockstring(accessing_obj,</span> <span class="pre">lockstring,</span> <span class="pre">bypass_superuser=False)</span></code> that allows this.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># inside command definition</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">check_lockstring</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"dummy:perm(Admin)"</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"You must be an Admin or higher to do this!"</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note here that the <code class="docutils literal notranslate"><span class="pre">access_type</span></code> can be left to a dummy value since this method does not actually do
|
||
a Lock lookup.</p>
|
||
</section>
|
||
<section id="default-locks">
|
||
<h2>Default locks<a class="headerlink" href="#default-locks" title="Permalink to this headline">¶</a></h2>
|
||
<p>Evennia sets up a few basic locks on all new objects and accounts (if we didn’t, noone would have
|
||
any access to anything from the start). This is all defined in the root <a class="reference internal" href="Typeclasses.html"><span class="doc std std-doc">Typeclasses</span></a>
|
||
of the respective entity, in the hook method <code class="docutils literal notranslate"><span class="pre">basetype_setup()</span></code> (which you usually don’t want to
|
||
edit unless you want to change how basic stuff like rooms and exits store their internal variables).
|
||
This is called once, before <code class="docutils literal notranslate"><span class="pre">at_object_creation</span></code>, so just put them in the latter method on your
|
||
child object to change the default. Also creation commands like <code class="docutils literal notranslate"><span class="pre">create</span></code> changes the locks of
|
||
objects you create - for example it sets the <code class="docutils literal notranslate"><span class="pre">control</span></code> lock_type so as to allow you, its creator, to
|
||
control and delete the object.</p>
|
||
</section>
|
||
<section id="more-lock-definition-examples">
|
||
<h2>More Lock definition examples<a class="headerlink" href="#more-lock-definition-examples" title="Permalink to this headline">¶</a></h2>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>examine: attr(eyesight, excellent) or perm(Builders)
|
||
</pre></div>
|
||
</div>
|
||
<p>You are only allowed to do <em>examine</em> on this object if you have ‘excellent’ eyesight (that is, has
|
||
an Attribute <code class="docutils literal notranslate"><span class="pre">eyesight</span></code> with the value <code class="docutils literal notranslate"><span class="pre">excellent</span></code> defined on yourself) or if you have the
|
||
“Builders” permission string assigned to you.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>open: holds('the green key') or perm(Builder)
|
||
</pre></div>
|
||
</div>
|
||
<p>This could be called by the <code class="docutils literal notranslate"><span class="pre">open</span></code> command on a “door” object. The check is passed if you are a
|
||
Builder or has the right key in your inventory.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>cmd: perm(Builders)
|
||
</pre></div>
|
||
</div>
|
||
<p>Evennia’s command handler looks for a lock of type <code class="docutils literal notranslate"><span class="pre">cmd</span></code> to determine if a user is allowed to even
|
||
call upon a particular command or not. When you define a command, this is the kind of lock you must
|
||
set. See the default command set for lots of examples. If a character/account don’t pass the <code class="docutils literal notranslate"><span class="pre">cmd</span></code>
|
||
lock type the command will not even appear in their <code class="docutils literal notranslate"><span class="pre">help</span></code> list.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>cmd: not perm(no_tell)
|
||
</pre></div>
|
||
</div>
|
||
<p>“Permissions” can also be used to block users or implement highly specific bans. The above example
|
||
would be be added as a lock string to the <code class="docutils literal notranslate"><span class="pre">tell</span></code> command. This will allow everyone <em>not</em> having the
|
||
“permission” <code class="docutils literal notranslate"><span class="pre">no_tell</span></code> to use the <code class="docutils literal notranslate"><span class="pre">tell</span></code> command. You could easily give an account the “permission”
|
||
<code class="docutils literal notranslate"><span class="pre">no_tell</span></code> to disable their use of this particular command henceforth.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">dbref</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">id</span>
|
||
<span class="n">lockstring</span> <span class="o">=</span> <span class="s2">"control:id(</span><span class="si">%s</span><span class="s2">);examine:perm(Builders);delete:id(</span><span class="si">%s</span><span class="s2">) or perm(Admin);get:all()"</span> <span class="o">%</span>
|
||
<span class="p">(</span><span class="n">dbref</span><span class="p">,</span> <span class="n">dbref</span><span class="p">)</span>
|
||
<span class="n">new_obj</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">lockstring</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This is how the <code class="docutils literal notranslate"><span class="pre">create</span></code> command sets up new objects. In sequence, this permission string sets the
|
||
owner of this object be the creator (the one running <code class="docutils literal notranslate"><span class="pre">create</span></code>). Builders may examine the object
|
||
whereas only Admins and the creator may delete it. Everyone can pick it up.</p>
|
||
</section>
|
||
<section id="a-complete-example-of-setting-locks-on-an-object">
|
||
<h2>A complete example of setting locks on an object<a class="headerlink" href="#a-complete-example-of-setting-locks-on-an-object" title="Permalink to this headline">¶</a></h2>
|
||
<p>Assume we have two objects - one is ourselves (not superuser) and the other is an <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Object</span></a>
|
||
called <code class="docutils literal notranslate"><span class="pre">box</span></code>.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > create/drop box
|
||
> desc box = "This is a very big and heavy box."
|
||
</pre></div>
|
||
</div>
|
||
<p>We want to limit which objects can pick up this heavy box. Let’s say that to do that we require the
|
||
would-be lifter to to have an attribute <em>strength</em> on themselves, with a value greater than 50. We
|
||
assign it to ourselves to begin with.</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > set self/strength = 45
|
||
</pre></div>
|
||
</div>
|
||
<p>Ok, so for testing we made ourselves strong, but not strong enough. Now we need to look at what
|
||
happens when someone tries to pick up the the box - they use the <code class="docutils literal notranslate"><span class="pre">get</span></code> command (in the default set).
|
||
This is defined in <code class="docutils literal notranslate"><span class="pre">evennia/commands/default/general.py</span></code>. In its code we find this snippet:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s1">'get'</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">get_err_msg</span><span class="p">:</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">get_err_msg</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"You can't get that."</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>So the <code class="docutils literal notranslate"><span class="pre">get</span></code> command looks for a lock with the type <em>get</em> (not so surprising). It also looks for an
|
||
<a class="reference internal" href="Attributes.html"><span class="doc std std-doc">Attribute</span></a> on the checked object called <em>get_err_msg</em> in order to return a customized
|
||
error message. Sounds good! Let’s start by setting that on the box:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> > set box/get_err_msg = You are not strong enough to lift this box.
|
||
</pre></div>
|
||
</div>
|
||
<p>Next we need to craft a Lock of type <em>get</em> on our box. We want it to only be passed if the accessing
|
||
object has the attribute <em>strength</em> of the right value. For this we would need to create a lock
|
||
function that checks if attributes have a value greater than a given value. Luckily there is already
|
||
such a one included in evennia (see <code class="docutils literal notranslate"><span class="pre">evennia/locks/lockfuncs.py</span></code>), called <code class="docutils literal notranslate"><span class="pre">attr_gt</span></code>.</p>
|
||
<p>So the lock string will look like this: <code class="docutils literal notranslate"><span class="pre">get:attr_gt(strength,</span> <span class="pre">50)</span></code>. We put this on the box now:</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> lock box = get:attr_gt(strength, 50)
|
||
</pre></div>
|
||
</div>
|
||
<p>Try to <code class="docutils literal notranslate"><span class="pre">get</span></code> the object and you should get the message that we are not strong enough. Increase your
|
||
strength above 50 however and you’ll pick it up no problem. Done! A very heavy box!</p>
|
||
<p>If you wanted to set this up in python code, it would look something like this:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span>
|
||
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_object</span>
|
||
|
||
<span class="c1"># create, then set the lock</span>
|
||
<span class="n">box</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"box"</span><span class="p">)</span>
|
||
<span class="n">box</span><span class="o">.</span><span class="n">locks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"get:attr_gt(strength, 50)"</span><span class="p">)</span>
|
||
|
||
<span class="c1"># or we can assign locks in one go right away</span>
|
||
<span class="n">box</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">"box"</span><span class="p">,</span> <span class="n">locks</span><span class="o">=</span><span class="s2">"get:attr_gt(strength, 50)"</span><span class="p">)</span>
|
||
|
||
<span class="c1"># set the attributes</span>
|
||
<span class="n">box</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">desc</span> <span class="o">=</span> <span class="s2">"This is a very big and heavy box."</span>
|
||
<span class="n">box</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">get_err_msg</span> <span class="o">=</span> <span class="s2">"You are not strong enough to lift this box."</span>
|
||
|
||
<span class="c1"># one heavy box, ready to withstand all but the strongest...</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="on-djangos-permission-system">
|
||
<h2>On Django’s permission system<a class="headerlink" href="#on-djangos-permission-system" title="Permalink to this headline">¶</a></h2>
|
||
<p>Django also implements a comprehensive permission/security system of its own. The reason we don’t
|
||
use that is because it is app-centric (app in the Django sense). Its permission strings are of the
|
||
form <code class="docutils literal notranslate"><span class="pre">appname.permstring</span></code> and it automatically adds three of them for each database model in the app</p>
|
||
<ul class="simple">
|
||
<li><p>for the app evennia/object this would be for example ‘object.create’, ‘object.admin’ and
|
||
‘object.edit’. This makes a lot of sense for a web application, not so much for a MUD, especially
|
||
when we try to hide away as much of the underlying architecture as possible.</p></li>
|
||
</ul>
|
||
<p>The django permissions are not completely gone however. We use it for validating passwords during
|
||
login. It is also used exclusively for managing Evennia’s web-based admin site, which is a graphical
|
||
front-end for the database of Evennia. You edit and assign such permissions directly from the web
|
||
interface. It’s stand-alone from the permissions described above.</p>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
<div class="clearer"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<p class="logo"><a href="../index.html">
|
||
<img class="logo" src="../_static/evennia_logo.png" alt="Logo"/>
|
||
</a></p>
|
||
<div id="searchbox" style="display: none" role="search">
|
||
<h3 id="searchlabel">Quick search</h3>
|
||
<div class="searchformwrapper">
|
||
<form class="search" action="../search.html" method="get">
|
||
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||
<input type="submit" value="Go" />
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<script>$('#searchbox').show(0);</script>
|
||
<p><h3><a href="../index.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">Locks</a><ul>
|
||
<li><a class="reference internal" href="#setting-and-checking-a-lock">Setting and checking a lock</a></li>
|
||
<li><a class="reference internal" href="#defining-locks">Defining locks</a><ul>
|
||
<li><a class="reference internal" href="#valid-access-types">Valid access_types</a></li>
|
||
<li><a class="reference internal" href="#custom-access-types">Custom access_types</a></li>
|
||
<li><a class="reference internal" href="#lock-functions">Lock functions</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#checking-simple-strings">Checking simple strings</a></li>
|
||
<li><a class="reference internal" href="#default-locks">Default locks</a></li>
|
||
<li><a class="reference internal" href="#more-lock-definition-examples">More Lock definition examples</a></li>
|
||
<li><a class="reference internal" href="#a-complete-example-of-setting-locks-on-an-object">A complete example of setting locks on an object</a></li>
|
||
<li><a class="reference internal" href="#on-djangos-permission-system">On Django’s permission system</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<div role="note" aria-label="source link">
|
||
<!--h3>This Page</h3-->
|
||
<ul class="this-page-menu">
|
||
<li><a href="../_sources/Components/Locks.md.txt"
|
||
rel="nofollow">Show Page Source</a></li>
|
||
</ul>
|
||
</div><h3>Links</h3>
|
||
<ul>
|
||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
||
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
||
<li>
|
||
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
||
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
||
<a href="https://evennia.blogspot.com/">Blog</a>
|
||
</li>
|
||
</ul>
|
||
<h3>Versions</h3>
|
||
<ul>
|
||
<li><a href="Locks.html">1.0-dev (develop branch)</a></li>
|
||
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||
</ul>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="General Index"
|
||
>index</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">Locks</a></li>
|
||
</ul>
|
||
<div class="develop">develop branch</div>
|
||
</div>
|
||
<div class="footer" role="contentinfo">
|
||
© Copyright 2020, The Evennia developer community.
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||
</div>
|
||
</body>
|
||
</html> |