#! /usr/bin/env python
# -*- coding: utf-8 -*-

# 10/06/2014: cleon :  création
# Script permettant de générer la configuration EoleSSO

import urllib
import json
import hashlib
import os
import time
import sys

from creole.client import CreoleClient

if CreoleClient().get_creole('activer_econnect', 'non')=="oui":
    force=False
    if len(sys.argv)==2 and sys.argv[1]=="--force":
        force=True

    SSO_APPS_DIR="/usr/share/sso/app_filters"
    SSO_APPS_FILE=SSO_APPS_DIR + "/econnect_apps.ini"
    SSO_CONF_MD5="/tmp/econnect.sso"
    LOCK_FILE="/tmp/econnect.lock"

    ECONNECT_TOKEN_FILE="/root/.econnect.token"
    ECONNECT_URL_FILE="/root/.econnect.url"

    # Existe t'il un token ?
    if not os.path.isfile(ECONNECT_TOKEN_FILE):
        print "econnect token non trouvé"
        sys.exit(2)

    # URL de API (web_url)
    # URL est stocké dans un fichier, afin de faciliter la migration sur 2.4
    # ceci evite de modifier ce code pour récupérer la variable
    # web_url dans le dico et jongler entre 2.3 et 2.4
    if not os.path.isfile(ECONNECT_URL_FILE):
        print "econnect url token non trouvé"
        sys.exit(2)

    f=open(ECONNECT_URL_FILE,'r')
    API_URL=f.read().strip()
    f.close()

    # Une seule instance doit fonctionner
    if os.path.isfile(LOCK_FILE) and (time.time()-os.path.getmtime(LOCK_FILE))<120:
        print "lock existe %s (%i seconds)" % (LOCK_FILE,time.time()-os.path.getmtime(LOCK_FILE))
        sys.exit(1)

    # lock file
    if os.path.isfile(LOCK_FILE):
        print "lock existe %s >2mn, force unlock" % LOCK_FILE
        os.unlink(LOCK_FILE)
    file(LOCK_FILE, 'w').write(str(os.getpid()))

    # Récupération du token d'authentification
    f=open(ECONNECT_TOKEN_FILE,'r')
    token=f.read().strip()
    f.close()

    # Récupréation de la configuration via l'API
    url="https://%s/econnect/api/ressources/sso?token=%s" % (API_URL,token)
    try:
        filehandle = urllib.urlopen(url)
        content=filehandle.read()
        filehandle.close()
    except Exception as inst:
        print "Une erreur est survenue lors de la récupération SSO url=%s" % url
        print inst
        os.unlink(LOCK_FILE)
        sys.exit(3)

    # Avant d'aller plus loin, vérifions si le json est OK
    try:
        decoded=json.loads(content)
        json.dumps(decoded, sort_keys=True, indent=4)
    except Exception as inst:
        print "Une erreur est survenue lors de la récupération SSO"
        print content
        os.unlink(LOCK_FILE)
        sys.exit(3)

    # On va vérifier si la conf à changé
    lastmd5=""
    newmd5=hashlib.md5(content).hexdigest()
    if os.path.isfile(SSO_CONF_MD5):
        f=open(SSO_CONF_MD5,'r')
        lastmd5=f.read()
        f.close()

    # non => on ne fait rien si pas en mode force
    if newmd5==lastmd5 and not force:
        os.unlink(LOCK_FILE)
        sys.exit(0)

    # oui => on va mettre à jour la conf sso

    # Ecriture du md5
    f=open(SSO_CONF_MD5,'w')
    f.write(newmd5)
    f.close

    # Fichier de configuration sso : econnect_apps.ini
    fapps=open(SSO_APPS_FILE,'w')

    print "%s" % (time.strftime('%c'))
    print "Generation de configuration SSO"
    count=0

    # Pour chaque appli, on va écrire un econnect_<app>.ini
    for app in decoded:
        print " -> %s" % app["name"]
        count=count+1

        # Si anciens fichiers sso existent on supprime
        if app["name"] != "econnect":

            lastSSO=SSO_APPS_DIR+"/%s.ini" % app["name"]
            if  os.path.isfile( lastSSO ):
                os.remove(lastSSO)

            lastSSO=SSO_APPS_DIR+"/%s_apps.ini" % app["name"]
            if  os.path.isfile( lastSSO ):
                os.remove(lastSSO)

        # ecriture du filtre
        fapps.write("[%s]\nbaseurl=%s\nscheme=%s\naddr=%s\ntypeaddr=%s\nfilter=econnect_%s\n\n" % (app["name"],app["baseurl"],app["scheme"],app["addr"],app["typeaddr"],app["name"] ) )
        ffilter=open(SSO_APPS_DIR+"/econnect_%s.ini" % app["name"], 'w' )
        ffilter.write(("%s\n" % app["filter"]).encode("UTF-8"))
        ffilter.close()

    if count==0:
        print " -> Aucune ressource SSO activée ou configurée"


    fapps.close()
    os.unlink(LOCK_FILE)

    print os.popen("service eole-sso reload").read()
