From fba70d15bc6a58ae0ca11fc9052069124b09a012 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Mon, 29 Oct 2012 20:15:14 +0100 Subject: [PATCH] Add configuration variable conf.supybot.capabilities.private. This variable is a list of capabilities that are considered as 'private', ie. the bot won't tell anyone but admins that a user has it, nor will the bot give a list of users with this capability. --- plugins/User/plugin.py | 9 +++++++++ plugins/User/test.py | 10 +++++++++- src/callbacks.py | 8 ++++++-- src/ircdb.py | 3 +++ test/test_callbacks.py | 7 +++++-- 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/plugins/User/plugin.py b/plugins/User/plugin.py index e71ae2094..ed8e40f26 100644 --- a/plugins/User/plugin.py +++ b/plugins/User/plugin.py @@ -54,6 +54,15 @@ class User(callbacks.Plugin): predicates = [] for (option, arg) in optlist: if option == 'capability': + try: + u = ircdb.users.getUser(msg.prefix) + if arg in conf.supybot.capabilities.private() and \ + not u._checkCapability('admin'): + raise KeyError + except KeyError: + # Note that it may be raised by checkCapability too. + irc.error(_('This is a private capability. Only admins ' + 'can see who has it.'), Raise=True) def p(u, cap=arg): try: return u._checkCapability(cap) diff --git a/plugins/User/test.py b/plugins/User/test.py index 6b72902f0..61057754b 100644 --- a/plugins/User/test.py +++ b/plugins/User/test.py @@ -33,7 +33,7 @@ import supybot.world as world import supybot.ircdb as ircdb class UserTestCase(PluginTestCase): - plugins = ('User', 'Admin') + plugins = ('User', 'Admin', 'Config') prefix1 = 'somethingElse!user@host.tld' prefix2 = 'EvensomethingElse!user@host.tld' def testHostmaskList(self): @@ -95,6 +95,14 @@ class UserTestCase(PluginTestCase): self.assertRegexp('user list --capability testcap', 'no matching') self.assertNotError('admin capability add biff testcap') self.assertResponse('user list --capability testcap', 'biff') + self.assertNotError('config capabilities.private testcap') + self.assertRegexp('user list --capability testcap', 'Error:.*private') + self.assertNotError('admin capability add biff admin') + self.assertResponse('user list --capability testcap', 'biff') + self.assertNotError('admin capability remove biff admin') + self.assertRegexp('user list --capability testcap', 'Error:.*private') + self.assertNotError('config capabilities.private ""') + self.assertResponse('user list --capability testcap', 'biff') self.assertNotError('admin capability remove biff testcap') self.assertRegexp('user list --capability testcap', 'no matching') diff --git a/src/callbacks.py b/src/callbacks.py index 3ca01cf8e..7c24496cf 100644 --- a/src/callbacks.py +++ b/src/callbacks.py @@ -484,8 +484,12 @@ class RichReplyMethods(object): log.warning('Denying %s for lacking %q capability.', self.msg.prefix, capability) if not self._getConfig(conf.supybot.reply.error.noCapability): - v = self._getConfig(conf.supybot.replies.noCapability) - s = self.__makeReply(v % capability, s) + if capability in conf.supybot.capabilities.private(): + v = self._getConfig(conf.supybot.replies.genericNoCapability) + else: + v = self._getConfig(conf.supybot.replies.noCapability) + v %= capability + s = self.__makeReply(v, s) return self._error(s, **kwargs) else: log.debug('Not sending capability error, ' diff --git a/src/ircdb.py b/src/ircdb.py index 4169e9930..3d7bd8e5f 100644 --- a/src/ircdb.py +++ b/src/ircdb.py @@ -1082,6 +1082,9 @@ conf.registerGlobalValue(conf.supybot.capabilities, 'default', registry.Boolean(True, """Determines whether the bot by default will allow users to have a capability. If this is disabled, a user must explicitly have the capability for whatever command he wishes to run.""")) +conf.registerGlobalValue(conf.supybot.capabilities, 'private', + registry.SpaceSeparatedListOfStrings([], """Determines what capabilities + the bot will never tell to a non-admin whether or not a user has them.""")) # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/test/test_callbacks.py b/test/test_callbacks.py index 4d1c815b9..f07ab902e 100644 --- a/test/test_callbacks.py +++ b/test/test_callbacks.py @@ -531,13 +531,16 @@ class PluginRegexpTestCase(PluginTestCase): self.assertResponse('test', 'test ') class RichReplyMethodsTestCase(PluginTestCase): - plugins = () + plugins = ('Config',) class NoCapability(callbacks.Plugin): def error(self, irc, msg, args): irc.errorNoCapability('admin') def testErrorNoCapability(self): self.irc.addCallback(self.NoCapability(self.irc)) - self.assertRegexp('error', 'admin') + self.assertRegexp('error', 'You don\'t have the admin capability') + self.assertNotError('config capabilities.private admin') + self.assertRegexp('error', 'Error: You\'re missing some capability') + self.assertNotError('config capabilities.private ""') class SourceNestedPluginTestCase(PluginTestCase):