#!/usr/bin/python3
# -*- coding: utf-8  -*-

import os
import sys
import tempfile
import subprocess
from string import ascii_letters, digits
from scribe.importation.config import WRITE_PRIVE

home = '/home'

def display_help():
    print("Vérifie la présence des répertoires personnels des utilisateurs et leur ré-applique les droits par défaut")
    print("{} [user] [-f --fix]".format(sys.argv[0]))
    print("    user : appliquer à un utilisateur spécifique ")
    print("    --fix : forcer la résolution des erreurs par suppression des répertoires adhomes")

def argparser():
    # ce n'est pas propre, mais j'hérite de cet état, je fais au mieux et au plus bref...
    # récupère l'ID du groupe
    arglen = len(sys.argv)
    fix = False
    user = None
    if arglen == 1:
        return None, None
    if sys.argv[1] in ['-h', '--help']:
        display_help()
        sys.exit(0)

    if arglen > 1:
        for i in sys.argv[1:]:
            if not i.startswith('-'):
                user = i
            if i == '--fix':
                fix = True

    return user, fix

def create_eleve_dirs(rep):
    dico = dict(rep=rep)
    if WRITE_PRIVE:
        cmd = """[ ! -d "%(rep)s/perso/prive" ] && mkdir -p %(rep)s/perso/prive
""" % dico
    else:
        cmd = """[ ! -d "%(rep)s/perso" ] && mkdir -p %(rep)s/perso
""" % dico
    os.system(cmd)

def create_prof_dirs(rep):
    dico = dict(rep=rep)
    cmd = """[ ! -d "%(rep)s/perso" ] && mkdir -p %(rep)s/perso
""" % dico
    os.system(cmd)

def create_adm_dirs(rep):
    dico = dict(rep=rep)
    cmd = """[ ! -d "%(rep)s/perso" ] && mkdir -p %(rep)s/perso
""" % dico
    os.system(cmd)

def get_groupe(user):
    cmde = 'id %s|grep eleves' % user
    cmdp = 'id %s|grep professeurs' % user
    cmda = 'id %s|grep administratifs' % user
    if subprocess.getstatusoutput(cmde)[0] == 0:
        return 'eleve'
    if subprocess.getstatusoutput(cmdp)[0] == 0:
        return 'professeur'
    if subprocess.getstatusoutput(cmda)[0] == 0:
        return 'administratif'
    return None

def place_droit(user, rep):
    # Attention, ne doit pas casser/modifier les droits de ~/profile.V6
    perso = os.path.join(rep, 'perso')
    dico = dict(user=user, rep=rep, perso=perso)

    # droits élèves
    drte = """setfacl -Rbk %(perso)s
setfacl -bk %(rep)s
chown %(user)s:root %(rep)s
chown -R %(user)s:root %(perso)s
setfacl -PRm u::rwx,g::---,o::--- %(perso)s
setfacl -PRm u:%(user)s:rwx %(perso)s
setfacl -Pm u:%(user)s:rwx %(rep)s
setfacl -PRm g:professeurs:r-x %(perso)s
getfacl --access --absolute-names  %(rep)s | setfacl -d -M- %(rep)s
getfacl --access --absolute-names %(perso)s | setfacl -dR -M- %(perso)s
# cette ACL ne doit pas etre ajoutee en ACL par defaut
setfacl -Pm g:professeurs:--x %(rep)s
if [ -d %(rep)s/.ftp ]; then
chown -R %(user)s:root %(rep)s/.ftp
setfacl -PRm u::rwx,g::---,o::--- %(rep)s/.ftp
setfacl -PRm u:%(user)s:rwx %(rep)s/.ftp
getfacl --access --absolute-names %(rep)s/.ftp | setfacl -dR -M- %(rep)s/.ftp
fi
""" % dico
    if WRITE_PRIVE:
        drte += """if [ -d %(rep)s/perso/prive ];then
setfacl -m g:professeurs:--- %(rep)s/perso/prive
getfacl --access --absolute-names  %(rep)s/perso/prive | setfacl -dR -M- %(rep)s/perso/prive
fi
""" % dico

   # droits enseignants
    drtp = """setfacl -Rbk %(perso)s
setfacl -bk %(rep)s
chown %(user)s:root %(rep)s
chown -R %(user)s:root %(perso)s
setfacl -Pm u:%(user)s:rwx %(rep)s
setfacl -PRm u:%(user)s:rwx %(perso)s
getfacl --access --absolute-names  %(rep)s | setfacl -dR -M- %(perso)s
if [ -d %(rep)s/.ftp ]; then
chown -R %(user)s:root %(rep)s/.ftp
setfacl -PRm u::rwx,g::---,o::--- %(rep)s/.ftp
setfacl -PRm u:%(user)s:rwx %(rep)s/.ftp
getfacl --access --absolute-names %(rep)s/.ftp | setfacl -dR -M- %(rep)s/.ftp
fi
""" % dico

    # droits administratifs
    drta = drtp

    grp = get_groupe(user)
    if not grp:
        print('  ###  Utilisateur %s non trouvé  ###' % user)
        return
    print("Traitement de", user, grp)
    if grp == 'eleve':
        create_eleve_dirs(rep)
        os.system(drte)
        return
    if grp == 'professeur':
        create_prof_dirs(rep)
        os.system(drtp)
        return
    if grp == 'administratif':
        create_adm_dirs(rep)
        os.system(drta)
        return

def user_symlink(dico, fixlink):
    # dico = { userrep, adrep, backup_dir }
    warns, backuped = False, False
    if os.path.exists(dico['userrep']) and not os.path.islink(dico['userrep']):
        print("###  Attention %(userrep)s n'est pas un lien symbolique ###" % dico)
        if not fixlink:
            # on ne fixe pas le link, on avertie qu'il y a un pb
            warns = True
            return warns, backuped
        print('FIX : Traitement de "%(userrep)s"' % dico)
        if os.path.isdir(dico['adrep']):
            # si le dossier /home/adhomes/<login> existe aussi
            # on le déplace dans backup_dir
            backuped = True
            cmdmv = """mv %(adrep)s %(backup_dir)s
            """ % dico
            os.system(cmdmv)
            print('### Dossier "%(adrep)s" déplacé dans "%(backup_dir)s"' % dico)
        cmdfix = """mv %(userrep)s %(adrep)s
        ln -nsf %(adrep)s %(userrep)s
        """ % dico
        os.system(cmdfix)
    return warns, backuped

def check_links():
    users = os.listdir('/home/adhomes/')
    for user in users:
        userrep = os.path.join(home, user[0], user)
        userrep_parent = os.path.join(home, user[0])
        adrep = os.path.join('/home/adhomes/', user)
        if not os.path.islink(userrep) and not os.path.exists(userrep):
            if not os.path.exists(userrep_parent):
                os.makedirs(userrep_parent)
            dico = dict(adrep=adrep, userrep=userrep)
            print('Lien symbolique %(userrep)s absent, création' % dico)
            os.system("""ln -nsf %(adrep)s %(userrep)s""" % dico)

def main():
    personne, fixlink = argparser()
    backuped = False
    warns = False
    if fixlink:
        backup_dir = tempfile.mkdtemp(prefix='/home/')
    else:
        # inutile de créer un dossier si l'on ne compte pas réparer/déplacer des perso
        backup_dir = None
    if not personne:
        check_links()
        charslist = ascii_letters + digits
        for i in charslist:
            rep = os.path.join(home, i)
            if not os.path.isdir(rep):
                continue
            users = os.listdir(rep)
            for user in users:
                adrep = os.path.join('/home/adhomes', user)
                userrep = os.path.join(rep, user)
                dico = dict(adrep=adrep, userrep=userrep, backup_dir=backup_dir)
                w, b = user_symlink(dico, fixlink)
                if w:
                    warns = True
                else:
                    place_droit(user, adrep)
                if b: backuped = True
        if not backuped and backup_dir:
            os.system('rm -rf %s'%backup_dir)

    else:
        user = personne
        adrep = os.path.join('/home/adhomes', user)
        userrep = os.path.join(home, user[0], user)
        dico = dict(adrep=adrep, userrep=userrep, backup_dir=backup_dir)
        w, b = user_symlink(dico, fixlink)
        if w:
            warns = True
        else:
            place_droit(user, adrep)
        if b: backuped = True
        if not backuped and backup_dir:
            os.system('rm -rf %s' % backup_dir)

    if backuped:
        print('Des dossier ont été sauvegardés dans "%s"' % backup_dir)
    if warns:
        print("Des erreurs ont été rencontrées. Veuillez les résoudres ou utiliser l'option --fix pour forcer leur résolution (peut entrainer une perte de données)")

    # https://dev-eole.ac-dijon.fr/issues/15051
    drt_admin = """setfacl -Rm u:www-data:r-x /home/a/admin/perso/ressources
    setfacl -Rdm u:www-data:r-x /home/a/admin/perso/ressources
    setfacl -m u:www-data:--x /home/a/admin/perso
    setfacl -m u:www-data:--x /home/a/admin
    """
    if os.path.isdir('/home/a/admin/perso/ressources'):
        os.system(drt_admin)


if __name__ == '__main__':
    main()
