mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
is_ooc(): thread session through lock system
This commit is contained in:
parent
3761a7cb21
commit
708662dd48
8 changed files with 57 additions and 24 deletions
|
|
@ -250,7 +250,9 @@ def _progressive_cmd_run(cmd, generator, response=None):
|
|||
if isinstance(value, (int, float)):
|
||||
utils.delay(value, _progressive_cmd_run, cmd, generator)
|
||||
elif isinstance(value, str):
|
||||
_GET_INPUT(cmd.caller, value, _process_input, cmd=cmd, generator=generator)
|
||||
_GET_INPUT(
|
||||
cmd.caller, value, _process_input, session=cmd.session, cmd=cmd, generator=generator
|
||||
)
|
||||
else:
|
||||
raise ValueError("unknown type for a yielded value in command: {}".format(type(value)))
|
||||
|
||||
|
|
@ -698,7 +700,10 @@ def cmdhandler(
|
|||
# Parse the input string and match to available cmdset.
|
||||
# This also checks for permissions, so all commands in match
|
||||
# are commands the caller is allowed to call.
|
||||
matches = yield _COMMAND_PARSER(raw_string, cmdset, caller)
|
||||
try:
|
||||
matches = yield _COMMAND_PARSER(raw_string, cmdset, caller, session=session)
|
||||
except TypeError:
|
||||
matches = yield _COMMAND_PARSER(raw_string, cmdset, caller)
|
||||
|
||||
# Deal with matches
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ def try_num_differentiators(raw_string):
|
|||
return None, None
|
||||
|
||||
|
||||
def cmdparser(raw_string, cmdset, caller, match_index=None):
|
||||
def cmdparser(raw_string, cmdset, caller, match_index=None, session=None, **kwargs):
|
||||
"""
|
||||
This function is called by the cmdhandler once it has
|
||||
gathered and merged all valid cmdsets valid for this particular parsing.
|
||||
|
|
@ -166,7 +166,7 @@ def cmdparser(raw_string, cmdset, caller, match_index=None):
|
|||
matches = build_matches(raw_string, cmdset, include_prefixes=False)
|
||||
|
||||
# only select command matches we are actually allowed to call.
|
||||
matches = [match for match in matches if match[2].access(caller, "cmd")]
|
||||
matches = [match for match in matches if match[2].access(caller, "cmd", session=session)]
|
||||
|
||||
# try to bring the number of matches down to 1
|
||||
if len(matches) > 1:
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ from django.utils.text import slugify
|
|||
from evennia.locks.lockhandler import LockHandler
|
||||
from evennia.utils.ansi import ANSIString
|
||||
from evennia.utils.evtable import EvTable
|
||||
from evennia.utils.utils import fill, is_iter, lazy_property, make_iter
|
||||
from evennia.utils.utils import is_iter, lazy_property, make_iter
|
||||
|
||||
CMD_IGNORE_PREFIXES = settings.CMD_IGNORE_PREFIXES
|
||||
_RE_CMD_LOCKFUNC_IN_LOCKSTRING = re.compile(r"(^|;|\s)cmd\:\w+", re.DOTALL)
|
||||
|
|
@ -383,7 +383,7 @@ class Command(metaclass=CommandMeta):
|
|||
return k, v
|
||||
return None, None
|
||||
|
||||
def access(self, srcobj, access_type="cmd", default=False):
|
||||
def access(self, srcobj, access_type="cmd", default=False, session=None):
|
||||
"""
|
||||
This hook is called by the cmdhandler to determine if srcobj
|
||||
is allowed to execute this command. It should return a boolean
|
||||
|
|
@ -395,9 +395,10 @@ class Command(metaclass=CommandMeta):
|
|||
access_type (str, optional): The lock type to check.
|
||||
default (bool, optional): The fallback result if no lock
|
||||
of matching `access_type` is found on this Command.
|
||||
session (Session, optional): The session to pass to lock functions.
|
||||
|
||||
"""
|
||||
return self.lockhandler.check(srcobj, access_type, default=default)
|
||||
return self.lockhandler.check(srcobj, access_type, default=default, session=session)
|
||||
|
||||
def msg(self, text=None, to_obj=None, from_obj=None, session=None, **kwargs):
|
||||
"""
|
||||
|
|
@ -595,7 +596,7 @@ Command \"{cmdname}\" has no defined `func()` method. Available properties on th
|
|||
"help-entry-detail",
|
||||
kwargs={"category": slugify(self.help_category), "topic": slugify(self.key)},
|
||||
)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
return "#"
|
||||
|
||||
def web_get_admin_url(self):
|
||||
|
|
|
|||
|
|
@ -421,7 +421,9 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
|
|||
cmdset.make_unique(caller)
|
||||
# retrieve all available commands and database / file-help topics.
|
||||
# also check the 'cmd:' lock here
|
||||
cmd_help_topics = [cmd for cmd in cmdset if cmd and cmd.access(caller, "cmd")]
|
||||
cmd_help_topics = [
|
||||
cmd for cmd in cmdset if cmd and cmd.access(caller, "cmd", session=self.session)
|
||||
]
|
||||
# get all file-based help entries, checking perms
|
||||
file_help_topics = {topic.key.lower().strip(): topic for topic in FILE_HELP_ENTRIES.all()}
|
||||
# get db-based help entries, checking perms
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ your settings file:
|
|||
"""
|
||||
|
||||
|
||||
def cmdparser(raw_string, cmdset, caller, match_index=None):
|
||||
def cmdparser(raw_string, cmdset, caller, match_index=None, **kwargs):
|
||||
"""
|
||||
This function is called by the cmdhandler once it has
|
||||
gathered and merged all valid cmdsets valid for this particular parsing.
|
||||
|
|
|
|||
|
|
@ -518,14 +518,13 @@ def is_ooc(accessing_obj, accessed_obj, *args, **kwargs):
|
|||
account = obj.account if utils.inherits_from(obj, evennia.DefaultObject) else obj
|
||||
if not account:
|
||||
return True
|
||||
try:
|
||||
session = accessed_obj.session
|
||||
except AttributeError:
|
||||
# note-this doesn't work well
|
||||
# for high multisession mode. We may need
|
||||
# to change to sessiondb to resolve this
|
||||
sessions = session = account.sessions.get()
|
||||
session = sessions[0] if sessions else None
|
||||
session = kwargs.get("session", None)
|
||||
if session is None:
|
||||
try:
|
||||
session = accessed_obj.session
|
||||
except AttributeError:
|
||||
sessions = account.sessions.get()
|
||||
session = sessions[0] if sessions else None
|
||||
if not session:
|
||||
# this suggests we are not even logged in; treat as ooc.
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ class LockHandler:
|
|||
access_type, rhs = [part.strip() for part in lockdef.split(":", 1)]
|
||||
if not access_type:
|
||||
err = _(
|
||||
"Lock: '{lockdef}' has no access_type " "(left-side of colon is empty)."
|
||||
"Lock: '{lockdef}' has no access_type (left-side of colon is empty)."
|
||||
).format(lockdef=lockdef)
|
||||
if validate_only:
|
||||
return False, err
|
||||
|
|
@ -514,13 +514,15 @@ class LockHandler:
|
|||
|
||||
"""
|
||||
old_lockstring = self.get(access_type)
|
||||
if not lockstring.strip().lower() in old_lockstring.lower():
|
||||
if lockstring.strip().lower() not in old_lockstring.lower():
|
||||
lockstring = "{old} {op} {new}".format(
|
||||
old=old_lockstring, op=op, new=lockstring.strip()
|
||||
)
|
||||
self.add(lockstring)
|
||||
|
||||
def check(self, accessing_obj, access_type, default=False, no_superuser_bypass=False):
|
||||
def check(
|
||||
self, accessing_obj, access_type, default=False, no_superuser_bypass=False, session=None
|
||||
):
|
||||
"""
|
||||
Checks a lock of the correct type by passing execution off to
|
||||
the lock function(s).
|
||||
|
|
@ -580,7 +582,16 @@ class LockHandler:
|
|||
evalstring, func_tup, raw_string = self.locks[access_type]
|
||||
# execute all lock funcs in the correct order, producing a tuple of True/False results.
|
||||
true_false = tuple(
|
||||
bool(tup[0](accessing_obj, self.obj, *tup[1], access_type=access_type, **tup[2]))
|
||||
bool(
|
||||
tup[0](
|
||||
accessing_obj,
|
||||
self.obj,
|
||||
*tup[1],
|
||||
access_type=access_type,
|
||||
session=session,
|
||||
**tup[2],
|
||||
)
|
||||
)
|
||||
for tup in func_tup
|
||||
)
|
||||
# the True/False tuple goes into evalstring, which combines them
|
||||
|
|
|
|||
|
|
@ -7,13 +7,15 @@ the stability and integrity of the codebase during updates.
|
|||
This module tests the lock functionality of Evennia.
|
||||
|
||||
"""
|
||||
|
||||
from evennia.server.serversession import ServerSession
|
||||
from evennia.utils.test_resources import BaseEvenniaTest
|
||||
|
||||
try:
|
||||
# this is a special optimized Django version, only available in current Django devel
|
||||
from django.utils.unittest import TestCase, override_settings
|
||||
from django.utils.unittest import override_settings
|
||||
except ImportError:
|
||||
from django.test import TestCase, override_settings
|
||||
from django.test import override_settings
|
||||
|
||||
from evennia import settings_default
|
||||
from evennia.locks import lockfuncs
|
||||
|
|
@ -220,6 +222,19 @@ class TestLockfuncs(BaseEvenniaTest):
|
|||
self.account.unpuppet_all()
|
||||
self.assertEqual(True, lockfuncs.is_ooc(self.account, self.char1))
|
||||
|
||||
def test_is_ooc__multi_session_mixed(self):
|
||||
"""Test that two sessions on the same account can have different IC/OOC states."""
|
||||
ic_session = self.session
|
||||
|
||||
# Create a bare unpuppeted session. Full login flow steals the puppet from ic_session in
|
||||
# MULTISESSION_MODE 0.
|
||||
ooc_session = ServerSession()
|
||||
ooc_session.sessid = 2
|
||||
ooc_session.puppet = None
|
||||
|
||||
self.assertFalse(lockfuncs.is_ooc(self.account, self.char1, session=ic_session))
|
||||
self.assertTrue(lockfuncs.is_ooc(self.account, self.char1, session=ooc_session))
|
||||
|
||||
|
||||
class TestPermissionCheck(BaseEvenniaTest):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue