mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 13:56:30 +01:00
649 lines
No EOL
63 KiB
HTML
649 lines
No EOL
63 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<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>
|
||
<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>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<div class="section" 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">Commands</span></a>,
|
||
<a class="reference internal" href="Objects.html"><span class="doc">Objects</span></a>, <a class="reference internal" href="Scripts.html"><span class="doc">Scripts</span></a>, <a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a>, <a class="reference internal" href="Help-System.html"><span class="doc">Help System</span></a>,
|
||
<a class="reference external" href="Components/Communications.html#Msg">messages</a> and <a class="reference external" href="Components/Communications.html#Channels">channels</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>
|
||
<div class="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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">></span> <span class="n">lock</span> <span class="n">obj</span> <span class="o">=</span> <span class="o"><</span><span class="n">lockstring</span><span class="o">></span>
|
||
</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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><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>
|
||
</td></tr></table></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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3</pre></div></td><td class="code"><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>
|
||
</td></tr></table></div>
|
||
</div>
|
||
<div class="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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4</pre></div></td><td class="code"><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>
|
||
</td></tr></table></div>
|
||
<p>Formally, a lockstring has the following syntax:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><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>
|
||
</td></tr></table></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-default 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="n">edit</span><span class="p">:</span><span class="nb">all</span><span class="p">();</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>
|
||
<div class="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">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">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 external" href="Components/Objects.html#Characters">Characters</a>:</p>
|
||
<ul>
|
||
<li><p>Same as for Objects</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference external" href="Components/Objects.html#Exits">Exits</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">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">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 external" href="Components/Communications.html#Channels">Channels</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">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>
|
||
</div>
|
||
<div class="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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><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>
|
||
</td></tr></table></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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3</pre></div></td><td class="code"><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>
|
||
</td></tr></table></div>
|
||
</div>
|
||
<div class="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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8</pre></div></td><td class="code"><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="bp">False</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>The above could for example be used in a lock function like this:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2</pre></div></td><td class="code"><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="s2">"edit: id(</span><span class="si">%i</span><span class="s2">)"</span> <span class="o">%</span> <span class="n">owner_object</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>We could check if the “edit” lock is passed with something like this:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4</pre></div></td><td class="code"><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>
|
||
</td></tr></table></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 external" href="Components/Locks.html#permissions">below</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">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>
|
||
</div>
|
||
</div>
|
||
<div class="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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4</pre></div></td><td class="code"><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>
|
||
</td></tr></table></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>
|
||
</div>
|
||
<div class="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">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>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="permissions">
|
||
<h1>Permissions<a class="headerlink" href="#permissions" title="Permalink to this headline">¶</a></h1>
|
||
<blockquote>
|
||
<div><p>This section covers the underlying code use of permissions. If you just want to learn how to
|
||
practically assign permissions in-game, refer to the <a class="reference internal" href="../Concepts/Building-Permissions.html"><span class="doc">Building Permissions</span></a>
|
||
page, which details how you use the <code class="docutils literal notranslate"><span class="pre">perm</span></code> command.</p>
|
||
</div></blockquote>
|
||
<p>A <em>permission</em> is simply a list of text strings stored in the handler <code class="docutils literal notranslate"><span class="pre">permissions</span></code> on <code class="docutils literal notranslate"><span class="pre">Objects</span></code>
|
||
and <code class="docutils literal notranslate"><span class="pre">Accounts</span></code>. Permissions can be used as a convenient way to structure access levels and
|
||
hierarchies. It is set by the <code class="docutils literal notranslate"><span class="pre">perm</span></code> command. Permissions are especially handled by the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">pperm()</span></code> lock functions listed above.</p>
|
||
<p>Let’s say we have a <code class="docutils literal notranslate"><span class="pre">red_key</span></code> object. We also have red chests that we want to unlock with this key.</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">perm</span> <span class="n">red_key</span> <span class="o">=</span> <span class="n">unlocks_red_chests</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This gives the <code class="docutils literal notranslate"><span class="pre">red_key</span></code> object the permission “unlocks_red_chests”. Next we lock our red chests:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">lock</span> <span class="n">red</span> <span class="n">chest</span> <span class="o">=</span> <span class="n">unlock</span><span class="p">:</span><span class="n">perm</span><span class="p">(</span><span class="n">unlocks_red_chests</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>What this lock will expect is to the fed the actual key object. The <code class="docutils literal notranslate"><span class="pre">perm()</span></code> lock function will
|
||
check the permissions set on the key and only return true if the permission is the one given.</p>
|
||
<p>Finally we need to actually check this lock somehow. Let’s say the chest has an command <code class="docutils literal notranslate"><span class="pre">open</span> <span class="pre"><key></span></code>
|
||
sitting on itself. Somewhere in its code the command needs to figure out which key you are using and
|
||
test if this key has the correct permission:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="c1"># self.obj is the chest </span>
|
||
<span class="c1"># and used_key is the key we used as argument to</span>
|
||
<span class="c1"># the command. The self.caller is the one trying</span>
|
||
<span class="c1"># to unlock the chest</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">used_key</span><span class="p">,</span> <span class="s2">"unlock"</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">"The key does not fit!"</span><span class="p">)</span>
|
||
<span class="k">return</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>All new accounts are given a default set of permissions defined by
|
||
<code class="docutils literal notranslate"><span class="pre">settings.PERMISSION_ACCOUNT_DEFAULT</span></code>.</p>
|
||
<p>Selected permission strings can be organized in a <em>permission hierarchy</em> by editing the tuple
|
||
<code class="docutils literal notranslate"><span class="pre">settings.PERMISSION_HIERARCHY</span></code>. Evennia’s default permission hierarchy is as follows:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">Developer</span> <span class="c1"># like superuser but affected by locks</span>
|
||
<span class="n">Admin</span> <span class="c1"># can administrate accounts</span>
|
||
<span class="n">Builder</span> <span class="c1"># can edit the world</span>
|
||
<span class="n">Helper</span> <span class="c1"># can edit help files</span>
|
||
<span class="n">Player</span> <span class="c1"># can chat and send tells (default level)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>(Also the plural form works, so you could use <code class="docutils literal notranslate"><span class="pre">Developers</span></code> etc too).</p>
|
||
<blockquote>
|
||
<div><p>There is also a <code class="docutils literal notranslate"><span class="pre">Guest</span></code> level below <code class="docutils literal notranslate"><span class="pre">Player</span></code> that is only active if <code class="docutils literal notranslate"><span class="pre">settings.GUEST_ENABLED</span></code> is
|
||
set. This is never part of <code class="docutils literal notranslate"><span class="pre">settings.PERMISSION_HIERARCHY</span></code>.</p>
|
||
</div></blockquote>
|
||
<p>The main use of this is that if you use the lock function <code class="docutils literal notranslate"><span class="pre">perm()</span></code> mentioned above, a lock check for
|
||
a particular permission in the hierarchy will <em>also</em> grant access to those with <em>higher</em> hierarchy
|
||
access. So if you have the permission “Admin” you will also pass a lock defined as <code class="docutils literal notranslate"><span class="pre">perm(Builder)</span></code>
|
||
or any of those levels below “Admin”.</p>
|
||
<p>When doing an access check from an <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a> or Character, the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> lock function will
|
||
always first use the permissions of any Account connected to that Object before checking for
|
||
permissions on the Object. In the case of hierarchical permissions (Admins, Builders etc), the
|
||
Account permission will always be used (this stops an Account from escalating their permission by
|
||
puppeting a high-level Character). If the permission looked for is not in the hierarchy, an exact
|
||
match is required, first on the Account and if not found there (or if no Account is connected), then
|
||
on the Object itself.</p>
|
||
<p>Here is how you use <code class="docutils literal notranslate"><span class="pre">perm</span></code> to give an account more permissions:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">perm</span><span class="o">/</span><span class="n">account</span> <span class="n">Tommy</span> <span class="o">=</span> <span class="n">Builders</span>
|
||
<span class="n">perm</span><span class="o">/</span><span class="n">account</span><span class="o">/</span><span class="k">del</span> <span class="n">Tommy</span> <span class="o">=</span> <span class="n">Builders</span> <span class="c1"># remove it again</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note the use of the <code class="docutils literal notranslate"><span class="pre">/account</span></code> switch. It means you assign the permission to the
|
||
<a class="reference internal" href="Accounts.html"><span class="doc">Accounts</span></a> Tommy instead of any <a class="reference internal" href="Objects.html"><span class="doc">Character</span></a> that also happens to be named
|
||
“Tommy”.</p>
|
||
<p>Putting permissions on the <em>Account</em> guarantees that they are kept, <em>regardless</em> of which Character
|
||
they are currently puppeting. This is especially important to remember when assigning permissions
|
||
from the <em>hierarchy tree</em> - as mentioned above, an Account’s permissions will overrule that of its
|
||
character. So to be sure to avoid confusion you should generally put hierarchy permissions on the
|
||
Account, not on their Characters (but see also <a class="reference external" href="Components/Locks.html#Quelling">quelling</a>).</p>
|
||
<p>Below is an example of an object without any connected account</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">obj1</span><span class="o">.</span><span class="n">permissions</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"Builders"</span><span class="p">,</span> <span class="s2">"cool_guy"</span><span class="p">]</span>
|
||
<span class="n">obj2</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">"enter:perm_above(Accounts) and perm(cool_guy)"</span><span class="p">)</span>
|
||
|
||
<span class="n">obj2</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">obj1</span><span class="p">,</span> <span class="s2">"enter"</span><span class="p">)</span> <span class="c1"># this returns True!</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>And one example of a puppet with a connected account:</p>
|
||
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5</pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">account</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"Accounts"</span><span class="p">)</span>
|
||
<span class="n">puppet</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"Builders"</span><span class="p">,</span> <span class="s2">"cool_guy"</span><span class="p">)</span>
|
||
<span class="n">obj2</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">"enter:perm_above(Accounts) and perm(cool_guy)"</span><span class="p">)</span>
|
||
|
||
<span class="n">obj2</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">puppet</span><span class="p">,</span> <span class="s2">"enter"</span><span class="p">)</span> <span class="c1"># this returns False!</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<div class="section" id="superusers">
|
||
<h2>Superusers<a class="headerlink" href="#superusers" title="Permalink to this headline">¶</a></h2>
|
||
<p>There is normally only one <em>superuser</em> account and that is the one first created when starting
|
||
Evennia (User #1). This is sometimes known as the “Owner” or “God” user. A superuser has more than
|
||
full access - it completely <em>bypasses</em> all locks so no checks are even run. This allows for the
|
||
superuser to always have access to everything in an emergency. But it also hides any eventual errors
|
||
you might have made in your lock definitions. So when trying out game systems you should either use
|
||
quelling (see below) or make a second Developer-level character so your locks get tested correctly.</p>
|
||
</div>
|
||
<div class="section" id="quelling">
|
||
<h2>Quelling<a class="headerlink" href="#quelling" title="Permalink to this headline">¶</a></h2>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">quell</span></code> command can be used to enforce the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> lockfunc to ignore permissions on the
|
||
Account and instead use the permissions on the Character only. This can be used e.g. by staff to
|
||
test out things with a lower permission level. Return to the normal operation with <code class="docutils literal notranslate"><span class="pre">unquell</span></code>. Note
|
||
that quelling will use the smallest of any hierarchical permission on the Account or Character, so
|
||
one cannot escalate one’s Account permission by quelling to a high-permission Character. Also the
|
||
superuser can quell their powers this way, making them affectable by locks.</p>
|
||
</div>
|
||
<div class="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-default notranslate"><div class="highlight"><pre><span></span><span class="n">examine</span><span class="p">:</span> <span class="n">attr</span><span class="p">(</span><span class="n">eyesight</span><span class="p">,</span> <span class="n">excellent</span><span class="p">)</span> <span class="ow">or</span> <span class="n">perm</span><span class="p">(</span><span class="n">Builders</span><span class="p">)</span>
|
||
</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-default notranslate"><div class="highlight"><pre><span></span><span class="nb">open</span><span class="p">:</span> <span class="n">holds</span><span class="p">(</span><span class="s1">'the green key'</span><span class="p">)</span> <span class="ow">or</span> <span class="n">perm</span><span class="p">(</span><span class="n">Builder</span><span class="p">)</span>
|
||
</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-default notranslate"><div class="highlight"><pre><span></span><span class="n">cmd</span><span class="p">:</span> <span class="n">perm</span><span class="p">(</span><span class="n">Builders</span><span class="p">)</span>
|
||
</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-default notranslate"><div class="highlight"><pre><span></span><span class="n">cmd</span><span class="p">:</span> <span class="ow">not</span> <span class="n">perm</span><span class="p">(</span><span class="n">no_tell</span><span class="p">)</span>
|
||
</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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4</pre></div></td><td class="code"><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>
|
||
</td></tr></table></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>
|
||
</div>
|
||
<div class="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">Object</span></a>
|
||
called <code class="docutils literal notranslate"><span class="pre">box</span></code>.</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">></span> <span class="n">create</span><span class="o">/</span><span class="n">drop</span> <span class="n">box</span>
|
||
<span class="o">></span> <span class="n">desc</span> <span class="n">box</span> <span class="o">=</span> <span class="s2">"This is a very big and heavy box."</span>
|
||
</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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">></span> <span class="nb">set</span> <span class="bp">self</span><span class="o">/</span><span class="n">strength</span> <span class="o">=</span> <span class="mi">45</span>
|
||
</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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6</pre></div></td><td class="code"><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>
|
||
</td></tr></table></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">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-default notranslate"><div class="highlight"><pre><span></span> <span class="o">></span> <span class="nb">set</span> <span class="n">box</span><span class="o">/</span><span class="n">get_err_msg</span> <span class="o">=</span> <span class="n">You</span> <span class="n">are</span> <span class="ow">not</span> <span class="n">strong</span> <span class="n">enough</span> <span class="n">to</span> <span class="n">lift</span> <span class="n">this</span> <span class="n">box</span><span class="o">.</span>
|
||
</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-default notranslate"><div class="highlight"><pre><span></span> <span class="n">lock</span> <span class="n">box</span> <span class="o">=</span> <span class="n">get</span><span class="p">:</span><span class="n">attr_gt</span><span class="p">(</span><span class="n">strength</span><span class="p">,</span> <span class="mi">50</span><span class="p">)</span>
|
||
</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"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
|
||
2
|
||
3
|
||
4
|
||
5
|
||
6
|
||
7
|
||
8
|
||
9
|
||
10
|
||
11
|
||
12
|
||
13
|
||
14
|
||
15</pre></div></td><td class="code"><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="bp">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="bp">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>
|
||
</td></tr></table></div>
|
||
</div>
|
||
<div class="section" id="on-django-s-permission-system">
|
||
<h2>On Django’s permission system<a class="headerlink" href="#on-django-s-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>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<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>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#permissions">Permissions</a><ul>
|
||
<li><a class="reference internal" href="#superusers">Superusers</a></li>
|
||
<li><a class="reference internal" href="#quelling">Quelling</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-django-s-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>Versions</h3>
|
||
<ul>
|
||
<li><a href="Locks.html">1.0-dev (develop branch)</a></li>
|
||
<li><a href="../../0.9.1/index.html">0.9.1 (master 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>
|
||
<div class="footer" role="contentinfo">
|
||
© Copyright 2020, The Evennia developer community.
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.1.
|
||
</div>
|
||
</body>
|
||
</html> |