diff --git a/src/channels/models.py b/src/channels/models.py index eb74bf605..6c42962e3 100644 --- a/src/channels/models.py +++ b/src/channels/models.py @@ -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'] \ No newline at end of file diff --git a/src/commands/batchprocess.py b/src/commands/batchprocess.py index 1bb6d662a..ea5a139a1 100644 --- a/src/commands/batchprocess.py +++ b/src/commands/batchprocess.py @@ -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 diff --git a/src/commands/comsys.py b/src/commands/comsys.py index aa8675e78..31b51f49a 100644 --- a/src/commands/comsys.py +++ b/src/commands/comsys.py @@ -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 diff --git a/src/commands/general.py b/src/commands/general.py index 0710fe311..63b6b7cf0 100644 --- a/src/commands/general.py +++ b/src/commands/general.py @@ -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 : 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()): diff --git a/src/commands/imc2.py b/src/commands/imc2.py index e1555ac6a..728d3267b 100644 --- a/src/commands/imc2.py +++ b/src/commands/imc2.py @@ -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",)) diff --git a/src/commands/info.py b/src/commands/info.py index a96c61038..e364ecc63 100644 --- a/src/commands/info.py +++ b/src/commands/info.py @@ -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",)), diff --git a/src/commands/irc.py b/src/commands/irc.py index 99a63459f..61c31232e 100644 --- a/src/commands/irc.py +++ b/src/commands/irc.py @@ -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): """ diff --git a/src/commands/objmanip.py b/src/commands/objmanip.py index 1f0cc7b40..5380f0ecc 100644 --- a/src/commands/objmanip.py +++ b/src/commands/objmanip.py @@ -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) diff --git a/src/commands/paging.py b/src/commands/paging.py index 809854993..b7926b7aa 100644 --- a/src/commands/paging.py +++ b/src/commands/paging.py @@ -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), \ No newline at end of file +GLOBAL_CMD_TABLE.add_command("page", cmd_page, priv_tuple=('channels.page',)) diff --git a/src/commands/privileged.py b/src/commands/privileged.py index 75aed2703..bc53de6c2 100644 --- a/src/commands/privileged.py +++ b/src/commands/privileged.py @@ -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] [] = [] + @setperm[/switch] [] = [] Switches: add : add a permission from del : delete a permission from list : list all permissions, or those set on - @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 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 . 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] [] [= ] + @setgroup[/switch] [] [= ] 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) + diff --git a/src/commands/search.py b/src/commands/search.py index 9e7b954c4..8f9ce6e85 100644 --- a/src/commands/search.py +++ b/src/commands/search.py @@ -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")), \ No newline at end of file + priv_tuple=("objects.info")), diff --git a/src/commands/unloggedin.py b/src/commands/unloggedin.py index 4f45285d2..a993773c3 100644 --- a/src/commands/unloggedin.py +++ b/src/commands/unloggedin.py @@ -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): diff --git a/src/comsys.py b/src/comsys.py index 6de9e05fa..d1e7704d9 100644 --- a/src/comsys.py +++ b/src/comsys.py @@ -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 = "*" diff --git a/src/config_defaults.py b/src/config_defaults.py index bac5b947f..1a8997a31 100644 --- a/src/config_defaults.py +++ b/src/config_defaults.py @@ -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' diff --git a/src/genperms/models.py b/src/genperms/models.py index f9853be19..70b07008a 100644 --- a/src/genperms/models.py +++ b/src/genperms/models.py @@ -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 diff --git a/src/helpsys/management/commands/edit_helpfiles.py b/src/helpsys/management/commands/edit_helpfiles.py index e0163e7a7..7e08995cf 100644 --- a/src/helpsys/management/commands/edit_helpfiles.py +++ b/src/helpsys/management/commands/edit_helpfiles.py @@ -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': diff --git a/src/helpsys/models.py b/src/helpsys/models.py index 706366434..e3781cf02 100644 --- a/src/helpsys/models.py +++ b/src/helpsys/models.py @@ -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 diff --git a/src/imc2/models.py b/src/imc2/models.py index 40b84c669..af8cd23a0 100644 --- a/src/imc2/models.py +++ b/src/imc2/models.py @@ -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) \ No newline at end of file + return "%s <-> %s" % (self.channel, self.imc2_channel_name) diff --git a/src/initial_setup.py b/src/initial_setup.py index 03658a997..1e72bd2f5 100644 --- a/src/initial_setup.py +++ b/src/initial_setup.py @@ -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(): """ diff --git a/src/irc/models.py b/src/irc/models.py index 98effd62a..a964a3de7 100644 --- a/src/irc/models.py +++ b/src/irc/models.py @@ -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) diff --git a/src/objects/managers/object.py b/src/objects/managers/object.py index 5a5e56e8e..ad96e38ce 100644 --- a/src/objects/managers/object.py +++ b/src/objects/managers/object.py @@ -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 # diff --git a/src/objects/models.py b/src/objects/models.py index 09db00f8a..8f047b8c3 100755 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -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 diff --git a/src/session.py b/src/session.py index 687d5a4b5..8a000cf4e 100755 --- a/src/session.py +++ b/src/session.py @@ -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