# -*- coding: UTF-8 -*-
#
# Copyright (C) 2007 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 tables import sysuser_table
from gnuviechadmin.exceptions import *
from gnuviechadmin.util import passwordutils, getenttools

from BackendEntity import *
from BackendEntityHandler import *

class Sysuser(BackendEntity):
    """Entity class for system users."""

    _shortkeys = ("sysuserid", "clientid", "username", "home", "shell")

    def __init__(self, verbose = False, **kwargs):
        BackendEntity.__init__(self, verbose)
        self.sysuserid = None
        self.username = None
        self.usertype = None
        self.home = None
        self.shell = None
        self.clearpass = None
        self.md5pass = None
        self.clientid = None
        self.sysuid = None
        for (key, value) in kwargs.items():
            self.__setattr__(key, value)
        if not self.username:
            self.username = self.getnextsysusername()
        if not self.usertype:
            self.usertype = self.getdefaultsysusertype()
        if not self.home:
            self.home = self.gethome(self.username)
        if not self.shell:
            self.shell = self.getdefaultshell()
        (self.clearpass, self.md5pass) = \
                         passwordutils.get_pw_tuple(self.clearpass)
        if not self.sysuid:
            self.sysuid = self.getnextsysuid()
        self.validate()

    def getnextsysusername(self):
        prefix = self.config.get('sysuser', 'nameprefix')
        usernames = [user.username for user in \
                     getenttools.finduserbyprefix(prefix)]
        maxid = max([int(username[len(prefix):]) for username in usernames])
        for num in range(1, maxid + 1):
            username = "%s%02d" % (prefix, num)
            if not username in usernames:
                return username

    def getdefaultsysusertype(self):
        return 1

    def gethome(self, sysusername):
        """Gets a valid home directory for the given user name."""
        return os.path.join(self.config.get('sysuser', 'homedirbase'),
                            sysusername)

    def getdefaultshell(self):
        return False

    def getshellbinary(self):
        if self.shell:
            return self.config.get('sysuser', 'shellyes')
        return self.config.get('sysuser', 'shellno')

    def getnextsysuid(self):
        uid = int(self.config.get('sysuser', 'minuid'))
        muid = getenttools.getmaxuid(int(self.config.get('sysuser',
                                                         'maxuid')))
        if muid >= uid:
            uid = muid + 1
        return uid

    def populate_home(self):
        templatedir = self.config.get('sysuser', 'hometemplate')
        cmdline = 'install -d --owner="%(username)s" --group="%(group)s" "%(home)s"' % {
            'username' : self.username,
            'group'    : self.config.get('sysuser', 'defaultgroup'),
            'home'     : self.home }
        self.sucommand(cmdline)
        cmdline = 'cp -R "%(template)s" "%(home)s"' % {
            'template' : templatedir,
            'home'     : self.home }
        self.sucommand(cmdline)
        cmdline = 'chown -R "%(username)s":"%(group)s" %(home)s' % {
            'username' : self.username,
            'group'    : self.config.get('sysuser', 'defaultgroup'),
            'home'     : self.home }
        self.sucommand(cmdline)

    def create_hook(self):
        gecos = self.config.get('sysuser', 'gecos')
        gecos = gecos % (self.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.home,
            'shell'     : self.getshellbinary(),
            'sysuid'    : self.sysuid,
            'group'     : self.config.get('sysuser', 'defaultgroup'),
            'gecos'     : gecos,
            'username'  : self.username}
        self.sucommand(cmdline)
        cmdline = 'chpasswd --encrypted'
        inline = '%(username)s:%(md5pass)s' % {
            'username' : self.username,
            'md5pass'  : self.md5pass}
        self.sucommand(cmdline, inline)
        self.populate_home()

    def delete_hook(self):
        backupdir = os.path.join(self.config.get('common',
                                                 'backupdir'),
                                 self.config.get('sysuser',
                                                 'homebackupdir'))
        if not os.path.isdir(backupdir):
            cmdline = 'mkdir -p "%(backupdir)s"' % {
                '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.username}
        self.sucommand(cmdline)

sysusermapper = mapper(Sysuser, sysuser_table)

class SysuserHandler(BackendEntityHandler):
    """BackendEntityHandler for Sysuser entities."""

    def __init__(self, verbose = False):
        BackendEntityHandler.__init__(self, Sysuser, verbose)