diff --git a/plugins/Config/plugin.py b/plugins/Config/plugin.py index 8276a5e3c..80737ab94 100644 --- a/plugins/Config/plugin.py +++ b/plugins/Config/plugin.py @@ -65,9 +65,15 @@ def getWrapper(name): def getCapability(name): capability = 'owner' # Default to requiring the owner capability. + if not name.startswith('supybot') and not name.startswith('users'): + name = 'supybot.' + name parts = registry.split(name) + group = getattr(conf, parts.pop(0)) while parts: - part = parts.pop() + part = parts.pop(0) + group = group.get(part) + if not getattr(group, '_opSettable', True): + return 'owner' if ircutils.isChannel(part): # If a registry value has a channel in it, it requires a # 'channel,op' capability, or so we assume. We'll see if we're diff --git a/plugins/Config/test.py b/plugins/Config/test.py index 9015f749d..7e9195d04 100644 --- a/plugins/Config/test.py +++ b/plugins/Config/test.py @@ -28,13 +28,23 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from supybot.test import * +import random +from supybot.test import * import supybot.conf as conf +_letters = 'abcdefghijklmnopqrstuvwxyz' +def random_string(): + return ''.join(random.choice(_letters) for _ in range(16)) + class ConfigTestCase(ChannelPluginTestCase): # We add utilities so there's something in supybot.plugins. - plugins = ('Config', 'Utilities') + plugins = ('Config', 'User', 'Utilities') + + prefix1 = 'somethingElse!user@host1.tld' + prefix2 = 'EvensomethingElse!user@host2.tld' + prefix3 = 'Completely!Different@host3.tld__no_testcap__' + def testGet(self): self.assertNotRegexp('config get supybot.reply', r'registry\.Group') self.assertResponse('config supybot.protocols.irc.throttleTime', '0.0') @@ -110,5 +120,52 @@ class ConfigTestCase(ChannelPluginTestCase): conf.supybot.commands.allowShell.setValue(True) conf.supybot.directories.plugins.setValue(old_plugins_dirs) + def testOpEditable(self): + var_name = 'testOpEditable' + random_string() + conf.registerChannelValue(conf.supybot.plugins.Config, var_name, + registry.Integer(0, 'help')) + self.assertNotError('register bar passwd', frm=self.prefix3, + private=True) + self.assertRegexp('whoami', 'bar', frm=self.prefix3) + ircdb.users.getUser('bar').addCapability(self.channel + ',op') + + self.assertRegexp('config plugins.Config.%s 1' % var_name, + '^Completely: Error: ', + frm=self.prefix3) + self.assertResponse('config plugins.Config.%s' % var_name, + 'Global: 0; #test: 0') + + self.assertNotRegexp('config channel plugins.Config.%s 1' % var_name, + '^Completely: Error: ', + frm=self.prefix3) + self.assertResponse('config plugins.Config.%s' % var_name, + 'Global: 0; #test: 1') + + def testOpNonEditable(self): + var_name = 'testOpNonEditable' + random_string() + conf.registerChannelValue(conf.supybot.plugins.Config, var_name, + registry.Integer(0, 'help'), opSettable=False) + self.assertNotError('register bar passwd', frm=self.prefix3, + private=True) + self.assertRegexp('whoami', 'bar', frm=self.prefix3) + ircdb.users.getUser('bar').addCapability(self.channel + ',op') + + self.assertRegexp('config plugins.Config.%s 1' % var_name, + '^Completely: Error: ', + frm=self.prefix3) + self.assertResponse('config plugins.Config.%s' % var_name, + 'Global: 0; #test: 0') + + self.assertRegexp('config channel plugins.Config.%s 1' % var_name, + '^Completely: Error: ', + frm=self.prefix3) + self.assertResponse('config plugins.Config.%s' % var_name, + 'Global: 0; #test: 0') + + self.assertNotRegexp('config channel plugins.Config.%s 1' % var_name, + '^Completely: Error: ') + self.assertResponse('config plugins.Config.%s' % var_name, + 'Global: 0; #test: 1') + # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/src/conf.py b/src/conf.py index d5cf0cf76..9f4ad907c 100644 --- a/src/conf.py +++ b/src/conf.py @@ -86,9 +86,10 @@ def registerGlobalValue(group, name, value): value.channelValue = False return group.register(name, value) -def registerChannelValue(group, name, value): +def registerChannelValue(group, name, value, opSettable=True): value._supplyDefault = True value.channelValue = True + value._opSettable = opSettable g = group.register(name, value) gname = g._name.lower() for name in registry._cache.keys():