evennia/docs/6.x/Components/Permissions.html
2026-02-15 19:06:04 +01:00

341 lines
No EOL
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Permissions &#8212; Evennia latest documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=d75fae25" />
<link rel="stylesheet" type="text/css" href="../_static/nature.css?v=279e0f84" />
<link rel="stylesheet" type="text/css" href="../_static/custom.css?v=e4a91a55" />
<script src="../_static/documentation_options.js?v=c6e86fd7"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Locks" href="Locks.html" />
<link rel="prev" title="Help System" href="Help-System.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<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="right" >
<a href="Locks.html" title="Locks"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Help-System.html" title="Help System"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Components-Overview.html" accesskey="U">Core Components</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Permissions</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="permissions">
<h1>Permissions<a class="headerlink" href="#permissions" title="Link to this heading"></a></h1>
<p>A <em>permission</em> is simply a text string 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>. Think of it as a specialized sort of <a class="reference internal" href="Tags.html"><span class="std std-doc">Tag</span></a> - one specifically dedicated to access checking. They are thus often tightly coupled to <a class="reference internal" href="Locks.html"><span class="std std-doc">Locks</span></a>. Permission strings are not case-sensitive, so “Builder” is the same as “builder” etc.</p>
<p>Permissions are 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 and checked by the <code class="docutils literal notranslate"><span class="pre">PermissionHandler.check</span></code> method as well as by the specially the <code class="docutils literal notranslate"><span class="pre">perm()</span></code> and <code class="docutils literal notranslate"><span class="pre">pperm()</span></code> <a class="reference internal" href="Locks.html"><span class="std std-doc">lock functions</span></a>.</p>
<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>
<section id="the-super-user">
<h2>The super user<a class="headerlink" href="#the-super-user" title="Link to this heading"></a></h2>
<p>There are strictly speaking two types of users in Evennia, the <em>super user</em> and everyone else. The
superuser is the first user you create, object <code class="docutils literal notranslate"><span class="pre">#1</span></code>. This is the all-powerful server-owner account.
Technically the superuser not only has access to everything, it <em>bypasses</em> the permission checks
entirely.</p>
<p>This makes the superuser impossible to lock out, but makes it unsuitable to actually play-
test the games locks and restrictions with (see <code class="docutils literal notranslate"><span class="pre">quell</span></code> below). Usually there is no need to have
but one superuser.</p>
</section>
<section id="working-with-permissions">
<h2>Working with Permissions<a class="headerlink" href="#working-with-permissions" title="Link to this heading"></a></h2>
<p>In-game, you use the <code class="docutils literal notranslate"><span class="pre">perm</span></code> command to add and remove permissions</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; perm/account Tommy = Builders
&gt; perm/account/del Tommy = Builders
</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="std std-doc">Accounts</span></a> Tommy instead of any <a class="reference internal" href="Objects.html"><span class="std std-doc">Character</span></a> that also happens to be named “Tommy”. If you dont want to use <code class="docutils literal notranslate"><span class="pre">/account</span></code>, you can also prefix the name with <code class="docutils literal notranslate"><span class="pre">*</span></code> to indicate an Account is sought:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; perm *Tommy = Builders
</pre></div>
</div>
<p>There can be reasons for putting permissions on Objects (especially NPCS), but for granting powers to players, you should usually put the permission on the <code class="docutils literal notranslate"><span class="pre">Account</span></code> - this guarantees that they are kept, <em>regardless</em> of which Character they are currently puppeting.</p>
<p>This is especially important to remember when assigning permissions from the <em>hierarchy tree</em> (see below), as an Accounts 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/puppets.</p>
<p>If you <em>do</em> want to start using the permissions on your <em>puppet</em>, you use <code class="docutils literal notranslate"><span class="pre">quell</span></code></p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; quell
&gt; unquell
</pre></div>
</div>
<p>This drops to the permissions on the puppeted object, and then back to your Account-permissions again. Quelling is useful if you want to try something “as” someone else. Its also useful for superusers since this makes them susceptible to locks (so they can test things).</p>
<p>In code, you add/remove Permissions via the <code class="docutils literal notranslate"><span class="pre">PermissionHandler</span></code>, which sits on all
typeclassed entities as the property <code class="docutils literal notranslate"><span class="pre">.permissions</span></code>:</p>
<div class="highlight-python notranslate"><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">&quot;Builders&quot;</span><span class="p">)</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">&quot;cool_guy&quot;</span><span class="p">)</span>
<span class="n">obj</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">&quot;Blacksmith&quot;</span><span class="p">)</span>
<span class="n">obj</span><span class="o">.</span><span class="n">permissions</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">&quot;Blacksmith&quot;</span><span class="p">)</span>
</pre></div>
</div>
<section id="the-permission-hierarchy">
<h3>The permission hierarchy<a class="headerlink" href="#the-permission-hierarchy" title="Link to this heading"></a></h3>
<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>. Evennias default permission hierarchy is as follows
(in increasing order of power):</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> Guest # temporary account, only used if GUEST_ENABLED=True (lowest)
Player # can chat and send tells (default level)
Helper # can edit help files
Builder # can edit the world
Admin # can administrate accounts
Developer # like superuser but affected by locks (highest)
</pre></div>
</div>
<p>(Besides being case-insensitive, hierarchical permissions also understand the plural form, so you could use <code class="docutils literal notranslate"><span class="pre">Developers</span></code> and <code class="docutils literal notranslate"><span class="pre">Developer</span></code> interchangeably).</p>
<p>When checking a hierarchical permission (using one of the methods to follow), you will pass checks for your level <em>and below</em>. That is, if you have the “Admin” hierarchical permission, you will also pass checks asking for “Builder”, “Helper” and so on.</p>
<p>By contrast, if you check for a non-hierarchical permission, like “Blacksmith” you must have <em>exactly</em> that permission to pass.</p>
</section>
<section id="checking-permissions">
<h3>Checking permissions<a class="headerlink" href="#checking-permissions" title="Link to this heading"></a></h3>
<p>Its important to note that you check for the permission of a <em>puppeted</em> <a class="reference internal" href="Objects.html"><span class="std std-doc">Object</span></a> (like a Character), the check will always first use the permissions of any <code class="docutils literal notranslate"><span class="pre">Account</span></code> 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>
</section>
<section id="checking-with-obj-permissions-check">
<h3>Checking with obj.permissions.check()<a class="headerlink" href="#checking-with-obj-permissions-check" title="Link to this heading"></a></h3>
<p>The simplest way to check if an entity has a permission is to check its <em>PermissionHandler</em>, stored as <code class="docutils literal notranslate"><span class="pre">.permissions</span></code> on all typeclassed entities.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>if obj.permissions.check(&quot;Builder&quot;):
# allow builder to do stuff
if obj.permissions.check(&quot;Blacksmith&quot;, &quot;Warrior&quot;):
# do stuff for blacksmiths OR warriors
if obj.permissions.check(&quot;Blacksmith&quot;, &quot;Warrior&quot;, require_all=True):
# only for those that are both blacksmiths AND warriors
</pre></div>
</div>
<p>Using the <code class="docutils literal notranslate"><span class="pre">.check</span></code> method is the way to go, it will take hierarchical
permissions into account, check accounts/sessions etc.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Don&#39;t confuse `.permissions.check()` with `.permissions.has()`. The .has()
method checks if a string is defined specifically on that PermissionHandler.
It will not consider permission-hierarchy, puppeting etc. `.has` can be useful
if you are manipulating permissions, but use `.check` for access checking.
</pre></div>
</div>
</div>
</section>
<section id="lock-funcs">
<h3>Lock funcs<a class="headerlink" href="#lock-funcs" title="Link to this heading"></a></h3>
<p>While the <code class="docutils literal notranslate"><span class="pre">PermissionHandler</span></code> offers a simple way to check perms, <a class="reference internal" href="Locks.html"><span class="std std-doc">Lock
strings</span></a> offers a mini-language for describing how something is accessed.
The <code class="docutils literal notranslate"><span class="pre">perm()</span></code> <em>lock function</em> is the main tool for using Permissions in locks.</p>
<p>Lets 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-none notranslate"><div class="highlight"><pre><span></span>perm red_key = unlocks_red_chests
</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-none notranslate"><div class="highlight"><pre><span></span>lock red chest = unlock:perm(unlocks_red_chests)
</pre></div>
</div>
<p>When trying to unlock the red chest with this key, the chest Typeclass could
then take the key and do an access check:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in some typeclass file where chest is defined</span>
<span class="k">class</span><span class="w"> </span><span class="nc">TreasureChest</span><span class="p">(</span><span class="n">Object</span><span class="p">):</span>
<span class="c1"># ...</span>
<span class="k">def</span><span class="w"> </span><span class="nf">open_chest</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">who</span><span class="p">,</span> <span class="n">tried_key</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">chest</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">who</span><span class="p">,</span> <span class="n">tried_key</span><span class="p">,</span> <span class="s2">&quot;unlock&quot;</span><span class="p">):</span>
<span class="n">who</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;The key does not fit!&quot;</span><span class="p">)</span>
<span class="k">return</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">who</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;The key fits! The chest opens.&quot;</span><span class="p">)</span>
<span class="c1"># ...</span>
</pre></div>
</div>
<p>There are several variations to the default <code class="docutils literal notranslate"><span class="pre">perm</span></code> lockfunc:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">perm_above</span></code> - requires a hierarchical permission <em>higher</em> than the one
provided. Example: <code class="docutils literal notranslate"><span class="pre">&quot;edit:</span> <span class="pre">perm_above(Player)&quot;</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">pperm</span></code> - looks <em>only</em> for permissions on <code class="docutils literal notranslate"><span class="pre">Accounts</span></code>, never at any puppeted
objects (regardless of hierarchical perm or not).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">pperm_above</span></code> - like <code class="docutils literal notranslate"><span class="pre">perm_above</span></code>, but for Accounts only.</p></li>
</ul>
</section>
<section id="some-examples">
<h3>Some examples<a class="headerlink" href="#some-examples" title="Link to this heading"></a></h3>
<p>Adding permissions and checking with locks</p>
<div class="highlight-python notranslate"><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">&quot;Builder&quot;</span><span class="p">)</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">&quot;cool_guy&quot;</span><span class="p">)</span>
<span class="n">account</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">&quot;enter:perm_above(Player) and perm(cool_guy)&quot;</span><span class="p">)</span>
<span class="n">account</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">&quot;enter&quot;</span><span class="p">)</span> <span class="c1"># this returns True!</span>
</pre></div>
</div>
<p>An example of a puppet with a connected account:</p>
<div class="highlight-python notranslate"><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">&quot;Player&quot;</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">&quot;Builders&quot;</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">&quot;cool_guy&quot;</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">&quot;enter:perm_above(Accounts) and perm(cool_guy)&quot;</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">&quot;enter&quot;</span><span class="p">)</span> <span class="c1"># this returns False, since puppet permission</span>
<span class="c1"># is lower than Account&#39;s perm, and perm takes</span>
<span class="c1"># precedence.</span>
</pre></div>
</div>
</section>
</section>
<section id="quelling">
<h2>Quelling<a class="headerlink" href="#quelling" title="Link to this heading"></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 ones Account permission by quelling to a high-permission
Character. Also the superuser can quell their powers this way, making them
affectable by locks.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/evennia_logo.png" alt="Logo of Evennia"/>
</a></p>
<search 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" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
<h3><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Permissions</a><ul>
<li><a class="reference internal" href="#the-super-user">The super user</a></li>
<li><a class="reference internal" href="#working-with-permissions">Working with Permissions</a><ul>
<li><a class="reference internal" href="#the-permission-hierarchy">The permission hierarchy</a></li>
<li><a class="reference internal" href="#checking-permissions">Checking permissions</a></li>
<li><a class="reference internal" href="#checking-with-obj-permissions-check">Checking with obj.permissions.check()</a></li>
<li><a class="reference internal" href="#lock-funcs">Lock funcs</a></li>
<li><a class="reference internal" href="#some-examples">Some examples</a></li>
</ul>
</li>
<li><a class="reference internal" href="#quelling">Quelling</a></li>
</ul>
</li>
</ul>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="Help-System.html"
title="previous chapter">Help System</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="Locks.html"
title="next chapter">Locks</a></p>
</div>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Components/Permissions.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
<li><a href="https://github.com/evennia/evennia">Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Doc Versions</h3>
<ul>
<li>
<a href="https://www.evennia.com/docs/latest/index.html">latest (main branch)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/5.x/index.html">v5.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/4.x/index.html">v4.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/3.x/index.html">v3.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/2.x/index.html">v2.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/1.x/index.html">v1.0.0 branch (outdated)</a>
</li>
<li>
<a href="https://www.evennia.com/docs/0.x/index.html">v0.9.5 branch (outdated)</a>
</li>
</ul>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="Related">
<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="right" >
<a href="Locks.html" title="Locks"
>next</a> |</li>
<li class="right" >
<a href="Help-System.html" title="Help System"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Evennia</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="Components-Overview.html" >Core Components</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Permissions</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2024, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
</div>
</body>
</html>