3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-01 01:09:22 +01:00

Revamp configuration to support multiple accounts (#319)

This commit is contained in:
James Lu 2016-11-07 21:01:28 -08:00
parent 34fd45dce9
commit 93ca62aa49
3 changed files with 53 additions and 18 deletions

13
conf.py
View File

@ -51,11 +51,20 @@ def validateConf(conf):
for section in ('bot', 'servers', 'login', 'logging'): for section in ('bot', 'servers', 'login', 'logging'):
assert conf.get(section), "Missing %r section in config." % section assert conf.get(section), "Missing %r section in config." % section
assert type(conf['login'].get('password')) == type(conf['login'].get('user')) == str and \ # Make sure at least one form of authentication is valid.
conf['login']['password'] != "changeme", "You have not set the login details correctly!" old_login_valid = type(conf['login'].get('password')) == type(conf['login'].get('user')) == str
newlogins = conf['login'].get('accounts', {})
new_login_valid = len(newlogins) >= 1
assert old_login_valid or new_login_valid, "No accounts were set, aborting!"
for account, block in newlogins.items():
assert type(account) == str, "Bad username format %s" % account
assert type(block.get('password')) == str, "Bad password %s for account %s" % (block.get('password'), account)
assert conf['login'].get('password') != "changeme", "You have not set the login details correctly!"
return conf return conf
def loadConf(filename, errors_fatal=True): def loadConf(filename, errors_fatal=True):
"""Loads a PyLink configuration file from the filename given.""" """Loads a PyLink configuration file from the filename given."""
global confname, conf, fname global confname, conf, fname

View File

@ -16,6 +16,18 @@ from pylinkirc.log import log
# Essential, core commands go here so that the "commands" plugin with less-important, # Essential, core commands go here so that the "commands" plugin with less-important,
# but still generic functions can be reloaded. # but still generic functions can be reloaded.
def _login(irc, source, username):
"""Internal function to process logins."""
irc.users[source].account = username
irc.reply('Successfully logged in as %s.' % username)
log.info("(%s) Successful login to %r by %s",
irc.name, username, irc.getHostmask(source))
def _loginfail(irc, source, username):
"""Internal function to process login failures."""
irc.reply('Error: Incorrect credentials.')
log.warning("(%s) Failed login to %r from %s", irc.name, username, irc.getHostmask(source))
@utils.add_cmd @utils.add_cmd
def identify(irc, source, args): def identify(irc, source, args):
"""<username> <password> """<username> <password>
@ -30,18 +42,29 @@ def identify(irc, source, args):
except IndexError: except IndexError:
irc.reply('Error: Not enough arguments.') irc.reply('Error: Not enough arguments.')
return return
# Usernames are case-insensitive, passwords are NOT.
if username.lower() == conf.conf['login']['user'].lower() and password == conf.conf['login']['password']: username = username.lower()
realuser = conf.conf['login']['user']
irc.users[source].account = realuser # Process new-style accounts. Note: usernames are case-insensitive, passwords are NOT.
irc.reply('Successfully logged in as %s.' % realuser) for account, block in conf.conf['login'].get('accounts', {}).items():
log.info("(%s) Successful login to %r by %s", if account.lower() == username:
irc.name, username, irc.getHostmask(source)) # Username matched config.
if password and password == block.get('password'):
# Password exists and matched config. TODO: hash user passwords in config.
_login(irc, source, account)
break
else:
_loginfail(irc, source, account)
break
else: else:
irc.reply('Error: Incorrect credentials.') # Process legacy logins (login:user).
u = irc.users[source] if username.lower() == conf.conf['login'].get('user', '').lower() and password == conf.conf['login'].get('password'):
log.warning("(%s) Failed login to %r from %s", realuser = conf.conf['login']['user']
irc.name, username, irc.getHostmask(source)) _login(irc, source, realuser)
else:
# Username not found.
_loginfail(irc, source, username)
@utils.add_cmd @utils.add_cmd
def shutdown(irc, source, args): def shutdown(irc, source, args):

View File

@ -46,9 +46,12 @@ bot:
save_delay: 300 save_delay: 300
login: login:
# PyLink administrative login - Change this, or the service will not start! accounts:
user: admin # Creates an account with username "user1".
password: changeme user1:
# Defines the password for the user.
password: "somestring"
servers: servers:
# Please note: these are only EXAMPLE link blocks. You should edit them and # Please note: these are only EXAMPLE link blocks. You should edit them and
@ -97,7 +100,7 @@ servers:
# disable autoconnect entirely. # disable autoconnect entirely.
autoconnect: 5 autoconnect: 5
# Sets the ping frequency in seconds (i.e. how long we should wait between # Sets the ping frequency in seconds (i.e. how long we should wait between
# sending pings to our uplink). When more than two consecutive pings are missed, # sending pings to our uplink). When more than two consecutive pings are missed,
# PyLink will disconnect with a ping timeout. This defaults to 90 if not set. # PyLink will disconnect with a ping timeout. This defaults to 90 if not set.
pingfreq: 90 pingfreq: 90
@ -320,7 +323,7 @@ plugins:
# nick or configurable prefix characters. # nick or configurable prefix characters.
#- fantasy #- fantasy
# Changehost plugin: Automatically changes the hostmask (i.e. sets vHosts) on # Changehost plugin: Automatically changes the hostmask (i.e. sets vHosts) on
# matching users as they connect. This requires the changehost: block # matching users as they connect. This requires the changehost: block
# to be configured correctly below. # to be configured correctly below.
#- changehost #- changehost