mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 22:06:30 +01:00
317 lines
No EOL
23 KiB
HTML
317 lines
No EOL
23 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
|
||
<title>Permissions — Evennia 1.0-dev documentation</title>
|
||
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
<script src="../_static/language_data.js"></script>
|
||
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
|
||
<link rel="shortcut icon" href="../_static/favicon.ico"/>
|
||
<link rel="index" title="Index" href="../genindex.html" />
|
||
<link rel="search" title="Search" href="../search.html" />
|
||
</head><body>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="General Index"
|
||
accesskey="I">index</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">Permissions</a></li>
|
||
</ul>
|
||
<div class="develop">develop branch</div>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section class="tex2jax_ignore mathjax_ignore" id="permissions">
|
||
<h1>Permissions<a class="headerlink" href="#permissions" title="Permalink to this headline">¶</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="doc 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="doc 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="doc 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="managing-permissions">
|
||
<h2>Managing Permissions<a class="headerlink" href="#managing-permissions" title="Permalink to this headline">¶</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> perm/account Tommy = Builders
|
||
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="doc std std-doc">Accounts</span></a> Tommy instead of any <a class="reference internal" href="Objects.html"><span class="doc std std-doc">Character</span></a> that also
|
||
happens to be named “Tommy”.</p>
|
||
<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. This is especially important to
|
||
remember when assigning permissions from the <em>hierarchy tree</em> (see below), as 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 internal" href="#quelling"><span class="std std-doc">quelling</span></a>).</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">"Builders"</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">"cool_guy"</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">"Blacksmith"</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">"Blacksmith"</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="the-permission-hierarchy">
|
||
<h2>The permission hierarchy<a class="headerlink" href="#the-permission-hierarchy" title="Permalink to this headline">¶</a></h2>
|
||
<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
|
||
(in increasing order of power):</p>
|
||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> Player # can chat and send tells (default level) (lowest)
|
||
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>
|
||
<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. The Guest is is never part of <code class="docutils literal notranslate"><span class="pre">settings.PERMISSION_HIERARCHY</span></code>.</p>
|
||
</div></blockquote>
|
||
<p>When checking a hierarchical permission (using one of the methods to follow),
|
||
you will pass checks for your level and all <em>below</em> you. That is, even if the
|
||
check explicitly checks for “Builder” level access, you will actually pass if you have
|
||
one of “Builder”, “Admin” or “Developer”. By contrast, if you check for a
|
||
non-hierarchical permission, like “Blacksmith” you <em>must</em> have exactly
|
||
that permission to pass.</p>
|
||
</section>
|
||
<section id="checking-permissions">
|
||
<h2>Checking permissions<a class="headerlink" href="#checking-permissions" title="Permalink to this headline">¶</a></h2>
|
||
<p>It’s important to note that you check for the permission of a <em>puppeted</em>
|
||
<a class="reference internal" href="Objects.html"><span class="doc 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 id="checking-with-obj-permissions-check">
|
||
<h3>Checking with obj.permissions.check()<a class="headerlink" href="#checking-with-obj-permissions-check" title="Permalink to this headline">¶</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("Builder"):
|
||
# allow builder to do stuff
|
||
|
||
if obj.permissions.check("Blacksmith", "Warrior"):
|
||
# do stuff for blacksmiths OR warriors
|
||
|
||
if obj.permissions.check("Blacksmith", "Warrior", 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'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="Permalink to this headline">¶</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="doc 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>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-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="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="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">"unlock"</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">"The key does not fit!"</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">"The key fits! The chest opens."</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">"edit:</span> <span class="pre">perm_above(Player)"</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="Permalink to this headline">¶</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">"Builder"</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">"cool_guy"</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">"enter:perm_above(Player) and perm(cool_guy)"</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">"enter"</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">"Player"</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="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">"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, since puppet permission</span>
|
||
<span class="c1"># is lower than Account's perm, and perm takes</span>
|
||
<span class="c1"># precedence.</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<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 and will always pass the <code class="docutils literal notranslate"><span class="pre">PermissionHandler.check()</span></code> check. This allows
|
||
for the superuser to always have access to everything in an emergency. But it
|
||
could also hide 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 that does not bypass such checks.</p>
|
||
</section>
|
||
<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>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
<div class="clearer"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<p class="logo"><a href="../index.html">
|
||
<img class="logo" src="../_static/evennia_logo.png" alt="Logo"/>
|
||
</a></p>
|
||
<div id="searchbox" style="display: none" role="search">
|
||
<h3 id="searchlabel">Quick search</h3>
|
||
<div class="searchformwrapper">
|
||
<form class="search" action="../search.html" method="get">
|
||
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||
<input type="submit" value="Go" />
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<script>$('#searchbox').show(0);</script>
|
||
<p><h3><a href="../index.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">Permissions</a><ul>
|
||
<li><a class="reference internal" href="#managing-permissions">Managing Permissions</a></li>
|
||
<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><ul>
|
||
<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="#superusers">Superusers</a></li>
|
||
<li><a class="reference internal" href="#quelling">Quelling</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/Permissions.md.txt"
|
||
rel="nofollow">Show Page Source</a></li>
|
||
</ul>
|
||
</div><h3>Links</h3>
|
||
<ul>
|
||
<li><a href="https://www.evennia.com">Home page</a> </li>
|
||
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
||
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
||
<li>
|
||
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
||
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
||
<a href="https://evennia.blogspot.com/">Blog</a>
|
||
</li>
|
||
</ul>
|
||
<h3>Versions</h3>
|
||
<ul>
|
||
<li><a href="Permissions.html">1.0-dev (develop branch)</a></li>
|
||
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
||
</ul>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="General Index"
|
||
>index</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="../index.html">Evennia 1.0-dev</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">Permissions</a></li>
|
||
</ul>
|
||
<div class="develop">develop branch</div>
|
||
</div>
|
||
<div class="footer" role="contentinfo">
|
||
© Copyright 2020, The Evennia developer community.
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
||
</div>
|
||
</body>
|
||
</html> |