Example #1
0
def update_actif():
    """
    Toggle l'état d'une fiche ancien : actif, inactif

    :return:
    """

    if current_user.id_ancien is not None:
        ancien = annuaire.find_ancien_by_id(current_user.id_ancien)

        if ancien is not None:
            annuaire.update_actif(ancien['id_ancien'], not ancien['actif'])
            app.logger.info(
                "ANCIEN - successfully updated ancien :%s, set actif : %s, user : %s",
                ancien['id_ancien'],
                not ancien['actif'],
                current_user.id)

            mot = "est à nouveau visible"
            if ancien['actif']:
                mot = "n'est plus visible"

            flash("Votre fiche %s dans l'annuaire" % mot, "success")

    return redirect(url_for('compte'))
Example #2
0
def create_ancien_api():
    """
    Créer ma fiche ancien

    :param id_ancien:
    :return:
    """
    if current_user.id_ancien is None:
        abort(501, "Not implemented (yet) !")

    else:
        ancien = annuaire.find_ancien_by_id(current_user.id_ancien, actif=None, nouveau=None, bloque=None)

        if ancien is None:
            # TODO : Bug ....
            abort(500, "Nous n'avons pas trouve ta fiche ancien."
                       "Si le probleme persiste, merci de contacter les administrateurs.")

        elif ancien["nouveau"]:
            # TODO : en attente de validation ...
            # TODO : Quel code retour ?
            abort(400, "Ta fiche ancien est en attente de validation. Un mail te sera envoye lors de la validation.")

        else:
            # TODO : duplicate
            # TODO : quel code retour ? 419 ?
            abort(419, "Tu as deja une fiche ancien ! Tu ne peux pas en creer une seconde.")
Example #3
0
def _get_info_perso_template(ancien_form=None, adresse_form=None):
    """
    Permet de render le template _info_perso pour l'ancien en cours.

    :param adresse_form:    le formulaire d'adresse à inclure
    :param ancien_form:     le formulaire d'infos persos à inclure

    On prend des formulaires en entrée pour gérer les erreurs.


    NB: la modificaiton in-line des infos perso (sans page reload) ne
        permet plus de render des templates complets côté serveur. Plutôt
        que de réécrire l'intégralité de l'appli côté client, on render des
        templates partiels qu'on injecte dans la page sur des appels POST.

        Ce n'est pas super propre, mais c'est la vie :3
    """
    ancien = None
    adresse = None

    if current_user is not None and current_user.id_ancien is not None:

        ancien = annuaire.find_ancien_by_id(current_user.id_ancien)

        #~~~~~~~~~~~~~#
        # INFOS PERSO #
        #~~~~~~~~~~~~~#
        if ancien_form is None:
            ancien_form = user.update_ancien_form()
            ancien_form.load_ancien(ancien)

        #~~~~~~~~~#
        # ADRESSE #
        #~~~~~~~~~#
        if adresse_form is None:
            adresse_form = user.update_adresse_form()
            adresse_form.set_pays(PAYS)
            adresse = annuaire.find_adresse_by_id_ancien(current_user.id_ancien)
            if adresse is not None:
                adresse_form.load_adresse(adresse)

    else:
        if ancien_form is None:
            ancien_form = user.update_ancien_form()

        if adresse_form is None:
            adresse_form = user.update_adresse_form()
            adresse_form.set_pays(PAYS)


    return render_template(
        'annuaire/profile/_infos_perso.html',
        ancien=ancien,
        adresse=adresse,
        ancien_form=ancien_form,
        adresse_form=adresse_form,
        utilisateur=current_user,
        editable=True
    )
Example #4
0
def linkedin_associer():
    """
    Fonction de callback appelée par LinkedIn.
    Associer un compte ancien à un compte LinkedIn.

    Permet de :
    - Afficher le widget linkedin dans le profil de l'Ancien
    - Se connecter avec LinkedIn.

    Worfklow :
    - Request un token
    - Faire un appel sur l'API "people" pour obtenir l'id_linkedin et l'url du profil.
    - Récupérer ces données et les insérer en base
    """
    success = False
    app.logger.info(
            "LINKEDIN - begin authorize for ancien : %s, user : %s",
            current_user.id_ancien,
            current_user.id)

    if current_user.id_ancien is not None:
        ancien = annuaire.find_ancien_by_id(current_user.id_ancien)
        if ancien is not None:
            access_token = __get_linkedin_token(url_for('linkedin_associer', _external=True))
            api_url = "https://api.linkedin.com/v1/people/~:(id,public-profile-url)?oauth2_access_token=%s" % access_token
            api_req =  requests.get(api_url)
            if api_req is not None and api_req.status_code == requests.codes.ok:
                parsed = etree.fromstring(api_req.text.encode("utf-8"))
                if parsed is not None:
                    id_linkedin = None
                    url_linkedin = None
                    for e in parsed:
                        if e.tag == "id":
                            id_linkedin = e.text
                        elif e.tag == "public-profile-url":
                            url_linkedin = e.text
                    if url_linkedin is not None and id_linkedin is not None:
                        success = annuaire.update_linkedin_ancien(ancien['id_ancien'], id_linkedin, url_linkedin)
                        app.logger.info(
                            "LINKEDIN - successful update for user : %s, ancien : %s, id_linkedin : %s, url public profile : %s",
                            current_user.id, ancien['id_ancien'], id_linkedin, url_linkedin)

            if not success:
                app.logger.error(
                    "LINKEDIN - bad people API request for user : %s, code : %s, request response : %s",
                    current_user.id, api_req.status_code, api_req.text)

    if success:
        flash("Profil linkedin correctement connecté !", "success")
    else:
        flash("Oups ! Il y a eu un problème pendant la connexion. Merci de contacter l'administrateur.", "danger")
    return redirect(url_for("compte"))
Example #5
0
def ancien_by_id_api(id_ancien):
    """
    API pour afficher un ancien.

    L'attribut complet=True permet d'avoir le profil complet de l'ancien,
    avec adresses et expérience.

    :param id_ancien:
    :return:
    """

    # Problème de routing Flask, on raise une 500.
    #   -> Normalement si id_ancien is None on devrait taper dans fulltext_api
    if id_ancien is None:
        abort(500)

    is_this_me = current_user is not None and current_user.id_ancien == id_ancien

    kwargs = {"actif": True, "bloque": False}
    if is_this_me or current_user.admin:
        kwargs = {"actif": None, "bloque": None}

    # Chargement de l'ancien
    ancien = annuaire.find_ancien_by_id(id_ancien, **kwargs)

    # Cas 1 : il n'existe pas
    if ancien is None:
        abort(
            404,
            "Ancien non trouvé, parce que : "
            "a. Il n'y a pas d'ancien avec cet identifiant "
            "b. Un ancien existe mais il a souhaité masquer sa fiche "
            "c. Un ancien exsite mais a été bloqué par un administrateur",
        )

    # cas 2 : il est bloqué
    # (donc normalement ici c'est l'utilisateur concerné qui consulte la fiche)
    elif is_this_me and ancien["bloque"]:
        abort(403, "Ton profil a été bloqué par un administrateur ...")

    else:
        excluded_columns = ["id_linkedin", "actif", "bloque", "nouveau", "fulltext"]
        ancien_dict = helper.row_to_json(ancien, excluded_columns)

        if request.args.get("complet", None) is not None:
            ancien_dict["adresses"] = helper.row_to_json(annuaire.find_adresse_by_id_ancien(id_ancien))
            ancien_dict["experiences"] = [
                helper.row_to_json(r) for r in annuaire.find_experience_by_id_ancien(id_ancien)
            ]

        return json.dumps(ancien_dict)
Example #6
0
def _get_valid_ancien():
    """
    Récupérer l'ancien associé à l'utilisateur courant.

    Si l'ancien n'existe pas,   abort   404
    Si l'ancien est bloqué,     abort   403 (??)

    :return: L'ancien :o)
    """
    ancien = annuaire.find_ancien_by_id(current_user.id_ancien, actif=None, nouveau=False, bloque=None)
    if ancien is None:
        abort(404, "Pas d'ancien associe a ce compte.")
    elif ancien["bloque"]:
        abort(403, "Il semblerai que tu compte soit bloque. "
           "Merci de contacter un administrateur pour le "
           "faire debloquer.")
    else:
        return ancien
Example #7
0
def ancien(id_ancien):
    """
    Afficher le profil d'un ancien.

    Si l'ancien est l'ancien associé à l'utilisateur, alors on affiche des formulaires d'update pour :
    - Les infos perso
    - L'adresse perso
    - Les expériences pros
    - Le mot de passe

    On affiche également les fonctionnalités linkedin :
    - Associer / dissocier mon compte
    - Importer des expériences

    :param int id_ancien: L'id de l'ancien étudié
    :return:
    """

    is_this_me =  current_user is not None and current_user.id_ancien == id_ancien

    kwargs = { "actif" : True, "bloque" : False }
    if is_this_me or current_user.admin:
        kwargs = { "actif" : None, "bloque" : None }

    # Chargement de l'ancien
    ancien = annuaire.find_ancien_by_id(id_ancien, **kwargs)


    # Cas 1 : il n'existe pas
    if ancien is None:
        abort(404, "Il semblerait que la page n'existe pas ...")

    # cas 2 : il est bloqué
    # (donc normalement ici c'est l'utilisateur concerné qui consulte la fiche)
    elif is_this_me and ancien['bloque']:
        flash(
            "Ton compte a été désactivé par les administrateurs."
            "Nous t'invitons à les contacter pour le débloquer.",
            "danger"
        )
        return redirect(url_for("annuaire_view"))

    # Cas 3 : cas nominal !
    else:
        ancien_form = user.update_ancien_form()
        adresse_form = user.update_adresse_form()
        adresse_form.set_pays(PAYS)
        experience_forms = {}
        new_experience_form = None
        linkedin_url = None
        import_linkedin_url = None
        password_form = user.change_password_form()


        # get data by id ancien
        adresse = annuaire.find_adresse_by_id_ancien(id_ancien)
        experiences = annuaire.find_experience_by_id_ancien(id_ancien).fetchall()

        for exp in experiences:
            form = user.update_experience_form()
            form.set_pays(PAYS)
            form.load_experience(exp)
            experience_forms[exp['experience_id_experience']] = form

        # Ici on regarde si il s'agit bien de l'utilisateur
        if is_this_me:

            #~~~~~~~~~#
            # ADRESSE #
            #~~~~~~~~~#
            adresse = annuaire.find_adresse_by_id_ancien(current_user.id_ancien)
            if adresse is not None:
                adresse_form.load_adresse(adresse)

            #~~~~~~~~~~~~~#
            # INFOS PERSO #
            #~~~~~~~~~~~~~#
            ancien_form = user.update_ancien_form()
            ancien_form.load_ancien(ancien)

            #~~~~~~~~~~~~~~~~~~#
            # AJOUT EXPERIENCE #
            #~~~~~~~~~~~~~~~~~~#
            new_experience_form = user.update_experience_form()
            new_experience_form.set_pays(PAYS)


            #~~~~~~~~~~~~~~~~~~#
            # Gestion LinkedIn #
            #~~~~~~~~~~~~~~~~~~#
            # Connexion à LinkedIn
            if ancien['url_linkedin'] is None:
                linkedin_url = ("https://www.linkedin.com/uas/oauth2/authorization?"
                                    "response_type=code&"
                                    "client_id=%s&"
                                    "scope=r_basicprofile"
                                    "&state=%s"
                                    "&redirect_uri=%s" %
                                    (app.config['LINKEDIN_KEY'],
                                     #app.config['LINKEDIN_SCOPE'],
                                     generate_csrf_token(),
                                     url_for('linkedin_associer', _external=True)))

            # import des expériences pro linkeding
            import_linkedin_url = ("https://www.linkedin.com/uas/oauth2/authorization?"
                                "response_type=code&"
                                "client_id=%s&"
                                "scope=r_basicprofile"
                                "&state=%s"
                                "&redirect_uri=%s" %
                                (app.config['LINKEDIN_KEY'],
                                 #app.config['LINKEDIN_SCOPE'],
                                 generate_csrf_token(),
                                 url_for('linkedin_importer', _external=True)))

            print import_linkedin_url



        # load page
        return render_template(
            'annuaire/ancien.html',
            admin=current_user.admin,
            ancien=ancien,
            adresse=adresse,
            ancien_form=ancien_form,
            adresse_form=adresse_form,
            experiences=experiences,
            utilisateur=current_user,
            editable=is_this_me,
            experience_forms=experience_forms,
            new_experience_form = new_experience_form,
            linkedin_url = linkedin_url,
            import_linkedin_url= import_linkedin_url,
            password_form = password_form
        )
Example #8
0
def linkedin_importer():
    """
    Fonction de callback appelée par LinkedIn.
    Importer les expériences depuis linkedin

    Worfklow :
    - Request un token
    - Faire un appel sur l'API "people" pour obtenir les "positions"
    - Récupérer ces données et les insérer en base

    Sujet ouvert :
    - Est-ce qu'on met à jour une position déjà existante (écraser)
    - Ou alors est-ce qu'on l'importe une deuxième fois ?
        -> Pour l'instant, on importe une deuxième fois
    """
    import_success = False
    saved_positions = 0
    app.logger.info(
            "LINKEDIN - begin import for ancien : %s, user : %s",
            current_user.id_ancien,
            current_user.id)

    if current_user.id_ancien is not None:
        ancien = annuaire.find_ancien_by_id(current_user.id_ancien)
        if ancien is not None:
            access_token = __get_linkedin_token(url_for('linkedin_importer', _external=True))
            api_url = "https://api.linkedin.com/v1/people/~:(id,positions)?oauth2_access_token=%s" % access_token
            api_req =  requests.get(api_url)
            if api_req is not None and api_req.status_code == requests.codes.ok:
                parsed = etree.fromstring(api_req.text.encode("utf-8"))
                if parsed is not None:
                    positions = []
                    for e in parsed:
                        if e.tag == "positions":
                            positions = __get_positions(e)

                    if len(positions) > 0:

                        # récupérer les positions existantes pour update. A voir.
                        # sql_experiences = annuaire.find_experience_by_id_ancien(utilisateur.id_ancien)
                        # experiences = sql_experiences.fetchall()
                        # sql_experiences.close()

                        import_success = True

                        for position in positions:
                            app.logger.info(
                                "LINKEDIN - saving experience for user %s, enreprise : %s, position : %s, id_xp : %s",
                                current_user.id,
                                position['entreprise'],
                                position['position'],
                                position['id_experience_linkedin']
                            )
                            success = annuaire.update_experience(
                                current_user.id_ancien,
                                None,
                                None,
                                None,
                                None,
                                None,
                                position['entreprise'],
                                position['position'],
                                position['description'],
                                None,
                                None,
                                None,
                                None,
                                position['date_debut'],
                                position['date_fin'],
                                position['id_experience_linkedin']
                            )

                            if not success:
                                app.logger.error("LINKEDIN - error saving experience for user %s, id experience : %s")
                                app.logger.warning(position)
                                import_success=False
                            else:
                                saved_positions += 1
                    else:
                        app.logger.warning("LINKEDIN - no positions found for user : %s", current_user.id)

                else:
                    app.logger.error("LINKEDIN - blank API response file for user : %s", current_user.id)

            elif api_req is None:
                app.logger.error("LINKEDIN - bad people API request for user : %s, null response", current_user.id)
            else:
                app.logger.error(
                    "LINKEDIN - bad people API request for user : %s, code : %s, request response : %s",
                    current_user.id,
                    api_req.status_code,
                    api_req.text
                )

    if import_success:
        flash("%s expériences importées avec succès !" % saved_positions, "success")
    else:
        flash("Oups ! Il y a eu un problème pendant la connexion. Merci de contacter l'administrateur.", "danger")

    return redirect(url_for("compte"))
Example #9
0
def update_photo():
    """
    Mettre à jour la photo d'un ancien.

    POST :  on récupère la photo, on la sauvegarde, on vire l'ancienne
            et on re-render les infos persos (+ csrf token)

            Le cas de suppression est géré par un flag ?suppr=true dans
            l'url de la requête (bof bof ...)
    """

    res = {}
    res["content"] = None
    res["csrf_token"] = generate_csrf_token()
    res["success"] = False

    if current_user.id_ancien is None:
        return res
    else:
        ancien = annuaire.find_ancien_by_id(current_user.id_ancien)
        if ancien is None:
            return res
        else:

            # récupérer le file uploadé
            uploaded_file = None
            try:
                uploaded_file = request.files['file']
            except:
                pass

            if request.form.get("suppr"):
                 # supprimer la photo dans la fiche ancien
                app.logger.info(
                    "PHOTO - remove for : %s",
                    ancien['id_ancien'])

                annuaire.update_photo(ancien['id_ancien'], None)

                # supression de l'ancienne photo
                try:
                    os.remove(os.path.join(app.config['UPLOAD_FOLDER'], secure_filename(ancien['photo'])))
                    app.logger.info(
                        "PHOTO - ancien : %s, removed file : %s",
                        ancien['id_ancien'],
                        ancien['photo']
                    )
                except:
                    app.logger.info(
                        "PHOTO - failed to remove for : %s",
                        ancien['id_ancien'])
                flash("Photo supprimée", "warning")

            elif uploaded_file and _allowed_file(uploaded_file.filename):

                # upload de l'ancienne photo
                id_photo = user.get_next_photo_id()
                extension = uploaded_file.filename.rsplit('.', 1)[1]
                filename = secure_filename(str(id_photo)+"."+extension)
                uploaded_file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

                # mise à jour de la fiche ancien avec la nouvelle photo
                annuaire.update_photo(ancien['id_ancien'], filename)
                app.logger.info(
                    "PHOTO - succes for user with %s, ancien : %s, photo name : %s, number : %s",
                    current_user.id,
                    ancien['id_ancien'],
                    uploaded_file.filename,
                    id_photo)

                # supression de l'ancienne photo
                try:
                    os.remove(os.path.join(app.config['UPLOAD_FOLDER'], secure_filename(ancien['photo'])))
                    app.logger.info(
                        "PHOTO - ancien : %s, removed file : %s",
                        ancien['id_ancien'],
                        ancien['photo'])
                except:
                    app.logger.info(
                        "PHOTO - failed to remove for : %s",
                        ancien['id_ancien'])

                flash('Photo mise à jour', 'success')

            elif uploaded_file and not _allowed_file(uploaded_file.filename):
                app.logger.info(
                    "PHOTO - forbidden for ancien : %s, photo : %s",
                    ancien['id_ancien'],
                    uploaded_file.filename)
                flash("Format de photo invalide", "danger")


            res["content"] = _get_info_perso_template()
            res["success"] = True
    return json.dumps(res)
Example #10
0
def update_info_perso():
    """
    Page pour mettre à jour les infos perso d'un ancien.
        -> Infos perso
        -> Adresse perso

    Deux fois (adresse+infos) trois étapes :
        1. Valider les données
        2. Le cas échéant, les sauvegarder
        3. Regénérer le template et le renvoyer avec un nouveau csrf token
    """

    res = {}
    res["content"] = None
    res["csrf_token"] = generate_csrf_token()
    res["success"] = False

    form_ancien_to_render = None

    form = user.update_ancien_form()

    info_ok = False

    if current_user is not None:

        #~~~~~~~~~~~~~#
        # INFOS PERSO #
        #~~~~~~~~~~~~~#
        ancien = annuaire.find_ancien_by_id(current_user.id_ancien)

        if ancien is not None:
            form.load_ancien(ancien)

            # Confirmer
            form = user.update_ancien_form(request.form)
            form_confirmed = form.validate()


            # si tout va bien, mettre a jour.
            if form_confirmed:
                success = annuaire.update_fiche_ancien(
                    ancien['id_ancien'],
                    form.telephone.data,
                    form.mobile.data,
                    form.site.data,
                    form.mail_perso.data
                )
                if success:
                    app.logger.info(
                        "UPDATE INFO - successfully update info for user with id %s, id ancien : %s",
                        current_user.id,
                        ancien['id_ancien']
                        )
                    info_ok = True

                else:
                    app.logger.info("UPDATE INFO - failed insert for user with id %s", current_user.id)

            else:
                form_ancien_to_render = form
                app.logger.info("UPDATE INFO - failed insert for user with id %s", current_user.id)


        #~~~~~~~~~#
        # ADRESSE #
        #~~~~~~~~~#
        adresse_form = user.update_adresse_form()
        adresse_form.set_pays(PAYS)

        if current_user.id_ancien is not None:
            adresse = annuaire.find_adresse_by_id_ancien(current_user.id_ancien)
            if adresse is not None:
                adresse_form.load_adresse(adresse)

            # Confirmer
            adresse_form = user.update_adresse_form(request.form)
            adresse_form.set_pays(PAYS)
            form_confirmed = adresse_form.validate()

            # si tout va bien, mettre a jour.
            if form_confirmed:
                annuaire.update_adresse_perso(
                    current_user.id_ancien,
                    adresse_form.ville.data,
                    adresse_form.pays.data,
                    adresse_form.adresse.data,
                    adresse_form.code.data
                )
                if info_ok:
                    flash("Informations personnelles mises à jour", "success")


        res["content"] = _get_info_perso_template(ancien_form=form_ancien_to_render)
        res["success"] = True

    return json.dumps(res)
Example #11
0
def create_ancien():
    """
    Créer un ancien, associé à mon compte personnel. L'ancien est créé et son status
    est "nouveau".

    1.      Si l'ancien n'existe pas
    1.a.    Afficher un formulaire à remplir par l'ancien.
    1.b.    Si le formulaire est valide, on crée l'ancien
    1.c.    On ajoute l'ancien
    1.d.    On linke le nouvel ancien à l'utilisateur courant

    2.      Si l'ancien existe mais est "nouveau"
    2.a.    On affiche un message à l'utilisateur actuel

    3.      Si l'ancien est existe mais n'est pas nouveau
    3.a.    On flashe une erreur et on redirige l'utilisateur vers son compte


    :return: None.
    """

    # Trouver si l'utilisateur a un ancien associé
    ancien = annuaire.find_ancien_by_id(current_user.id_ancien, actif=None, nouveau=None, bloque=None)

    form = user.create_ancien_form()

    # Cas #1 : Créer l'ancien
    if ancien is None:
        if request.method == "POST":

            app.logger.info(
                "CREATE ANCIEN - Creating ancien for user %s",
                current_user.id
            )

            form = user.create_ancien_form(request.form)

            # Cas #1.1 : Si le form est valable, on insère l'ancien, on l'associe, et on envoie l'utilisateur
            # sur la page de l'annuaire
            if form.validate():
                id_ancien = annuaire.create_ancien(
                    prenom=form.prenom.data,
                    nom=form.nom.data,
                    promo=int(form.promo.data),
                    ecole=form.ecole.data,
                    mail_asso=current_user.mail,
                    diplome=form.diplome.data
                )

                user.update_id_ancien(current_user.id, id_ancien)

                flash(
                    "F&eacute;licitations ! Ta fiche ancien a &eacute;t&eacute; cr&eacute;e.<br>"
                    "Elle est maintenant en attente de validation par un administrateur.<br>"
                    "Une fois ta fiche valid&eacute;e, tu recevras un mail de confirmation.",
                    "success"
                )

                app.logger.info(
                    "CREATE ANCIEN - Success ! Ancien with id :s; created for user with ID %s",
                    id_ancien,
                    current_user.id
                )


                return redirect(url_for("annuaire_view"))

            # Cas #1.2 : Si le form n'est pas valide, on flashe une erreur
            # Puis on tombe dans le cas #1.3
            else:

                app.logger.warning(
                    "CREATE ANCIEN - Failed formulaire for user with ID %s",
                    current_user.id
                )
                flash(
                    "Oops ! Probl&eacute;me &agrave; la cr&eacute;ation de la fiche."
                    "danger"
                )


        # Cas #1.3 : render le formulaire (avec ou sans erreurs)
        return render_template(
            'user/creation/creation.html',
            form=form
        )

    # Cas #2 : l'ancien a été créé mais pas activé
    if ancien is not None and ancien["nouveau"]:
        return render_template(
            'user/creation/attente.html',
            ancien=ancien
        )

    # Cas #3 : Il y a déjà un ancien ! redir
    else:
        flash(
            "Un ancien existe d&eacute;j&agrave;.",
            "danger"
        )
        return redirect(url_for("compte"))
Example #12
0
def compte():
    """
    Permet, entre autres, d'associer un utilisateur à un ancien :
    - Si l'utilisateur U n'a pas d'ancien associé
        - Trouver si il y a un ancien A tel que A.mail_asso == U.mail
            - Si oui, vérifier qu'il n'y a pas d'utilisateur U2
            tel que U2.id_ancien == A.id_ancien
                - Si U2 n'existe pas, alors UPDATE U tel que U.id_ancien = A.id_ancien

    """


    # Trouver si l'utilisateur a un ancien associé
    ancien = annuaire.find_ancien_by_id(current_user.id_ancien, actif=None, bloque=None, nouveau=None)

    # Si l'utilisateur n'a pas d'ancien, on va vérifier
    # Via le mail asso, s'il existe un ancien dans la base pour lui
    if ancien is None:
        ancien_temp = annuaire.find_ancien_by_mail_asso(current_user.mail)

        # si il y a effectivement un ancien, vérifier
        # qu'il n'est pas déjà associé à un utilisateur
        if ancien_temp is not None:
            app.logger.info(
                "USER ASSOCIATION - trying to associate user %s with ancien %s",
                current_user.id,
                ancien_temp['id_ancien']
            )
            user_temp = user.find_user_by_id_ancien(ancien_temp['id_ancien'])

            # Si ça n'existe pas, alors faire l'association
            if user_temp is None:
                # On récupère le nouvel utilisateur
                sql_res = user.update_id_ancien(current_user.id, ancien_temp['id_ancien'])

                # Si l'association réussit
                # réucpérer l'ancien
                if sql_res :
                    app.logger.info(
                        "USER ASSOCIATION - Success, associated user %s with ancien %s",
                        current_user.id,
                        ancien_temp['id_ancien']
                    )
                    return redirect(url_for("ancien", id_ancien=ancien_temp['id_ancien']))

                else:
                    app.logger.error(
                        "USER ASSOCIATION - Oops ... update went wrong."
                    )

            else:
                app.logger.warning(
                    "USER ASSOCIATION - user %s already associated with ancien %s",
                    user_temp.id,
                    ancien_temp['id_ancien']
                )
        else:
            # Sinon, on le laisse créer sa fiche !
            return redirect(url_for("create_ancien"))

    elif ancien['nouveau']:
        return redirect(url_for("create_ancien")) # cas spécifique : ancien en cours de création

    else:
        return redirect(url_for("ancien", id_ancien=current_user.id_ancien))