mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-12-23 11:12:47 +01:00
NickAuth: First commit.
This commit is contained in:
parent
6ea2d062b7
commit
659f6ebceb
6
plugins/NickAuth/README.txt
Normal file
6
plugins/NickAuth/README.txt
Normal file
@ -0,0 +1,6 @@
|
||||
This plugin allows users to use their network services account to
|
||||
authenticate to the bot.
|
||||
|
||||
They first have to use @nickauth nick add <the nick>, then use @auth
|
||||
every time they want to be authenticated.
|
||||
|
66
plugins/NickAuth/__init__.py
Normal file
66
plugins/NickAuth/__init__.py
Normal file
@ -0,0 +1,66 @@
|
||||
###
|
||||
# Copyright (c) 2012, Valentin Lorentz
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions, and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions, and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the author of this software nor the name of
|
||||
# contributors to this software may be used to endorse or promote products
|
||||
# derived from this software without specific prior written consent.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
###
|
||||
|
||||
"""
|
||||
Add a description of the plugin (to be presented to the user inside the wizard)
|
||||
here. This should describe *what* the plugin does.
|
||||
"""
|
||||
|
||||
import supybot
|
||||
import supybot.world as world
|
||||
|
||||
# Use this for the version of this plugin. You may wish to put a CVS keyword
|
||||
# in here if you're keeping the plugin in CVS or some similar system.
|
||||
__version__ = ""
|
||||
|
||||
# XXX Replace this with an appropriate author or supybot.Author instance.
|
||||
__author__ = supybot.authors.unknown
|
||||
|
||||
# This is a dictionary mapping supybot.Author instances to lists of
|
||||
# contributions.
|
||||
__contributors__ = {}
|
||||
|
||||
# This is a url where the most recent plugin package can be downloaded.
|
||||
__url__ = '' # 'http://supybot.com/Members/yourname/NickAuth/download'
|
||||
|
||||
import config
|
||||
import plugin
|
||||
reload(plugin) # In case we're being reloaded.
|
||||
# Add more reloads here if you add third-party modules and want them to be
|
||||
# reloaded when this plugin is reloaded. Don't forget to import them as well!
|
||||
|
||||
if world.testing:
|
||||
import test
|
||||
|
||||
Class = plugin.Class
|
||||
configure = config.configure
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
52
plugins/NickAuth/config.py
Normal file
52
plugins/NickAuth/config.py
Normal file
@ -0,0 +1,52 @@
|
||||
###
|
||||
# Copyright (c) 2012, Valentin Lorentz
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions, and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions, and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the author of this software nor the name of
|
||||
# contributors to this software may be used to endorse or promote products
|
||||
# derived from this software without specific prior written consent.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
###
|
||||
|
||||
import supybot.conf as conf
|
||||
import supybot.registry as registry
|
||||
from supybot.i18n import PluginInternationalization, internationalizeDocstring
|
||||
|
||||
_ = PluginInternationalization('NickAuth')
|
||||
|
||||
def configure(advanced):
|
||||
# This will be called by supybot to configure this module. advanced is
|
||||
# a bool that specifies whether the user identified himself as an advanced
|
||||
# user or not. You should effect your configuration by manipulating the
|
||||
# registry as appropriate.
|
||||
from supybot.questions import expect, anything, something, yn
|
||||
conf.registerPlugin('NickAuth', True)
|
||||
|
||||
|
||||
NickAuth = conf.registerPlugin('NickAuth')
|
||||
# This is where your configuration variables (if any) should go. For example:
|
||||
# conf.registerGlobalValue(NickAuth, 'someConfigVariableName',
|
||||
# registry.Boolean(False, _("""Help for someConfigVariableName.""")))
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
1
plugins/NickAuth/local/__init__.py
Normal file
1
plugins/NickAuth/local/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# Stub so local is a module, used for third-party modules
|
166
plugins/NickAuth/plugin.py
Normal file
166
plugins/NickAuth/plugin.py
Normal file
@ -0,0 +1,166 @@
|
||||
###
|
||||
# Copyright (c) 2012, Valentin Lorentz
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions, and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions, and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the author of this software nor the name of
|
||||
# contributors to this software may be used to endorse or promote products
|
||||
# derived from this software without specific prior written consent.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
###
|
||||
|
||||
import time
|
||||
|
||||
import supybot.conf as conf
|
||||
import supybot.utils as utils
|
||||
import supybot.ircdb as ircdb
|
||||
from supybot.commands import *
|
||||
import supybot.ircmsgs as ircmsgs
|
||||
import supybot.plugins as plugins
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.callbacks as callbacks
|
||||
from supybot.i18n import PluginInternationalization, internationalizeDocstring
|
||||
|
||||
_ = PluginInternationalization('NickAuth')
|
||||
|
||||
@internationalizeDocstring
|
||||
class NickAuth(callbacks.Plugin):
|
||||
"""Support authentication based on nicks and network services."""
|
||||
def __init__(self, irc):
|
||||
super(NickAuth, self).__init__(irc)
|
||||
self._requests = {}
|
||||
class nick(callbacks.Commands):
|
||||
def _check_auth(self, irc, msg, user):
|
||||
if user is None:
|
||||
irc.error(_('You are not authenticated.'), Raise=True)
|
||||
if not user.checkHostmask(msg.prefix):
|
||||
try:
|
||||
u = ircdb.users.getUser(msg.prefix)
|
||||
except KeyError:
|
||||
irc.error(_('You are not authenticated.'),
|
||||
Raise=True)
|
||||
if not u._checkCapability('owner'):
|
||||
irc.error(_('You must be owner to do that.'),
|
||||
Raise=True)
|
||||
|
||||
@internationalizeDocstring
|
||||
def add(self, irc, msg, args, network, user, nick):
|
||||
"""[<network>] <user> <nick>
|
||||
|
||||
Add <nick> to the list of nicks owned by the <user> on the
|
||||
<network>. You have to register this nick to the network
|
||||
services to be authenticated.
|
||||
<network> defaults to the current network.
|
||||
"""
|
||||
network = network.network or irc.network
|
||||
user = user or ircdb.users.getUser(msg.prefix)
|
||||
self._check_auth(irc, msg, user)
|
||||
try:
|
||||
user.addNick(network, nick)
|
||||
except KeyError:
|
||||
irc.error(_('This nick is already used by someone on this '
|
||||
'network.'), Raise=True)
|
||||
irc.replySuccess()
|
||||
add = wrap(add, [optional('networkIrc'),
|
||||
optional('otherUser'),
|
||||
'nick'])
|
||||
|
||||
@internationalizeDocstring
|
||||
def remove(self, irc, msg, args, network, user, nick):
|
||||
"""[<network>] <user> <nick>
|
||||
|
||||
Remove <nick> from the list of nicks owned by the <user> on the
|
||||
<network>.
|
||||
<network> defaults to the current network.
|
||||
"""
|
||||
network = network.network or irc.network
|
||||
user = user or ircdb.users.getUser(msg.prefix)
|
||||
self._check_auth(user, irc, msg)
|
||||
try:
|
||||
user.removeNick(network, nick)
|
||||
except KeyError:
|
||||
irc.error(_('This nick is not registered to you on this '
|
||||
'network.'), Raise=True)
|
||||
irc.replySuccess()
|
||||
remove = wrap(remove, [optional('networkIrc'),
|
||||
optional('otherUser'),
|
||||
'nick'])
|
||||
|
||||
@internationalizeDocstring
|
||||
def list(self, irc, msg, args, network, user):
|
||||
"""[<network>] [<user>]
|
||||
|
||||
Lists nicks of the <user> on the network.
|
||||
<network> defaults to the current network.
|
||||
"""
|
||||
network = network.network or irc.network
|
||||
user = user or ircdb.users.getUser(msg.prefix)
|
||||
self._check_auth(irc, msg, user)
|
||||
try:
|
||||
list_ = user.nicks[network]
|
||||
if list_:
|
||||
irc.reply(format('%L', list_))
|
||||
else:
|
||||
raise KeyError
|
||||
except KeyError:
|
||||
irc.error(_('You have no recognized nick on this '
|
||||
'network.'), Raise=True)
|
||||
list = wrap(list, [optional('networkIrc'),
|
||||
optional('otherUser')])
|
||||
|
||||
@internationalizeDocstring
|
||||
def auth(self, irc, msg, args):
|
||||
"""takes no argument
|
||||
|
||||
Tries to authenticate you using network services.
|
||||
If you get no reply, it means you are not authenticated to the
|
||||
network services."""
|
||||
nick = ircutils.toLower(msg.nick)
|
||||
self._requests[(irc.network, msg.nick)] = (time.time(), msg.prefix, irc)
|
||||
irc.queueMsg(ircmsgs.whois(nick, nick))
|
||||
auth = wrap(auth, [])
|
||||
|
||||
def do330(self, irc, msg):
|
||||
mynick, theirnick, theiraccount, garbage = msg.args
|
||||
# I would like to use a dict comprehension, but we have to support
|
||||
# Python 2.6 :(
|
||||
self._requests = dict([(x,y) for x,y in self._requests.items()
|
||||
if y[0]+60>time.time()])
|
||||
try:
|
||||
(timestamp, prefix, irc) = self._requests.pop((irc.network, theirnick))
|
||||
except KeyError:
|
||||
return
|
||||
user = ircdb.users.getUserFromNick(irc.network, theiraccount)
|
||||
if not user:
|
||||
user = ircdb.users.getUserFromNick(irc.network, theirnick)
|
||||
if user:
|
||||
user.addAuth(prefix)
|
||||
ircdb.users.setUser(user, flush=False)
|
||||
irc.reply(_('You are now authenticated as %s.') % user.name)
|
||||
else:
|
||||
irc.error(_('No user has this nick on this network.'))
|
||||
|
||||
|
||||
Class = NickAuth
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
92
plugins/NickAuth/test.py
Normal file
92
plugins/NickAuth/test.py
Normal file
@ -0,0 +1,92 @@
|
||||
###
|
||||
# Copyright (c) 2012, Valentin Lorentz
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions, and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions, and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the author of this software nor the name of
|
||||
# contributors to this software may be used to endorse or promote products
|
||||
# derived from this software without specific prior written consent.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
###
|
||||
|
||||
import supybot.ircdb as ircdb
|
||||
from supybot.test import *
|
||||
|
||||
class NickAuthTestCase(PluginTestCase):
|
||||
plugins = ('NickAuth', 'User')
|
||||
|
||||
prefix1 = 'something!user@host.tld'
|
||||
def _procedure(self, nickserv_reply):
|
||||
self.assertNotError('register foobar 123')
|
||||
self.assertResponse('user list', 'foobar')
|
||||
self.assertNotError('hostmask remove foobar %s' % self.prefix)
|
||||
self.assertNotError('identify foobar 123')
|
||||
self.assertNotError('nick add foobar baz')
|
||||
self.assertNotError('unidentify')
|
||||
self.prefix = self.prefix1
|
||||
self.assertError('nick add foobar qux')
|
||||
self.nick = self.prefix.split('!')[0]
|
||||
|
||||
self.assertError('hostmask list')
|
||||
self.irc.feedMsg(ircmsgs.privmsg(self.irc.nick,
|
||||
'auth',
|
||||
prefix=self.prefix))
|
||||
self.assertIs(self.irc.takeMsg().command, 'WHOIS')
|
||||
self.assertError('hostmask list')
|
||||
|
||||
self.irc.feedMsg(ircmsgs.privmsg(self.irc.nick,
|
||||
'auth',
|
||||
prefix=self.prefix))
|
||||
self.assertEqual(self.irc.takeMsg().command, 'WHOIS')
|
||||
if nickserv_reply:
|
||||
self.irc.feedMsg(ircmsgs.IrcMsg(':leguin.freenode.net 330 pgjrgrg '
|
||||
'%s baz :is logged in as' % self.nick))
|
||||
msg = self.irc.takeMsg()
|
||||
self.assertNotEqual(msg, None)
|
||||
self.assertEqual(msg.args[1], 'You are now authenticated as foobar.')
|
||||
self.assertResponse('hostmask list',
|
||||
'foobar has no registered hostmasks.')
|
||||
else:
|
||||
msg = self.irc.takeMsg()
|
||||
self.assertEqual(msg, None)
|
||||
self.assertError('hostmask list')
|
||||
|
||||
def testAuth(self):
|
||||
self._procedure(True)
|
||||
def testNoAuth(self):
|
||||
self._procedure(False)
|
||||
|
||||
def testList(self):
|
||||
self.assertNotError('register foobar 123')
|
||||
self.assertRegexp('nick list', 'You have no recognized nick')
|
||||
self.assertNotError('nick add foo')
|
||||
self.assertRegexp('nick list', 'foo')
|
||||
self.assertNotError('nick add %s bar' % self.nick)
|
||||
self.assertRegexp('nick list', 'foo and bar')
|
||||
self.assertNotError('nick add %s %s baz' % (self.irc.network, self.nick))
|
||||
self.assertRegexp('nick list', 'foo, bar, and baz')
|
||||
self.assertRegexp('nick list %s' % self.irc.network, 'foo, bar, and baz')
|
||||
self.assertRegexp('nick list %s foobar' % self.irc.network,
|
||||
'foo, bar, and baz')
|
||||
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
Loading…
Reference in New Issue
Block a user