- Implemented permission system management inside the game

- changed @chperm to @setperm to avoid confusion with channel commands
- added @setgroup command for adding user group permissions
- Moved permissions/group setup into settings file to allow admins to tweak without going into evennia engine.
- Add all new players to default permission group (defined in settings)
- Defined a basic group hierarchy, removed permission 'genperms.builder' in favour of a group named builders instead, containing all relevant permissions.
- Filtered out all django's automatic permissions in @setperm/list to make permission system more controlled by admin.
- Probably fixed bug that caused new users to not be signed up to channels (more testing needed)
- Added Exception handler in unloggedin method create, this was killing tracebacks upon user creation.
/Griatch
This commit is contained in:
Griatch 2009-10-03 14:40:34 +00:00
parent 77f2186d9a
commit 7f7306a6e4
23 changed files with 341 additions and 214 deletions

View file

@ -2,6 +2,7 @@
Models for the help system.
"""
from django.db import models
from django.conf import settings
from django.contrib.auth.models import User, Group
from src.objects.models import Object
from src.ansi import parse_ansi
@ -22,10 +23,7 @@ class CommChannel(models.Model):
class Meta:
ordering = ['-name']
permissions = (
('emit_commchannel', 'May @cemit over channels.'),
('channel_admin', 'May administer comm channels.')
)
permissions = settings.PERM_CHANNELS
def get_name(self):
"""
@ -113,8 +111,9 @@ class CommChannelMessage(models.Model):
message = models.TextField()
date_sent = models.DateTimeField(editable=False, auto_now_add=True)
class Meta:
ordering = ['-date_sent']
def __str__(self):
return "%s: %s" % (self.channel.name, self.message)
class Meta:
ordering = ['-date_sent']

View file

@ -175,7 +175,7 @@ def cmd_batchprocess(command):
source_object = command.source_object
#check permissions
#check permissions; this is a superuser only command.
if not source_object.is_superuser():
source_object.emit_to(defines_global.NOPERMS_MSG)
return

View file

@ -10,10 +10,6 @@ from src import ansi
from src.util import functions_general
from src.objects.models import Object
from src.cmdtable import GLOBAL_CMD_TABLE
#from src.imc2.models import IMC2ChannelMapping
#from src.imc2.packets import IMC2PacketIceMsgBroadcasted
#from src.irc.models import IRCChannelMapping
#from src.irc.connection import IRC_CHANNELS
def cmd_addcom(command):
"""
@ -85,9 +81,7 @@ def cmd_addcom(command):
except CommChannel.DoesNotExist:
# Failed to match iexact on channel's 'name' attribute.
source_object.emit_to("Could not find channel %s." % chan_name)
GLOBAL_CMD_TABLE.add_command("addcom", cmd_addcom),
GLOBAL_CMD_TABLE.add_command("addcom", cmd_addcom)
def cmd_delcom(command):
"""
@ -275,14 +269,13 @@ def cmd_cdestroy(command):
source_object.emit_to("Could not find channel %s." % (cname,))
else:
is_controlled_by_plr = name_matches[0].controlled_by(source_object)
if is_controlled_by_plr:
if is_controlled_by_plr or source_object.has_perm("channels.channel_admin"):
source_object.emit_to("Channel %s destroyed." % (name_matches[0],))
name_matches.delete()
else:
source_object.emit_to("Permission denied.")
return
GLOBAL_CMD_TABLE.add_command("@cdestroy", cmd_cdestroy,
priv_tuple=("objects.delete_commchannel")),
GLOBAL_CMD_TABLE.add_command("@cdestroy", cmd_cdestroy)
def cmd_cset(command):
"""
@ -327,7 +320,7 @@ def cmd_cboot(command):
return
#do we have power over this channel?
if not channel.controlled_by(source_object):
if not channel.controlled_by(source_object) or source_object.has_perm("channels.channel_admin"):
source_object.emit_to("You don't have that power in channel '%s'." % cname)
return
@ -432,7 +425,7 @@ def cmd_cemit(command):
#pipe to external channels (IRC, IMC) eventually mapped to this channel
comsys.send_cexternal(cname_parsed, cmessage, caller=source_object)
GLOBAL_CMD_TABLE.add_command("@cemit", cmd_cemit),
GLOBAL_CMD_TABLE.add_command("@cemit", cmd_cemit,priv_tuple=("channels.emit_commchannel",))
def cmd_cwho(command):
"""
@ -503,8 +496,7 @@ def cmd_ccreate(command):
# Create and set the object up.
new_chan = comsys.create_channel(cname, source_object)
source_object.emit_to("Channel %s created." % (new_chan.get_name(),))
GLOBAL_CMD_TABLE.add_command("@ccreate", cmd_ccreate,
priv_tuple=("objects.add_commchannel",))
GLOBAL_CMD_TABLE.add_command("@ccreate", cmd_ccreate)
def cmd_cchown(command):
"""
@ -526,7 +518,7 @@ def cmd_cchown(command):
source_object.emit_to("Channel '%s' not found." % cname)
return
#check so we have ownership to give away.
if not channel.controlled_by(source_object):
if not channel.controlled_by(source_object) and not source_object.has_perm("channels.channel_admin"):
source_object.emit_to("You don't control this channel.")
return
#find the new owner

View file

@ -4,6 +4,7 @@ now.
"""
import time
from django.conf import settings
from django.contrib.auth.models import User
from src.config.models import ConfigValue
from src.helpsys.models import HelpEntry
from src.objects.models import Object
@ -334,7 +335,7 @@ def cmd_examine(command):
# Send it all
source_object.emit_to(s)
GLOBAL_CMD_TABLE.add_command("examine", cmd_examine)
GLOBAL_CMD_TABLE.add_command("examine", cmd_examine,priv_tuple=("objects.info",))
def cmd_quit(command):
"""
@ -452,6 +453,31 @@ def cmd_pose(command):
source_object.get_location().emit_to_contents(sent_msg)
GLOBAL_CMD_TABLE.add_command("pose", cmd_pose)
def cmd_group(command):
"""@group
Usage:
@group
This command shows you which user permission groups you are a member of, if any.
"""
source_object = command.source_object
user = User.objects.get(username=source_object.get_name(show_dbref=False,no_ansi=True))
s = ""
if source_object.is_superuser():
s += "\n This is a SUPERUSER account! Group membership does not matter."
if not user.is_active:
s += "\n ACCOUNT NOT ACTIVE."
for g in user.groups.all():
s += "\n -- %s" % g
for p in g.permissions.all():
s += "\n --- %s" % p.name
if not s:
s = "You are not a member of any groups." % source_object.get_name(show_dbref=False)
else:
s = "\nYour (%s's) group memberships: %s" % (source_object.get_name(show_dbref=False),s)
source_object.emit_to(s)
GLOBAL_CMD_TABLE.add_command("@group", cmd_group,auto_help=True)
def cmd_help(command):
"""
@ -539,8 +565,8 @@ def cmd_help(command):
if 'add' in switches:
#try to add/replace help text for a command
if not source_object.is_staff():
source_object.emit_to("Only staff can add new help entries.")
if not source_object.has_perm("helpsys.add_help"):
source_object.emit_to(defines_global.NOPERMS_MSG)
return
spl = (topicstr.split(':',1))
if len(spl) != 2:
@ -559,11 +585,11 @@ def cmd_help(command):
elif 'append' in switches or 'app' in switches:
#append text to a help entry
if not source_object.is_staff():
source_object.emit_to("Only staff can append to help entries.")
if not source_object.has_perm("helpsys.add_help"):
source_object.emit_to(defines_global.NOPERMS_MSG)
return
spl = (topicstr.split(':',1))
if len(spl) != 2:
if len(spl) != 2:
source_object.emit_to("""Format is help/append <topic>:<text to add>
Use the /newline switch to make a new paragraph.""")
return
@ -582,8 +608,8 @@ def cmd_help(command):
elif 'del' in switches or 'delete' in switches:
#delete a help entry
if not source_object.is_staff():
source_object.emit_to("Only staff can add delete help entries.")
if not source_object.has_perm("helpsys.del_help"):
source_object.emit_to(defines_global.NOPERMS_MSG)
return
topics = edit_help.del_help(source_object,topicstr)
if type(topics) != type(list()):

View file

@ -117,7 +117,8 @@ def cmd_imcstatus(command):
retval += '-' * 50
source_object.emit_to(retval)
GLOBAL_CMD_TABLE.add_command("imcstatus", cmd_imcstatus)
GLOBAL_CMD_TABLE.add_command("imcstatus", cmd_imcstatus,
priv_tuple=('imc2.admin_imc_channels',))
def cmd_IMC2chan(command):
@ -179,5 +180,5 @@ def cmd_IMC2chan(command):
source_object.emit_to(outstring)
GLOBAL_CMD_TABLE.add_command("@imc2chan",cmd_IMC2chan,auto_help=True,staff_help=True,
priv_tuple=("objects.add_commchannel",))
priv_tuple=("imc2.admin_imc_channels",))

View file

@ -99,7 +99,7 @@ def cmd_list(command):
source_object.emit_to("Flags: "+" ".join(flags.SERVER_FLAGS))
else:
source_object.emit_to(msg_invalid)
GLOBAL_CMD_TABLE.add_command("@list", cmd_list),
GLOBAL_CMD_TABLE.add_command("@list", cmd_list,priv_tuple=("genperms.game_info",)),
def cmd_ps(command):
"""
@ -131,4 +131,4 @@ def cmd_stats(command):
stats_dict["things"],
stats_dict["players"],
stats_dict["garbage"]))
GLOBAL_CMD_TABLE.add_command("@stats", cmd_stats),
GLOBAL_CMD_TABLE.add_command("@stats", cmd_stats, priv_tuple=("genperms.game_info",)),

View file

@ -56,7 +56,7 @@ def cmd_IRC2chan(command):
source_object.emit_to(outstring)
GLOBAL_CMD_TABLE.add_command("@irc2chan",cmd_IRC2chan,auto_help=True,staff_help=True,
priv_tuple=("objects.add_commchannel",))
priv_tuple=("irc.admin_irc_channels",))
def cmd_IRCjoin(command):
"""
@ -101,7 +101,7 @@ def cmd_IRCjoin(command):
GLOBAL_CMD_TABLE.add_command("@ircjoin",cmd_IRCjoin,auto_help=True,
staff_help=True,
priv_tuple=("objects.add_commchannel",))
priv_tuple=("irc.admin_irc_channels",))
def cmd_IRCchanlist(command):
"""

View file

@ -65,7 +65,7 @@ def cmd_teleport(command):
source_object.move_to(target_obj, quiet=tel_quietly)
GLOBAL_CMD_TABLE.add_command("@teleport", cmd_teleport,
priv_tuple=("genperms.builder"))
priv_tuple=("objects.teleport",))
def cmd_alias(command):
"""
@ -165,7 +165,7 @@ def cmd_wipe(command):
target_obj.clear_attribute(attr.get_name())
source_object.emit_to("%s - %d attributes wiped." % (target_obj.get_name(),
len(attr_matches)))
GLOBAL_CMD_TABLE.add_command("@wipe", cmd_wipe)
GLOBAL_CMD_TABLE.add_command("@wipe", cmd_wipe,priv_tuple=("objects.wipe",))
def cmd_set(command):
"""
@ -250,7 +250,7 @@ def cmd_set(command):
s += '\nFlag %s=%s set.' % (target_name, flag.upper())
target.set_flag(flag, True)
source_object.emit_to(s[1:])
GLOBAL_CMD_TABLE.add_command("@set", cmd_set)
GLOBAL_CMD_TABLE.add_command("@set", cmd_set, priv_tuple=("objects.modify_attributes",))
def cmd_cpattr(command):
"""
@ -332,7 +332,7 @@ def cmd_cpattr(command):
to_objname, to_attr)
source_object.emit_to(s)
GLOBAL_CMD_TABLE.add_command("@cpattr", cmd_cpattr,
priv_tuple=("genperms.builder",))
priv_tuple=("objects.modify_attributes",))
def cmd_mvattr(command):
@ -394,7 +394,7 @@ def cmd_mvattr(command):
source_object.emit_to(s)
GLOBAL_CMD_TABLE.add_command("@mvattr", cmd_mvattr,
priv_tuple=("genperms.builder",))
priv_tuple=("objects.modify_attributes",))
def cmd_find(command):
"""
@ -420,7 +420,7 @@ def cmd_find(command):
else:
source_object.emit_to("No name matches found for: %s" % (searchstring,))
GLOBAL_CMD_TABLE.add_command("@find", cmd_find,
priv_tuple=("genperms.builder"))
priv_tuple=("objects.info",))
def cmd_create(command):
"""
@ -474,7 +474,7 @@ def cmd_create(command):
GLOBAL_CMD_TABLE.add_command("@create", cmd_create,
priv_tuple=("genperms.builder"),auto_help=True,staff_help=True)
priv_tuple=("objects.create",),auto_help=True,staff_help=True)
def cmd_copy(command):
"""Usage:
@ -539,7 +539,7 @@ def cmd_copy(command):
reset_text = " (using default attrs/flags)"
source_object.emit_to("Copied object '%s'%s%s%s." % (objname,name_text,loc_text,reset_text))
GLOBAL_CMD_TABLE.add_command("@copy", cmd_copy,
priv_tuple=("genperms.builder"),auto_help=True,staff_help=True)
priv_tuple=("objects.create",),auto_help=True,staff_help=True)
@ -552,7 +552,7 @@ def cmd_nextfree(command):
nextfree = Object.objects.get_nextfree_dbnum()
command.source_object.emit_to("Next free object number: #%s" % nextfree)
GLOBAL_CMD_TABLE.add_command("@nextfree", cmd_nextfree,
priv_tuple=("genperms.builder"),auto_help=True,staff_help=True)
priv_tuple=("objects.info",),auto_help=True,staff_help=True)
def cmd_open(command):
"""
@ -625,7 +625,7 @@ def cmd_open(command):
None)
source_object.emit_to("You open an unlinked exit - %s" % new_object)
GLOBAL_CMD_TABLE.add_command("@open", cmd_open,
priv_tuple=("genperms.builder"))
priv_tuple=("objects.dig",))
def cmd_chown(command):
"""
@ -655,7 +655,7 @@ def cmd_chown(command):
if not target_obj:
return
if not source_object.controls_other(target_obj):
if not source_object.controls_other(target_obj) and not source_object.has_perm("objects.admin_ownership"):
source_object.emit_to(defines_global.NOCONTROL_MSG)
return
@ -676,7 +676,7 @@ def cmd_chown(command):
# We haven't provided a target.
source_object.emit_to("Who should be the new owner of the object?")
return
GLOBAL_CMD_TABLE.add_command("@chown", cmd_chown)
GLOBAL_CMD_TABLE.add_command("@chown", cmd_chown, priv_tuple=("objects.modify_attributes","objects.admin_ownership"))
def cmd_chzone(command):
"""
@ -728,7 +728,7 @@ def cmd_chzone(command):
# We haven't provided a target zone.
source_object.emit_to("What should the object's zone be set to?")
return
GLOBAL_CMD_TABLE.add_command("@chzone", cmd_chzone)
GLOBAL_CMD_TABLE.add_command("@chzone", cmd_chzone, priv_tuple=("objects.dig",))
def cmd_link(command):
"""
@ -780,7 +780,7 @@ def cmd_link(command):
source_object.emit_to("You must provide a destination to link to.")
return
GLOBAL_CMD_TABLE.add_command("@link", cmd_link,
priv_tuple=("genperms.builder"))
priv_tuple=("objects.dig",))
def cmd_unlink(command):
"""
@ -806,7 +806,7 @@ def cmd_unlink(command):
target_obj.set_home(None)
source_object.emit_to("You have unlinked %s." % target_obj.get_name())
GLOBAL_CMD_TABLE.add_command("@unlink", cmd_unlink,
priv_tuple=("genperms.builder"))
priv_tuple=("objects.dig",))
def cmd_dig(command):
"""
@ -933,7 +933,7 @@ def cmd_dig(command):
source_object.move_to(new_room)
GLOBAL_CMD_TABLE.add_command("@dig", cmd_dig,
priv_tuple=("genperms.builder"),)
priv_tuple=("objects.dig",))
def cmd_name(command):
"""
@ -1080,7 +1080,7 @@ def cmd_recover(command):
GLOBAL_CMD_TABLE.add_command("@recover", cmd_recover,
priv_tuple=("genperms.builder"),auto_help=True,staff_help=True)
priv_tuple=("objects.create",),auto_help=True,staff_help=True)
def cmd_destroy(command):
"""
@ -1157,4 +1157,4 @@ def cmd_destroy(command):
source_object.emit_to("You schedule %s for destruction." % target_obj.get_name())
GLOBAL_CMD_TABLE.add_command("@destroy", cmd_destroy,
priv_tuple=("genperms.builder"),auto_help=True,staff_help=True)
priv_tuple=("objects.create",),auto_help=True,staff_help=True)

View file

@ -127,4 +127,4 @@ def cmd_page(command):
# Now set the LASTPAGED attribute
source_object.set_attribute("LASTPAGED", ','.join(
["#%d" % (x.id) for x in targets]))
GLOBAL_CMD_TABLE.add_command("page", cmd_page),
GLOBAL_CMD_TABLE.add_command("page", cmd_page, priv_tuple=('channels.page',))

View file

@ -3,9 +3,7 @@ This file contains commands that require special permissions to use. These
are generally @-prefixed commands, but there are exceptions.
"""
from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group
from django.contrib.auth.models import User
from django.contrib.auth.models import Permission, Group, User
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from src.objects.models import Object
@ -133,7 +131,7 @@ def cmd_newpassword(command):
newpass = eq_args[1]
if not command.command_argument or len(searchstring) == 0:
source_object.emit_to("What player's password do you want to change")
source_object.emit_to("What player's password do you want to change?")
return
if len(newpass) == 0:
source_object.emit_to("You must supply a new password.")
@ -256,17 +254,30 @@ def cmd_shutdown(command):
GLOBAL_CMD_TABLE.add_command("@shutdown", cmd_shutdown,
priv_tuple=("genperms.process_control",))
def cmd_chperm(command):
"""@chperm
# permission administration
# Django automatically creates a host of permissions that we don't want to
# mess with, but which are not very useful from inside the game. While these
# permissions are ok to use, we only show the permissions that we have defined
# in our settings file in order to give better control.
APPS_NOSHOW = ("news","admin","auth","config","contentypes",
"flatpages","news","sessions","sites")
SETTINGS_PERM_NAMES = []
for apps in settings.PERM_ALL_DEFAULTS + settings.PERM_ALL_CUSTOM:
for permtuples in apps:
SETTINGS_PERM_NAMES.append(permtuples[1])
def cmd_setperm(command):
"""@setperm
Usage:
@chperm[/switch] [<user>] = [<permission>]
@setperm[/switch] [<user>] = [<permission>]
Switches:
add : add a permission from <user>
del : delete a permission from <user>
list : list all permissions, or those set on <user>
@chperm (change permission) sets/clears individual permission bits on a user.
This command sets/clears individual permission bits on a user.
Use /list without any arguments to see all available permissions or those
defined on the <user> argument.
"""
@ -276,32 +287,31 @@ def cmd_chperm(command):
if not args:
if "list" not in switches:
source_object.emit_to("Usage: @chperm[/switch] [user] = [permission]")
source_object.emit_to("Usage: @setperm[/switch] [user] = [permission]")
return
else:
#just print all available permissions
s = "\n---Permission name %s ---Description" % (24 * " ")
for p in Permission.objects.all():
permlist = [perm for perm in Permission.objects.all() if perm.content_type.app_label not in APPS_NOSHOW and
perm.name in SETTINGS_PERM_NAMES]
for p in permlist:
app = p.content_type.app_label
s += "\n%s.%s%s\t%s" % (app, p.codename, (35 - len(app) - len(p.codename)) * " ", p.name)
if app not in APPS_NOSHOW:
s += "\n%s.%s%s\t%s" % (app, p.codename, (35 - len(app) - len(p.codename)) * " ", p.name)
source_object.emit_to(s)
return
#we have command arguments.
arglist = args.split('=',1)
obj_name = arglist[0].strip()
if not obj_name:
source_object.emit_to("Usage: @chperm[/switch] [user] [= permission]")
source_object.emit_to("Usage: @setperm[/switch] [user] [= permission]")
return
obj = source_object.search_for_object(obj_name)
if not obj:
return
if not obj.is_player():
source_object.emit_to("Only players may have permissions.")
return
try:
user = User.objects.get(username=obj.get_name(show_dbref=False,no_ansi=True))
except:
raise
user = obj.get_user_account()
if not user:
return
if len(arglist) == 1:
#if we didn't have any =, we list the permissions set on <object>.
s = ""
@ -312,16 +322,18 @@ def cmd_chperm(command):
if obj.is_staff():
s += "\n Member of staff (can enter Admin interface)"
aperms = user.get_all_permissions()
if aperms:
s += "\n Extra User permissions:"
gperms = user.get_group_permissions()
for p in aperms:
if p in gperms:
s += "\n --- %s (from group)" % p
else:
s += "\n ---- %s (custom assigned)" % p
gperms = user.get_group_permissions()
uperms = [perm for perm in aperms if perm not in gperms]
if gperms:
s += "\n Group-inherited Permissions:"
for p in gperms:
s += "\n --- %s" % p
if uperms:
s += "\n Individually granted Permisssions:"
for p in uperms:
s += "\n ---- %s" % p
if not s:
s = "User %s has no extra permissions." % obj.get_name()
s = "User %s has no permissions." % obj.get_name()
else:
s = "\nPermissions for user %s: %s" % (obj.get_name(),s)
source_object.emit_to(s)
@ -338,11 +350,11 @@ def cmd_chperm(command):
except Permission.DoesNotExist:
source_object.emit_to("Permission type '%s' is not a valid permission.\nUse @chperm/list for help with valid permission strings." % perm_string)
return
if not switches:
source_object.emit_to("You must supply a switch /add or /del.")
return
if "add" in switches:
#add the permission to this user
if not source_object.has_perm("auth.add_permission"):
source_object.emit_to(defines_global.NOPERMS_MSG)
return
#add the permission to this user
if user.is_superuser:
source_object.emit_to("As a superuser you always have all permissions.")
return
@ -350,16 +362,12 @@ def cmd_chperm(command):
source_object.emit_to("User already has this permission.")
return
user.user_permissions.add(permission)
user.save()
obj.save()
user.save();obj.save()
source_object.emit_to("%s gained the permission '%s'." % (obj.get_name(), permission.name))
obj.emit_to("%s gave you the permission '%s'." % (source_object.get_name(show_dbref=False,no_ansi=True),
permission.name))
if "del" in switches:
#delete the permission from this user
if not source_object.has_perm("auth.delete_permission"):
source_object.emit_to(defines_global.NOPERMS_MSG)
return
if user.is_superuser:
source_object.emit_to("As a superuser you always have all permissions.")
return
@ -367,25 +375,24 @@ def cmd_chperm(command):
source_object.emit_to("User is already lacking this permission.")
return
user.user_permissions.remove(permission)
user.save()
obj.save()
user.save();obj.save()
source_object.emit_to("%s lost the permission '%s'." % (obj.get_name(), permission.name))
obj.emit_to("%s removed your permission '%s'." % (source_object.get_name(show_dbref=False,no_ansi=True),
permission.name))
GLOBAL_CMD_TABLE.add_command("@chperm", cmd_chperm,
priv_tuple=("auth.change_permission",), auto_help=True, staff_help=True)
GLOBAL_CMD_TABLE.add_command("@setperm", cmd_setperm,
priv_tuple=("auth.change_permission","genperms.admin_perm"), auto_help=True, staff_help=True)
def cmd_chgroup(command):
"""@chgroup
def cmd_setgroup(command):
"""@setgroup
Usage:
@chgroup[/switch] [<user>] [= <group>]
@setgroup[/switch] [<user>] [= <group>]
switches
add : add user to a group
del : remove user from a group
list : list all groups a user is part of, or list all available groups if no user is given
Changes the group membership of a user.
Changes and views the group membership of a user.
"""
source_object = command.source_object
args = command.command_argument
@ -393,7 +400,7 @@ def cmd_chgroup(command):
if not args:
if "list" not in switches:
source_object.emit_to("Usage: @chgroup[/switch] [user] [= permission]")
source_object.emit_to("Usage: @setgroup[/switch] [user] [= permission]")
return
else:
#just print all available permissions
@ -402,14 +409,15 @@ def cmd_chgroup(command):
s += "\n %s" % g.name
for p in g.permissions.all():
app = p.content_type.app_label
s += "\n --- %s.%s%s\t%s" % (app, p.codename, (35 - len(app) - len(p.codename)) * " ", p.name)
if app not in APPS_NOSHOW:
s += "\n --- %s.%s%s\t%s" % (app, p.codename, (35 - len(app) - len(p.codename)) * " ", p.name)
source_object.emit_to(s)
return
#we have command arguments.
arglist = args.split('=',1)
obj_name = arglist[0].strip()
if not obj_name:
source_object.emit_to("Usage: @chgroup[/switch] [user] = [permission]")
source_object.emit_to("Usage: @setgroup[/switch] [user] = [permission]")
return
obj = source_object.search_for_object(obj_name)
if not obj:
@ -417,10 +425,9 @@ def cmd_chgroup(command):
if not obj.is_player():
source_object.emit_to("Only players may be members of permission groups.")
return
try:
user = User.objects.get(username=obj.get_name(show_dbref=False,no_ansi=True))
except:
raise
user = obj.get_user_account()
if not user:
return
if len(arglist) == 1:
#if we didn't have any =, we list the groups this user is member of
s = ""
@ -429,7 +436,10 @@ def cmd_chgroup(command):
if not user.is_active:
s += "\n ACCOUNT NOT ACTIVE."
for g in user.groups.all():
s += "\n --- %s" % g
s += "\n --- %s" % g
for p in g.permissions.all():
app = p.content_type.app_label
s += "\n -- %s.%s%s\t%s" % (app, p.codename, (35 - len(app) - len(p.codename)) * " ", p.name)
if not s:
s = "User %s is not a member of any groups." % obj.get_name()
else:
@ -439,15 +449,15 @@ def cmd_chgroup(command):
# we supplied an argument on the form obj = group
group_string = arglist[1].strip()
try:
group = Group.objects.get(name=group_string)
group = Group.objects.get(name=group_string)
except Group.DoesNotExist:
source_object.emit_to("Group '%s' is not a valid group. Remember that the name is case-sensitive.\nUse @chperm/list for help with valid group names." % group_string)
return
if not switches:
source_object.emit_to("You must supply a switch /add or /del.")
return
if "add" in switches:
#add the user to this group
if not source_object.has_perm("auth.add_group"):
source_object.emit_to(defines_global.NOPERMS_MSG)
return
if user.is_superuser:
source_object.emit_to("As a superuser, group access does not matter.")
return
@ -455,16 +465,12 @@ def cmd_chgroup(command):
source_object.emit_to("User is already a member of this group.")
return
user.groups.add(group)
user.save()
obj.save()
user.save(); obj.save()
source_object.emit_to("%s added to group '%s'." % (obj.get_name(), group.name))
obj.emit_to("%s added you to the group '%s'." % (source_object.get_name(show_dbref=False,no_ansi=True),
group.name))
if "del" in switches:
#delete the permission from this user
if not source_object.has_perm("auth.delete_group"):
source_object.emit_to(defines_global.NOPERMS_MSG)
return
if user.is_superuser:
source_object.emit_to("As a superuser, group access does not matter.")
return
@ -473,10 +479,10 @@ def cmd_chgroup(command):
return
user.groups.remove(group)
user.save()
obj.save()
user.save(); obj.save()
source_object.emit_to("%s was removed from group '%s'." % (obj.get_name(), group.name))
obj.emit_to("%s removed you from group '%s'." % (source_object.get_name(show_dbref=False,no_ansi=True),
group.name))
GLOBAL_CMD_TABLE.add_command("@chgroup", cmd_chgroup,
priv_tuple=("auth.change_group",), auto_help=True, staff_help=True)
GLOBAL_CMD_TABLE.add_command("@setgroup", cmd_setgroup,
priv_tuple=("auth.change_group","genperms.admin_group"), auto_help=True, staff_help=True)

View file

@ -232,4 +232,4 @@ def cmd_search(command):
display_results(source_object, search_query)
GLOBAL_CMD_TABLE.add_command("@search", cmd_search,
priv_tuple=("genperms.builder")),
priv_tuple=("objects.info")),

View file

@ -1,12 +1,13 @@
"""
Commands that are available from the connect screen.
"""
import traceback
from django.contrib.auth.models import User
from src.objects.models import Attribute, Object
from src import defines_global
from src.util import functions_general
from src.cmdtable import GLOBAL_UNCON_CMD_TABLE
from src.logger import log_errmsg
def cmd_connect(command):
"""
@ -104,7 +105,14 @@ def cmd_create(command):
elif len(password) < 3:
session.msg("Your password must be at least 3 characters or longer.\n\rFor best security, make it at least 8 characters long, avoid making it a real word and mix numbers into it.")
else:
Object.objects.create_user(command, uname, email, password)
try:
Object.objects.create_user(command, uname, email, password)
except:
# we have to handle traceback ourself at this point, if we don't errors will givo no feedback.
session.msg("This is a bug. Please e-mail an admin if the problem persists.\n%s" % traceback.format_exc())
log_errmsg(traceback.format_exc())
raise
GLOBAL_UNCON_CMD_TABLE.add_command("create", cmd_create)
def cmd_quit(command):

View file

@ -338,7 +338,7 @@ def send_cexternal(cname, cmessage, caller=None, from_external=None):
# Look for IMC2 channel maps. If one is found, send an ice-msg-b
# packet to the network.
print "caller found: %s (%s). Msg: %s" % (caller,from_external,cmessage)
#logger.msg_infomsg("caller found: %s (%s). Msg: %s" % (caller,from_external,cmessage))
imccaller = caller
imccmessage = cmessage
@ -349,7 +349,7 @@ def send_cexternal(cname, cmessage, caller=None, from_external=None):
imccaller, imccmessage = cmessage.split("@",1)
#throw away IRC channel name; IMC users need not know it
imccmessage = (imccmessage.split(":",1)[1]).strip()
print "caller: %s cmessage: %s" % (imccaller, imccmessage)
#logger.msg_infomsg("caller: %s cmessage: %s" % (imccaller, imccmessage))
else:
imccaller = "*"

View file

@ -66,40 +66,122 @@ DATABASE_HOST = ''
# Empty string defaults to localhost. Not used with sqlite3.
DATABASE_PORT = ''
## Permissions
## The variables in this section are used by each evennia subsystem to tell which permissions to define.
## These variables are called by the respective subsystem ('application' in django lingo) of Evennia. The final
## look of the permission will be 'app.permission', e.g. 'irc.admin.irc_channels'.
## Note that beyond what is listed here, django automatically creates 3 add/change/delete permissions
## for each model defined in each appliction. These are however not used by any default commands in
## game and are filtered out in e.g. @adminperm/list in order to give the admin more overview.
## Note that all variables here must be proper nested tuples of tuples. ( (),(), )
# Communication channels in-game
# irc permissions
PERM_IRC = (
('admin_irc_channels', 'May administer IRC channels.'),)
# imc2 permissions
PERM_IMC2 = (
('admin_imc_channels', 'May administer IMC channels.'),)
# general channel permissions
PERM_CHANNELS = (
('emit_commchannel', 'May @cemit over channels.'),
('channel_admin', 'May administer comm channels.'),
('page','May page other users.'),)
# help system access permissions
PERM_HELPSYS = (
("staff_help", "May see staff help topics."),
("add_help", "May add or append to help entries"),
("del_help", "May delete help entries"),)
# object manipulation/information permissions
PERM_OBJECTS = (
("teleport","May teleport an object to any location."),
("wipe","May wipe all attributes on an object."),
("modify_attributes","May modify/delete/add attributes to an object."),
("info","May search for and examine objects."),
("create", "May create, copy and destroy objects."),
("dig", "May dig new rooms, open new exits and link them."),
("admin_ownership", "May change ownership of any object."),
("see_dbref","May see an object's dbref."),)
# misc general and admin permissions
PERM_GENPERMS = (
("announce", "May make announcements to everyone."),
("admin_perm", "Can modify individual permissions."),
("admin_group", "Can manage membership in groups."),
("process_control", "May shutdown/restart/reload the game"),
("manage_players", "Can change passwords, siteban, etc."),
("game_info", "Can review game metadata"),)
"""
Your names of various default comm channels for emitting
debug- or informative messages.
"""
## These permissions are not yet used in the default engine.
## ("boot", "May use @boot to kick players"),
## ("chown_all", "Can @chown anything to anyone."),
## ("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"),
## ("tel_anywhere", "May @teleport anywhere"),
## ("tel_anyone", "May @teleport anything"),
## ("see_session_data", "May see detailed player session data"),)
# Gathering of all permission tuple groups. This is used by e.g. @adminperm to only show these permissions.
PERM_ALL_DEFAULTS = (PERM_IRC, PERM_IMC2, PERM_CHANNELS, PERM_HELPSYS, PERM_OBJECTS, PERM_GENPERMS)
# If you defined your own tuple groups, add them below.
PERM_ALL_CUSTOM = ()
## Permission Groups
## Permission groups clump the permissions into larger chunks for quick assigning to
## a user (e.g. a builder). Each permission is written on the form app.permission,
## e.g. 'helpsys.view_staff_help'. Each group can contain an arbitrary number of
## permissions. A user is added to a group with the default @admingroup command.
## Superusers are automatically members of all groups.
# A dict defining the groups, on the form {group_name:(perm1,perm2,...),...}
PERM_GROUPS = \
{"Immortals":('irc.admin_irc_channels','imc2.admin_imc_channels','channels.emit_commchannel',
'channels.channel_admin','channels.page','helpsys.staff_help','helpsys.add_help',
'helpsys.del_help','objects.teleport','objects.wipe','objects.modify_attributes',
'objects.info','objects.create','objects.dig','objects.see_dbref','objects.admin_ownership',
'genperms.announce','genperms.admin_perm','genperms.admin_group','genperms.process_control',
'genperms.manage_players','genperms.game_info'),
"Wizards": ('irc.admin_irc_channels','imc2.admin_imc_channels','channels.emit_commchannel',
'channels.channel_admin','channels.page','helpsys.staff_help','helpsys.add_help',
'helpsys.del_help','objects.teleport','objects.wipe','objects.see_dbref',
'objects.modify_attributes',
'objects.info','objects.create','objects.dig','objects.admin_ownership','genperms.announce',
'genperms.game_info'),
"Builders":('channels.emit_commchannel','channels.page','helpsys.staff_help','helpsys.add_help',
'helpsys.del_help','objects.teleport','objects.wipe','objects.see_dbref',
'objects.modify_attributes', 'objects.info','objects.create','objects.dig',
'genperms.game_info'),
"Player Helpers":('channels.emit_commchannel', 'channels.page', 'helpsys.staff_help',
'helpsys.add_help','helpsys.del_help'),
"Players":('channels.emit_commchannel','channels.page')
}
# By defining a default player group, all players may start with some permissions pre-set.
PERM_DEFAULT_PLAYER_GROUP = "Players"
# Your names of various default comm channels for emitting debug- or informative messages.
COMMCHAN_MUD_INFO = 'MUDInfo'
COMMCHAN_MUD_CONNECTIONS = 'MUDConnections'
COMMCHAN_IMC2_INFO = 'MUDInfo'
COMMCHAN_IRC_INFO = 'MUDInfo'
"""
IMC Configuration
IMC (Inter-MUD communication) allows for an evennia chat channel that connects
to people on other MUDs also using the IMC. Your evennia server do *not* have
to be open to the public to use IMC; it works as a stand-alone chat client.
Copy and paste this section to your game/settings.py file and change the
values to fit your needs.
Evennia's IMC2 client was developed against MudByte's network. You must
register your MUD on the network before you can use it, go to
http://www.mudbytes.net/imc2-intermud-join-network.
Choose 'Other unsupported IMC2 version' from the choices and
and enter your information there. You have to enter the same
'short mud name', 'client password' and 'server password' as you
define in this file.
The Evennia discussion channel is on server02.mudbytes.net:9000.
"""
## IMC Configuration
## IMC (Inter-MUD communication) allows for an evennia chat channel that connects
## to people on other MUDs also using the IMC. Your evennia server do *not* have
## to be open to the public to use IMC; it works as a stand-alone chat client.
##
## Copy and paste this section to your game/settings.py file and change the
## values to fit your needs.
##
## Evennia's IMC2 client was developed against MudByte's network. You must
## register your MUD on the network before you can use it, go to
## http://www.mudbytes.net/imc2-intermud-join-network.
##
## Choose 'Other unsupported IMC2 version' from the choices and
## and enter your information there. You have to enter the same
## 'short mud name', 'client password' and 'server password' as you
## define in this file.
## The Evennia discussion channel is on server02.mudbytes.net:9000.
# Change to True if you want IMC active at all.
IMC2_ENABLED = False
@ -120,12 +202,10 @@ IMC2_DEBUG = False
# This isn't something you should generally change.
IMC2_PROTOCOL_VERSION = '2'
"""
IRC config. This allows your evennia channels to connect to an external IRC
channel. Evennia will connect under a nickname that then echoes what is
said on the channel to IRC and vice versa.
Obs - make sure the IRC network allows bots.
"""
## IRC config. This allows your evennia channels to connect to an external IRC
## channel. Evennia will connect under a nickname that then echoes what is
## said on the channel to IRC and vice versa.
## Obs - make sure the IRC network allows bots.
#Activate the IRC bot.
IRC_ENABLED = False
@ -138,8 +218,6 @@ IRC_CHANNEL = ""
#Under what nickname should Evennia connect to the channel
IRC_NICKNAME = ""
# Local time zone for this installation. All choices can be found here:
# http://www.postgresql.org/docs/8.0/interactive/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
TIME_ZONE = 'America/New_York'

View file

@ -1,4 +1,5 @@
from django.db import models
from django.conf import settings
class GenericPerm(models.Model):
"""
@ -6,19 +7,4 @@ class GenericPerm(models.Model):
fit under a particular module.
"""
class Meta:
permissions = (
("announce", "May use @wall to make announcements"),
("boot", "May use @boot to kick players"),
("builder", "Can build and modify objects"),
("chown_all", "Can @chown anything to anyone."),
("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"),
("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."),
)
permissions = settings.PERM_GENPERMS

View file

@ -5,6 +5,7 @@ well as creating auto-docs of commands based on their doc strings.
The system supports help-markup for multiple help entries as well
as a dynamically updating help index.
"""
from django.contrib.auth.models import User
from src.helpsys.models import HelpEntry
from src.ansi import ANSITable
@ -44,7 +45,7 @@ def _create_help(topicstr, entrytext, staff_only=False, force_create=False,
elif pobject:
#checks access rights before searching (this should have been
#done already at the command level)
if not pobject.is_staff(): return []
if not pobject.has_perm("helpsys.add_help"): return []
topic = HelpEntry.objects.find_topicmatch(pobject, topicstr)
else:
return []
@ -197,7 +198,8 @@ def get_help_index(pobject,filter=None):
filter='staff' - view only staff-specific help files
filter='player' - view only those files visible to all
"""
if pobject.is_staff():
if pobject.has_perm("helpsys.staff_help"):
if filter == 'staff':
helpentries = HelpEntry.objects.filter(staff_only=True).order_by('topicname')
elif filter == 'player':

View file

@ -2,6 +2,7 @@
Models for the help system.
"""
from django.db import models
from django.conf import settings
from src import ansi
from src.helpsys.managers import HelpEntryManager
@ -18,6 +19,7 @@ class HelpEntry(models.Model):
class Meta:
verbose_name_plural = "Help entries"
ordering = ['topicname']
permissions = settings.PERM_HELPSYS
def __str__(self):
return self.topicname

View file

@ -1,4 +1,5 @@
from django.db import models
from django.conf import settings
from src.channels.models import CommChannel
class IMC2ChannelMapping(models.Model):
@ -14,6 +15,7 @@ class IMC2ChannelMapping(models.Model):
class Meta:
verbose_name = "IMC2 Channel mapping"
verbose_name_plural = "IMC2 Channel mappings"
permissions = settings.PERM_IMC2
def __str__(self):
return "%s <-> %s" % (self.channel, self.imc2_channel_name)
return "%s <-> %s" % (self.channel, self.imc2_channel_name)

View file

@ -5,13 +5,12 @@ other things.
Everything starts at handle_setup()
"""
from django.contrib.auth.models import User, Group
from django.contrib.auth.models import User, Group, Permission
from django.core import management
from django.conf import settings
from src.objects.models import Object
from src.config.models import ConfigValue, CommandAlias, ConnectScreen
from src import comsys, defines_global
from src import comsys, defines_global, logger
def get_god_user():
"""
Returns the initially created 'god' User object.
@ -54,13 +53,21 @@ def create_objects():
def create_groups():
"""
Creates the default permissions groups.
Creates the default permissions groups and assign permissions to each as defined in settings.
"""
groups = ("Immortals", "Wizards", "Builders", "Player Helpers")
for group in groups:
for group_name, perm_tuple in settings.PERM_GROUPS.items():
newgroup = Group()
newgroup.name = group
newgroup.name = group_name
newgroup.save()
for perm_string in perm_tuple:
#assign permissions to the group
app_label, codename = perm_string.split(".",1)
try:
permission = Permission.objects.filter(content_type__app_label=app_label).get(codename=codename)
except Permission.DoesNotExist:
logger.log_errmsg("Initial_setup: Permission %s is not defined." % perm_string)
continue
newgroup.permissions.add(permission)
def create_channels():
"""

View file

@ -1,4 +1,5 @@
from django.db import models
from django.conf import settings
from src.channels.models import CommChannel
class IRCChannelMapping(models.Model):
@ -13,8 +14,9 @@ class IRCChannelMapping(models.Model):
class Meta:
verbose_name = "IRC Channel mapping"
verbose_name_plural = "IRC Channel mappings"
verbose_name_plural = "IRC Channel mappings"
permissions = settings.PERM_IRC
def __str__(self):
return "%s <-> %s (%s)" % (self.channel, self.irc_channel_name,
self.irc_server_name)

View file

@ -242,8 +242,7 @@ class ObjectManager(models.Manager):
if match_type == "exact":
return [prospect for prospect in searchlist
if ostring == str(prospect.get_attribute_value(attribute_name))]
else:
print [type(p) for p in searchlist]
else:
return [prospect for prospect in searchlist
if ostring in str(prospect.get_attribute_value(attribute_name))]
else:
@ -466,9 +465,7 @@ class ObjectManager(models.Manager):
# pluck the user ID from it.
if not str(uid).isdigit():
uid = uid.id
logger.log_infomsg('Next usable object ID is %d. (recycled)' % uid)
else:
logger.log_infomsg('Next usable object ID is %d. (new)' % uid)
logger.log_infomsg('Create_user: Recycling object ID %d.' % uid)
user = User.objects.create_user(uname, email, password)
# It stinks to have to do this but it's the only trivial way now.
@ -480,7 +477,6 @@ class ObjectManager(models.Manager):
# Update the session to use the newly created User object's ID.
command.session.uid = uid
logger.log_infomsg('User created with id %d.' % command.session.uid)
# Grab the user object again since we've changed it and the old reference
# is no longer valid.
@ -495,16 +491,20 @@ class ObjectManager(models.Manager):
# The User and player Object are ready, do anything needed by the
# game to further prepare things.
user_object.scriptlink.at_player_creation()
# Activate the player's session and set them loose.
command.session.login(user, first_login=True)
logger.log_infomsg('Registration: %s' % user_object.get_name())
# Add the user to all of the CommChannel objects that are flagged
# is_joined_by_default.
command.session.add_default_channels()
# Add user to the default permission group, if defined set in preferences.
command.session.add_default_group()
logger.log_infomsg("Registered new user: %s" % user_object.get_name())
# Activate the player's session and set them loose.
command.session.login(user, first_login=True)
#
# ObjectManager Copy method
#

View file

@ -127,6 +127,10 @@ class Object(models.Model):
#state system can set a particular command table to be used (not persistent).
state = None
class Meta:
ordering = ['-date_created', 'id']
permissions = settings.PERM_OBJECTS
def __cmp__(self, other):
"""
Used to figure out if one object is the same as another.
@ -136,9 +140,6 @@ class Object(models.Model):
def __str__(self):
return "%s" % (self.get_name(no_ansi=True),)
class Meta:
ordering = ['-date_created', 'id']
def dbref(self):
"""Returns the object's dbref id on the form #NN, directly
usable by Object.objects.dbref_search()
@ -206,8 +207,8 @@ class Object(models.Model):
if self.is_player():
return session_mgr.sessions_from_object(self)
else:
return []
return []
def emit_to(self, message):
"""
Emits something to any sessions attached to the object.
@ -291,7 +292,7 @@ class Object(models.Model):
looker_user = self.get_user_account()
if looker_user:
# Builders see dbrefs
return looker_user.has_perm('genperms.builder')
return looker_user.has_perm('objects.see_dbref')
else:
return False
@ -300,7 +301,9 @@ 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.
perm: (string) A string representing the desired permission. This
is on the form app.perm , e.g. 'objects.see_dbref' as
defined in the settings file.
"""
if not self.is_player():
return False

View file

@ -7,6 +7,7 @@ import sys
from datetime import datetime
from twisted.conch.telnet import StatefulTelnetProtocol
from django.contrib.auth.models import User
from django.contrib.auth.models import Group
from django.conf import settings
from util import functions_general
from src.objects.models import Object
@ -202,15 +203,27 @@ class SessionProtocol(StatefulTelnetProtocol):
Adds the player to the default channels.
"""
# Add the default channels.
for chan in CommChannel.objects.filter(is_joined_by_default=True):
#logger.log_infomsg("ADDING BY DEFAULT %s" % chan)
chan_alias = chan.get_default_chan_alias()
membership = CommChannelMembership(channel=chan,
listener=self.get_pobject(),
user_alias=chan_alias)
membership.save()
for chan in CommChannel.objects.filter(is_joined_by_default=True):
chan_alias = chan.get_default_chan_alias()
comsys.plr_add_channel(self.get_pobject(), chan_alias, chan)
comsys.plr_set_channel_listening(self, chan_alias, True)
def add_default_group(self):
default_group = settings.PERM_DEFAULT_PLAYER_GROUP.strip()
if not default_group:
logger.log_infomsg("settings.DEFAULT_PLAYER_GROUP is not set. Using no group.")
return
try:
group = Group.objects.get(name=default_group)
except Group.DoesNotExist:
logger.log_errmsg("settings.DEFAULT_PLAYER_GROUP = %s is not a valid group. Using no group." % default_group)
return
pobj = self.get_pobject()
user = User.objects.get(username=pobj.get_name(show_dbref=False,no_ansi=True))
user.groups.add(group)
logger.log_infomsg("Added new player to default permission group '%s'." % default_group)
user.save(); pobj.save()
def __str__(self):
"""
String representation of the user session class. We use