<h1>Locks<aclass="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 (<aclass="reference internal"href="Commands.html"><spanclass="doc">Commands</span></a>, <aclass="reference internal"href="Objects.html"><spanclass="doc">Objects</span></a>, <aclass="reference internal"href="Scripts.html"><spanclass="doc">Scripts</span></a>, <aclass="reference internal"href="Accounts.html"><spanclass="doc">Accounts</span></a>, <aclass="reference internal"href="Help-System.html"><spanclass="doc">Help System</span></a>, <aclass="reference external"href="/Communications.html#Msg">messages</a> and <aclass="reference external"href="/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, <codeclass="docutils literal notranslate"><spanclass="pre">34</span></code> are allowed to delete it. So whenever a player tries to run <codeclass="docutils literal notranslate"><spanclass="pre">delete</span></code> on the object, the <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">34</span></code>. Only then will it allow <codeclass="docutils literal notranslate"><spanclass="pre">delete</span></code> to go on with its job.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre"><lockstring></span></code> should look in the next section.</p>
<p>Code-wise, Evennia handles locks through what is usually called <codeclass="docutils literal notranslate"><spanclass="pre">locks</span></code> on all relevant entities. This is a handler that allows you to add, delete and check locks.</p>
<p>One can call <codeclass="docutils literal notranslate"><spanclass="pre">locks.check()</span></code> to perform a lock check, but to hide the underlying implementation all objects also have a convenience function called <codeclass="docutils literal notranslate"><spanclass="pre">access</span></code>. This should preferably be used. In the example below, <codeclass="docutils literal notranslate"><spanclass="pre">accessing_obj</span></code> is the object requesting the ‘delete’ access whereas <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code> is the object that might get deleted. This is how it would look (and does look) from inside the <codeclass="docutils literal notranslate"><spanclass="pre">delete</span></code> command:</p>
<spanclass="n">accessing_obj</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"Sorry, you may not delete that."</span><spanclass="p">)</span>
<spanclass="k">return</span>
</pre></div>
</td></tr></table></div>
</div>
<divclass="section"id="defining-locks">
<h2>Defining locks<aclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">locks</span></code> property using <codeclass="docutils literal notranslate"><spanclass="pre">obj.locks.add()</span></code>.</p>
<p>Here are some examples of lock strings (not including the quotes):</p>
4</pre></div></td><tdclass="code"><divclass="highlight"><pre><span></span><spanclass="n">delete</span><spanclass="p">:</span><spanclass="nb">id</span><spanclass="p">(</span><spanclass="mi">34</span><spanclass="p">)</span><spanclass="c1"># only allow obj #34 to delete</span>
<spanclass="n">edit</span><spanclass="p">:</span><spanclass="nb">all</span><spanclass="p">()</span><spanclass="c1"># let everyone edit </span>
<spanclass="c1"># only those who are not "very_weak" or are Admins may pick this up</span>
<p>where <codeclass="docutils literal notranslate"><spanclass="pre">[]</span></code> marks optional parts. <codeclass="docutils literal notranslate"><spanclass="pre">AND</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">OR</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">NOT</span></code> are not case sensitive and excess spaces are ignored. <codeclass="docutils literal notranslate"><spanclass="pre">lockfunc1,</span><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">access_type</span></code>), a colon (<codeclass="docutils literal notranslate"><spanclass="pre">:</span></code>) and then an expression involving function calls that determine what is needed to pass the lock. Each function returns either <codeclass="docutils literal notranslate"><spanclass="pre">True</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">False</span></code>. <codeclass="docutils literal notranslate"><spanclass="pre">AND</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">OR</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">NOT</span></code> work as they do normally in Python. If the total result is <codeclass="docutils literal notranslate"><spanclass="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 (<codeclass="docutils literal notranslate"><spanclass="pre">;</span></code>) in the lockstring. The string below yields the same result as the previous example:</p>
<h3>Valid access_types<aclass="headerlink"href="#valid-access-types"title="Permalink to this headline">¶</a></h3>
<p>An <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">access_type</span></code> names that you (or the default command set) actually checks for, as in the example of <codeclass="docutils literal notranslate"><spanclass="pre">delete</span></code> above that uses the ‘delete’<codeclass="docutils literal notranslate"><spanclass="pre">access_type</span></code>.</p>
<p>Below are the access_types checked by the default commandset.</p>
<li><p><codeclass="docutils literal notranslate"><spanclass="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><codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">call:false()</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">examine</span></code> - who may examine this object’s properties.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">delete</span></code> - who may delete the object.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">edit</span></code> - who may edit properties and attributes of the object.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">view</span></code> - if the <codeclass="docutils literal notranslate"><spanclass="pre">look</span></code> command will display/list this object</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">get</span></code>- who may pick up the object and carry it around.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">puppet</span></code> - who may “become” this object and control it as their “character”.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">attrcreate</span></code> - who may create new attributes on the object (default True)</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">control</span></code> - who is administrating the channel. This means the ability to delete the channel, boot listeners etc.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">send</span></code> - who may send to the channel.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">listen</span></code> - who may subscribe and listen to the channel.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">examine</span></code> - who may view this help entry (usually everyone)</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">traverse:</span><spanclass="pre"><lock</span><spanclass="pre">functions></span></code>.</p>
</div>
<divclass="section"id="custom-access-types">
<h3>Custom access_types<aclass="headerlink"href="#custom-access-types"title="Permalink to this headline">¶</a></h3>
<p>As stated above, the <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="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>
<p>This will create a ‘read’ access type for Characters having the <codeclass="docutils literal notranslate"><spanclass="pre">Player</span></code> permission or above and a ‘post’ access type for those with <codeclass="docutils literal notranslate"><spanclass="pre">Admin</span></code> permissions or above (see below how the <codeclass="docutils literal notranslate"><spanclass="pre">perm()</span></code> lock function works). When it comes time to test these permissions, simply check like this (in this example, the <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code> may be a board on the bulletin board system and <codeclass="docutils literal notranslate"><spanclass="pre">accessing_obj</span></code> is the player trying to read the board):</p>
<spanclass="n">accessing_obj</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"Sorry, you may not read that."</span><spanclass="p">)</span>
<spanclass="k">return</span>
</pre></div>
</td></tr></table></div>
</div>
<divclass="section"id="lock-functions">
<h3>Lock functions<aclass="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 <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">evennia/locks/lockfuncs.py</span></code> and you can start adding your own in <codeclass="docutils literal notranslate"><spanclass="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>
8</pre></div></td><tdclass="code"><divclass="highlight"><pre><span></span><spanclass="c1"># A simple example lock function. Called with e.g. `id(34)`. This is</span>
<spanclass="c1"># defined in, say mygame/server/conf/lockfuncs.py</span>
4</pre></div></td><tdclass="code"><divclass="highlight"><pre><span></span><spanclass="c1"># as part of a Command's func() method, for example</span>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You don't have access to edit this!"</span><spanclass="p">)</span>
<spanclass="k">return</span>
</pre></div>
</td></tr></table></div>
<p>In this example, everyone except the <codeclass="docutils literal notranslate"><spanclass="pre">caller</span></code> with the right <codeclass="docutils literal notranslate"><spanclass="pre">id</span></code> will get the error.</p>
<blockquote>
<div><p>(Using the <codeclass="docutils literal notranslate"><spanclass="pre">*</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">**</span></code> syntax causes Python to magically put all extra arguments into a list <codeclass="docutils literal notranslate"><spanclass="pre">args</span></code> and all keyword arguments into a dictionary <codeclass="docutils literal notranslate"><spanclass="pre">kwargs</span></code> respectively. If you are unfamiliar with how <codeclass="docutils literal notranslate"><spanclass="pre">*args</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code> work, see the Python manuals).</p>
</div></blockquote>
<p>Some useful default lockfuncs (see <codeclass="docutils literal notranslate"><spanclass="pre">src/locks/lockfuncs.py</span></code> for more):</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">true()/all()</span></code> - give access to everyone</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="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><codeclass="docutils literal notranslate"><spanclass="pre">perm(perm)</span></code> - this tries to match a given <codeclass="docutils literal notranslate"><spanclass="pre">permission</span></code> property, on an Account firsthand, on a Character second. See <aclass="reference external"href="/Locks.html#permissions">below</a>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">perm_above(perm)</span></code> - like <codeclass="docutils literal notranslate"><spanclass="pre">perm</span></code> but requires a “higher” permission level than the one given.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">id(num)/dbref(num)</span></code> - checks so the access_object has a certain dbref/id.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">attr(attrname)</span></code> - checks if a certain <aclass="reference internal"href="Attributes.html"><spanclass="doc">Attribute</span></a> exists on accessing_object.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">attr(attrname,</span><spanclass="pre">value)</span></code> - checks so an attribute exists on accessing_object <em>and</em> has the given value.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">attr_gt(attrname,</span><spanclass="pre">value)</span></code> - checks so accessing_object has a value larger (<codeclass="docutils literal notranslate"><spanclass="pre">></span></code>) than the given value.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">attr_ge,</span><spanclass="pre">attr_lt,</span><spanclass="pre">attr_le,</span><spanclass="pre">attr_ne</span></code> - corresponding for <codeclass="docutils literal notranslate"><spanclass="pre">>=</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre"><</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre"><=</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">!=</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">holds(objid)</span></code> - checks so the accessing objects contains an object of given name or dbref.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">inside()</span></code> - checks so the accessing object is inside the accessed object (the inverse of <codeclass="docutils literal notranslate"><spanclass="pre">holds()</span></code>).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">pperm(perm)</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">pid(num)/pdbref(num)</span></code> - same as <codeclass="docutils literal notranslate"><spanclass="pre">perm</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">id/dbref</span></code> but always looks for permissions and dbrefs of <em>Accounts</em>, not on Characters.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">serversetting(settingname,</span><spanclass="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>
<divclass="section"id="checking-simple-strings">
<h2>Checking simple strings<aclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">check_lockstring(accessing_obj,</span><spanclass="pre">lockstring,</span><spanclass="pre">bypass_superuser=False)</span></code> that allows this.</p>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You must be an Admin or higher to do this!"</span><spanclass="p">)</span>
<spanclass="k">return</span>
</pre></div>
</td></tr></table></div>
<p>Note here that the <codeclass="docutils literal notranslate"><spanclass="pre">access_type</span></code> can be left to a dummy value since this method does not actually do a Lock lookup.</p>
</div>
<divclass="section"id="default-locks">
<h2>Default locks<aclass="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 <aclass="reference internal"href="Typeclasses.html"><spanclass="doc">Typeclasses</span></a> of the respective entity, in the hook method <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">create</span></code> changes the locks of objects you create - for example it sets the <codeclass="docutils literal notranslate"><spanclass="pre">control</span></code> lock_type so as to allow you, its creator, to control and delete the object.</p>
</div>
</div>
<divclass="section"id="permissions">
<h1>Permissions<aclass="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 <aclass="reference internal"href="Building-Permissions.html"><spanclass="doc">Building Permissions</span></a> page, which details how you use the <codeclass="docutils literal notranslate"><spanclass="pre">perm</span></code> command.</p>
</div></blockquote>
<p>A <em>permission</em> is simply a list of text strings stored in the handler <codeclass="docutils literal notranslate"><spanclass="pre">permissions</span></code> on <codeclass="docutils literal notranslate"><spanclass="pre">Objects</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">Accounts</span></code>. Permissions can be used as a convenient way to structure access levels and hierarchies. It is set by the <codeclass="docutils literal notranslate"><spanclass="pre">perm</span></code> command. Permissions are especially handled by the <codeclass="docutils literal notranslate"><spanclass="pre">perm()</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">pperm()</span></code> lock functions listed above.</p>
<p>Let’s say we have a <codeclass="docutils literal notranslate"><spanclass="pre">red_key</span></code> object. We also have red chests that we want to unlock with this key.</p>
<p>This gives the <codeclass="docutils literal notranslate"><spanclass="pre">red_key</span></code> object the permission “unlocks_red_chests”. Next we lock our red chests:</p>
<p>What this lock will expect is to the fed the actual key object. The <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">open</span><spanclass="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>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"The key does not fit!"</span><spanclass="p">)</span>
<spanclass="k">return</span>
</pre></div>
</td></tr></table></div>
<p>All new accounts are given a default set of permissions defined by <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">settings.PERMISSION_HIERARCHY</span></code>. Evennia’s default permission hierarchy is as follows:</p>
<divclass="highlight-default notranslate"><divclass="highlight"><pre><span></span><spanclass="n">Developer</span><spanclass="c1"># like superuser but affected by locks</span>
<spanclass="n">Admin</span><spanclass="c1"># can administrate accounts</span>
<spanclass="n">Builder</span><spanclass="c1"># can edit the world</span>
<spanclass="n">Helper</span><spanclass="c1"># can edit help files</span>
<spanclass="n">Player</span><spanclass="c1"># can chat and send tells (default level)</span>
</pre></div>
</div>
<p>(Also the plural form works, so you could use <codeclass="docutils literal notranslate"><spanclass="pre">Developers</span></code> etc too).</p>
<blockquote>
<div><p>There is also a <codeclass="docutils literal notranslate"><spanclass="pre">Guest</span></code> level below <codeclass="docutils literal notranslate"><spanclass="pre">Player</span></code> that is only active if <codeclass="docutils literal notranslate"><spanclass="pre">settings.GUEST_ENABLED</span></code> is set. This is never part of <codeclass="docutils literal notranslate"><spanclass="pre">settings.PERMISSION_HIERARCHY</span></code>.</p>
</div></blockquote>
<p>The main use of this is that if you use the lock function <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">perm(Builder)</span></code> or any of those levels below “Admin”.</p>
<p>When doing an access check from an <aclass="reference internal"href="Objects.html"><spanclass="doc">Object</span></a> or Character, the <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">perm</span></code> to give an account more permissions:</p>
<spanclass="n">perm</span><spanclass="o">/</span><spanclass="n">account</span><spanclass="o">/</span><spanclass="k">del</span><spanclass="n">Tommy</span><spanclass="o">=</span><spanclass="n">Builders</span><spanclass="c1"># remove it again</span>
</pre></div>
</div>
<p>Note the use of the <codeclass="docutils literal notranslate"><spanclass="pre">/account</span></code> switch. It means you assign the permission to the <aclass="reference internal"href="Accounts.html"><spanclass="doc">Accounts</span></a> Tommy instead of any <aclass="reference internal"href="Objects.html"><spanclass="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 <aclass="reference external"href="/Locks.html#Quelling">quelling</a>).</p>
<p>Below is an example of an object without any connected account</p>
<spanclass="n">obj2</span><spanclass="o">.</span><spanclass="n">locks</span><spanclass="o">.</span><spanclass="n">add</span><spanclass="p">(</span><spanclass="s2">"enter:perm_above(Accounts) and perm(cool_guy)"</span><spanclass="p">)</span>
<spanclass="n">obj2</span><spanclass="o">.</span><spanclass="n">access</span><spanclass="p">(</span><spanclass="n">obj1</span><spanclass="p">,</span><spanclass="s2">"enter"</span><spanclass="p">)</span><spanclass="c1"># this returns True!</span>
</pre></div>
</td></tr></table></div>
<p>And one example of a puppet with a connected account:</p>
<spanclass="n">obj2</span><spanclass="o">.</span><spanclass="n">locks</span><spanclass="o">.</span><spanclass="n">add</span><spanclass="p">(</span><spanclass="s2">"enter:perm_above(Accounts) and perm(cool_guy)"</span><spanclass="p">)</span>
<spanclass="n">obj2</span><spanclass="o">.</span><spanclass="n">access</span><spanclass="p">(</span><spanclass="n">puppet</span><spanclass="p">,</span><spanclass="s2">"enter"</span><spanclass="p">)</span><spanclass="c1"># this returns False!</span>
</pre></div>
</td></tr></table></div>
<divclass="section"id="superusers">
<h2>Superusers<aclass="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>
<divclass="section"id="quelling">
<h2>Quelling<aclass="headerlink"href="#quelling"title="Permalink to this headline">¶</a></h2>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">quell</span></code> command can be used to enforce the <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="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>
<p>You are only allowed to do <em>examine</em> on this object if you have ‘excellent’ eyesight (that is, has an Attribute <codeclass="docutils literal notranslate"><spanclass="pre">eyesight</span></code> with the value <codeclass="docutils literal notranslate"><spanclass="pre">excellent</span></code> defined on yourself) or if you have the “Builders” permission string assigned to you.</p>
<divclass="highlight-default notranslate"><divclass="highlight"><pre><span></span><spanclass="nb">open</span><spanclass="p">:</span><spanclass="n">holds</span><spanclass="p">(</span><spanclass="s1">'the green key'</span><spanclass="p">)</span><spanclass="ow">or</span><spanclass="n">perm</span><spanclass="p">(</span><spanclass="n">Builder</span><spanclass="p">)</span>
</pre></div>
</div>
<p>This could be called by the <codeclass="docutils literal notranslate"><spanclass="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>
<p>Evennia’s command handler looks for a lock of type <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">cmd</span></code> lock type the command will not even appear in their <codeclass="docutils literal notranslate"><spanclass="pre">help</span></code> list.</p>
<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 <codeclass="docutils literal notranslate"><spanclass="pre">tell</span></code> command. This will allow everyone <em>not</em> having the “permission” <codeclass="docutils literal notranslate"><spanclass="pre">no_tell</span></code> to use the <codeclass="docutils literal notranslate"><spanclass="pre">tell</span></code> command. You could easily give an account the “permission” <codeclass="docutils literal notranslate"><spanclass="pre">no_tell</span></code> to disable their use of this particular command henceforth.</p>
<spanclass="n">lockstring</span><spanclass="o">=</span><spanclass="s2">"control:id(</span><spanclass="si">%s</span><spanclass="s2">);examine:perm(Builders);delete:id(</span><spanclass="si">%s</span><spanclass="s2">) or perm(Admin);get:all()"</span><spanclass="o">%</span><spanclass="p">(</span><spanclass="n">dbref</span><spanclass="p">,</span><spanclass="n">dbref</span><spanclass="p">)</span>
<p>This is how the <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">create</span></code>). Builders may examine the object whereas only Admins and the creator may delete it. Everyone can pick it up.</p>
<h2>A complete example of setting locks on an object<aclass="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 <aclass="reference internal"href="Objects.html"><spanclass="doc">Object</span></a> called <codeclass="docutils literal notranslate"><spanclass="pre">box</span></code>.</p>
<spanclass="o">></span><spanclass="n">desc</span><spanclass="n">box</span><spanclass="o">=</span><spanclass="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>
<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 <codeclass="docutils literal notranslate"><spanclass="pre">get</span></code> command (in the default set). This is defined in <codeclass="docutils literal notranslate"><spanclass="pre">evennia/commands/default/general.py</span></code>. In its code we find this snippet:</p>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You can't get that."</span><spanclass="p">)</span>
<spanclass="k">return</span>
</pre></div>
</td></tr></table></div>
<p>So the <codeclass="docutils literal notranslate"><spanclass="pre">get</span></code> command looks for a lock with the type <em>get</em> (not so surprising). It also looks for an <aclass="reference internal"href="Attributes.html"><spanclass="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>
<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 <codeclass="docutils literal notranslate"><spanclass="pre">evennia/locks/lockfuncs.py</span></code>), called <codeclass="docutils literal notranslate"><spanclass="pre">attr_gt</span></code>.</p>
<p>So the lock string will look like this: <codeclass="docutils literal notranslate"><spanclass="pre">get:attr_gt(strength,</span><spanclass="pre">50)</span></code>. We put this on the box now:</p>
<p>Try to <codeclass="docutils literal notranslate"><spanclass="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>
<spanclass="n">box</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">desc</span><spanclass="o">=</span><spanclass="s2">"This is a very big and heavy box."</span>
<spanclass="n">box</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">get_err_msg</span><spanclass="o">=</span><spanclass="s2">"You are not strong enough to lift this box."</span>
<spanclass="c1"># one heavy box, ready to withstand all but the strongest...</span>
<h2>On Django’s permission system<aclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">appname.permstring</span></code> and it automatically adds three of them for each database model in the app - 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>
<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>