From b64bdabe02e5d30113df5052050cfb9b62683a74 Mon Sep 17 00:00:00 2001 From: Jeremy Stanley Date: Tue, 22 Jan 2019 01:44:57 +0000 Subject: [PATCH] Add support for user preferences Make it possible for users to list, view and set values of any account facets white-listed in configuration. Also add administrator-only preferences as a convenience option. To have a means of exercising this, make the active state prompt dynamic so that each user can set it as a preferences. Include sample configuration, regression tests and documentation. --- doc/source/configuration.rst | 35 ++++++++++++++++++++++++++++++++++- doc/source/data_model.rst | 7 ++++++- etc/mudpy.yaml | 7 ++++++- mudpy/command.py | 34 ++++++++++++++++++++++++++++++++++ mudpy/misc.py | 4 ++-- mudpy/tests/fixtures/test_daemon.yaml | 7 ++++++- mudpy/tests/selftest.py | 14 +++++++++++++- share/command.yaml | 10 ++++++++++ 8 files changed, 111 insertions(+), 7 deletions(-) diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst index bca9161..d0f8093 100644 --- a/doc/source/configuration.rst +++ b/doc/source/configuration.rst @@ -2,7 +2,7 @@ configuration =============== -.. Copyright (c) 2004-2018 mudpy authors. Permission to use, copy, +.. Copyright (c) 2004-2019 mudpy authors. Permission to use, copy, modify, and distribute this software is granted under terms provided in the LICENSE file distributed with this software. @@ -422,3 +422,36 @@ written. Example:: .mudpy.timing.status: 6000 + +.mudpy.user +----------- + +.mudpy.user.pref_admin +~~~~~~~~~~~~~~~~~~~~~~ + +list, optional + +This can be used to list facets an administrative user is allowed to +set or override on their own ``account`` element, in addition to any +in the `.mudpy.user.pref_allow`_ list. Note that this is merely a +convenience, as an administrator is already able to call the ``set`` +command to set values for facets of any element. + +Example:: + + .mudpy.user.pref_admin: + - loglevel + +.mudpy.user.pref_allow +~~~~~~~~~~~~~~~~~~~~~~ + +list, optional + +This can be used to list facets any user is allowed to set or +override on their own ``account`` element with the ``preference`` +command. + +Example:: + + .mudpy.user.pref_allow: + - prompt diff --git a/doc/source/data_model.rst b/doc/source/data_model.rst index af7a4b0..807c788 100644 --- a/doc/source/data_model.rst +++ b/doc/source/data_model.rst @@ -2,7 +2,7 @@ data model ============ -.. Copyright (c) 2004-2018 mudpy authors. Permission to use, copy, +.. Copyright (c) 2004-2019 mudpy authors. Permission to use, copy, modify, and distribute this software is granted under terms provided in the LICENSE file distributed with this software. @@ -127,6 +127,11 @@ kept by default. Timing-specific settings and scheduling for the main loop. +.mudpy.user +~~~~~~~~~~~ + +User-focused settings such as access controls. + storage ------- diff --git a/etc/mudpy.yaml b/etc/mudpy.yaml index 3cc39d9..8eccba3 100644 --- a/etc/mudpy.yaml +++ b/etc/mudpy.yaml @@ -1,5 +1,5 @@ --- -_copy: Copyright (c) 2004-2017 mudpy authors. Permission to use, copy, +_copy: Copyright (c) 2004-2019 mudpy authors. Permission to use, copy, modify, and distribute this software is granted under terms provided in the LICENSE file distributed with this software. @@ -89,3 +89,8 @@ _lock: true .mudpy.timing.increment: 0.1 .mudpy.timing.save: 600 .mudpy.timing.status: 6000 + +.mudpy.user.pref_admin: + - loglevel +.mudpy.user.pref_allow: + - prompt diff --git a/mudpy/command.py b/mudpy/command.py index 2eaf383..ebd9036 100644 --- a/mudpy/command.py +++ b/mudpy/command.py @@ -235,6 +235,40 @@ def move(actor, parameters): actor.send("You cannot go that way.") +def preferences(actor, parameters): + """List, view and change actor preferences.""" + message = "" + arguments = parameters.split() + allowed_prefs = set() + user_config = actor.universe.contents.get("mudpy.user") + if user_config: + allowed_prefs.update(user_config.get("pref_allow", [])) + if actor.owner.account.get("administrator"): + allowed_prefs.update(user_config.get("pref_admin", [])) + if not arguments: + message += "These are your current preferences:" + for pref in allowed_prefs: + message += ("$(eol) $(red)%s $(grn)%s$(nrm)" + % (pref, actor.owner.account.get(pref))) + elif arguments[0] not in allowed_prefs: + message += ( + 'Preference "%s" does not exist. Try the `preferences` command by ' + "itself for a list of valid preferences." % arguments[0]) + elif len(arguments) == 1: + message += "%s" % actor.owner.account.get(arguments[0]) + else: + pref = arguments[0] + value = " ".join(arguments[1:]) + try: + actor.owner.account.set(pref, value) + message += 'Preference "%s" set to "%s".' % (pref, value) + except ValueError: + message = ( + 'Preference "%s" cannot be set to type "%s".' % ( + pref, type(value))) + actor.send(message) + + def quit(actor): """Leave the world and go back to the main menu.""" if actor.owner: diff --git a/mudpy/misc.py b/mudpy/misc.py index 930d4d7..2bf4db3 100644 --- a/mudpy/misc.py +++ b/mudpy/misc.py @@ -1,6 +1,6 @@ """Miscellaneous functions for the mudpy engine.""" -# Copyright (c) 2004-2018 mudpy authors. Permission to use, copy, +# Copyright (c) 2004-2019 mudpy authors. Permission to use, copy, # modify, and distribute this software is granted under terms # provided in the LICENSE file distributed with this software. @@ -722,7 +722,7 @@ class User: if not just_prompt: output += "$(eol)" if add_prompt: - output += "> " + output += self.account.get("prompt", ">") + " " mode = self.avatar.get("mode") if mode: output += "(" + mode + ") " diff --git a/mudpy/tests/fixtures/test_daemon.yaml b/mudpy/tests/fixtures/test_daemon.yaml index a2bf565..8edfc59 100644 --- a/mudpy/tests/fixtures/test_daemon.yaml +++ b/mudpy/tests/fixtures/test_daemon.yaml @@ -1,5 +1,5 @@ --- -_copy: Copyright (c) 2004-2017 mudpy authors. Permission to use, copy, +_copy: Copyright (c) 2004-2019 mudpy authors. Permission to use, copy, modify, and distribute this software is granted under terms provided in the LICENSE file distributed with this software. @@ -90,3 +90,8 @@ _lock: true .mudpy.timing.increment: 0.1 .mudpy.timing.save: 5 .mudpy.timing.status: 25 + +.mudpy.user.pref_admin: + - loglevel +.mudpy.user.pref_allow: + - prompt diff --git a/mudpy/tests/selftest.py b/mudpy/tests/selftest.py index 40ea0f3..43e93ae 100644 --- a/mudpy/tests/selftest.py +++ b/mudpy/tests/selftest.py @@ -1,4 +1,4 @@ -# Copyright (c) 2004-2018 mudpy authors. Permission to use, copy, +# Copyright (c) 2004-2019 mudpy authors. Permission to use, copy, # modify, and distribute this software is granted under terms # provided in the LICENSE file distributed with this software. @@ -158,6 +158,17 @@ test_admin_setup = ( (2, "Whom would you like to awaken?", ""), ) +test_preferences = ( + (0, "> ", "preferences"), + (0, r"prompt \x1b\[32m.*> ", "preferences prompt #"), + (0, r"# ", "preferences prompt"), + (0, r"#.*# ", "preferences prompt >"), + (2, "> ", "preferences loglevel 0"), + (2, "> ", "preferences"), + (2, r"loglevel \x1b\[32m0\x1b\[0m.*> ", "preferences loglevel zero"), + (2, r'''cannot be set to type ""\..*> ''', ""), +) + test_crlf_eol = ( # Send a CR+LF at the end of the line instead of the default CR+NUL, # to make sure they're treated the same @@ -303,6 +314,7 @@ dialogue = ( (test_actor_disappears, "actor spontaneous disappearance"), (test_account1_teardown, "second account teardown"), (test_admin_setup, "admin account setup"), + (test_preferences, "set and show preferences"), (test_crlf_eol, "send crlf from the client as eol"), (test_telnet_iac, "escape stray telnet iac bytes"), (test_telnet_unknown, "strip unknown telnet command"), diff --git a/share/command.yaml b/share/command.yaml index 08bf518..6d009b2 100644 --- a/share/command.yaml +++ b/share/command.yaml @@ -54,6 +54,16 @@ command.move.description: Move in a specific direction. command.move.help: You move in a direction by entering:$(eol)$(eol) move north +command.preferences.action: mudpy.command.preferences(actor, parameters) +command.preferences.description: View or change your preferences. +command.preferences.help: If invoked with no parameters, all your current + preferences and their values are listed. If one parameter is supplied, the + value of the preference with that name is displayed. If more than one + parameter is supplied, the first must be the name of a preference and the + remainder is the value to which you wish to change it. + Examples:$(eol)$(eol) preferences$(eol) preferences + prompt$(eol) preferences prompt $ + command.quit.action: mudpy.command.quit(actor) command.quit.description: Leave the World. command.quit.help: This will deactivate your avatar and return you to the main -- 2.11.0