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

"""Musite − wiki musical

Musite est une sorte de wiki, pensé pour gérer des documents contenant des
partitions de musique, mais adaptable à toutes sortes d'autres usages.

Ce fichier gère la partie interface du site, renvoyant les pages correspondant
aux urls saisies dans le navigateur.Si j'ai bien compris ce qu'est une vue
dans le modèle MVC, ce doit être à peu près ça.
"""

__appname__ = 'serveur'
__license__ = 'MIT'


# Import de librairies externes ###############################################

import os
import sys

LIB = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'deps')
sys.path.insert(0, LIB)
import bottle as b
from bottle import request as rq
from deps.i18n import I18NPlugin as Traduction
from deps import HTMLTags as h
from deps.mistune import markdown

from deps.controleur import Projet, Dossier, Document, DocumentGabc
from deps import outils as f
from deps.outils import i18n_path, _
from deps import auth as a
from deps import utilisateurs as u
from etc import config as cfg


# Paramètres bottle ###########################################################

b.TEMPLATE_PATH += cfg.MODELES
APP = b.Bottle()


# Méthodes globales :  ########################################################


# I. Bidouille et décorateurs destinés à éviter les redondances ########

@APP.hook('before_request')
def strip_path():
    """Effacement du / final s'il y en a un dans l'url
    """
    rq.environ['PATH_INFO'] = rq.environ['PATH_INFO'].rstrip('/')


def page(fonction):
    """Mise en forme commune à toutes les pages

    Cette fonction est un décorateur à appliquer à toutes les fonctions
    affichant des pages, mais non à celles qui retournent des données
    particulières, tels les css ou les fichiers statiques.
    """
    def afficher(*arguments, **parametres):
        """Décorateur
        """
        contenu = fonction(*arguments, **parametres)
        contenu['rq'] = rq
        return b.template('page', contenu)
    return afficher


# II. pages du site ########

#   1. Accueil
@APP.get('/')
@page
def accueil():
    """ Page d'accueil du site
    """
    try:
        actions = {_('Créer projet'): '_creerprojet'} \
            if a.authentifier(rq.auth[0], rq.auth[1]) \
            else {}
    except TypeError as err:
        f.traiter_erreur(err)
        # Cette exception est levée en l'absence d'authentification
        actions = {}
    liens = {_('Projets'): '_projets'}
    try:
        with open(os.path.join(
            cfg.PAGES,
            'md',
            'Accueil.{}.md'.format(rq.locale)
        ), 'r') as acc:
            corps = markdown(acc.read(-1))
    except FileNotFoundError as err:
        f.traiter_erreur(err)
        with open(os.path.join(cfg.PAGES, 'md', 'Accueil.fr.md'), 'r') as acc:
            corps = markdown(acc.read(-1))
    return {
        'corps': corps,
        'actions': actions,
        'liens': liens
    }


@APP.get('/_projets')
@page
def lister_projets():
    """Liste des projets existants
    """
    try:
        actions = {
            _('Créer projet'): '_creerprojet',
            _('Cloner projet'): '_clonerprojet',
        } \
            if a.authentifier(rq.auth[0], rq.auth[1]) \
            else {}
    except TypeError as err:
        f.traiter_erreur(err)
        # Cette exception est levée en l'absence d'authentification
        actions = {}
    listefichiers = f.Dossier(cfg.DATA).lister(profondeur=1)
    # Formatage de la liste des fichiers.
    liste = [
        h.A(
            projet, href=i18n_path('/{}'.format(projet))
        )
        for projet in sorted(listefichiers[cfg.DATA])
        if os.path.isdir(os.path.join(cfg.DATA, projet))
    ]
    return {
        'corps': b.template('liste', liste=liste),
        'actions': actions
    }


#   2. Authentification et administration
@APP.get('/authentification')
@APP.get('/authentification/<action>')
@b.auth_basic(a.authentifier, _('Accès réservé'))
@page
def authentifier():
    """ Page destinée à forcer l'authentification.
    """
    return {
        'corps':
            _('Bonjour, {} !').format(rq.auth[0])
            + h.BR() + h.BR()
            + h.A(_('Retour à la page précédente'), href=rq['HTTP_REFERER']),
    }


@APP.get('/admin')
@APP.get('/admin/<action>')
@b.auth_basic(a.admin, _('Vous devez être administrateur'))
@page
def admin(action=''):
    """ Pages réservées à l'administrateur.
    """
    retour = {'actions': {_('Utilisateurs'): 'admin/utilisateurs'}}
    if action == 'utilisateurs':
        retour['corps'] = b.template('utilisateurs')
    else:
        try:
            with open(os.path.join(
                cfg.PAGES,
                'md',
                'Admin.{}.md'.format(rq.locale)
            ), 'r') as adm:
                retour['corps'] = markdown(adm.read(-1))
        except FileNotFoundError as err:
            f.traiter_erreur(err)
            with open(os.path.join(
                cfg.PAGES, 'md', 'Admin.fr.md'<commit_msg>Ignorer l'absence d'en-tête REFERER<commit_after>#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""Musite − wiki musical

Musite est une sorte de wiki, pensé pour gérer des documents contenant des
partitions de musique, mais adaptable à toutes sortes d'autres usages.

Ce fichier gère la partie interface du site, renvoyant les pages correspondant
aux urls saisies dans le navigateur.Si j'ai bien compris ce qu'est une vue
dans le modèle MVC, ce doit être à peu près ça.
"""

__appname__ = 'serveur'
__license__ = 'MIT'


# Import de librairies externes ###############################################

import os
import sys

LIB = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'deps')
sys.path.insert(0, LIB)
import bottle as b
from bottle import request as rq
from deps.i18n import I18NPlugin as Traduction
from deps import HTMLTags as h
from deps.mistune import markdown

from deps.controleur import Projet, Dossier, Document, DocumentGabc
from deps import outils as f
from deps.outils import i18n_path, _
from deps import auth as a
from deps import utilisateurs as u
from etc import config as cfg


# Paramètres bottle ###########################################################

b.TEMPLATE_PATH += cfg.MODELES
APP = b.Bottle()


# Méthodes globales :  ########################################################


# I. Bidouille et décorateurs destinés à éviter les redondances ########

@APP.hook('before_request')
def strip_path():
    """Effacement du / final s'il y en a un dans l'url
    """
    rq.environ['PATH_INFO'] = rq.environ['PATH_INFO'].rstrip('/')


def page(fonction):
    """Mise en forme commune à toutes les pages

    Cette fonction est un décorateur à appliquer à toutes les fonctions
    affichant des pages, mais non à celles qui retournent des données
    particulières, tels les css ou les fichiers statiques.
    """
    def afficher(*arguments, **parametres):
        """Décorateur
        """
        contenu = fonction(*arguments, **parametres)
        contenu['rq'] = rq
        return b.template('page', contenu)
    return afficher


# II. pages du site ########

#   1. Accueil
@APP.get('/')
@page
def accueil():
    """ Page d'accueil du site
    """
    try:
        actions = {_('Créer projet'): '_creerprojet'} \
            if a.authentifier(rq.auth[0], rq.auth[1]) \
            else {}
    except TypeError as err:
        f.traiter_erreur(err)
        # Cette exception est levée en l'absence d'authentification
        actions = {}
    liens = {_('Projets'): '_projets'}
    try:
        with open(os.path.join(
            cfg.PAGES,
            'md',
            'Accueil.{}.md'.format(rq.locale)
        ), 'r') as acc:
            corps = markdown(acc.read(-1))
    except FileNotFoundError as err:
        f.traiter_erreur(err)
        with open(os.path.join(cfg.PAGES, 'md', 'Accueil.fr.md'), 'r') as acc:
            corps = markdown(acc.read(-1))
    return {
        'corps': corps,
        'actions': actions,
        'liens': liens
    }


@APP.get('/_projets')
@page
def lister_projets():
    """Liste des projets existants
    """
    try:
        actions = {
            _('Créer projet'): '_creerprojet',
            _('Cloner projet'): '_clonerprojet',
        } \
            if a.authentifier(rq.auth[0], rq.auth[1]) \
            else {}
    except TypeError as err:
        f.traiter_erreur(err)
        # Cette exception est levée en l'absence d'authentification
        actions = {}
    listefichiers = f.Dossier(cfg.DATA).lister(profondeur=1)
    # Formatage de la liste des fichiers.
    liste = [
        h.A(
            projet, href=i18n_path('/{}'.format(projet))
        )
        for projet in sorted(listefichiers[cfg.DATA])
        if os.path.isdir(os.path.join(cfg.DATA, projet))
    ]
    return {
        'corps': b.template('liste', liste=liste),
        'actions': actions
    }


#   2. Authentification et administration
@APP.get('/authentification')
@APP.get('/authentification/<action>')
@b.auth_basic(a.authentifier, _('Accès réservé'))
@page
def authentifier():
    """ Page destinée à forcer l'authentification.
    """
    return {
        'corps':
            _('Bonjour, {} !').format(rq.auth[0])
            + h.BR() + h.BR()
            + (
                h.A(_('Retour à la page précédente'), href=rq['HTTP_REFERER'])
                if 'HTTP_REFERER' in rq else ''
            ),
    }


@APP.get('/admin')
@APP.get('/admin/<action>')
@b.auth_basic(a.admin, _('Vous devez être administrateur'))
@page
def admin(action=''):
    """ Pages réservées à l'administrateur.
    """
    retour = {'actions': {_('Utilisateurs'): 'admin/utilisateurs'}}
    if action == 'utilisateurs':
        retour['corps'] = b.template('utilisateurs')
    else:
        try:
            with open(os.path.join(
                cfg.PAGES,
                'md',
                'Admin.{}.md'.format(rq.locale)
            ), 'r') as adm:
                retour['corps'] = markdown(adm.read(-1))
        except FileNotFoundError as err:
            f.traiter_erreur(err)
            with open(os.path.join(
                cfg.PAGES, 'md', 'Admin.fr.md'
{'fraction_non_alphanumeric': 0.16112204724409449, 'fraction_numerical': 0.004330708661417323, 'mean_word_length': 2.619878874242964, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2515229', 'n_tokens_mistral': 3385, 'n_tokens_neox': 3382, 'n_words': 873}