#!/usr/bin/python # -*- coding: utf-8 -*- from __future__ import with_statement from collections import defaultdict import ConfigParser import crypt import random import os # Defaults settings LOAD_FILE = SAVE_FILE = DEFAULT_FILE = os.path.join(os.path.dirname(__file__), 'auth.cfg') TRACDB_PATH = '/home/tracmaster/sites/hg_trac/src/hg_trac/db/trac.db' class groups_set(set): def __init__(self, arg): """ Converts automatically a CSV row into a set of groups. """ if isinstance(arg, (str, unicode)): arg = map(lambda x: x.strip(), arg.split()) super(groups_set, self).__init__(arg) def remove(self, element): try: super(groups_set, self).remove(element) except KeyError: pass def __str__(self): return ' '.join(self) def crypt_password(password): letters = 'abcdefghijklmnopqrstuvwxyz' \ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' \ '0123456789/.' salt = random.choice(letters) + random.choice(letters) return crypt.crypt(password, salt) def update_trac(users): import sqlite3 as sqlite connector = sqlite.connect(TRACDB_PATH) cursor = connector.cursor() for login, user in users.iteritems(): cursor.executemany("replace into session_attribute values (?, 1, ?, ?)", [(login, 'email', user.get('email', '')), (login, 'name', user.fullname)]) connector.commit() cursor.close() class User(dict): def __init__(self): """Default attributes""" self['groups'] = groups_set([]) def __setitem__(self, name, value): if name == 'groups': # forces groups to be a groups_set value = groups_set(value) elif name == 'password': # crypts automatically password value = crypt_password(value) name = 'crypted_password' super(User, self).__setitem__(name, value) @property def fullname(self): fullname = "%s %s" % (self.get('firstname', ''), self.get('lastname', '')) return fullname.strip() class UsersDict(dict): """ Proxifies the configuration file.""" save_pipelines = [update_trac] def __init__(self, load_file=LOAD_FILE, save_file=SAVE_FILE): self.load_file = load_file or DEFAULT_FILE self.save_file = save_file or self.load_file @property def _users(self): if not getattr(self, '_loaded', False): parser = ConfigParser.ConfigParser() parser.read(self.load_file) users = defaultdict(User) for name, value in parser.items('Users'): login, attr = name.rsplit('.', 1) users[login][attr] = value users[login].login = login self._loaded = users return self._loaded def __iter__(self): return self._users.__iter__() def __contains__(self, key): return key in self._users def __getitem__(self, name): return self._users[name] def __setitem__(self, name, value): if not isinstance(value, User): raise ValueError('Must be a User') self._users[name] = value def __delitem__(self, name): del self._users[name] def save(self): parser = ConfigParser.RawConfigParser() parser.add_section('Users') for login, infos in self._users.iteritems(): for attr, value in infos.iteritems(): if value is None: continue if isinstance(value, (list, tuple, set)): v = ', '.join(value) else: v = value parser.set('Users', '%s.%s' % (login, attr), value) with open(self.save_file, 'wb') as configfile: parser.write(configfile) for pipe in self.save_pipelines: pipe(self._users) users = UsersDict() def check_password(environ, user, password): if user not in users: return None return True if 'crypted_password' not in users[user]: # enforce password return False crypted_password = users[user]['crypted_password'] return crypt.crypt(password, crypted_password) == crypted_password def groups_for_user(environ, user): if user in users and 'groups' in users[user]: return list(users[user]['groups']) return [] if __name__ == '__main__': # des helpers # createuser [login] [password] [email] [firstname] [lastname] # set [login] [attr] [value] # set [login] password [new_password] # addgroup [login] [group] # delgroup [login] [group] from optparse import OptionParser parser = OptionParser(usage='%prog options [options [...]]', description='Allow you to manage authentification. ' 'Main options are : createuser, set, addgroup and delgroup.' ) parser.add_option("-l", "--load-file", dest="loadfile", default=LOAD_FILE, help="set the cfg file to be read") parser.add_option("-s", "--save-file", dest="savefile", default=SAVE_FILE, help="set the cfg file to be written") parser.add_option("-t", "--tracdb-path", dest="tracdb_path", default=TRACDB_PATH, help="set the trac.db to be updated") (options, args) = parser.parse_args() LOAD_FILE = options.loadfile SAVE_FILE = options.savefile TRACDB_PATH = options.tracdb_path if not args: parser.print_help() if args[0] == 'set': try: login, attr, value = args[1], args[2], args[3:] users[login][attr] = ' '.join(value) users.save() print '%s.%s = %s' % (login, attr, ' '.join(value)) exit(0) except IndexError: parser.set_usage('%prog set [login] [attr] [value]') parser.set_description('Exemple: set user1 password new_password') parser.print_help() elif args[0] == 'createuser': try: _, login, password, email, firstname, lastname = args users[login]['password'] = password users[login]['email'] = email users[login]['firstname'] = firstname users[login]['lastname'] = lastname users.save() print '%s.password = %s' % (login, password) print '%s.email = %s' % (login, email) print '%s.firstname = %s' % (login, firstname) print '%s.lastname = %s' % (login, lastname) exit(0) except IndexError: parser.set_usage('%prog createuser [login] [password] [email] [firstname] [lastname]') parser.set_description('Exemple: createuser user1 new_password email@domain FirstName LastName') parser.print_help() elif args[0] == 'addgroup': try: login, groups = args[1], args[2:] for group in groups: users[login]['groups'].add(group) users.save() print '%s.group = %s' % (login, users[login]['groups']) exit(0) except IndexError: parser.set_usage('%prog addgroup [login] [group]') parser.set_description('Exemple: addgroup xba group1 group2 group3') parser.print_help() elif args[0] == 'delgroup': try: login, groups = args[1], args[2:] for group in groups: users[login]['groups'].remove(group) users.save() print '%s.group = %s' % (login, users[login]['groups']) exit(0) except IndexError: parser.set_usage('%prog delgroup [login] [group]') parser.set_description('Exemple: delgroup xba group1 group2 group3') parser.print_help() else: print 'Usage: set [login] [attr] [value]' print 'Exemple: set user1 password new_password' print 'Usage: createuser [login] [password] [email] [firstname] [lastname]' print 'Exemple: createuser user1 new_password email@domain FirstName LastName' print 'Usage: addgroup [login] [group]' print 'Exemple: addgroup user1 group1 group2 group3' print 'Usage: delgroup [login] [group]' print 'Exemple: delgroup user1 group1 group2 group3' exit(1)