Merge pull request #3347 from volundmush/generate_default_locks
Improved lock-setting logic
This commit is contained in:
commit
5307a6c547
4 changed files with 107 additions and 50 deletions
|
|
@ -276,6 +276,12 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
|
||||||
# Used by account.create_character() to choose default typeclass for characters.
|
# Used by account.create_character() to choose default typeclass for characters.
|
||||||
default_character_typeclass = settings.BASE_CHARACTER_TYPECLASS
|
default_character_typeclass = settings.BASE_CHARACTER_TYPECLASS
|
||||||
|
|
||||||
|
lockstring = (
|
||||||
|
"examine:perm(Admin);edit:perm(Admin);"
|
||||||
|
"delete:perm(Admin);boot:perm(Admin);msg:all();"
|
||||||
|
"noidletimeout:perm(Builder) or perm(noidletimeout)"
|
||||||
|
)
|
||||||
|
|
||||||
# properties
|
# properties
|
||||||
@lazy_property
|
@lazy_property
|
||||||
def cmdset(self):
|
def cmdset(self):
|
||||||
|
|
@ -1411,12 +1417,7 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# A basic security setup
|
# A basic security setup
|
||||||
lockstring = (
|
self.locks.add(self.lockstring)
|
||||||
"examine:perm(Admin);edit:perm(Admin);"
|
|
||||||
"delete:perm(Admin);boot:perm(Admin);msg:all();"
|
|
||||||
"noidletimeout:perm(Builder) or perm(noidletimeout)"
|
|
||||||
)
|
|
||||||
self.locks.add(lockstring)
|
|
||||||
|
|
||||||
# The ooc account cmdset
|
# The ooc account cmdset
|
||||||
self.cmdset.add_default(_CMDSET_ACCOUNT, persistent=True)
|
self.cmdset.add_default(_CMDSET_ACCOUNT, persistent=True)
|
||||||
|
|
|
||||||
|
|
@ -338,9 +338,16 @@ class LockHandler:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if isinstance(lockstring, str):
|
if isinstance(lockstring, str):
|
||||||
lockdefs = lockstring.split(";")
|
lockdefs = [
|
||||||
|
stripped for lockdef in lockstring.split(";") if (stripped := lockdef.strip())
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
lockdefs = [lockdef for locks in lockstring for lockdef in locks.split(";")]
|
lockdefs = [
|
||||||
|
stripped
|
||||||
|
for locks in lockstring
|
||||||
|
for lockdef in locks.split(";")
|
||||||
|
if (stripped := lockdef.strip())
|
||||||
|
]
|
||||||
lockstring = ";".join(lockdefs)
|
lockstring = ";".join(lockdefs)
|
||||||
|
|
||||||
err = ""
|
err = ""
|
||||||
|
|
|
||||||
|
|
@ -213,10 +213,6 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
# Used for sorting / filtering in inventories / room contents.
|
# Used for sorting / filtering in inventories / room contents.
|
||||||
_content_types = ("object",)
|
_content_types = ("object",)
|
||||||
|
|
||||||
# lockstring of newly created objects, for easy overloading.
|
|
||||||
# Will be formatted with the appropriate attributes.
|
|
||||||
lockstring = "control:id({account_id}) or perm(Admin);delete:id({account_id}) or perm(Admin)"
|
|
||||||
|
|
||||||
objects = ObjectManager()
|
objects = ObjectManager()
|
||||||
|
|
||||||
# populated by `return_appearance`
|
# populated by `return_appearance`
|
||||||
|
|
@ -1032,6 +1028,27 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
obj.msg(_(string))
|
obj.msg(_(string))
|
||||||
obj.move_to(home, move_type="teleport")
|
obj.move_to(home, move_type="teleport")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_default_lockstring(
|
||||||
|
cls, account: "DefaultAccount" = None, caller: "DefaultObject" = None, **kwargs
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Classmethod called during .create() to determine default locks for the object.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
account (Account): Account to attribute this object to.
|
||||||
|
caller (DefaultObject): The object which is creating this one.
|
||||||
|
**kwargs: Arbitrary input.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
lockstring (str): A lockstring to use for this object.
|
||||||
|
"""
|
||||||
|
pid = f"pid({account.id})" if account else None
|
||||||
|
cid = f"id({caller.id})" if caller else None
|
||||||
|
admin = "perm(Admin)"
|
||||||
|
trio = " or ".join([x for x in [pid, cid, admin] if x])
|
||||||
|
return ";".join([f"{x}:{trio}" for x in ["control", "delete", "edit"]])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(
|
def create(
|
||||||
cls,
|
cls,
|
||||||
|
|
@ -1080,8 +1097,8 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
|
|
||||||
# Create a sane lockstring if one wasn't supplied
|
# Create a sane lockstring if one wasn't supplied
|
||||||
lockstring = kwargs.get("locks")
|
lockstring = kwargs.get("locks")
|
||||||
if account and not lockstring:
|
if (account or caller) and not lockstring:
|
||||||
lockstring = cls.lockstring.format(account_id=account.id)
|
lockstring = cls.get_default_lockstring(account=account, caller=caller, **kwargs)
|
||||||
kwargs["locks"] = lockstring
|
kwargs["locks"] = lockstring
|
||||||
|
|
||||||
# Create object
|
# Create object
|
||||||
|
|
@ -1100,7 +1117,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
obj.db.desc = desc
|
obj.db.desc = desc
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append("An error occurred while creating this '%s' object." % key)
|
errors.append(f"An error occurred while creating this '{key}' object: {e}")
|
||||||
logger.log_err(e)
|
logger.log_err(e)
|
||||||
|
|
||||||
return obj, errors
|
return obj, errors
|
||||||
|
|
@ -2543,6 +2560,33 @@ class DefaultCharacter(DefaultObject):
|
||||||
"edit:pid({account_id}) or perm(Admin)"
|
"edit:pid({account_id}) or perm(Admin)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_default_lockstring(
|
||||||
|
cls, account: "DefaultAccount" = None, caller: "DefaultObject" = None, **kwargs
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Classmethod called during .create() to determine default locks for the object.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
account (Account): Account to attribute this object to.
|
||||||
|
caller (DefaultObject): The object which is creating this one.
|
||||||
|
**kwargs: Arbitrary input.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
lockstring (str): A lockstring to use for this object.
|
||||||
|
"""
|
||||||
|
pid = f"pid({account.id})" if account else None
|
||||||
|
character = kwargs.get("character", None)
|
||||||
|
cid = f"id({character})" if character else None
|
||||||
|
|
||||||
|
puppet = "puppet:" + " or ".join(
|
||||||
|
[x for x in [pid, cid, "perm(Developer)", "pperm(Developer)"] if x]
|
||||||
|
)
|
||||||
|
delete = "delete:" + " or ".join([x for x in [pid, "perm(Admin)"] if x])
|
||||||
|
edit = "edit:" + " or ".join([x for x in [pid, "perm(Admin)"] if x])
|
||||||
|
|
||||||
|
return ";".join([puppet, delete, edit])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, key, account=None, **kwargs):
|
def create(cls, key, account=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
@ -2613,21 +2657,20 @@ class DefaultCharacter(DefaultObject):
|
||||||
account.characters.add(obj)
|
account.characters.add(obj)
|
||||||
|
|
||||||
# Add locks
|
# Add locks
|
||||||
if not locks and account:
|
if not locks:
|
||||||
# Allow only the character itself and the creator account to puppet this character
|
# Allow only the character itself and the creator account to puppet this character
|
||||||
# (and Developers).
|
# (and Developers).
|
||||||
locks = cls.lockstring.format(character_id=obj.id, account_id=account.id)
|
locks = cls.get_default_lockstring(account=account, character=obj)
|
||||||
elif not locks and not account:
|
|
||||||
locks = cls.lockstring.format(character_id=obj.id, account_id=-1)
|
|
||||||
|
|
||||||
obj.locks.add(locks)
|
if locks:
|
||||||
|
obj.locks.add(locks)
|
||||||
|
|
||||||
# If no description is set, set a default description
|
# If no description is set, set a default description
|
||||||
if description or not obj.db.desc:
|
if description or not obj.db.desc:
|
||||||
obj.db.desc = description if description else _("This is a character.")
|
obj.db.desc = description if description else _("This is a character.")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append(f"An error occurred while creating object '{key} object.")
|
errors.append(f"An error occurred while creating object '{key} object: {e}")
|
||||||
logger.log_err(e)
|
logger.log_err(e)
|
||||||
|
|
||||||
return obj, errors
|
return obj, errors
|
||||||
|
|
@ -2825,14 +2868,6 @@ class DefaultRoom(DefaultObject):
|
||||||
# Generally, a room isn't expected to HAVE a location, but maybe in some games?
|
# Generally, a room isn't expected to HAVE a location, but maybe in some games?
|
||||||
_content_types = ("room",)
|
_content_types = ("room",)
|
||||||
|
|
||||||
# lockstring of newly created rooms, for easy overloading.
|
|
||||||
# Will be formatted with the {id} of the creating object.
|
|
||||||
lockstring = (
|
|
||||||
"control:id({id}) or perm(Admin); "
|
|
||||||
"delete:id({id}) or perm(Admin); "
|
|
||||||
"edit:id({id}) or perm(Admin)"
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(
|
def create(
|
||||||
cls,
|
cls,
|
||||||
|
|
@ -2891,12 +2926,10 @@ class DefaultRoom(DefaultObject):
|
||||||
obj = create.create_object(**kwargs)
|
obj = create.create_object(**kwargs)
|
||||||
|
|
||||||
# Add locks
|
# Add locks
|
||||||
if not locks and account:
|
if not locks:
|
||||||
locks = cls.lockstring.format(id=account.id)
|
locks = cls.get_default_lockstring(account=account, caller=caller, room=obj)
|
||||||
elif not locks and not account:
|
if locks:
|
||||||
locks = cls.lockstring.format(id=obj.id)
|
obj.locks.add(locks)
|
||||||
|
|
||||||
obj.locks.add(locks)
|
|
||||||
|
|
||||||
# Record creator id and creation IP
|
# Record creator id and creation IP
|
||||||
if ip:
|
if ip:
|
||||||
|
|
@ -2909,7 +2942,7 @@ class DefaultRoom(DefaultObject):
|
||||||
obj.db.desc = description if description else _("This is a room.")
|
obj.db.desc = description if description else _("This is a room.")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append("An error occurred while creating this '%s' object." % key)
|
errors.append(f"An error occurred while creating this '{key}' object: {e}")
|
||||||
logger.log_err(e)
|
logger.log_err(e)
|
||||||
|
|
||||||
return obj, errors
|
return obj, errors
|
||||||
|
|
@ -3000,14 +3033,6 @@ class DefaultExit(DefaultObject):
|
||||||
exit_command = ExitCommand
|
exit_command = ExitCommand
|
||||||
priority = 101
|
priority = 101
|
||||||
|
|
||||||
# lockstring of newly created exits, for easy overloading.
|
|
||||||
# Will be formatted with the {id} of the creating object.
|
|
||||||
lockstring = (
|
|
||||||
"control:id({id}) or perm(Admin); "
|
|
||||||
"delete:id({id}) or perm(Admin); "
|
|
||||||
"edit:id({id}) or perm(Admin)"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Helper classes and methods to implement the Exit. These need not
|
# Helper classes and methods to implement the Exit. These need not
|
||||||
# be overloaded unless one want to change the foundation for how
|
# be overloaded unless one want to change the foundation for how
|
||||||
# Exits work. See the end of the class for hook methods to overload.
|
# Exits work. See the end of the class for hook methods to overload.
|
||||||
|
|
@ -3110,11 +3135,10 @@ class DefaultExit(DefaultObject):
|
||||||
obj = create.create_object(**kwargs)
|
obj = create.create_object(**kwargs)
|
||||||
|
|
||||||
# Set appropriate locks
|
# Set appropriate locks
|
||||||
if not locks and account:
|
if not locks:
|
||||||
locks = cls.lockstring.format(id=account.id)
|
locks = cls.get_default_lockstring(account=account, caller=caller, exit=obj)
|
||||||
elif not locks and not account:
|
if locks:
|
||||||
locks = cls.lockstring.format(id=obj.id)
|
obj.locks.add(locks)
|
||||||
obj.locks.add(locks)
|
|
||||||
|
|
||||||
# Record creator id and creation IP
|
# Record creator id and creation IP
|
||||||
if ip:
|
if ip:
|
||||||
|
|
@ -3127,7 +3151,7 @@ class DefaultExit(DefaultObject):
|
||||||
obj.db.desc = description if description else _("This is an exit.")
|
obj.db.desc = description if description else _("This is an exit.")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append("An error occurred while creating this '%s' object." % key)
|
errors.append(f"An error occurred while creating this '{key}' object: {e}")
|
||||||
logger.log_err(e)
|
logger.log_err(e)
|
||||||
|
|
||||||
return obj, errors
|
return obj, errors
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,31 @@ class DefaultObjectTest(BaseEvenniaTest):
|
||||||
# partial match to 'colon' - multimatch error since stack is not homogenous
|
# partial match to 'colon' - multimatch error since stack is not homogenous
|
||||||
self.assertEqual(self.char1.search("co", stacked=2), None)
|
self.assertEqual(self.char1.search("co", stacked=2), None)
|
||||||
|
|
||||||
|
def test_get_default_lockstring_base(self):
|
||||||
|
pattern = f"control:pid({self.account.id}) or id({self.char1.id}) or perm(Admin);delete:pid({self.account.id}) or id({self.char1.id}) or perm(Admin);edit:pid({self.account.id}) or id({self.char1.id}) or perm(Admin)"
|
||||||
|
self.assertEqual(
|
||||||
|
DefaultObject.get_default_lockstring(account=self.account, caller=self.char1), pattern
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_get_default_lockstring_room(self):
|
||||||
|
pattern = f"control:pid({self.account.id}) or id({self.char1.id}) or perm(Admin);delete:pid({self.account.id}) or id({self.char1.id}) or perm(Admin);edit:pid({self.account.id}) or id({self.char1.id}) or perm(Admin)"
|
||||||
|
self.assertEqual(
|
||||||
|
DefaultRoom.get_default_lockstring(account=self.account, caller=self.char1), pattern
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_get_default_lockstring_exit(self):
|
||||||
|
pattern = f"control:pid({self.account.id}) or id({self.char1.id}) or perm(Admin);delete:pid({self.account.id}) or id({self.char1.id}) or perm(Admin);edit:pid({self.account.id}) or id({self.char1.id}) or perm(Admin)"
|
||||||
|
self.assertEqual(
|
||||||
|
DefaultExit.get_default_lockstring(account=self.account, caller=self.char1), pattern
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_get_default_lockstring_character(self):
|
||||||
|
pattern = f"puppet:pid({self.account.id}) or perm(Developer) or pperm(Developer);delete:pid({self.account.id}) or perm(Admin);edit:pid({self.account.id}) or perm(Admin)"
|
||||||
|
self.assertEqual(
|
||||||
|
DefaultCharacter.get_default_lockstring(account=self.account, caller=self.char1),
|
||||||
|
pattern,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestObjectManager(BaseEvenniaTest):
|
class TestObjectManager(BaseEvenniaTest):
|
||||||
"Test object manager methods"
|
"Test object manager methods"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue