#-*-coding:utf-8-*-
"""
    Tests de la gestion des groupes ldap
"""
from scribe.eolegroup import Group
from scribe.eoleshare import Share
from os.path import isdir, join
from py.test import raises
from scribe.errors import LdapExistingGroup, LdapExistingUser, SystemExistingUser, NotEmptyNiveau
from scribe.ldapconf import CLASS_PATH, GROUP_PATH, MAIL_DOMAIN, OPT_PATH, CONTAINER_PATH_MAIL
from subprocess import getstatusoutput

SYMPA_EXPL = join(CONTAINER_PATH_MAIL, 'var/lib/sympa/expl')
SYMPA_ALIAS = join(CONTAINER_PATH_MAIL, 'etc/mail/sympa/aliases')
ALIAS_TMPL = MAIL_DOMAIN['restreint']+'-{1}{0}: "|/usr/lib/sympa/bin/queue {1}{0}@'+MAIL_DOMAIN['restreint']+'"'

def getfacl(group_name, dirname, default=False):
    grep = 'group:%s:' % group_name
    if default:
        grep = 'default:%s' % grep
    ret_code, ret_value = getstatusoutput("getfacl %s 2>/dev/null | grep ^%s " % (dirname, grep))
    if not ret_code % 256:
        return ret_value
    else:
        raise Exception("Erreur dans getfacl")

def _getsympaalias():
    return open(SYMPA_ALIAS).read().split('\n')


class TestGroup():
    """
        test la création de groupe avec nouvelle connexion à chaque action
    """

    gr_name = 'test__groupe__'
    gr_name2 = 'test__groupe2__'

    def setup_class(cls):
        cls.gr = Group()

    def test_add_groupe(self):
        # methode avec gestion de la connexion auto
        self.gr.add_groupe(self.gr_name)
        assert self.gr.get_attr(self.gr_name, 'description') == ['Groupe %s' % (self.gr_name,)]

    def test_add_groupe_with_share(self):
        self.gr.add_groupe(self.gr_name2, partage='rw')
        assert self.gr.get_attr(self.gr_name2, 'description') == ['Groupe %s' % (self.gr_name2,)]
        assert isdir(join(GROUP_PATH, self.gr_name2))

    def test_get_groups(self):
        assert self.gr_name2 in self.gr.get_groups() and self.gr_name in self.gr.get_groups()

    def test_del_groupe(self):
        self.gr.delete(self.gr_name)
        assert self.gr.get_attr(self.gr_name, 'description') == []

    def test_del_groupe_with_share(self):
        self.gr.delete(self.gr_name2)
        assert self.gr.get_attr(self.gr_name2, 'description') == []

    def teardown_class(cls):
        pass


class TestClasse():
    """
        test la création de classe et niveau avec une seule connexion (utilisation des _methode)
    """

    nv_name = 'test__niveau__'
    cl_name = 'test__classe__'
    cl_name2 = 'test__classe__2'
    equipe_name = 'profs-%s' % cl_name
    cl_dirname = join(CLASS_PATH, cl_name)
    work_cl_dirname = join(GROUP_PATH, cl_name)
    cl_data_dirname = join(work_cl_dirname, 'donnees')
    cl_work_dirname = join(work_cl_dirname, 'travail')
    equipe_dirname = join(GROUP_PATH, equipe_name)

    def setup_class(cls):
        cls.gr = Group()

    def test_add_groupes(self):
        self.gr.ldap_admin.connect()
        self.gr._add('Niveau', self.nv_name)
        self.gr._add('Classe', self.cl_name, niveau=self.nv_name)
        self.gr._add('Classe', self.cl_name2, domaine='restreint', niveau=self.nv_name)
        assert self.gr._is_group(self.nv_name) and self.gr._is_group(self.cl_name)
        assert self.gr._is_share(self.cl_name) and self.gr._is_share(self.equipe_name)

    def test_get_groups(self):
        assert self.cl_name2 in self.gr._get_groups() and self.cl_name in self.gr._get_groups() and self.nv_name in self.gr._get_groups()
        assert self.cl_name2 not in self.gr._get_groups(_type='Niveau')

    def test_cl_smb(self):
        """
            Teste la création samba de la classe
        """
        assert self.gr._get_attr(self.cl_name, 'description') == ['Classe %s' % self.cl_name]
        assert 'classe' in self.gr._get_attr(self.cl_name, 'objectClass')

    def test_cl_mail(self):
        """
            Teste la création de la mailing-list de la classe et des alias
        """
        assert self.gr._get_attr(self.cl_name2, 'mail')[0] == "%s@%s" % (self.cl_name2, MAIL_DOMAIN['restreint'])
        assert isdir('%s/%s/%s' % (SYMPA_EXPL, MAIL_DOMAIN['restreint'], self.cl_name2))
        aliases = _getsympaalias()
        assert ALIAS_TMPL.format(self.cl_name2, '') in aliases
        assert ALIAS_TMPL.format(self.cl_name2, 'profs-') in aliases
        assert ALIAS_TMPL.format(self.cl_name2, 'resp-') in aliases

    def test_cl_dir(self):
        """
            Test le répertoire classe
        """
        assert isdir(self.cl_dirname)
        assert getfacl('professeurs', self.cl_dirname) == "group:professeurs:r-x"
        assert getfacl('', self.cl_dirname) == "group::---"

    def test_workdir_dir(self):
        """
            Test les répertoires de travail de la classe
        """
        for dirname in self.work_cl_dirname, self.cl_data_dirname, self.cl_work_dirname:
            assert isdir(dirname)
            assert getfacl('', self.cl_dirname) == "group::---"
        assert getfacl('professeurs', self.work_cl_dirname) == "group:professeurs:r-x"
        assert getfacl('professeurs', self.cl_data_dirname) == "group:professeurs:rwx"
        assert getfacl('professeurs', self.cl_work_dirname) == "group:professeurs:rwx"

        assert getfacl(self.cl_name, self.work_cl_dirname) == "group:%s:r-x" % self.cl_name
        assert getfacl(self.cl_name, self.cl_data_dirname) == "group:%s:r-x" % self.cl_name
        assert getfacl(self.cl_name, self.cl_work_dirname) == "group:%s:rwx" % self.cl_name

    def test_equipe_dir(self):
        """
            test le répertoire d'équipe
        """
        assert getfacl(self.equipe_name, self.equipe_dirname) == "group:%s:rwx" % self.equipe_name

    def test_delete_not_empty_niveau(self):
        raises(NotEmptyNiveau, self.gr._delete, self.nv_name)

    def test_delete_cl(self):
        self.gr._delete(self.cl_name, rmdir=True)
        assert not self.gr._get_attr(self.cl_name, 'description')
        self.gr._delete(self.cl_name2, rmdir=True)
        assert not self.gr._get_attr(self.cl_name2, 'description')
        # teste l'option rmdir
        for dirname in self.work_cl_dirname, self.cl_data_dirname, self.cl_work_dirname:
            assert not isdir(dirname)
        assert not self.gr._is_share(self.cl_name)
        assert not self.gr._is_share(self.equipe_name)

    def test_delete_cl_mail(self):
        """
            Vérifie la suppression des listes de diffusion et des alias
        """
        assert not isdir('%s/%s/%s' % (SYMPA_EXPL, MAIL_DOMAIN['restreint'], self.cl_name2))
        aliases = _getsympaalias()
        assert ALIAS_TMPL.format(self.cl_name2, '') not in aliases
        assert ALIAS_TMPL.format(self.cl_name2, 'profs-') not in aliases
        assert ALIAS_TMPL.format(self.cl_name2, 'resp-') not in aliases

    def test_delete_niveau(self):
        self.gr._delete(self.nv_name, rmdir=True)
        self.gr.ldap_admin.close()


class TestOption():
    """
        test la création d'une option avec une seule connexion (utilisation des _methode)
    """

    opt_name = 'test__option__'
    equipe_name = 'profs-%s' % opt_name
    opt_dirname = join(OPT_PATH, opt_name)
    work_opt_dirname = join(GROUP_PATH, opt_name)
    opt_data_dirname = join(work_opt_dirname, 'donnees')
    opt_work_dirname = join(work_opt_dirname, 'travail')
    equipe_dirname = join(GROUP_PATH, equipe_name)

    def setup_class(cls):
        cls.gr = Group()

    def test_add_groupes(self):
        self.gr.ldap_admin.connect()
        self.gr._add('Option', self.opt_name, domaine='restreint')
        assert self.gr._is_group(self.opt_name) and self.gr._is_group(self.equipe_name)
        assert self.gr._is_share(self.opt_name) and self.gr._is_share(self.equipe_name)

    def test_get_groups(self):
        assert self.opt_name in self.gr._get_groups(_type='Option')
        assert self.opt_name not in self.gr._get_groups(_type='Classe')

    def test_opt_smb(self):
        """
            Teste la création de l'Option
        """
        assert self.gr._get_attr(self.opt_name, 'description') == ['Option %s' % self.opt_name]
        assert self.gr._get_attr(self.equipe_name, 'description') == ['Equipe %s' % self.equipe_name]

    def test_opt_mail(self):
        """
            Teste la création de la mailing-list de l'option et des alias
        """
        assert self.gr._get_attr(self.opt_name, 'mail')[0] == "%s@%s" % (self.opt_name, MAIL_DOMAIN['restreint'])
        assert isdir('%s/%s/%s' % (SYMPA_EXPL, MAIL_DOMAIN['restreint'], self.opt_name))
        # pas de liste pour les équipes pédago d'option
        assert ALIAS_TMPL.format(self.opt_name, '') in _getsympaalias()

    def test_opt_dir(self):
        """
            Test le répertoire option
        """
        assert isdir(self.opt_dirname)
        assert getfacl('professeurs', self.opt_dirname) == "group:professeurs:r-x"
        assert getfacl('', self.opt_dirname) == "group::---"

    def test_workdir_dir(self):
        """
            Test les répertoires de travail de l'option
        """
        for dirname in self.work_opt_dirname, self.opt_data_dirname, self.opt_work_dirname:
            assert isdir(dirname)
            assert getfacl('', self.opt_dirname) == "group::---"
        assert getfacl('professeurs', self.work_opt_dirname) == "group:professeurs:r-x"
        assert getfacl('professeurs', self.opt_data_dirname) == "group:professeurs:rwx"
        assert getfacl('professeurs', self.opt_work_dirname) == "group:professeurs:rwx"

        assert getfacl(self.opt_name, self.work_opt_dirname) == "group:%s:r-x" % self.opt_name
        assert getfacl(self.opt_name, self.opt_data_dirname) == "group:%s:r-x" % self.opt_name
        assert getfacl(self.opt_name, self.opt_work_dirname) == "group:%s:rwx" % self.opt_name

    def test_equipe_dir(self):
        """
            test le répertoire d'équipe
        """
        assert getfacl(self.equipe_name, self.equipe_dirname) == "group:%s:rwx" % self.equipe_name

    def test_delete_opt(self):
        self.gr._delete(self.opt_name, rmdir=True)
        assert not self.gr._get_attr(self.opt_name, 'description')
        # teste l'option rmdir
        for dirname in self.work_opt_dirname, self.opt_data_dirname, self.opt_work_dirname:
            assert not isdir(dirname)
        assert not self.gr._is_share(self.opt_name)
        assert not self.gr._is_share(self.equipe_name)

    def test_delete_opt_mail(self):
        """
            Vérifie la suppression des listes de diffusion et des alias
        """
        assert not isdir('%s/%s/%s' % (SYMPA_EXPL, MAIL_DOMAIN['restreint'], self.opt_name))
        # pas de liste pour les équipes pédago d'option
        assert ALIAS_TMPL.format(self.opt_name, '') not in _getsympaalias()

