Big commit. We now have a respectable command table with built in permission checking. I've commented this pretty well, so see cmdtable.py and cmdhandler.py for more details. There is also some assorted cleanup and an unrelated fix or two resulting from the new Twisted back-end. Note that for the permissions, you will eventually be able to override the codebase's permissions via the web interface for each command.

This commit is contained in:
Greg Taylor 2007-05-22 15:11:56 +00:00
parent 9746382614
commit 204ef6d4c5
7 changed files with 151 additions and 69 deletions

View file

@ -9,17 +9,15 @@ class GenericPerm(models.Model):
permissions = (
("announce", "May use @wall to make announcements"),
("boot", "May use @boot to kick players"),
("builder", "May build"),
("builder", "Can build and modify objects"),
("chown_all", "Can @chown anything to anyone."),
("control_all", "May control everything"),
("examine_all", "Can examine any object"),
("extended_who", "May see extended WHO list"),
("free_money", "Has infinite money"),
("long_fingers", "May get/look/examine etc. from a distance"),
("steal", "May give negative money"),
("set_hide", "May set themself invisible"),
("shutdown", "May @shutdown the site"),
("tel_anywhere", "May @teleport anywhere"),
("tel_anyone", "May @teleport anything"),
("see_session_data", "May see detailed player session data"),
("process_control", "May shutdown/restart/reload the game"),
("manage_players", "Can change passwords, siteban, etc."),
)

View file

@ -133,6 +133,8 @@ class Object(models.Model):
"""
Checks to see whether a user has the specified permission or is a super
user.
perm: (string) A string representing the desired permission.
"""
if not self.is_player():
return False
@ -145,6 +147,28 @@ class Object(models.Model):
else:
return False
def user_has_perm_list(self, perm_list):
"""
Checks to see whether a user has the specified permission or is a super
user. This form accepts an iterable of strings representing permissions,
if the user has any of them return true.
perm: (iterable) An iterable of strings of permissions.
"""
if not self.is_player():
return False
if self.is_superuser():
return True
for perm in perm_list:
# Stop searching perms on the first match.
if self.get_user_account().has_perm(perm):
return True
# Fall through to failure
return False
def owns_other(self, other_obj):
"""
See if the envoked object owns another object.
@ -170,10 +194,9 @@ class Object(models.Model):
if self.owns_other(other_obj):
# If said object owns the target, then give it the green.
return True
else:
# Still pending more stuff here, for now assume we have
# dominance. Bad assumption.
return True
# They've failed to meet any of the above conditions.
return False
def set_home(self, new_home):
"""
@ -643,6 +666,9 @@ class CommChannel(models.Model):
class Meta:
ordering = ['-name']
permissions = (
("emit_commchannel", "May @cemit over channels."),
)
class Admin:
list_display = ('name', 'owner')

View file

@ -1,5 +1,7 @@
from traceback import format_exc
import time
import defines_global
import commands_privileged
import commands_general
import commands_comsys
@ -60,6 +62,9 @@ def handle(cdat):
alias_list = server.cmd_alias_list
parsed_input['root_cmd'] = alias_list.get(parsed_input['root_cmd'],parsed_input['root_cmd'])
# This will hold the reference to the command's function.
cmd = None
if session.logged_in:
# Store the timestamp of the user's last command.
session.cmd_last = time.time()
@ -99,15 +104,28 @@ def handle(cdat):
parsed_input['root_cmd'] = '@cemit'
# Get the command's function reference (Or False)
cmd = cmdtable.return_cfunc(parsed_input['root_cmd'])
cmdtuple = cmdtable.return_cmdtuple(parsed_input['root_cmd'])
if cmdtuple:
# If there is a permissions element to the entry, check perms.
if cmdtuple[1]:
if not session.get_pobject().user_has_perm_list(cmdtuple[1]):
session.msg(defines_global.NOPERMS_MSG)
return
# If flow reaches this point, user has perms and command is ready.
cmd = cmdtuple[0]
else:
# Not logged in, look through the unlogged-in command table.
cmd = cmdtable.return_cfunc(parsed_input['root_cmd'], unlogged_cmd=True)
cmdtuple = cmdtable.return_cmdtuple(parsed_input['root_cmd'], unlogged_cmd=True)
if cmdtuple:
cmd = cmdtuple[0]
# Debugging stuff.
#session.msg("ROOT : %s" % (parsed_input['root_cmd'],))
#session.msg("SPLIT: %s" % (parsed_input['splitted'],))
if not cmd:
raise UnknownCommand
if callable(cmd):
cdat['uinput'] = parsed_input
try:

View file

@ -3,65 +3,79 @@ import commands_general
import commands_privileged
import commands_comsys
"""
Command Table Entries
---------------------
Each command entry consists of a key and a tuple containing a reference to the
command's function, and a tuple of the permissions to match against. The user
only need have one of the permissions in the permissions tuple to gain
access to the command. Obviously, super users don't have to worry about this
stuff. If the command is open to all (or you want to implement your own
privilege checking in the command function), use None in place of the
permissions tuple.
"""
# Unlogged-in Command Table
uncon_ctable = {
"connect": commands_unloggedin.cmd_connect,
"create": commands_unloggedin.cmd_create,
"quit": commands_unloggedin.cmd_quit,
"connect": (commands_unloggedin.cmd_connect, None),
"create": (commands_unloggedin.cmd_create, None),
"quit": (commands_unloggedin.cmd_quit, None),
}
# Command Table
ctable = {
"addcom": commands_comsys.cmd_addcom,
"comlist": commands_comsys.cmd_comlist,
"delcom": commands_comsys.cmd_delcom,
"drop": commands_general.cmd_drop,
"examine": commands_general.cmd_examine,
"get": commands_general.cmd_get,
"help": commands_general.cmd_help,
"idle": commands_general.cmd_idle,
"inventory": commands_general.cmd_inventory,
"look": commands_general.cmd_look,
"page": commands_general.cmd_page,
"pose": commands_general.cmd_pose,
"quit": commands_general.cmd_quit,
"say": commands_general.cmd_say,
"time": commands_general.cmd_time,
"uptime": commands_general.cmd_uptime,
"version": commands_general.cmd_version,
"who": commands_general.cmd_who,
"@ccreate": commands_comsys.cmd_ccreate,
"@cdestroy": commands_comsys.cmd_cdestroy,
"@cemit": commands_comsys.cmd_cemit,
"@clist": commands_comsys.cmd_clist,
"@create": commands_privileged.cmd_create,
"@description": commands_privileged.cmd_description,
"@destroy": commands_privileged.cmd_destroy,
"@dig": commands_privileged.cmd_dig,
"@emit": commands_privileged.cmd_emit,
"@find": commands_privileged.cmd_find,
"@link": commands_privileged.cmd_link,
"@list": commands_privileged.cmd_list,
"@name": commands_privileged.cmd_name,
"@nextfree": commands_privileged.cmd_nextfree,
"@newpassword": commands_privileged.cmd_newpassword,
"@open": commands_privileged.cmd_open,
"@password": commands_privileged.cmd_password,
"@reload": commands_privileged.cmd_reload,
"@set": commands_privileged.cmd_set,
"@shutdown": commands_privileged.cmd_shutdown,
"@teleport": commands_privileged.cmd_teleport,
"@unlink": commands_privileged.cmd_unlink,
"@wall": commands_privileged.cmd_wall,
"addcom": (commands_comsys.cmd_addcom, None),
"comlist": (commands_comsys.cmd_comlist, None),
"delcom": (commands_comsys.cmd_delcom, None),
"drop": (commands_general.cmd_drop, None),
"examine": (commands_general.cmd_examine, None),
"get": (commands_general.cmd_get, None),
"help": (commands_general.cmd_help, None),
"idle": (commands_general.cmd_idle, None),
"inventory": (commands_general.cmd_inventory, None),
"look": (commands_general.cmd_look, None),
"page": (commands_general.cmd_page, None),
"pose": (commands_general.cmd_pose, None),
"quit": (commands_general.cmd_quit, None),
"say": (commands_general.cmd_say, None),
"time": (commands_general.cmd_time, None),
"uptime": (commands_general.cmd_uptime, None),
"version": (commands_general.cmd_version, None),
"who": (commands_general.cmd_who, None),
"@ccreate": (commands_comsys.cmd_ccreate, ("objects.add_commchannel")),
"@cdestroy": (commands_comsys.cmd_cdestroy, ("objects.delete_commchannel")),
"@cemit": (commands_comsys.cmd_cemit, ("objects.emit_commchannel")),
"@clist": (commands_comsys.cmd_clist, None),
"@create": (commands_privileged.cmd_create, ("genperms.builder")),
"@description": (commands_privileged.cmd_description, None),
"@destroy": (commands_privileged.cmd_destroy, ("genperms.builder")),
"@dig": (commands_privileged.cmd_dig, ("genperms.builder")),
"@emit": (commands_privileged.cmd_emit, ("genperms.announce")),
"@find": (commands_privileged.cmd_find, ("genperms.builder")),
"@link": (commands_privileged.cmd_link, ("genperms.builder")),
"@list": (commands_privileged.cmd_list, ("genperms.process_control")),
"@name": (commands_privileged.cmd_name, None),
"@nextfree": (commands_privileged.cmd_nextfree, ("genperms.builder")),
"@newpassword": (commands_privileged.cmd_newpassword, ("genperms.manage_players")),
"@open": (commands_privileged.cmd_open, ("genperms.builder")),
"@password": (commands_privileged.cmd_password, None),
"@reload": (commands_privileged.cmd_reload, ("genperms.process_control")),
"@set": (commands_privileged.cmd_set, None),
"@shutdown": (commands_privileged.cmd_shutdown, ("genperms.process_control")),
"@teleport": (commands_privileged.cmd_teleport, ("genperms.builder")),
"@unlink": (commands_privileged.cmd_unlink, ("genperms.builder")),
"@wall": (commands_privileged.cmd_wall, ("genperms.announce")),
}
def return_cfunc(func_name, unlogged_cmd=False):
def return_cmdtuple(func_name, unlogged_cmd=False):
"""
Returns a reerence to the command's function. If there are no matches,
Returns a reference to the command's tuple. If there are no matches,
returns false.
"""
if not unlogged_cmd:
return ctable.get(func_name, False)
cfunc = ctable.get(func_name, False)
else:
return uncon_ctable.get(func_name, False)
cfunc = uncon_ctable.get(func_name, False)
return cfunc

View file

@ -1,9 +1,9 @@
import os
import resource
import defines_global
from django.contrib.auth.models import User
from apps.objects.models import Object
import defines_global
import cmdhandler
import session_mgr
import functions_general
@ -132,8 +132,12 @@ def cmd_description(cdat):
session.msg("I don't see that here.")
return
else:
new_desc = '='.join(eq_args[1:])
target_obj = results[0]
if not pobject.controls_other(target):
session.msg(defines_global.NOCONTROL_MSG)
return
new_desc = '='.join(eq_args[1:])
session.msg("%s - DESCRIPTION set." % (target_obj,))
target_obj.set_description(new_desc)
@ -403,6 +407,10 @@ def cmd_link(cdat):
# We know we can get the first entry now.
target = target[0]
if not pobject.controls_other(target):
session.msg(defines_global.NOCONTROL_MSG)
return
# If we do something like "@link blah=", we unlink the object.
if len(dest_name) == 0:
@ -451,6 +459,10 @@ def cmd_unlink(cdat):
session.msg("I don't see that here.")
return
else:
if not pobject.controls_other(results[0]):
session.msg(defines_global.NOCONTROL_MSG)
return
results[0].set_home(None)
session.msg("You have unlinked %s." % (results[0],))
@ -558,6 +570,10 @@ def cmd_set(cdat):
return
victim = victim[0]
if not pobject.controls_other(victim):
session.msg(defines_global.NOCONTROL_MSG)
return
attrib_args = eq_args[1].split(':')
if len(attrib_args) > 1:
@ -609,7 +625,9 @@ def cmd_find(cdat):
session = cdat['session']
server = cdat['server']
searchstring = ' '.join(cdat['uinput']['splitted'][1:])
pobject = session.get_pobject()
can_find = pobject.user_has_perm("genperms.builder")
if searchstring == '':
session.msg("No search pattern given.")
return
@ -630,7 +648,8 @@ def cmd_wall(cdat):
"""
session = cdat['session']
wallstring = ' '.join(cdat['uinput']['splitted'][1:])
pobject = session.get_pobject()
if wallstring == '':
session.msg("Announce what?")
return
@ -644,7 +663,8 @@ def cmd_shutdown(cdat):
"""
session = cdat['session']
server = cdat['server']
pobject = session.get_pobject()
session.msg('Shutting down...')
print 'Server shutdown by %s(#%d)' % (session.get_pobject().get_name(), session.get_pobject().id,)
print 'Server shutdown by %s' % (pobject.get_name(show_dbref=False),)
server.shutdown()

View file

@ -34,3 +34,9 @@ NOSET_ATTRIBS = ["MONEY", "ALIAS", "LASTPAGED", "CHANLIST", "LAST", "LASTSITE"]
# Server version number.
EVENNIA_VERSION = 'Pre-Alpha'
# The message to show when the user lacks permissions for something.
NOPERMS_MSG = "You do not have the necessary permissions to do that."
# Message seen when object doesn't control the other object.
NOCONTROL_MSG = "You don't have authority over that object."

View file

@ -35,7 +35,7 @@ class SessionProtocol(StatefulTelnetProtocol):
return self.transport.client
def prep_session(self):
#self.server = server
self.server = self.factory.server
self.address = self.getClientAddress()
self.name = None
self.uid = None
@ -187,7 +187,7 @@ class SessionProtocol(StatefulTelnetProtocol):
cmdhandler.handle(cdat)
functions_general.log_infomsg("Login: %s" % (self,))
pobject.set_attribute("Last", "%s" % (time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()),))
pobject.set_attribute("Lastsite", "%s" % (self.address,))
pobject.set_attribute("Lastsite", "%s" % (self.address[0],))
self.load_user_channels()
def msg(self, message):