From e05eabe5efbfbeeb3c498486b34bb00561d125f2 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 1 Oct 2009 23:28:58 +0000 Subject: [PATCH] * Implemented @chperm - a command for viewing and setting individual permissions on a user without using the admin interface. I consider expanding this later with a group handling method as well (@chgroup). The command supports viewing all permissions available in the game, viewing those set on a user, add and delete a permission. No refactoring of the permission models (moving them into their respective application) has been done yet. * Added del_event() to scheduler, allowing to remove events from the event queue. This allows for creating e.g. one-time events. . Griatch --- src/commands/privileged.py | 145 ++++++++++++++++++++++++++++++++++--- src/events.py | 9 ++- src/scheduler.py | 9 +++ 3 files changed, 152 insertions(+), 11 deletions(-) diff --git a/src/commands/privileged.py b/src/commands/privileged.py index b328fa332b..884005c811 100644 --- a/src/commands/privileged.py +++ b/src/commands/privileged.py @@ -2,6 +2,10 @@ 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 User +from django.contrib.contenttypes.models import ContentType from django.conf import settings from src.objects.models import Object from src import defines_global @@ -12,9 +16,6 @@ from src.scripthandler import rebuild_cache from src.util import functions_general from src.cmdtable import GLOBAL_CMD_TABLE - - - def cmd_reload(command): """ Reloads all modules. @@ -44,9 +45,9 @@ def cmd_reload(command): comsys.cemit_mudinfo("... all Command modules were reloaded.") GLOBAL_CMD_TABLE.add_command("@reload", cmd_reload, - priv_tuple=("genperms.process_control")), + priv_tuple=("genperms.process_control",)), GLOBAL_CMD_TABLE.add_command("@restart", cmd_reload, - priv_tuple=("genperms.process_control")), + priv_tuple=("genperms.process_control",)), def cmd_boot(command): """ @@ -119,7 +120,7 @@ def cmd_boot(command): session_mgr.remove_session(boot) return GLOBAL_CMD_TABLE.add_command("@boot", cmd_boot, - priv_tuple=("genperms.manage_players")) + priv_tuple=("genperms.manage_players",)) def cmd_newpassword(command): """ @@ -157,7 +158,7 @@ def cmd_newpassword(command): target_obj.emit_to("%s has changed your password." % (source_object.get_name(show_dbref=False),)) GLOBAL_CMD_TABLE.add_command("@newpassword", cmd_newpassword, - priv_tuple=("genperms.manage_players")) + priv_tuple=("genperms.manage_players",)) def cmd_home(command): """ @@ -170,7 +171,7 @@ def cmd_home(command): pobject.emit_to("There's no place like home...") pobject.move_to(pobject.get_home()) GLOBAL_CMD_TABLE.add_command("home", cmd_home, - priv_tuple=("genperms.tel_anywhere")) + priv_tuple=("genperms.tel_anywhere",)) def cmd_service(command): """ @@ -242,7 +243,7 @@ def cmd_service(command): return GLOBAL_CMD_TABLE.add_command("@service", cmd_service, - priv_tuple=("genperms.process_control")) + priv_tuple=("genperms.process_control",)) def cmd_shutdown(command): """ @@ -252,4 +253,128 @@ def cmd_shutdown(command): print 'Server shutdown by %s' % (command.source_object.get_name(show_dbref=False),) command.session.server.shutdown() GLOBAL_CMD_TABLE.add_command("@shutdown", cmd_shutdown, - priv_tuple=("genperms.process_control")) + priv_tuple=("genperms.process_control",)) + +def cmd_chperm(command): + """@chperm + + Usage: + @chperm[/switch] [] = [] + + Switches: + add : add a permission from + del : delete a permission from + list : list all permissions set on + + @chperm (change permission) sets/clears individual permission bits on a user. + Use /list without any arguments to see all available permissions. + """ + source_object = command.source_object + args = command.command_argument + switches = command.command_switches + + if not args: + if "list" not in switches: + source_object.emit_to("Usage: @chperm[/switch] [user] = [permission]") + return + else: + #just print all available permissions + s = "\n---Permission name %s ---Description" % (24 * " ") + for p in Permission.objects.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) + source_object.emit_to(s) + return + #we have command arguments. + arglist = args.split('=',1) + obj_name = arglist[0].strip() + 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 + if len(arglist) == 1: + #if we didn't have any =, we list the permissions set on . + s = "" + if obj.is_superuser(): + s += "\n This is a SUPERUSER account! All permissions are automatically set." + if not user.is_active: + s += "\n ACCOUNT NOT ACTIVE." + if obj.is_staff(): + s += "\n Member of staff (can enter Admin interface)" + groups = user.groups.all() + if groups: + s += "\n Group memberships:" + for g in groups: + s += "\n --- %s" % g + 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 (group)" + else: + s += "\n ---- %s" % p + if not s: + s = "User %s has no extra permissions." % obj.get_name() + else: + s = "\nPermissions for user %s: %s" % (obj.get_name(),s) + source_object.emit_to(s) + else: + # we supplied an argument on the form obj = perm + perm_string = arglist[1].strip() + try: + app_label, codename = perm_string.split(".",1) + except ValueError: + source_object.emit_to("Permission should be on the form 'application.permission' .") + return + try: + permission = Permission.objects.filter(content_type__app_label=app_label).get(codename=codename) + 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 "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 + if user.is_superuser: + source_object.emit_to("As a superuser you always have all permissions.") + return + if user.has_perm(perm_string): + source_object.emit_to("User already has this permission.") + return + user.user_permissions.add(permission) + 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 + print obj.has_perm_list(perm_string) + print obj.has_perm(perm_string) + if user.is_superuser: + source_object.emit_to("As a superuser you always have all permissions.") + return + if not user.has_perm(perm_string): + source_object.emit_to("User is already lacking this permission.") + return + user.user_permissions.remove(permission) + 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",)) + diff --git a/src/events.py b/src/events.py index ccd15a0c91..eae65237a7 100644 --- a/src/events.py +++ b/src/events.py @@ -38,7 +38,7 @@ class IntervalEvent(object): String representation of the event. """ return self.name - + def start_event_loop(self): """ Called to start up the event loop when the event is added to the @@ -49,6 +49,13 @@ class IntervalEvent(object): self.looped_task = task.LoopingCall(self.fire_event) # Start the task up with the specified interval. self.looped_task.start(self.interval, now=False) + + def stop_event_loop(self): + """ + Called to stop the event loop when the event is removed from the + scheduler. + """ + self.looped_task.stop() def event_function(self): """ diff --git a/src/scheduler.py b/src/scheduler.py index 6fca7cac3f..42fb2553bf 100644 --- a/src/scheduler.py +++ b/src/scheduler.py @@ -28,3 +28,12 @@ def add_event(event): else: schedule.append(event) event.start_event_loop() + +def del_event(event): + """ + Remove an event from scheduler. + """ + if event in schedule: + i = schedule.index(event) + schedule[i].stop_event_loop() + del schedule[i]