Add support for user preferences
authorJeremy Stanley <fungi@yuggoth.org>
Tue, 22 Jan 2019 01:44:57 +0000 (01:44 +0000)
committerJeremy Stanley <fungi@yuggoth.org>
Tue, 22 Jan 2019 02:25:54 +0000 (02:25 +0000)
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
doc/source/data_model.rst
etc/mudpy.yaml
mudpy/command.py
mudpy/misc.py
mudpy/tests/fixtures/test_daemon.yaml
mudpy/tests/selftest.py
share/command.yaml

index bca9161..d0f8093 100644 (file)
@@ -2,7 +2,7 @@
  configuration
 ===============
 
  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.
 
    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
 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
index af7a4b0..807c788 100644 (file)
@@ -2,7 +2,7 @@
  data model
 ============
 
  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.
 
    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.
 
 
 Timing-specific settings and scheduling for the main loop.
 
+.mudpy.user
+~~~~~~~~~~~
+
+User-focused settings such as access controls.
+
 storage
 -------
 
 storage
 -------
 
index 3cc39d9..8eccba3 100644 (file)
@@ -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.
 
     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.timing.increment: 0.1
 .mudpy.timing.save: 600
 .mudpy.timing.status: 6000
+
+.mudpy.user.pref_admin:
+    - loglevel
+.mudpy.user.pref_allow:
+    - prompt
index 2eaf383..ebd9036 100644 (file)
@@ -235,6 +235,40 @@ def move(actor, parameters):
         actor.send("You cannot go that way.")
 
 
         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:
 def quit(actor):
     """Leave the world and go back to the main menu."""
     if actor.owner:
index 930d4d7..2bf4db3 100644 (file)
@@ -1,6 +1,6 @@
 """Miscellaneous functions for the mudpy engine."""
 
 """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.
 
 # 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:
                 if not just_prompt:
                     output += "$(eol)"
                 if add_prompt:
-                    output += "> "
+                    output += self.account.get("prompt", ">") + " "
                     mode = self.avatar.get("mode")
                     if mode:
                         output += "(" + mode + ") "
                     mode = self.avatar.get("mode")
                     if mode:
                         output += "(" + mode + ") "
index a2bf565..8edfc59 100644 (file)
@@ -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.
 
     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.timing.increment: 0.1
 .mudpy.timing.save: 5
 .mudpy.timing.status: 25
+
+.mudpy.user.pref_admin:
+    - loglevel
+.mudpy.user.pref_allow:
+    - prompt
index 40ea0f3..43e93ae 100644 (file)
@@ -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.
 
 # 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?", ""),
 )
 
     (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 "<class 'str'>"\..*> ''', ""),
+)
+
 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
 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_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"),
     (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"),
index 08bf518..6d009b2 100644 (file)
@@ -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.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
 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