Skip to content
module.py 140 KiB
Newer Older
#!/usr/bin/python
# -*- coding: UTF-8 -*-

from cStringIO import StringIO
Marco De Donno's avatar
Marco De Donno committed
from datetime import datetime, timedelta
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from logging.config import dictConfig
from threading import Thread
from uuid import uuid4
import base64
import hashlib
Marco De Donno's avatar
Marco De Donno committed
from PIL import Image
from flask import Flask
from flask import jsonify
from flask import send_from_directory
from flask import request, has_request_context
from flask import send_file
from flask import session
from flask import url_for
from flask_compress import Compress
from flask_session import Session
from pyzbar import pyzbar
from werkzeug import abort, redirect
from werkzeug.http import http_date
Marco De Donno's avatar
Marco De Donno committed
from werkzeug.middleware.proxy_fix import ProxyFix
import gnupg
import pdf2image
Marco De Donno's avatar
Marco De Donno committed
import pyotp
import webauthn
from NIST.fingerprint import NISTf_auto
from PiAnoS import caseExistsInDB
from const import pfsp
import utils
from utils.decorator import admin_required, login_required, submission_has_access
from utils.template import my_render_template

from functions import dek_generate, do_encrypt_dek, do_decrypt_dek, dek_check
from functions import do_encrypt_user_session, do_decrypt_user_session
from functions import no_preview_image
from functions import mySMTP
import config
################################################################################

from version import __version__, __branch__, __commit__, __commiturl__, __treeurl__

################################################################################

logrequestre = re.compile( "(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*\[[^\]]+\]\s(.*)" )

class RequestFormatter( logging.Formatter ):
    def format( self, record ):
        if has_request_context():
            try:
                username = session[ "username" ] 
            except:
                username = "-"
            
            record.msg = "{REMOTE_ADDR} (" + username + ") - " + record.msg
            record.msg = record.msg.format( **request.headers.environ )
        
        m = logrequestre.match( record.msg )
        if m:
            record.msg = m.group( 2 )
        
        return super( RequestFormatter, self ).format( record )

class myFilter( object ):
    def filter( self, record ):
        if "{}/ping".format( config.baseurl ) in record.msg and " 200 " in record.msg:
            return 0
        else:
            return 1

class myStreamHandler( logging.StreamHandler ):
    def __init__( self ):
        logging.StreamHandler.__init__( self )
        self.addFilter( myFilter() )

Marco De Donno's avatar
Marco De Donno committed
    "version": 1,
    "formatters": {
        "default": {
            "()": "module.RequestFormatter",
            "format": "[%(asctime)s] %(levelname)s: \t%(message)s",
Marco De Donno's avatar
Marco De Donno committed
    "handlers": {
        "console": {
            "class": "module.myStreamHandler",
            "formatter": "default"
Marco De Donno's avatar
Marco De Donno committed
    "root": {
        "level": "INFO",
        "handlers": [ "console" ]
    }
} )

################################################################################

app = Flask( __name__ )
app.config.from_pyfile( "config.py" )
Compress( app )
Session( app )
Marco De Donno's avatar
Marco De Donno committed
if config.PROXY:
    app.wsgi_app = ProxyFix( app.wsgi_app )

################################################################################
#    Import the views
from views.base import base
app.register_blueprint( base, url_prefix = "/" )
app.register_blueprint( base, url_prefix = config.baseurl )
from views.files import files
app.register_blueprint( files, url_prefix = config.baseurl )
################################################################################
#    Headers

@app.after_request
def add_header( r ):
    for c in [ "/cdn", "/static" ]:
        if request.path.startswith( config.baseurl + c ):
        r.headers[ "Last-Modified" ] = http_date( datetime.now() )
        r.headers[ "Cache-Control" ] = "no-cache, no-store, must-revalidate, max-age=0, s-maxage=0"
        r.headers[ "Pragma" ] = "no-cache"
        r.headers[ "Expires" ] = "0"
    
################################################################################
#    Sessions

@app.before_request
def renew_session():
    """
        Reset the timer before the automatic-logout.
        This function is called before every HTTP call.
    """
    session.permanent = True
    app.permanent_session_lifetime = timedelta( seconds = config.session_timeout )

@app.route( config.baseurl + "/is_logged" )
def is_logged():
    """
        App route to know if the user is logged in the ICNML main application.
        This route is used by nginx to protect some other locations, for example
        the PiAnoS dedicated pages.
        The session countdown timer is resetted to allow the user to use the protected
        location for the rest of the timeout.
    """
    app.logger.info( "Check if the user is connected" )
    
    if session.get( "logged", False ):
        return "ok"
    
    else:
        return abort( 403 )

@app.route( config.baseurl + "/logout" )
def logout():
    """
        Logout the user, clear the session and redirect to the login page.
    """
    app.logger.info( "Logout and clear session" )
    
    session_clear_and_prepare()
    return redirect( url_for( "home" ) )
def session_clear_and_prepare():
    """
        Clear the session related to the user and initialize the login related variables.
    """
    session.clear()
    session[ "process" ] = "login"
    session[ "need_to_check" ] = [ "password" ]
    session[ "logged" ] = False
    session[ "session_security_key" ] = str( uuid4() )
Loading
Loading full blame...