diff --git a/bin/gva b/bin/gva index 927bfcb..4188803 100755 --- a/bin/gva +++ b/bin/gva @@ -1,7 +1,8 @@ #!/usr/bin/python -# -*- coding: UTF-8 -*- +# -*- python -*- +# -*- coding: utf-8 -*- # -# Copyright (C) 2007 by Jan Dittberner. +# Copyright (C) 2007, 2008 by Jan Dittberner. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/data/dbrepo/versions/2/2.py b/data/dbrepo/versions/2/2.py index 07b833f..dfcb66f 100644 --- a/data/dbrepo/versions/2/2.py +++ b/data/dbrepo/versions/2/2.py @@ -18,8 +18,7 @@ client = Table( Column('mobile', String(32)), Column('fax', String(32)), Column('email', String(64), unique=True, nullable=False), - schema = dbschema - ) + schema = dbschema) sysuser = Table( 'sysuser', meta, Column('sysuserid', Integer, primary_key=True), @@ -33,8 +32,7 @@ sysuser = Table( nullable=False), Column('sysuid', Integer, nullable=False, unique=True), Column('lastchange', DateTime, default=func.now()), - schema = dbschema - ) + schema = dbschema) domain = Table( 'domain', meta, Column('domainid', Integer, primary_key=True), @@ -45,8 +43,7 @@ domain = Table( Column('notified_serial', Integer), Column('sysuserid', Integer, ForeignKey(sysuser.c.sysuserid), nullable=False), - schema = dbschema - ) + schema = dbschema) record = Table( 'record', meta, Column('recordid', Integer, primary_key=True), @@ -58,16 +55,15 @@ record = Table( Column('ttl', Integer), Column('prio', Integer), Column('change_date', Integer), - schema = dbschema - ) + schema = dbschema) supermaster = Table( 'supermaster', meta, Column('ip', String(25), nullable=False), Column('nameserver', String(255), nullable=False), Column('account', Integer, ForeignKey(sysuser.c.sysuserid), nullable=False), - schema = dbschema - ) + schema = dbschema) + def upgrade(): client.create() @@ -76,6 +72,7 @@ def upgrade(): record.create() supermaster.create() + def downgrade(): supermaster.drop() record.drop() diff --git a/data/dbrepo/versions/3/3.py b/data/dbrepo/versions/3/3.py index 0744e72..15f50c7 100644 --- a/data/dbrepo/versions/3/3.py +++ b/data/dbrepo/versions/3/3.py @@ -17,8 +17,7 @@ mailaccount = Table( Column('home', String(128), nullable = False), Column('spamcheck', Boolean, nullable = False, default = False), Column('sajunkscore', Integer), - schema = dbschema - ) + schema = dbschema) mailaddress = Table( 'mailaddress', meta, Column('mailaddressid', Integer, primary_key = True), @@ -26,8 +25,7 @@ mailaddress = Table( nullable = False), Column('email', String(255), nullable = False), UniqueConstraint('email', 'domainid'), - schema = dbschema - ) + schema = dbschema) mailtarget = Table( 'mailtarget', meta, Column('mailtargetid', Integer, primary_key = True), @@ -35,14 +33,15 @@ mailtarget = Table( nullable = False), Column('target', String(128), nullable = False), UniqueConstraint('target', 'mailaddressid'), - schema = dbschema - ) + schema = dbschema) + def upgrade(): mailaccount.create() mailaddress.create() mailtarget.create() + def downgrade(): mailtarget.drop() mailaddress.drop() diff --git a/gnuviechadmin/__init__.py b/gnuviechadmin/__init__.py index eeb808b..a5c2587 100644 --- a/gnuviechadmin/__init__.py +++ b/gnuviechadmin/__init__.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. diff --git a/gnuviechadmin/backend/BackendEntity.py b/gnuviechadmin/backend/BackendEntity.py index 8990293..659692a 100644 --- a/gnuviechadmin/backend/BackendEntity.py +++ b/gnuviechadmin/backend/BackendEntity.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -20,7 +19,9 @@ # # Version: $Id$ -import os, logging, tempfile +import os +import logging +import tempfile from settings import config from gnuviechadmin.exceptions import * @@ -29,6 +30,7 @@ from subprocess import * import sqlalchemy from sqlalchemy.orm import object_mapper + class BackendEntity(object): """This is the abstract base class for all backend entity classes.""" @@ -75,10 +77,10 @@ class BackendEntity(object): for cmdline in cmdlines: toexec = "%s %s" % (suwrapper, cmdline) if predecessor is None: - p = Popen(toexec, shell = True, stdout = PIPE) + p = Popen(toexec, shell = True, stdout = PIPE) else: - p = Popen(toexec, shell = True, stdin = predecessor.stdout, - stdout = PIPE) + p = Popen(toexec, shell = True, stdin = predecessor.stdout, + stdout = PIPE) predecessor = p output = predecessor.communicate()[0] return predecessor.wait() @@ -110,4 +112,3 @@ class BackendEntity(object): cmd = 'cp "%s" "%s"' % (tmp.name, filename) self.sucommand(cmd) tmp.close() - diff --git a/gnuviechadmin/backend/BackendEntityHandler.py b/gnuviechadmin/backend/BackendEntityHandler.py index 687b629..9d7ad8c 100644 --- a/gnuviechadmin/backend/BackendEntityHandler.py +++ b/gnuviechadmin/backend/BackendEntityHandler.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -20,12 +19,15 @@ # # Version: $Id$ -import sqlalchemy, logging +import sqlalchemy +import logging from sqlalchemy.orm import create_session from gnuviechadmin.exceptions import * from BackendEntity import * + class BackendEntityHandler(object): + def __init__(self, entityclass, toclass, verbose = False): self.logger = logging.getLogger("%s.%s" % ( self.__class__.__module__, self.__class__.__name__)) @@ -40,7 +42,7 @@ class BackendEntityHandler(object): sess = create_session() transaction = sess.create_transaction() delegate = self.toclass(**kwargs) - entity = self.entityclass(delegate, self.verbose) + entity = self.entityclass(delegate, self.verbose) try: sess.save(delegate) sess.flush() diff --git a/gnuviechadmin/backend/BackendTo.py b/gnuviechadmin/backend/BackendTo.py index 30ff467..57be4e2 100644 --- a/gnuviechadmin/backend/BackendTo.py +++ b/gnuviechadmin/backend/BackendTo.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -21,11 +20,12 @@ # Version: $Id$ from sqlalchemy.orm import object_mapper, mapper, relation - from tables import * + class BackendTo(object): """Backend transfer object class.""" + def __init__(self, **kwargs): for (key, value) in kwargs.items(): self.__setattr__(key, value) @@ -37,7 +37,7 @@ class BackendTo(object): format = "%(class)s:" format = format + ", ".join([col + "=%(" + col + ")s" for col in \ cols]) - data = {'class' : self.__class__.__name__} + data = {'class': self.__class__.__name__} else: cols = self._shortkeys format = ",".join("%(" + col + ")s" for col in cols) @@ -45,30 +45,31 @@ class BackendTo(object): data.update(dict([(col, self.__getattribute__(col)) for col in cols])) return format % data + class Client(BackendTo): """Transfer object class for clients.""" _shortkeys = ('clientid', 'firstname', 'lastname', 'email') + class Sysuser(BackendTo): """Transfer object class for system users.""" _shortkeys = ("sysuserid", "clientid", "username", "home", "shell") + class Domain(BackendTo): """Transfer object class for DNS domains.""" _shortkeys = ("domainid", "sysuserid", "name", "type") + class Record(BackendTo): """Transfer object class for DNS domain records.""" _shortkeys = ("recordid", "domainid", "name", "type", "content") -client_mapper = mapper(Client, client_table) -sysuser_mapper = mapper(Sysuser, sysuser_table) -domain_mapper = mapper(Domain, domain_table) + +client_mapper = mapper(Client, client_table, { + 'sysusers': relation(Sysuser, backref = 'client')}) +sysuser_mapper = mapper(Sysuser, sysuser_table, { + 'domains': relation(Domain, backref = 'sysuser')}) +domain_mapper = mapper(Domain, domain_table, { + 'records': relation(Record, cascade = 'all', backref = 'domain')}) record_mapper = mapper(Record, record_table) - -client_mapper.add_property("sysusers", relation(Sysuser, backref = 'client')) - -sysuser_mapper.add_property("domains", relation(Domain, backref = 'sysuser')) - -domain_mapper.add_property("records", relation(Record, cascade = 'all', - backref = 'domain')) diff --git a/gnuviechadmin/backend/__init__.py b/gnuviechadmin/backend/__init__.py index 9c370e3..5e1f139 100644 --- a/gnuviechadmin/backend/__init__.py +++ b/gnuviechadmin/backend/__init__.py @@ -1,6 +1,6 @@ -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- # -# Copyright (C) 2007 by Jan Dittberner. +# Copyright (C) 2007, 2008 by Jan Dittberner. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/gnuviechadmin/backend/client.py b/gnuviechadmin/backend/client.py index 6af57db..dffb7f4 100644 --- a/gnuviechadmin/backend/client.py +++ b/gnuviechadmin/backend/client.py @@ -1,6 +1,6 @@ -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- # -# Copyright (C) 2007 by Jan Dittberner. +# Copyright (C) 2007, 2008 by Jan Dittberner. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ from BackendTo import * from BackendEntity import * from BackendEntityHandler import * + class ClientEntity(BackendEntity): """Entity class for clients.""" @@ -39,18 +40,18 @@ class ClientEntity(BackendEntity): def _client_mail(self): text = get_template(config.get('common', 'mailtemplates'), config.get('client', 'create.mail')).substitute({ - 'firstname' : self.delegateto.firstname, - 'lastname' : self.delegateto.lastname, - 'email' : self.delegateto.email, - 'address1' : self.delegateto.address1, - 'zipcode' : self.delegateto.zip, - 'city' : self.delegateto.city, - 'phone' : self.delegateto.phone}) + 'firstname': self.delegateto.firstname, + 'lastname': self.delegateto.lastname, + 'email': self.delegateto.email, + 'address1': self.delegateto.address1, + 'zipcode': self.delegateto.zip, + 'city': self.delegateto.city, + 'phone': self.delegateto.phone}) subject = get_template_string( config.get('client', 'create_subject')).substitute({ - 'firstname' : self.delegateto.firstname, - 'lastname' : self.delegateto.lastname}) - self.send_mail(subject, text) + 'firstname': self.delegateto.firstname, + 'lastname': self.delegateto.lastname}) + self.send_mail(subject, text) def create_hook(self, session): """Actions to perform when a client is created.""" @@ -69,6 +70,7 @@ class ClientEntity(BackendEntity): """Gets the default country.""" return config.get('common', 'defaultcountry') + class ClientHandler(BackendEntityHandler): """BackendEntityHandler for Client entities.""" diff --git a/gnuviechadmin/backend/domain.py b/gnuviechadmin/backend/domain.py index 8a74e30..5a27441 100644 --- a/gnuviechadmin/backend/domain.py +++ b/gnuviechadmin/backend/domain.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -18,9 +17,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # -# Version: $Id: client.py 1101 2007-02-28 21:15:20Z jan $ +# Version: $Id$ -import datetime, os +import datetime +import os from gnuviechadmin.exceptions import * from settings import * @@ -28,6 +28,7 @@ from BackendTo import Record, Domain from BackendEntity import BackendEntity from BackendEntityHandler import BackendEntityHandler + class DomainEntity(BackendEntity): """Entity class for DNS domains.""" @@ -130,12 +131,12 @@ class DomainEntity(BackendEntity): template = get_template(config.get('domain', 'htdocstemplate'), tpl) template = template.substitute({ - 'domain' : self.delegateto.name}) + 'domain': self.delegateto.name}) self.write_to_file(os.path.join(vhostdir, tpl), template) cmd = 'chown -R %(username)s:%(group)s "%(dir)s"' % { - 'username' : self.delegateto.sysuser.username, - 'group' : config.get('sysuser', 'defaultgroup'), - 'dir' : vhostdir} + 'username': self.delegateto.sysuser.username, + 'group': config.get('sysuser', 'defaultgroup'), + 'dir': vhostdir} self.sucommand(cmd) def _create_log_dir(self): @@ -164,8 +165,8 @@ class DomainEntity(BackendEntity): template = get_template(config.get('domain', 'conftemplates'), config.get('domain', 'statshtaccesstemplate')) template = template.substitute({ - 'domain' : self.delegateto.name, - 'userfile' : authfile}) + 'domain': self.delegateto.name, + 'userfile': authfile}) self.write_to_file(os.path.join(self._get_stats_dir(), '.htaccess'), template) @@ -178,10 +179,10 @@ class DomainEntity(BackendEntity): template = get_template(config.get('domain', 'conftemplates'), config.get('domain', 'modlogantemplate')) template = template.substitute({ - 'statsdir' : self._get_stats_dir(), - 'logdir' : self._get_log_dir(), - 'domain' : self.delegateto.name, - 'domainesc' : self.delegateto.name.replace('.', '\.')}) + 'statsdir': self._get_stats_dir(), + 'logdir': self._get_log_dir(), + 'domain': self.delegateto.name, + 'domainesc': self.delegateto.name.replace('.', '\.')}) self.write_to_file(os.path.join(modlogandir, self.delegateto.name + '.conf'), template) @@ -190,11 +191,11 @@ class DomainEntity(BackendEntity): template = get_template(config.get('domain', 'conftemplates'), config.get('domain', 'apachetemplate')) template = template.substitute({ - 'ipaddr' : self.ipaddr, - 'statsdir' : self._get_stats_dir(), - 'logdir' : self._get_log_dir(), - 'domain' : self.delegateto.name, - 'docroot' : self._get_vhost_dir()}) + 'ipaddr': self.ipaddr, + 'statsdir': self._get_stats_dir(), + 'logdir': self._get_log_dir(), + 'domain': self.delegateto.name, + 'docroot': self._get_vhost_dir()}) self.write_to_file(os.path.join(config.get('domain', 'sitesdir'), self.delegateto.name), template) @@ -202,14 +203,14 @@ class DomainEntity(BackendEntity): template = get_template(config.get('common', 'mailtemplates'), config.get('domain', 'create.mail')) text = template.substitute({ - 'sysuser' : self.delegateto.sysuser.username, - 'domain' : self.delegateto.name, - 'docroot' : self._get_vhost_dir(), - 'statspass' : self.delegateto.sysuser.clearpass}) + 'sysuser': self.delegateto.sysuser.username, + 'domain': self.delegateto.name, + 'docroot': self._get_vhost_dir(), + 'statspass': self.delegateto.sysuser.clearpass}) template = get_template_string(config.get('domain', 'create_subject')) subject = template.substitute({ - 'domain' : self.delegateto.name}) - self.send_mail(subject, text) + 'domain': self.delegateto.name}) + self.send_mail(subject, text) def create_hook(self, session): self.delegateto.records.append(Record( @@ -223,7 +224,7 @@ class DomainEntity(BackendEntity): name = self.delegateto.name, type = 'NS', content = self.ns2, ttl = config.getint('domain', 'defaultttl'))) self.delegateto.records.append(Record( - name = self.delegateto.name, type = 'MX', content = self.mx, + name = self.delegateto.name, type = 'MX', content = self.mx, ttl = config.getint('domain', 'defaultttl'), prio = config.getint('domain', 'defaultmxprio'))) self.delegateto.records.append(Record( @@ -258,65 +259,69 @@ class DomainEntity(BackendEntity): def _archive_stats_dir(self): archive = os.path.join(self.delegateto.sysuser.home, '%(domain)s-stats.tar.gz' % { - 'domain' : self.delegateto.name}) - cmd = 'tar czf "%(archive)s" --directory="%(statsbase)s" "%(statsdir)s"' % { - 'archive' : archive, - 'statsbase' : config.get('domain', 'statspath'), - 'statsdir' : self.delegateto.name} + 'domain': self.delegateto.name}) + cmd = 'tar czf "%(archive)s" --directory="%(statsbase)s" ' + \ + '"%(statsdir)s"' % { + 'archive': archive, + 'statsbase': config.get('domain', 'statspath'), + 'statsdir': self.delegateto.name} self.sucommand(cmd) cmd = 'rm -r "%(statsdir)s"' % { - 'statsdir' : self._get_stats_dir()} + 'statsdir': self._get_stats_dir()} self.sucommand(cmd) cmd = 'chown "%(username)s:%(group)s" "%(archive)s"' % { - 'username' : self.delegateto.sysuser.username, - 'group' : config.get('sysuser', 'defaultgroup'), - 'archive' : archive} + 'username': self.delegateto.sysuser.username, + 'group': config.get('sysuser', 'defaultgroup'), + 'archive': archive} self.sucommand(cmd) def _archive_log_dir(self): archive = os.path.join(self.delegateto.sysuser.home, '%(domain)s-logs.tar.gz' % { - 'domain' : self.delegateto.name}) - cmd = 'tar czf "%(archive)s" --directory="%(logbase)s" "%(logdir)s"' % { - 'archive' : archive, - 'logbase' : config.get('domain', 'logpath'), - 'logdir' : self.delegateto.name} + 'domain': self.delegateto.name}) + cmd = 'tar czf "%(archive)s" --directory="%(logbase)s" ' + \ + '"%(logdir)s"' % { + 'archive': archive, + 'logbase': config.get('domain', 'logpath'), + 'logdir': self.delegateto.name} self.sucommand(cmd) cmd = 'rm -r "%(logdir)s"' % { - 'logdir' : self._get_log_dir()} + 'logdir': self._get_log_dir()} self.sucommand(cmd) cmd = 'chown "%(username)s:%(group)s" "%(archive)s"' % { - 'username' : self.delegateto.sysuser.username, - 'group' : config.get('sysuser', 'defaultgroup'), - 'archive' : archive} + 'username': self.delegateto.sysuser.username, + 'group': config.get('sysuser', 'defaultgroup'), + 'archive': archive} self.sucommand(cmd) def _archive_vhost_dir(self): archive = os.path.join(self.delegateto.sysuser.home, '%(domain)s-vhost.tar.gz' % { - 'domain' : self.delegateto.name}) - cmd = 'tar czf "%(archive)s" --directory="%(vhostbase)s" "%(vhostdir)s"' % { - 'archive' : archive, - 'vhostbase' : self.delegateto.sysuser.home, - 'vhostdir' : self.delegateto.name} + 'domain': self.delegateto.name}) + cmd = 'tar czf "%(archive)s" --directory="%(vhostbase)s" ' + \ + '"%(vhostdir)s"' % { + 'archive': archive, + 'vhostbase': self.delegateto.sysuser.home, + 'vhostdir': self.delegateto.name} self.sucommand(cmd) cmd = 'rm -r "%(vhostdir)s"' % { - 'vhostdir' : os.path.join(self.delegateto.sysuser.home, + 'vhostdir': os.path.join(self.delegateto.sysuser.home, self.delegateto.name)} self.sucommand(cmd) cmd = 'chown "%(username)s:%(group)s" "%(archive)s"' % { - 'username' : self.delegateto.sysuser.username, - 'group' : config.get('sysuser', 'defaultgroup'), - 'archive' : archive} + 'username': self.delegateto.sysuser.username, + 'group': config.get('sysuser', 'defaultgroup'), + 'archive': archive} self.sucommand(cmd) - def delete_hook(self, session): + def delete_hook(self, session): self._delete_apache_conf() self._delete_stats_conf() self._archive_stats_dir() self._archive_log_dir() self._archive_vhost_dir() + class DomainHandler(BackendEntityHandler): """BackendEntityHandler for Domain entities.""" diff --git a/gnuviechadmin/backend/record.py b/gnuviechadmin/backend/record.py index 93b023e..f8d3f33 100644 --- a/gnuviechadmin/backend/record.py +++ b/gnuviechadmin/backend/record.py @@ -1,6 +1,6 @@ -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- # -# Copyright (C) 2007 by Jan Dittberner. +# Copyright (C) 2007, 2008 by Jan Dittberner. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -25,16 +25,19 @@ from domain import DomainEntity from BackendEntity import * from BackendEntityHandler import * + class RecordEntity(BackendEntity): """Entity class for DNS domain records.""" + def create_hook(self, session): domain = session.load(Domain, self.delegateto.domainid) DomainEntity(domain).update_serial(session) - + def delete_hook(self, session): domain = session.load(Domain, self.delegateto.domainid) DomainEntity(domain).update_serial(session) + class RecordHandler(BackendEntityHandler): """BackendEntityHandler for Record entities.""" diff --git a/gnuviechadmin/backend/settings.py b/gnuviechadmin/backend/settings.py index a13ac9a..2d089f1 100644 --- a/gnuviechadmin/backend/settings.py +++ b/gnuviechadmin/backend/settings.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -26,7 +25,10 @@ This module handles all central configuration of Gnuviech Admin. It parses configuration files and provides functions for reading templates.""" -import ConfigParser, os, string, logging.config +import ConfigParser +import os +import string +import logging.config # global settings which must not be user configurable required_version = 3 @@ -40,11 +42,13 @@ dbschema = None if config.get('database', 'uri').startswith('postgres://'): dbschema = 'gva' + def get_template_dir(dirname): """Returns the template directory for the given directory.""" templatepath = config.get('common', 'templatedir') return os.path.join(templatepath, dirname) + def get_template(dirname, filename): """Returns the template data from the given template file.""" templatefile = file(os.path.join(get_template_dir(dirname), @@ -52,6 +56,7 @@ def get_template(dirname, filename): templatedata = templatefile.read() return string.Template(templatedata.decode('utf_8')) + def get_template_string(templatestring): """Returns a template object for the given template string.""" return string.Template(templatestring) diff --git a/gnuviechadmin/backend/sysuser.py b/gnuviechadmin/backend/sysuser.py index ff58bcb..3077e93 100644 --- a/gnuviechadmin/backend/sysuser.py +++ b/gnuviechadmin/backend/sysuser.py @@ -27,6 +27,7 @@ from BackendEntity import * from BackendEntityHandler import * import os + class SysuserEntity(BackendEntity): """Entity class for system users.""" @@ -54,7 +55,8 @@ class SysuserEntity(BackendEntity): usernames = [user.username for user in \ getenttools.find_user_by_prefix(prefix)] if usernames: - maxid = max([int(username[len(prefix):]) for username in usernames]) + maxid = max([int(username[len(prefix):]) \ + for username in usernames]) maxid += 2 for number in range(1, maxid): username = "%s%02d" % (prefix, number) @@ -81,17 +83,18 @@ class SysuserEntity(BackendEntity): def _get_next_sysuid(self): return getenttools.get_next_uid(int(config.get('sysuser', 'minuid')), - int(config.get('sysuser', 'maxuid'))) + int(config.get('sysuser', 'maxuid'))) def _populate_home(self): templatedir = get_template_dir(config.get('sysuser', 'hometemplate')) olddir = os.getcwd() os.chdir(templatedir) cmd1 = 'find . -depth \! -regex ".*\.svn.*" \! -name "*~" -print0' - cmd2 = 'cpio --pass-through --owner=%(username)s.%(group)s --null --make-directories %(home)s' % { - 'username' : self.delegateto.username, - 'group' : config.get('sysuser', 'defaultgroup'), - 'home' : self.delegateto.home} + cmd2 = 'cpio --pass-through --owner=%(username)s.%(group)s --null ' + \ + '--make-directories %(home)s' % { + 'username': self.delegateto.username, + 'group': config.get('sysuser', 'defaultgroup'), + 'home': self.delegateto.home} self.supipe((cmd1, cmd2)) os.chdir(olddir) @@ -99,33 +102,35 @@ class SysuserEntity(BackendEntity): template = get_template(config.get('common', 'mailtemplates'), config.get('sysuser', 'create.mail')) text = template.substitute({ - 'uid' : self.delegateto.sysuid, - 'firstname' : self.delegateto.client.firstname, - 'lastname' : self.delegateto.client.lastname, - 'email' : self.delegateto.client.email, - 'username' : self.delegateto.username, - 'password' : self.delegateto.clearpass, - 'home' : self.delegateto.home, - 'shell' : self._get_shell_binary()}) + 'uid': self.delegateto.sysuid, + 'firstname': self.delegateto.client.firstname, + 'lastname': self.delegateto.client.lastname, + 'email': self.delegateto.client.email, + 'username': self.delegateto.username, + 'password': self.delegateto.clearpass, + 'home': self.delegateto.home, + 'shell': self._get_shell_binary()}) template = get_template_string(config.get('sysuser', 'create_subject')) subject = template.substitute({ - 'username' : self.delegateto.username}) + 'username': self.delegateto.username}) self.send_mail(subject, text) def create_hook(self, session): gecos = config.get('sysuser', 'gecos') % (self.delegateto.username) - cmdline = 'adduser --home "%(home)s" --shell "%(shell)s" --no-create-home --uid %(sysuid)d --ingroup "%(group)s" --disabled-password --gecos "%(gecos)s" %(username)s' % { - 'home' : self.delegateto.home, - 'shell' : self._get_shell_binary(), - 'sysuid' : self.delegateto.sysuid, - 'group' : config.get('sysuser', 'defaultgroup'), - 'gecos' : gecos, - 'username' : self.delegateto.username} + cmdline = 'adduser --home "%(home)s" --shell "%(shell)s" ' + \ + '--no-create-home --uid %(sysuid)d --ingroup "%(group)s" ' + \ + '--disabled-password --gecos "%(gecos)s" %(username)s' % { + 'home': self.delegateto.home, + 'shell': self._get_shell_binary(), + 'sysuid': self.delegateto.sysuid, + 'group': config.get('sysuser', 'defaultgroup'), + 'gecos': gecos, + 'username': self.delegateto.username} self.sucommand(cmdline) cmdline = 'chpasswd --encrypted' inline = '%(username)s:%(md5pass)s' % { - 'username' : self.delegateto.username, - 'md5pass' : self.delegateto.md5pass} + 'username': self.delegateto.username, + 'md5pass': self.delegateto.md5pass} self.sucommand(cmdline, inline) self._populate_home() self._mail_sysuser() @@ -141,15 +146,17 @@ class SysuserEntity(BackendEntity): config.get('sysuser', 'homebackupdir')) if not os.path.isdir(backupdir): cmdline = 'mkdir -p "%(backupdir)s"' % { - 'backupdir' : backupdir} + 'backupdir': backupdir} status = self.sucommand(cmdline) if status != 0: raise Exception("could not create backup directory") - cmdline = 'deluser --remove-home --backup --backup-to "%(backupdir)s" %(username)s' % { - 'backupdir' : backupdir, - 'username' : self.delegateto.username} + cmdline = 'deluser --remove-home --backup --backup-to ' + \ + ' "%(backupdir)s" %(username)s' % { + 'backupdir': backupdir, + 'username': self.delegateto.username} self.sucommand(cmdline) + class SysuserHandler(BackendEntityHandler): """BackendEntityHandler for Sysuser entities.""" diff --git a/gnuviechadmin/backend/tables.py b/gnuviechadmin/backend/tables.py index 3dde9b8..82ea91f 100644 --- a/gnuviechadmin/backend/tables.py +++ b/gnuviechadmin/backend/tables.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -31,7 +30,8 @@ try: config.get('database', 'uri'), config.get('database', 'repository')) if dbversion < required_version: - print("""Database version is %d but required version is %d. Trying automatic upgrade.""" % + print("""Database version is %d but required version is %d. Trying +automatic upgrade.""" % (dbversion, required_version)) try: migrate.versioning.api.upgrade( @@ -42,10 +42,11 @@ try: print "Automatic upgrade failed." raise elif dbversion > required_version: - print("""Database version is %d which is higher than the required version %d. I cannot handle this situation without possible data loss.""" % + print("""Database version is %d which is higher than the required +version %d. I cannot handle this situation without possible data loss.""" % (dbversion, required_version)) sys.exit(1) -except NoSuchTableError, nste: +except NoSuchTableError, nste: print """The database is not versioned. Trying automatic versioning.""" try: migrate.versioning.api.version_control( diff --git a/gnuviechadmin/cli/CliCommand.py b/gnuviechadmin/cli/CliCommand.py index 6520273..4ea6d3d 100644 --- a/gnuviechadmin/cli/CliCommand.py +++ b/gnuviechadmin/cli/CliCommand.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -19,10 +18,12 @@ # USA. # # Version: $Id$ - -import getopt, sys, logging +import getopt +import sys +import logging from gnuviechadmin.exceptions import GnuviechadminError + class CliCommand: """Base class for command line interface. @@ -65,17 +66,17 @@ Common options: %(option)s %(mandatory)s %(optiondesc)s -""" % { 'called' : sys.argv[0], - 'command' : self.name, - 'description' : self.description, - 'option' : '-v, --verbose', - 'optiondesc' : 'verbose operation', - 'mandatory' : " "} +""" % {'called': sys.argv[0], + 'command': self.name, + 'description': self.description, + 'option': '-v, --verbose', + 'optiondesc': 'verbose operation', + 'mandatory': " "} for commandname in self._optionmap.keys(): cmdl = "%(called)s %(command)s %(subcommand)s [-v|--verbose]" % { - 'called' : sys.argv[0], - 'command' : self.name, - 'subcommand' : commandname} + 'called': sys.argv[0], + 'command': self.name, + 'subcommand': commandname} desc = """ %s """ % (self._optionmap[commandname][0]) @@ -97,9 +98,9 @@ Common options: if not mandatory: cmd = cmd + "]" descmap = { - 'option' : ", ".join(pairs), - 'optiondesc' : optiondesc, - 'mandatory' : ' '} + 'option': ", ".join(pairs), + 'optiondesc': optiondesc, + 'mandatory': ' '} if mandatory: descmap['mandatory'] = '*' desc = desc + """ %(option)s diff --git a/gnuviechadmin/cli/__init__.py b/gnuviechadmin/cli/__init__.py index 262fc68..97634de 100644 --- a/gnuviechadmin/cli/__init__.py +++ b/gnuviechadmin/cli/__init__.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -19,7 +18,6 @@ # USA. # # Version: $Id$ - """This is the gnuviechadmin.cli package. This package provides modules for the command line interface of the diff --git a/gnuviechadmin/cli/client.py b/gnuviechadmin/cli/client.py index 29b9c7b..d26f6c2 100644 --- a/gnuviechadmin/cli/client.py +++ b/gnuviechadmin/cli/client.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -19,8 +18,9 @@ # USA. # # Version: $Id$ +import CliCommand +import sys -import CliCommand, sys class ClientCli(CliCommand.CliCommand): """Command line interface command for client management.""" @@ -28,37 +28,36 @@ class ClientCli(CliCommand.CliCommand): name = "client" description = "manage clients" _optionmap = { - 'create' : ("creates a new client", - [(["-f", "--firstname"], "firstname", - "the client's first name", True), - (["-l", "--lastname"], "lastname", - "the client's last name", True), - (["-t", "--title"], "title", - "the client's title", False), - (["-a", "--address"], "address1", - "the address of the client", True), - (["--address2"], "address2", - "second line of the client's address", False), - (["-z", "--zip"], "zip", - "the zipcode of the client's address", True), - (["-c", "--city"], "city", - "the city of the client's address", True), - (["--country"], "country", - "the client's country", False), - (["-e", "--email"], "email", - "the client's email address", True), - (["-p", "--phone"], "phone", - "the client's phone number", True), - (["-m", "--mobile"], "mobile", - "the client's mobile phone number", False), - (["-x", "--fax"], "fax", - "the client's fax number", False)]), - 'list' : ("lists existing clients", - []), - 'delete' : ("deletes the specified client if it has no dependent data", - [(["-c", "--clientid"], "clientid", - "the client id", True)])} - + 'create': ("creates a new client", + [(["-f", "--firstname"], "firstname", + "the client's first name", True), + (["-l", "--lastname"], "lastname", + "the client's last name", True), + (["-t", "--title"], "title", + "the client's title", False), + (["-a", "--address"], "address1", + "the address of the client", True), + (["--address2"], "address2", + "second line of the client's address", False), + (["-z", "--zip"], "zip", + "the zipcode of the client's address", True), + (["-c", "--city"], "city", + "the city of the client's address", True), + (["--country"], "country", + "the client's country", False), + (["-e", "--email"], "email", + "the client's email address", True), + (["-p", "--phone"], "phone", + "the client's phone number", True), + (["-m", "--mobile"], "mobile", + "the client's mobile phone number", False), + (["-x", "--fax"], "fax", + "the client's fax number", False)]), + 'list': ("lists existing clients", []), + 'delete': ("deletes the specified client if it has no dependent data", + [(["-c", "--clientid"], "clientid", + "the client id", True)])} + def _execute(self, subcommand): self.logger.debug("execute %s with data %s", subcommand, str(self._data)) diff --git a/gnuviechadmin/cli/domain.py b/gnuviechadmin/cli/domain.py index af39f32..8468153 100644 --- a/gnuviechadmin/cli/domain.py +++ b/gnuviechadmin/cli/domain.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -19,8 +18,9 @@ # USA. # # Version: $Id$ +import CliCommand +import sys -import CliCommand, sys class DomainCli(CliCommand.CliCommand): """Command line interface command for domain management.""" @@ -28,20 +28,19 @@ class DomainCli(CliCommand.CliCommand): name = "domain" description = "manage domains" _optionmap = { - 'create' : ("creates a new domain", - [(["-n", "--name"], "name", - "the domain name", True), - (["-t", "--type"], "type", - "domain type m for master or s for slave", False), - (["-m", "--master"], "master", - "master server for slave domains", False), - (["-s", "--sysuserid"], "sysuserid", - "system user id", True)]), - 'list' : ("lists existing domains", - []), - 'delete' : ("delete a domain", - [(["-d", "--domainid"], "domainid", - "the domain id", True)])} + 'create': ("creates a new domain", + [(["-n", "--name"], "name", + "the domain name", True), + (["-t", "--type"], "type", + "domain type m for master or s for slave", False), + (["-m", "--master"], "master", + "master server for slave domains", False), + (["-s", "--sysuserid"], "sysuserid", + "system user id", True)]), + 'list': ("lists existing domains", []), + 'delete': ("delete a domain", + [(["-d", "--domainid"], "domainid", + "the domain id", True)])} def _execute(self, subcommand): self.logger.debug("execute %s with data %s", subcommand, diff --git a/gnuviechadmin/cli/record.py b/gnuviechadmin/cli/record.py index 80de774..a2cd39e 100644 --- a/gnuviechadmin/cli/record.py +++ b/gnuviechadmin/cli/record.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -19,8 +18,9 @@ # USA. # # Version: $Id$ +import CliCommand +import sys -import CliCommand, sys class RecordCli(CliCommand.CliCommand): """Command line interface command for DNS record management.""" @@ -28,25 +28,25 @@ class RecordCli(CliCommand.CliCommand): name = "record" description = "manage DNS records" _optionmap = { - 'create' : ("creates a new record", - [(["-n", "--name"], "name", - "the record name", True), - (["-t", "--type"], "type", - "record type", True), - (["-c", "--content"], "content", - "record content", True), - (["-p", "--prio"], "prio", - "MX record priority", False), - (["--ttl"], "ttl", - "time to live", False), - (["-d", "--domainid"], "domainid", - "domain id", True)]), - 'list' : ("lists existing records", - [(["-d", "--domainid"], "domainid", - "domain id", False)]), - 'delete' : ("delete a record", - [(["-r", "--recordid"], "recordid", - "the record id", True)])} + 'create': ("creates a new record", + [(["-n", "--name"], "name", + "the record name", True), + (["-t", "--type"], "type", + "record type", True), + (["-c", "--content"], "content", + "record content", True), + (["-p", "--prio"], "prio", + "MX record priority", False), + (["--ttl"], "ttl", + "time to live", False), + (["-d", "--domainid"], "domainid", + "domain id", True)]), + 'list': ("lists existing records", + [(["-d", "--domainid"], "domainid", + "domain id", False)]), + 'delete': ("delete a record", + [(["-r", "--recordid"], "recordid", + "the record id", True)])} def _execute(self, subcommand): self.logger.debug("execute %s with data %s", subcommand, diff --git a/gnuviechadmin/cli/sysuser.py b/gnuviechadmin/cli/sysuser.py index cdae8d7..d0ca130 100644 --- a/gnuviechadmin/cli/sysuser.py +++ b/gnuviechadmin/cli/sysuser.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -19,33 +18,33 @@ # USA. # # Version: $Id$ +import CliCommand +import sys -import CliCommand, sys class SysuserCli(CliCommand.CliCommand): """Command line interface command for system user managament.""" - name = "sysuser" + name = "sysuser" description = "manage system users" - _optionmap = { - "create" : ("create a new system user with the given options.", - [(["-n", "--username"], "username", - "the system user name", False), - (["-t", "--usertype"], "usertype", - "the numeric user type", False), - (["-h", "--home"], "home", - "the home directory", False), - (["-s", "--shell"], "shell", - "true if the user should get shell access", False), - (["-p", "--password"], "clearpass", - "the password for the user", False), - (["-c", "--clientid"], "clientid", - "the client id", True)]), - "list" : ("list existing system users.", - []), - "delete" : ("delete a system user.", - [(["-s", "--sysuserid"], "sysuserid", - "the system user id", True)])} + _optionmap = { + "create": ("create a new system user with the given options.", + [(["-n", "--username"], "username", + "the system user name", False), + (["-t", "--usertype"], "usertype", + "the numeric user type", False), + (["-h", "--home"], "home", + "the home directory", False), + (["-s", "--shell"], "shell", + "true if the user should get shell access", False), + (["-p", "--password"], "clearpass", + "the password for the user", False), + (["-c", "--clientid"], "clientid", + "the client id", True)]), + "list": ("list existing system users.", []), + "delete": ("delete a system user.", + [(["-s", "--sysuserid"], "sysuserid", + "the system user id", True)])} def _execute(self, subcommand): self.logger.debug("execute %s with data %s", subcommand, diff --git a/gnuviechadmin/exceptions.py b/gnuviechadmin/exceptions.py index b90b2c5..f982c6c 100644 --- a/gnuviechadmin/exceptions.py +++ b/gnuviechadmin/exceptions.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -19,26 +18,30 @@ # USA. # # Version: $Id$ - """This file defines the gnuviechadmin specific exception types.""" + class GnuviechadminError(Exception): """This is the base class for domain specific exceptions of Gnuviechadmin.""" pass + class MissingFieldsError(GnuviechadminError): """This exception should be raised when a required field of a data class is missing.""" + def __init__(self, missingfields): self.missing = missingfields def __str__(self): return "the fields %s are missing." % (repr(self.missing)) + class CreationFailedError(GnuviechadminError): """This exception should be raised if a business object could not be created.""" + def __init__(self, classname, cause = None): self.classname = classname self.cause = cause @@ -49,9 +52,11 @@ class CreationFailedError(GnuviechadminError): msg += " The reason is %s." % (str(self.cause)) return msg + class DeleteFailedError(GnuviechadminError): """This exception should be raise if a business object coild not be deleted.""" + def __init__(self, classname, cause = None): self.classname = classname self.cause = cause @@ -62,9 +67,11 @@ class DeleteFailedError(GnuviechadminError): msg += " The reason is %s." % (str(self.cause)) return msg + class ValidationFailedError(GnuviechadminError): """This exception should be raised if the validation of a business object failed.""" + def __init__(self, instance, cause = None): self.instance = instance self.cause = cause @@ -75,9 +82,11 @@ class ValidationFailedError(GnuviechadminError): msg += " The reason is %s." % (str(self.cause)) return msg + class CannotDeleteError(GnuviechadminError): """This exception should be raised if an entity cannot be deleted because of some unmatched precondition.""" + def __init__(self, instance, cause = None): self.instance = instance self.cause = cause diff --git a/gnuviechadmin/util/__init__.py b/gnuviechadmin/util/__init__.py index 3b64c65..0dca7d2 100644 --- a/gnuviechadmin/util/__init__.py +++ b/gnuviechadmin/util/__init__.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. diff --git a/gnuviechadmin/util/getenttools.py b/gnuviechadmin/util/getenttools.py index 126133a..af20fcf 100644 --- a/gnuviechadmin/util/getenttools.py +++ b/gnuviechadmin/util/getenttools.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -22,10 +21,13 @@ """Tools for handling user and group information.""" -import pwd, grp +import pwd +import grp + class PasswdUser(object): """This class represents users in the user database.""" + def __init__(self, username, pw, uid, gid, gecos, home, shell): """Create a new PasswdUser.""" self.username = username @@ -45,8 +47,10 @@ class PasswdUser(object): self.home, self.shell) + class PasswdGroup(object): """This class represents lines in the groups database.""" + def __init__(self, groupname, pw, gid, members): """Create a new PasswdGroup.""" self.groupname = groupname @@ -60,18 +64,22 @@ class PasswdGroup(object): self.gid, ",".join(self.members)) + def parse_groups(): """Parses all available groups to PasswdGroup instances.""" return [PasswdGroup(*arr) for arr in grp.getgrall()] + def parse_users(): """Parses all available users to PasswdUser instances.""" return [PasswdUser(*arr) for arr in pwd.getpwall()] + def find_user_by_prefix(prefix): - """Finds all user entries with the given prefix.""" + """Finds all user entries with the given prefix.""" return [user for user in parse_users() if user.username.startswith(prefix)] + def get_user_by_id(uid): """Gets the user with the given user id.""" users = [user for user in parse_users() if user.uid == uid] @@ -79,6 +87,7 @@ def get_user_by_id(uid): return users[0] return None + def get_group_by_id(gid): """Gets the group with the given group id.""" groups = [group for group in parse_groups() if group.gid == gid] @@ -86,6 +95,7 @@ def get_group_by_id(gid): return groups[0] return None + def get_next_uid(lowerboundary = 10000, upperboundary = 65536): """Gets the first available user id in the given range. @@ -98,16 +108,19 @@ def get_next_uid(lowerboundary = 10000, upperboundary = 65536): """ for uid in range(lowerboundary, upperboundary): - try: - user = pwd.getpwuid(uid) - except KeyError: - return uid - raise Exception("no free uid found in range %d to %d", lowerboundary, upperboundary) + try: + user = pwd.getpwuid(uid) + except KeyError: + return uid + raise Exception("no free uid found in range %d to %d", + lowerboundary, upperboundary) + def get_max_uid(boundary = 65536): """Gets the highest uid value.""" return max([user.uid for user in parse_users() if user.uid <= boundary]) + def get_max_gid(boundary = 65536): """Gets the highest gid value.""" return max([group.gid for group in parse_groups() \ @@ -119,4 +132,3 @@ if __name__ == "__main__": print "User with max UID is %s" % (get_user_by_id(get_max_uid(40000))) print "Group with max GID is %s" % (get_group_by_id(get_max_gid(40000))) print "First free UID is %s" % (get_next_uid(10000, 40000)) - diff --git a/gnuviechadmin/util/gpgmail.py b/gnuviechadmin/util/gpgmail.py index 556d87a..f444aa2 100644 --- a/gnuviechadmin/util/gpgmail.py +++ b/gnuviechadmin/util/gpgmail.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -33,6 +32,7 @@ from pyme.constants.sig import mode from gnuviechadmin.backend.settings import config + def send_mail(subject, text): """Send a signed and possibly encrypted mail. @@ -56,33 +56,33 @@ def send_mail(subject, text): rcpt = config.get('common', 'mailto') c.signers_clear() for sigkey in [x for x in c.op_keylist_all(signer, 1)]: - if sigkey.can_sign: - c.signers_add(sigkey) - if not c.signers_enum(0): - raise Exception("No secret keys for signing available for %s." % ( - signer)) + if sigkey.can_sign: + c.signers_add(sigkey) + if not c.signers_enum(0): + raise Exception("No secret keys for signing available for %s." % ( + signer)) keylist = [] for key in c.op_keylist_all(rcpt, 0): - valid = 0 - subkey = key.subkeys - while subkey: - keyid = subkey.keyid - if keyid == None: - break - can_encrypt = subkey.can_encrypt - valid += can_encrypt - subkey = subkey.next - if valid: - keylist.append(key) + valid = 0 + subkey = key.subkeys + while subkey: + keyid = subkey.keyid + if keyid == None: + break + can_encrypt = subkey.can_encrypt + valid += can_encrypt + subkey = subkey.next + if valid: + keylist.append(key) if keylist: - c.op_encrypt_sign(keylist, 1, plain, cipher) + c.op_encrypt_sign(keylist, 1, plain, cipher) else: - c.op_sign(plain, cipher, mode.CLEAR) - cipher.seek(0,0) + c.op_sign(plain, cipher, mode.CLEAR) + cipher.seek(0, 0) msg = MIMEText(cipher.read()) if keylist: - msg.set_param("x-action", "pgp-encrypted") + msg.set_param("x-action", "pgp-encrypted") msg['Subject'] = subject msg['From'] = signer msg['To'] = rcpt diff --git a/gnuviechadmin/util/passwordutils.py b/gnuviechadmin/util/passwordutils.py index 2c3c5c4..cde79ff 100644 --- a/gnuviechadmin/util/passwordutils.py +++ b/gnuviechadmin/util/passwordutils.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -21,7 +20,9 @@ # Version: $Id$ """This module provides some functions for password handling.""" -import crypt, crack, random +import crypt +import crack +import random _pwchars = [] for _pair in (('0', '9'), ('A', 'Z'), ('a', 'z')): @@ -30,6 +31,7 @@ _saltchars = [_char for _char in _pwchars] for _char in "-+/*_@": _pwchars.append(ord(_char)) + def generatepassword(minlength = 8, maxlength = 12): """Generates a new random password with a given length. @@ -44,6 +46,7 @@ def generatepassword(minlength = 8, maxlength = 12): random.sample(_pwchars, random.randint(minlength, maxlength))]) + def checkpassword(password): """Checks the password with cracklib. @@ -58,7 +61,8 @@ def checkpassword(password): except ValueError, ve: print "Weak password:", ve return None - + + def md5_crypt_password(password): """Hashes the given password with MD5 and a random salt value. @@ -71,6 +75,7 @@ def md5_crypt_password(password): random.sample(_saltchars, 8)]) return crypt.crypt(password, '$1$' + salt) + def get_pw_tuple(password = None): """Gets a valid (password, hashvalue) tuple. @@ -82,3 +87,6 @@ def get_pw_tuple(password = None): while password == None or checkpassword(password) == None: password = generatepassword() return (password, md5_crypt_password(password)) + + +# TODO: implement a is_password_valid(hash, password) function diff --git a/gnuviechadmin/util/stmtcreator.py b/gnuviechadmin/util/stmtcreator.py old mode 100644 new mode 100755 index 7cae25c..345ba18 --- a/gnuviechadmin/util/stmtcreator.py +++ b/gnuviechadmin/util/stmtcreator.py @@ -1,4 +1,4 @@ -# -*- python -*- +#!/usr/bin/python # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -24,16 +24,23 @@ creation.""" if __name__ == '__main__': - from passwordutils import get_pw_tuple - import sys + from passwordutils import get_pw_tuple + import sys - for line in sys.stdin.readlines(): - parts = line.split() - if len(parts) < 4: - raise ValueError("""lines must consist of the elements: + for line in sys.stdin.readlines(): + parts = line.split() + if len(parts) < 4: + raise ValueError("""lines must consist of the elements: email@domain username uid domainid""") - (email, domain) = parts[0].split("@") - username = parts[1][0:5] - pwtuple = get_pw_tuple() - print "INSERT INTO mailpassword (id, clearpass, cryptpass, uid, gid, home, spamcheck) VALUES ('%s', '%s', '%s', %d, %d, '/home/mail/%s/%s', 'false');" % (parts[1], pwtuple[0], pwtuple[1], int(parts[2]), 119, username, parts[1]) - print "INSERT INTO mailaddress (domainid, email, target) VALUES (%d, '%s', '%s');" % (int(parts[3]), email, parts[1]) + (email, domain) = parts[0].split("@") + username = parts[1][0:5] + pwtuple = get_pw_tuple() + print "INSERT INTO mailpassword " + \ + "(id, clearpass, cryptpass, uid, gid, home, spamcheck) " + \ + "VALUES " + \ + "('%s', '%s', '%s', %d, %d, '/home/mail/%s/%s', 'false');" % ( + parts[1], pwtuple[0], pwtuple[1], int(parts[2]), 119, + username, parts[1]) + print "INSERT INTO mailaddress (domainid, email, target) " + \ + "VALUES (%d, '%s', '%s');" % ( + int(parts[3]), email, parts[1]) diff --git a/gnuviechadmin/xmlrpc/XMLRPCFacade.py b/gnuviechadmin/xmlrpc/XMLRPCFacade.py index 8591fd0..e5f9fa0 100644 --- a/gnuviechadmin/xmlrpc/XMLRPCFacade.py +++ b/gnuviechadmin/xmlrpc/XMLRPCFacade.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2008 by Jan Dittberner. @@ -19,12 +18,12 @@ # USA. # # Version: $Id$ - """This file defines a facade for exporting gnuviechadmin functionality via XMLRPC.""" from gnuviechadmin.xmlrpc.users import GVAUsers + class XMLRPCFacade(GVAUsers): """This class provides access to selected gnuviechadmin functionality for use via XMLRPC.""" diff --git a/gnuviechadmin/xmlrpc/__init__.py b/gnuviechadmin/xmlrpc/__init__.py index be77719..b4a2700 100644 --- a/gnuviechadmin/xmlrpc/__init__.py +++ b/gnuviechadmin/xmlrpc/__init__.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2008 by Jan Dittberner. @@ -19,7 +18,6 @@ # USA. # # Version: $Id$ - """This is the gnuviechadmin.xmlrpc package. This package provides modules for the XMLRPC interface of the diff --git a/gnuviechadmin/xmlrpc/users.py b/gnuviechadmin/xmlrpc/users.py index 076d23d..fa53b0f 100644 --- a/gnuviechadmin/xmlrpc/users.py +++ b/gnuviechadmin/xmlrpc/users.py @@ -1,20 +1,47 @@ -# -*- python -*- # -*- coding: utf-8 -*- +# +# Copyright (C) 2007, 2008 by Jan Dittberner. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +# Version: $Id$ +"""This file provides a authkit.users.Users implementation and several +UserProviders for authenticating different user types and enabling +password change functions.""" + from authkit.users import Users, AuthKitNoSuchUserError import logging log = logging.getLogger(__name__) + class UserProvider(Users): + """A base class for user providers.""" + def _get_user(self, username, password, role): return { - 'username' : username, - 'group' : None, - 'password' : password, - 'roles' : [role] - } + 'username': username, + 'group': None, + 'password': password, + 'roles': [role]} + class ClientUserProvider(UserProvider): + """A UserProvider implementation class for clients.""" + def user(self, username): print 'checking %s' % username if username == 'dummy': @@ -24,23 +51,34 @@ class ClientUserProvider(UserProvider): def list_roles(self): return ['client'] + class MailuserUserProvider(UserProvider): + """A UserProvider implementation class for mail users.""" + def user(self, username): raise AuthKitNoSuchUserError() def list_roles(self): return ['mailuser'] + class SysuserUserProvider(UserProvider): + """A UserProvider implementation class for system users.""" + def user(self, username): raise AuthKitNoSuchUserError() def list_roles(self): return ['sysuser'] + class GVAUsers(Users): + """This class provides an implementation of authkit.users.Users + which dispatches several methods to configured UserProvider + implementations.""" + def __init__(self, data, userproviders = [], encrypt = None): - """Initialize the GVAXMLRPCUsers instance.""" + """Initialize the GVAUsers instance.""" Users.__init__(self, data, encrypt) self.userproviders = [prov(self.data) for prov in userproviders] @@ -65,16 +103,16 @@ class GVAUsers(Users): def user(self, username): """Returns a dictionary in the following format: - + .. code-block :: Python - + { 'username': username, 'group': group, 'password': password, 'roles': [role1,role2,role3... etc] } - + The role names are ordered alphabetically Raises an exception if the user doesn't exist.""" for prov in self.userproviders: diff --git a/setup.py b/setup.py index c037e3e..c61c625 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,3 @@ -# -*- python -*- # -*- coding: utf-8 -*- # # Copyright (C) 2007, 2008 by Jan Dittberner. @@ -36,7 +35,7 @@ setup( setup_requires = [], include_package_data = True, - exclude_package_data = { '' : ['gva.cfg'] }, + exclude_package_data = {'': ['gva.cfg']}, author = 'Jan Dittberner', author_email = 'jan@dittberner.info', @@ -44,7 +43,7 @@ setup( long_description = """this is a suite of tools for administering a server it contains tools for maintaining e.g. clients, domains, users, mail accounts""", - license = 'GPL', + license = 'GPL', keywords = 'administration backend frontend', url = 'http://www.gnuviech-server.de/projects/gnuviechadmin', ) diff --git a/test/manage.py b/test/manage.py index d41a202..9676557 100644 --- a/test/manage.py +++ b/test/manage.py @@ -1,4 +1,5 @@ #!/usr/bin/python from migrate.versioning.shell import main -main(url='postgres://jan:heyyou97@localhost:5432/jan',repository='ormaptest_repo') +main(url='postgres://jan:heyyou97@localhost:5432/jan', + repository='ormaptest_repo') diff --git a/test/ormaptest.py b/test/ormaptest.py index c516d2e..03c41f7 100644 --- a/test/ormaptest.py +++ b/test/ormaptest.py @@ -1,26 +1,47 @@ #!/usr/bin/python -# -*- coding: UTF-8 -*- - +# -*- coding: utf-8 -*- +# +# Copyright (C) 2007, 2008 by Jan Dittberner. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +# Version: $Id$ from sqlalchemy import * meta = BoundMetaData('postgres://jan:heyyou97@localhost:5432/jan') domains_table = Table('domains', meta, autoload=True) records_table = Table('records', meta, autoload=True) + class Domain(object): + def __repr__(self): return "%s(%r,%r)" % ( self.__class__.__name__, self.id, self.name) + class Record(object): + def __repr__(self): return "%s(%r,%r,%r)" % ( self.__class__.__name__, self.id, self.domain_id, self.domain) recordmapper = mapper(Record, records_table) domainmapper = mapper(Domain, domains_table, properties = { - 'records': relation(Record, backref='domain') - }) + 'records': relation(Record, backref='domain')}) session = create_session() query = session.query(Domain) diff --git a/test/ormaptest_repo/versions/1/1.py b/test/ormaptest_repo/versions/1/1.py index 932d025..47b1bd6 100644 --- a/test/ormaptest_repo/versions/1/1.py +++ b/test/ormaptest_repo/versions/1/1.py @@ -7,8 +7,10 @@ account = Table('account', meta, Column('login', String(40)), Column('passwd', String(40))) + def upgrade(): account.create() + def downgrade(): account.drop() diff --git a/test/ormaptest_repo/versions/2/2.py b/test/ormaptest_repo/versions/2/2.py index 675e033..76f397b 100644 --- a/test/ormaptest_repo/versions/2/2.py +++ b/test/ormaptest_repo/versions/2/2.py @@ -4,8 +4,10 @@ from migrate import * meta = BoundMetaData(migrate_engine) account = Table('account', meta) + def upgrade(): account.drop() + def downgrade(): account.create() diff --git a/test/ormaptest_repo/versions/3/3.py b/test/ormaptest_repo/versions/3/3.py index 8d41742..821cc36 100644 --- a/test/ormaptest_repo/versions/3/3.py +++ b/test/ormaptest_repo/versions/3/3.py @@ -15,8 +15,7 @@ domains = Table('domains', meta, Column('type', String(6), nullable=False), Column('notified_serial', Integer), Column('account', String(40)), - UniqueConstraint('name', name='name_index') -) + UniqueConstraint('name', name='name_index')) records = Table('records', meta, Column('id', Integer, primary_key=True), @@ -28,17 +27,18 @@ records = Table('records', meta, Column('prio', Integer), Column('change_date', Integer), ForeignKeyConstraint(['domain_id'], ['domains.id'], - ondelete='CASCADE', name='domain_exists') -) + ondelete='CASCADE', name='domain_exists')) Index('domain_id', records.c.domain_id) Index('nametype_index', records.c.name, records.c.type) Index('rec_name_index', records.c.name) + def upgrade(): supermasters.create() domains.create() records.create() + def downgrade(): records.drop() domains.drop() diff --git a/testdb/addclient.py b/testdb/addclient.py index 264a8ed..dd0881d 100644 --- a/testdb/addclient.py +++ b/testdb/addclient.py @@ -1,74 +1,93 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- # -# Copyright (c) 2007 Jan Dittberner -# $Id$ +# Copyright (C) 2007, 2008 by Jan Dittberner. # -import getopt, sys +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +# Version: $Id$ +import getopt +import sys from gnuviechadmin.dblayer import * -def usage(): - print """Usage information: - ===================== - %(process)s -h|--help - - prints this help text - %(process)s --firstname= --lastname= \ - --address1= --town= --zipcode= \ - [--address2=] [--country=] [--state=] \ - [--active=true|false] [--phone=] [--mobile=] - - adds a new client - """ % {'process': sys.argv[0]} +def usage(): + print """Usage information: +===================== +%(process)s -h|--help +- prints this help text + +%(process)s --firstname= --lastname= \ + --address1= --town= --zipcode= \ + [--address2=] [--country=] [--state=] \ + [--active=true|false] [--phone=] [--mobile=] +- adds a new client +""" % {'process': sys.argv[0]} if __name__ == "__main__": - try: - (options, args) = getopt.getopt(sys.argv[1:], "h", - ['help', - 'firstname=', 'lastname=', 'address1=', - 'town=', 'zipcode=', 'address2=', - 'country=', 'state=', 'active=', - 'phone=', 'mobile=']) - except getopt.GetoptError: - usage() - sys.exit(1) + try: + (options, args) = getopt.getopt(sys.argv[1:], "h", + ['help', + 'firstname=', 'lastname=', + 'address1=', + 'town=', 'zipcode=', 'address2=', + 'country=', 'state=', 'active=', + 'phone=', 'mobile=']) + except getopt.GetoptError: + usage() + sys.exit(1) - if (not options or - dict(options).has_key('-h') or - dict(options).has_key('--help') or - not dict(options).has_key('--firstname') or - not dict(options).has_key('--lastname') or - not dict(options).has_key('--address1') or - not dict(options).has_key('--town') or - not dict(options).has_key('--zipcode') or - not dict(options)['--firstname'].strip() or - not dict(options)['--lastname'].strip() or - not dict(options)['--address1'].strip() or - not dict(options)['--town'].strip() or - not dict(options)['--zipcode'].strip()): - usage() - sys.exit(1) + if (not options or + '-h' in dict(options) or + '--help' in dict(options) or + not '--firstname' in dict(options) or + not '--lastname' in dict(options) or + not '--address1' in dict(options) or + not '--town' in dict(options) or + not '--zipcode' in dict(options) or + not dict(options)['--firstname'].strip() or + not dict(options)['--lastname'].strip() or + not dict(options)['--address1'].strip() or + not dict(options)['--town'].strip() or + not dict(options)['--zipcode'].strip()): + usage() + sys.exit(1) - po = dict(options) - for key in po.keys(): - po[key] = po[key].strip() - client = Client() - client.firstname = po['--firstname'] - client.lastname = po['--lastname'] - client.address1 = po['--address1'] - client.town = po['--town'] - client.zipcode = po['--zipcode'] - if po.has_key('--active'): - client.active = (po['--active'] == 'true') - else: - client.active = True - if po.has_key('--address2') and po['--address2']: - client.address2 = po['--address2'] - if po.has_key('--country') and po['--country']: - client.country = po['--country'] - if po.has_key('--state') and po['--state']: - client.state = po['--state'] - if po.has_key('--phone') and po['--phone']: - client.phone = po['--phone'] - if po.has_key('--mobile') and po['--mobile']: - client.mobile = po['--mobile'] - session.save(client) - session.flush() + po = dict(options) + for key in po.keys(): + po[key] = po[key].strip() + client = Client() + client.firstname = po['--firstname'] + client.lastname = po['--lastname'] + client.address1 = po['--address1'] + client.town = po['--town'] + client.zipcode = po['--zipcode'] + if '--active' in po: + client.active = (po['--active'] == 'true') + else: + client.active = True + if '--address2' in po and po['--address2']: + client.address2 = po['--address2'] + if '--country' in po and po['--country']: + client.country = po['--country'] + if '--state' in po and po['--state']: + client.state = po['--state'] + if '--phone' in po and po['--phone']: + client.phone = po['--phone'] + if '--mobile' in po and po['--mobile']: + client.mobile = po['--mobile'] + session.save(client) + session.flush() diff --git a/testdb/adddomain.py b/testdb/adddomain.py index 6ec1d1b..e8b0170 100644 --- a/testdb/adddomain.py +++ b/testdb/adddomain.py @@ -1,59 +1,77 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- # -# Copyright (c) 2007 Jan Dittberner -# $Id$ +# Copyright (C) 2007, 2008 by Jan Dittberner. # -import getopt, sys +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +# Version: $Id$ +import getopt +import sys from gnuviechadmin.dblayer import * -def usage(): - print """Usage information: - ===================== - %(process)s -h|--help - - prints this help text - %(process)s --domain= --sysuser= --type=MASTER|SLAVE \ - [[--ns=] [--mx=] [--a=] ...] - - adds a new domain - """ % {'process': sys.argv[0]} +def usage(): + print """Usage information: +===================== +%(process)s -h|--help +- prints this help text + +%(process)s --domain= --sysuser= --type=MASTER|SLAVE \ + [[--ns=] [--mx=] [--a=] ...] +- adds a new domain +""" % {'process': sys.argv[0]} if __name__ == "__main__": - try: - (options, args) = getopt.getopt(sys.argv[1:], "h", - ['help', - 'domain=', 'sysuser=', - 'type=', 'ns=', 'mx=', 'a=']) - except getopt.GetoptError: - usage() - sys.exit(1) + try: + (options, args) = getopt.getopt(sys.argv[1:], "h", + ['help', + 'domain=', 'sysuser=', + 'type=', 'ns=', 'mx=', 'a=']) + except getopt.GetoptError: + usage() + sys.exit(1) - if (not options or - dict(options).has_key('-h') or - dict(options).has_key('--help') or - not dict(options).has_key('--domain') or - not dict(options).has_key('--sysuser') or - not dict(options)['--sysuser'].strip() or - not dict(options)['--domain'].strip()): - usage() - sys.exit(1) + if (not options or + '-h' in dict(options) or + '--help' in dict(options) or + not '--domain' in dict(options) or + not '--sysuser' in dict(options) or + not dict(options)['--sysuser'].strip() or + not dict(options)['--domain'].strip()): + usage() + sys.exit(1) - po = {} - for (key, value) in options: - if po.has_key(key): - po[key].append(value.strip()) - else: - po[key] = [value.strip()] + po = {} + for (key, value) in options: + if key in po: + po[key].append(value.strip()) + else: + po[key] = [value.strip()] - # fetch the sysuser - query = session.query(SysUser) - sysuser = query.get_by(name = po['--sysuser'][0]) - if not sysuser: - print "Invalid system user" - allsysusers = query.get_by(name = '*') - if allsysusers: - print "Valid system users are:\n%s" % ("\n".join(allsysusers)) - else: - print "No system users defined yet." - sys.exit(1) + # fetch the sysuser + query = session.query(SysUser) + sysuser = query.get_by(name = po['--sysuser'][0]) + if not sysuser: + print "Invalid system user" + allsysusers = query.get_by(name = '*') + if allsysusers: + print "Valid system users are:\n%s" % ("\n".join(allsysusers)) + else: + print "No system users defined yet." + sys.exit(1) - print sysuser.domains + print sysuser.domains diff --git a/testdb/addpopuser.py b/testdb/addpopuser.py index 0b23a06..345190c 100644 --- a/testdb/addpopuser.py +++ b/testdb/addpopuser.py @@ -1,45 +1,64 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- # -# Copyright (c) 2007 Jan Dittberner -# $Id$ +# Copyright (C) 2007, 2008 by Jan Dittberner. # -import getopt, sys +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +# Version: $Id$ +import getopt +import sys from gnuviechadmin.dblayer import * -def usage(): - print """Usage information: - ===================== - %(process)s -h|--help - - prints this help text - %(process)s --domain= [--password=] - - adds a new pop user for the given domain - - if the optional password is ommitted a generated one is used - - the password is checked using cracklib - - if the password is too weak a generated one is used - """ % {'process': sys.argv[0]} +def usage(): + print """Usage information: +===================== +%(process)s -h|--help +- prints this help text + +%(process)s --domain= [--password=] +- adds a new pop user for the given domain +- if the optional password is ommitted a generated one is used +- the password is checked using cracklib +- if the password is too weak a generated one is used +""" % {'process': sys.argv[0]} if __name__ == "__main__": - try: - (options, args) = getopt.getopt(sys.argv[1:], "h", ['help', 'password=', 'domain=']) - except getopt.GetoptError: - usage() - sys.exit(1) - - if (not options or - dict(options).has_key('-h') or - dict(options).has_key('--help') or - not dict(options).has_key('--domain') or - not dict(options)['--domain'].strip()): - usage() - sys.exit(1) + try: + (options, args) = getopt.getopt(sys.argv[1:], "h", + ['help', 'password=', 'domain=']) + except getopt.GetoptError: + usage() + sys.exit(1) - # specify the domain - query = session.query(Domain) - domain = query.get_by(name = dict(options)['--domain'].strip()) - if not domain: - print "Invalid Domain" - print "valid domains are:\n%s" % ("\n".join(query.get())) - sys.exit(1) - - print domain.popaccounts + if (not options or + '-h' in dict(options) or + '--help' in dict(options) or + not '--domain' in dict(options) or + not dict(options)['--domain'].strip()): + usage() + sys.exit(1) + + # specify the domain + query = session.query(Domain) + domain = query.get_by(name = dict(options)['--domain'].strip()) + if not domain: + print "Invalid Domain" + print "valid domains are:\n%s" % ("\n".join(query.get())) + sys.exit(1) + + print domain.popaccounts diff --git a/testdb/addsysuser.py b/testdb/addsysuser.py index 9524d1e..10db521 100644 --- a/testdb/addsysuser.py +++ b/testdb/addsysuser.py @@ -1,53 +1,72 @@ #!/usr/bin/env python # -# Copyright (c) 2007 Jan Dittberner -# $Id$ +# Copyright (C) 2007, 2008 by Jan Dittberner. # -import getopt, sys +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +# Version: $Id$ +import getopt +import sys from gnuviechadmin.dblayer import * -def usage(): - print """Usage information: - ===================== - %(process)s -h|--help - - prints this help text - %(process)s --type=admin|reseller|client --clientid= \ - [--name=] [--home=] [--shell=] [--password] \ - [--sysuid=] - - adds a new system user - """ % {'process': sys.argv[0]} +def usage(): + print """Usage information: +===================== +%(process)s -h|--help +- prints this help text + +%(process)s --type=admin|reseller|client --clientid= \ + [--name=] [--home=] [--shell=] [--password] \ + [--sysuid=] +- adds a new system user +""" % {'process': sys.argv[0]} if __name__ == "__main__": - try: - (options, args) = getopt.getopt(sys.argv[1:], "h", - ['help', - 'type=', 'clientid=', 'name=', 'home=', - 'shell=', 'password=', 'sysuid=']) - except getopt.GetoptError: - usage() - sys.exit(1) + try: + (options, args) = getopt.getopt(sys.argv[1:], "h", + ['help', 'type=', 'clientid=', + 'name=', 'home=', 'shell=', + 'password=', 'sysuid=']) + except getopt.GetoptError: + usage() + sys.exit(1) - if (not options or - dict(options).has_key('-h') or - dict(options).has_key('--help') or - not dict(options).has_key('--type') or - not dict(options).has_key('--clientid') or - not dict(options)['--type'].strip() or - not dict(options)['--clientid'].strip() or - not dict(options)['--type'].strip() in ('admin', 'reseller', 'client')): - usage() - sys.exit(1) + if (not options or + '-h' in dict(options) or + '--help' in dict(options) or + not '--type' in dict(options) or + not '--clientid' in dict(options) or + not dict(options)['--type'].strip() or + not dict(options)['--clientid'].strip() or + not dict(options)['--type'].strip() in ('admin', 'reseller', + 'client')): + usage() + sys.exit(1) - query = session.query(Client) - client = query.get_by(clientid = dict(options)['--clientid'].strip()) - if not client: - print "Invalid client" + query = session.query(Client) + client = query.get_by(clientid = dict(options)['--clientid'].strip()) + if not client: + print "Invalid client" allclients = query.select() if allclients: - print "Valid clients are:\n- %s" % "\n- ".join([str(client) for client in allclients]) + print "Valid clients are:\n- %s" % "\n- ".join( + [str(client) for client in allclients]) else: print "No clients defined yet." sys.exit(1) - print client.sysusers + print client.sysusers diff --git a/testdb/dbschema/gnuviechadmin/versions/1/1.py b/testdb/dbschema/gnuviechadmin/versions/1/1.py index fb9fa29..71766a7 100644 --- a/testdb/dbschema/gnuviechadmin/versions/1/1.py +++ b/testdb/dbschema/gnuviechadmin/versions/1/1.py @@ -6,7 +6,7 @@ meta = BoundMetaData(migrate_engine) domains = Table('domains', meta, autoload = True) mailalias = Table( 'mailalias', meta, - Column('mailaliasid', Integer, primary_key = True), + Column('mailaliasid', Integer, primary_key = True), Column('domainid', Integer, ForeignKey('domains.id'), nullable = False), Column('email', String(255), nullable = False), Column('target', TEXT, nullable = False), @@ -24,10 +24,12 @@ mailpassword = Table( Column('spamcheck', Boolean, default = False), Column('sajunkscore', Integer)) + def upgrade(): mailalias.create() mailpassword.create() + def downgrade(): mailpassword.drop() mailalias.drop() diff --git a/testdb/dbschema/gnuviechadmin/versions/2/2.py b/testdb/dbschema/gnuviechadmin/versions/2/2.py index b6d96f9..f3959a3 100644 --- a/testdb/dbschema/gnuviechadmin/versions/2/2.py +++ b/testdb/dbschema/gnuviechadmin/versions/2/2.py @@ -31,10 +31,12 @@ sysuser_table = Table( Column('md5pass', String(34)), Column('sysuid', Integer)) + def upgrade(): client_table.create() sysuser_table.create() + def downgrade(): sysuser_table.drop() client_table.drop() diff --git a/testdb/dbschema/gnuviechadmin/versions/3/3.py b/testdb/dbschema/gnuviechadmin/versions/3/3.py index 452a7b8..d6c0c64 100644 --- a/testdb/dbschema/gnuviechadmin/versions/3/3.py +++ b/testdb/dbschema/gnuviechadmin/versions/3/3.py @@ -9,9 +9,11 @@ sysuidrefcol = Column('sysuserid', Integer, ForeignKey('sysuser.sysuserid'), nullable = False) + def upgrade(): sysuidrefcol.create(domains) + def downgrade(): col = domains.c.sysuserid col.drop() diff --git a/testdb/dbschema/manage.py b/testdb/dbschema/manage.py index f19965e..a35438c 100644 --- a/testdb/dbschema/manage.py +++ b/testdb/dbschema/manage.py @@ -1,4 +1,5 @@ #!/usr/bin/python from migrate.versioning.shell import main -main(url='postgres://jan:heyyou97@localhost:5432/testdb',repository='gnuviechadmin') +main(url='postgres://jan:heyyou97@localhost:5432/testdb', + repository='gnuviechadmin') diff --git a/testdb/gnuviechadmin/dblayer.py b/testdb/gnuviechadmin/dblayer.py index c9d3fb5..fad38d9 100644 --- a/testdb/gnuviechadmin/dblayer.py +++ b/testdb/gnuviechadmin/dblayer.py @@ -1,3 +1,23 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2007, 2008 by Jan Dittberner. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +# Version: $Id$ from sqlalchemy import * from entities import * diff --git a/testdb/gnuviechadmin/entities.py b/testdb/gnuviechadmin/entities.py index 8d406a3..29953ab 100644 --- a/testdb/gnuviechadmin/entities.py +++ b/testdb/gnuviechadmin/entities.py @@ -1,4 +1,27 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2007, 2008 by Jan Dittberner. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +# Version: $Id$ + + class Client(object): + def __repr__(self): return "%s(clientid=%s,firstname=%s,lastname=%s)" % \ (self.__class__.__name__, @@ -6,7 +29,9 @@ class Client(object): self.firstname, self.lastname) + class PopAccount(object): + def __repr__(self): return "%s(%s,%d,%d,%d,%s,%s,%s)" % \ (self.__class__.__name__, @@ -18,7 +43,9 @@ class PopAccount(object): self.cryptpass, self.clearpass) + class SysUser(object): + def __repr__(self): return "%s(%d,%s,%d,%s,%s,%s,%d,%d,%s,%d)" % \ (self.__class__.__name__, @@ -33,7 +60,9 @@ class SysUser(object): self.md5pass, self.sysuid) + class Domain(object): + def __repr__(self): return "%s(%d,%s,%s,%s,%s,%s,%s)" % \ (self.__class__.__name__,