ajout des fichiers pour la génération du paquet wheel et du paquet deb
This commit is contained in:
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
@@ -0,0 +1,6 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : account views and models
|
||||
|
||||
from .views import account
|
||||
@@ -0,0 +1,93 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : Account routes
|
||||
|
||||
#########################################################
|
||||
# Importation de modules externes #
|
||||
|
||||
import sys, re, os
|
||||
import logging as log
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from flask import Flask, Blueprint, request, abort, jsonify, current_app
|
||||
from flask_api import status
|
||||
from flask_jwt_extended import create_access_token
|
||||
from flask_jwt_extended import get_jwt
|
||||
from flask_jwt_extended import set_access_cookies
|
||||
from flask_jwt_extended import unset_jwt_cookies
|
||||
from flask_jwt_extended import get_jwt_identity
|
||||
from flask_jwt_extended import jwt_required, decode_token
|
||||
|
||||
import json
|
||||
import shutil
|
||||
import hashlib
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
#########################################################
|
||||
# Class et Methods #
|
||||
|
||||
account = Blueprint('account', __name__, url_prefix='/api/configurateur')
|
||||
|
||||
@account.errorhandler(HTTPException)
|
||||
def handle_exception(e):
|
||||
''' return JSON instead of HTML for HTTP errors '''
|
||||
response = e.get_response()
|
||||
# replace the body with JSON
|
||||
response.data = json.dumps({
|
||||
'code': e.code,
|
||||
'name': e.name,
|
||||
'description': e.description,
|
||||
})
|
||||
response.content_type = "application/json"
|
||||
return response
|
||||
|
||||
@account.after_request
|
||||
def refresh_expiring_tokens(response):
|
||||
''' Using an 'after_request' callback, we refresh any token that is within
|
||||
30 minutes of expiring.'''
|
||||
try:
|
||||
exp_timestamp = get_jwt()['exp']
|
||||
now = datetime.now(timezone.utc)
|
||||
target_timestamp = datetime.timestamp(now + current_app.config['DELTA'])
|
||||
if target_timestamp > exp_timestamp:
|
||||
current_app.logger.warning("On doit recréer un token JWT ....")
|
||||
access_token = create_access_token(identity=get_jwt_identity())
|
||||
# refresh token in storage place
|
||||
if os.path.exists(os.path.join("/tmp", current_app.config['PROJECT'])):
|
||||
with open(os.path.join("/tmp", current_app.config['PROJECT'], get_jwt_identity()['id']), 'w') as f:
|
||||
f.write(access_token)
|
||||
# Modifiy a Flask Response to set a cookie containing the access JWT.
|
||||
set_access_cookies(response, access_token)
|
||||
return response
|
||||
except (RuntimeError, KeyError):
|
||||
return response
|
||||
|
||||
@account.route('/update_passwd', methods=['POST'])
|
||||
@jwt_required()
|
||||
def update_password():
|
||||
''' Mise à jour du mot de passe utilisateur
|
||||
'''
|
||||
current_app.logger.info("Mise à jour du mot de passe de l'utilisateur")
|
||||
current_user = get_jwt_identity()
|
||||
# recuperation des attributs JSON de la requete
|
||||
data_req = request.get_json()
|
||||
current_app.logger.debug("request: {}".format(data_req))
|
||||
# load data from JSON database
|
||||
with open(current_app.config['DB_PATH'], 'r') as f:
|
||||
data = json.load(f)
|
||||
if 'old' in data_req:
|
||||
if data_req['old'] != data['utilisateur']['password']:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="Mauvais ancien mot de passe")
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="Ancien mot de passe invalide")
|
||||
if 'new' in data_req:
|
||||
data['utilisateur']['password'] = data_req['new']
|
||||
with open(current_app.config['DB_PATH'], 'w') as f:
|
||||
json.dump(data, f)
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="Nouveau mot de passe invalide")
|
||||
|
||||
content = {'message':'maj password successful!'}
|
||||
return content, status.HTTP_200_OK
|
||||
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : Configurateur Backend Flask API
|
||||
|
||||
#########################################################
|
||||
# Importation de modules externes #
|
||||
|
||||
import sys, re, os
|
||||
import logging as log
|
||||
from logging.config import dictConfig
|
||||
|
||||
from flask import Flask
|
||||
from flask.logging import default_handler
|
||||
from flask_cors import CORS, cross_origin
|
||||
from flask_jwt_extended import JWTManager
|
||||
|
||||
import jwt
|
||||
|
||||
from ConfBack.config import DefaultConfig
|
||||
from ConfBack.auth import auth
|
||||
from ConfBack.account import account
|
||||
from ConfBack.params import params
|
||||
from ConfBack.schedule import schedule
|
||||
from ConfBack.log import log as logs
|
||||
from ConfBack.manager import sock
|
||||
from ConfBack.infos import info
|
||||
|
||||
#########################################################
|
||||
# Corps principal du programme #
|
||||
|
||||
def create_app(config=None, app_name=None):
|
||||
''' Create and configure the app
|
||||
|
||||
:param config:
|
||||
configuration object
|
||||
|
||||
:param app_name:
|
||||
application name
|
||||
'''
|
||||
ret = True
|
||||
if app_name is None:
|
||||
app_name = DefaultConfig.PROJECT
|
||||
|
||||
# create the app
|
||||
# tells the app that configuration files are relative to the instance folder.
|
||||
app = Flask(app_name,
|
||||
instance_path=os.path.join(os.getcwd(), app_name),
|
||||
instance_relative_config=True)
|
||||
|
||||
if not configure_app(app, config):
|
||||
return None
|
||||
|
||||
configure_log(app)
|
||||
configure_blueprints(app)
|
||||
ret = configure_connexion(app)
|
||||
|
||||
return ret, app
|
||||
|
||||
def configure_app(app=None, config=None):
|
||||
''' configure the application with configuration file and/or object
|
||||
|
||||
:param app:
|
||||
Application object
|
||||
|
||||
:param config:
|
||||
Configuration object
|
||||
|
||||
:return bool:
|
||||
True if OK, otherwise False
|
||||
'''
|
||||
# load default config
|
||||
app.config.from_object(DefaultConfig)
|
||||
|
||||
try:
|
||||
if config:
|
||||
# load specific config
|
||||
app.config.from_object(config)
|
||||
except ModuleNotFoundError as e:
|
||||
print("Module de configuration non trouvé: {}".format(e))
|
||||
return False
|
||||
|
||||
# setup the Flask-JWT-Extended extension
|
||||
jwt = JWTManager(app)
|
||||
# setup the Flask-CORS extension for handling Cross Origin Resource Sharing
|
||||
CORS(app, resources={r"/api/*": {
|
||||
"origins": ["http://localhost:4200",
|
||||
"http://localhost:6000",
|
||||
"http://127.0.0.1:4200",
|
||||
"http://127.0.0.1:6000"],
|
||||
# "origins": "*",
|
||||
"supports_credentials": True
|
||||
}})
|
||||
return True
|
||||
|
||||
def configure_log(app=None):
|
||||
''' Configure log handler
|
||||
|
||||
:param app:
|
||||
Application object
|
||||
|
||||
:return None:
|
||||
'''
|
||||
if not os.path.exists(app.config['LOG_FOLDER']):
|
||||
try:
|
||||
os.makedirs(app.config['LOG_FOLDER'])
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# On vire tous les handlers
|
||||
for h in app.logger.handlers:
|
||||
app.logger.removeHandler(h)
|
||||
|
||||
# Set info level on logger, which might be overwritten by handers.
|
||||
# Suppress DEBUG messages.
|
||||
app.logger.setLevel(log.DEBUG)
|
||||
|
||||
formatter = log.Formatter('%(asctime)s - %(name)s [%(module)s.%(funcName)s:%(lineno)d] - %(levelname)s - %(message)s')
|
||||
info_log = os.path.join(app.config['LOG_FOLDER'], DefaultConfig.PROJECT + '.log')
|
||||
info_file_handler = log.handlers.RotatingFileHandler(info_log, maxBytes=100000, backupCount=10)
|
||||
info_file_handler.setLevel(log.DEBUG)
|
||||
info_file_handler.setFormatter(formatter)
|
||||
app.logger.addHandler(info_file_handler)
|
||||
|
||||
fl = log.StreamHandler()
|
||||
fl.setLevel(log.DEBUG)
|
||||
fl.setFormatter(formatter)
|
||||
app.logger.addHandler(fl)
|
||||
|
||||
#logging.getLogger('apscheduler').setLevel(logging.DEBUG)
|
||||
|
||||
def configure_blueprints(app=None):
|
||||
''' configure blueprints
|
||||
|
||||
:param app:
|
||||
Application object
|
||||
|
||||
:return None:
|
||||
'''
|
||||
for bp in [auth, logs, account, params, schedule, info]:
|
||||
app.register_blueprint(bp)
|
||||
|
||||
def configure_connexion(app=None):
|
||||
''' Confgure AF_UNIX connexion with KineIntercom
|
||||
process
|
||||
'''
|
||||
ret = False
|
||||
try:
|
||||
sock.connect(app.config['UNIX_ADDR'])
|
||||
ret = True
|
||||
except TimeoutError as e:
|
||||
app.logger.error("Erreur de connexion avec le processus KineIntercom")
|
||||
ret = False
|
||||
except ConnectionRefusedError as e:
|
||||
app.logger.error("Connexion refusée avec le processus KineIntercom")
|
||||
ret = False
|
||||
return ret
|
||||
@@ -0,0 +1,6 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : auth views and models
|
||||
|
||||
from .views import auth
|
||||
@@ -0,0 +1,152 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : Auth routes
|
||||
|
||||
#########################################################
|
||||
# Importation de modules externes #
|
||||
|
||||
import sys, re, os
|
||||
import logging as log
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from flask import Flask, Blueprint, request, abort, jsonify, current_app
|
||||
from flask_api import status
|
||||
from flask_jwt_extended import create_access_token
|
||||
from flask_jwt_extended import get_jwt
|
||||
from flask_jwt_extended import set_access_cookies
|
||||
from flask_jwt_extended import unset_jwt_cookies
|
||||
from flask_jwt_extended import get_jwt_identity
|
||||
from flask_jwt_extended import jwt_required, decode_token
|
||||
|
||||
import json
|
||||
import shutil
|
||||
import hashlib
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
#########################################################
|
||||
# Class et Methods #
|
||||
|
||||
auth = Blueprint('auth', __name__, url_prefix='/api/configurateur')
|
||||
|
||||
@auth.errorhandler(HTTPException)
|
||||
def handle_exception(e):
|
||||
''' return JSON instead of HTML for HTTP errors '''
|
||||
response = e.get_response()
|
||||
# replace the body with JSON
|
||||
response.data = json.dumps({
|
||||
'code': e.code,
|
||||
'name': e.name,
|
||||
'description': e.description,
|
||||
})
|
||||
response.content_type = "application/json"
|
||||
return response
|
||||
|
||||
@auth.after_request
|
||||
def refresh_expiring_tokens(response):
|
||||
''' Using an 'after_request' callback, we refresh any token that is within
|
||||
30 minutes of expiring.'''
|
||||
try:
|
||||
exp_timestamp = get_jwt()['exp']
|
||||
now = datetime.now(timezone.utc)
|
||||
target_timestamp = datetime.timestamp(now + current_app.config['DELTA'])
|
||||
if target_timestamp > exp_timestamp:
|
||||
current_app.logger.warning("On doit recréer un token JWT ....")
|
||||
access_token = create_access_token(identity=get_jwt_identity())
|
||||
# refresh token in storage place
|
||||
if os.path.exists(os.path.join("/tmp", current_app.config['PROJECT'])):
|
||||
with open(os.path.join("/tmp", current_app.config['PROJECT'], get_jwt_identity()['id']), 'w') as f:
|
||||
f.write(access_token)
|
||||
# Modifiy a Flask Response to set a cookie containing the access JWT.
|
||||
set_access_cookies(response, access_token)
|
||||
return response
|
||||
except (RuntimeError, KeyError):
|
||||
return response
|
||||
|
||||
@auth.route('/login', methods=['POST'])
|
||||
def login():
|
||||
''' Authenticate User
|
||||
'''
|
||||
auth = request.authorization
|
||||
current_app.logger.info("Connexion de l'utilisateur : {}".format(auth.username))
|
||||
if not auth or not auth.username or not auth.password:
|
||||
current_app.logger.error("Login and Password required !")
|
||||
abort(401, description='Login and Password required')
|
||||
|
||||
try:
|
||||
hashstr = hashlib.sha256(auth.password.encode('utf-8')).hexdigest()
|
||||
with open(current_app.config['DB_PATH'], 'r') as f:
|
||||
data = json.load(f)
|
||||
# authenticate user with his username and password hash
|
||||
if hashstr == data['utilisateur']['password']:
|
||||
# create a new access token
|
||||
current_app.logger.debug("create JWT Token with id: {}".format(auth.username))
|
||||
token = create_access_token(identity={'id': auth.username})
|
||||
if not os.path.exists(os.path.join("/tmp", current_app.config['PROJECT'])):
|
||||
os.mkdir(os.path.join("/tmp", current_app.config['PROJECT']))
|
||||
with open(os.path.join("/tmp", current_app.config['PROJECT'], auth.username), 'w') as f:
|
||||
f.write(token)
|
||||
content = jsonify({'message': 'login successful !'})
|
||||
# set token as cookie
|
||||
set_access_cookies(content, token)
|
||||
return content, status.HTTP_200_OK
|
||||
current_app.logger.error("Authorization failed !")
|
||||
except Exception as e:
|
||||
current_app.logger.error("Erreur : {}".format(e))
|
||||
abort(500, description='Authentification impossible')
|
||||
abort(401, description="Authorization failed !")
|
||||
|
||||
@auth.route('/logout', methods=['POST'])
|
||||
@jwt_required()
|
||||
def logout():
|
||||
''' Handles HTTP requests to URL: /api/configurateur/logout
|
||||
'''
|
||||
current_app.logger.info("Deconnexion de l'utilisateur")
|
||||
current_user = get_jwt_identity()
|
||||
content = jsonify({'message': 'logout successful !'})
|
||||
unset_jwt_cookies(content)
|
||||
userpath = os.path.join("/tmp", current_app.config['PROJECT'])
|
||||
if os.path.exists(userpath):
|
||||
shutil.rmtree(userpath)
|
||||
return content, status.HTTP_200_OK
|
||||
|
||||
@auth.route('/current', methods=['GET'])
|
||||
@jwt_required()
|
||||
def current_user():
|
||||
''' retourne l'utilisateur courant connecté
|
||||
'''
|
||||
# Access the identity of the current user with get_jwt_identity
|
||||
current_user = get_jwt_identity()
|
||||
return jsonify(current_user)
|
||||
|
||||
@auth.route('/userConnected', methods=['GET'])
|
||||
def user_connected():
|
||||
''' retourne "oui" si un utilisateur est déjà connecté sinon "non"
|
||||
'''
|
||||
flag = False
|
||||
resp = 'non'
|
||||
uid = ''
|
||||
path = os.path.join("/tmp", current_app.config['PROJECT'])
|
||||
if os.path.exists(path):
|
||||
# search unique file in path
|
||||
for root, dirs, files in os.walk(path):
|
||||
for f in files:
|
||||
uid = str(f)
|
||||
# retreive token in file
|
||||
with open(os.path.join(path, f), 'r') as fp:
|
||||
token = fp.read()
|
||||
exp = decode_token(token, allow_expired = True)['exp']
|
||||
now = datetime.now(timezone.utc)
|
||||
target = datetime.timestamp(now)
|
||||
if target > exp:
|
||||
current_app.logger.warning("Le token de l'ancien utilisateur a expiré")
|
||||
# remove tmp dir
|
||||
shutil.rmtree(os.path.join("/tmp", current_app.config['PROJECT']))
|
||||
flag = True
|
||||
break
|
||||
|
||||
if not flag:
|
||||
current_app.logger.warning("Un autre utilisateur est déjà connecté")
|
||||
resp = 'oui'
|
||||
content = ({'message':resp, 'uid':uid})
|
||||
return jsonify(content), status.HTTP_200_OK
|
||||
@@ -0,0 +1,70 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# @author: vincent.benoit@benserv.fr
|
||||
# @brief: Flask Config classes
|
||||
|
||||
import os
|
||||
import datetime
|
||||
|
||||
class BaseConfig(object):
|
||||
PROJECT = "configurateur"
|
||||
|
||||
# Get app root path, also can use flask.root_path.
|
||||
PROJECT_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
|
||||
DEBUG = False
|
||||
TESTING = False
|
||||
FLASK_ENV = 'production'
|
||||
|
||||
ADMINS = ['vincent.benoit@benserv.fr']
|
||||
|
||||
LOG_FOLDER = os.path.join(os.getcwd(), 'log')
|
||||
APP_NAME = "KineIntercom"
|
||||
|
||||
SECRET_KEY = "d]omg;<*|uHfs}ogN=dk_$YW"
|
||||
|
||||
# Setup the Flask-JWT-Extended extension
|
||||
JWT_SECRET_KEY = "xbNNvwHCY*cN,)Yq;A,e(]|P"
|
||||
JWT_COOKIE_SECURE = False
|
||||
JWT_TOKEN_LOCATION = ["cookies"]
|
||||
JWT_ACCESS_TOKEN_EXPIRES = datetime.timedelta(minutes=30)
|
||||
DELTA = datetime.timedelta(minutes=20) # in minutes
|
||||
# Controls if Cross Site Request Forgery (CSRF) protection is enabled when using cookies
|
||||
# This should always be True in production
|
||||
JWT_COOKIE_CSRF_PROTECT = True
|
||||
JWT_CSRF_IN_COOKIES = True
|
||||
JWT_COOKIE_SAMESITE = "None"
|
||||
|
||||
STATIC_FOLDER = os.path.join(os.getcwd(), 'static')
|
||||
UPLOAD_FOLDER = STATIC_FOLDER + '/upload'
|
||||
DOWNLOAD_FOLDER = STATIC_FOLDER + '/download'
|
||||
ALLOWED_EXTENSIONS = {'json', 'tar', 'txt'}
|
||||
MAX_CONTENT_LENGTH = 200 * 1024 * 1024 # 100 megabytes
|
||||
|
||||
# Database path
|
||||
DB_PATH = os.path.join(os.getcwd(), 'db.json')
|
||||
UNIX_ADDR = "/tmp/uds_socket"
|
||||
|
||||
class DefaultConfig(BaseConfig):
|
||||
DEBUG = True
|
||||
TESTING = True
|
||||
FLASK_ENV = 'development'
|
||||
|
||||
SECRET_KEY = "secretkey10"
|
||||
|
||||
# Setup the Flask-JWT-Extended extension
|
||||
JWT_SECRET_KEY = "secretkeyjwt10"
|
||||
JWT_ACCESS_TOKEN_EXPIRES = datetime.timedelta(minutes=10)
|
||||
DELTA = datetime.timedelta(minutes=5) # in minutes
|
||||
|
||||
class ProdConfig(BaseConfig):
|
||||
DEBUG = False
|
||||
TESTING = False
|
||||
FLASK_ENV = 'production'
|
||||
|
||||
ROOT_BASE_FOLDER = "/opt"
|
||||
# Log Folder path
|
||||
LOG_FOLDER = "/var/log/kineintercom"
|
||||
# Database path
|
||||
DB_PATH = os.path.join('/etc/kineintercom', 'db.json')
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : info views and models
|
||||
|
||||
from .views import info
|
||||
@@ -0,0 +1,81 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : info routes
|
||||
|
||||
#########################################################
|
||||
# Importation de modules externes #
|
||||
|
||||
import sys, re, os
|
||||
import logging as log
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from flask import Flask, Blueprint, request, abort, jsonify, current_app
|
||||
from flask_api import status
|
||||
from flask_jwt_extended import create_access_token
|
||||
from flask_jwt_extended import get_jwt
|
||||
from flask_jwt_extended import set_access_cookies
|
||||
from flask_jwt_extended import get_jwt_identity
|
||||
from flask_jwt_extended import jwt_required
|
||||
|
||||
import json
|
||||
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
#########################################################
|
||||
# Class et Methods #
|
||||
|
||||
info = Blueprint('info', __name__, url_prefix='/api/configurateur')
|
||||
|
||||
@info.errorhandler(HTTPException)
|
||||
def handle_exception(e):
|
||||
''' return JSON instead of HTML for HTTP errors '''
|
||||
response = e.get_response()
|
||||
# replace the body with JSON
|
||||
response.data = json.dumps({
|
||||
'code': e.code,
|
||||
'name': e.name,
|
||||
'description': e.description,
|
||||
})
|
||||
response.content_type = "application/json"
|
||||
return response
|
||||
|
||||
@info.after_request
|
||||
def refresh_expiring_tokens(response):
|
||||
''' Using an 'after_request' callback, we refresh any token that is within
|
||||
30 minutes of expiring.'''
|
||||
try:
|
||||
exp_timestamp = get_jwt()['exp']
|
||||
now = datetime.now(timezone.utc)
|
||||
target_timestamp = datetime.timestamp(now + current_app.config['DELTA'])
|
||||
if target_timestamp > exp_timestamp:
|
||||
current_app.logger.warning("On doit recréer un token ....")
|
||||
access_token = create_access_token(identity=get_jwt_identity())
|
||||
# refresh token in storage place
|
||||
if os.path.exists(os.path.join("/tmp", current_app.config['PROJECT'])):
|
||||
with open(os.path.join("/tmp", current_app.config['PROJECT'], get_jwt_identity()['id']), 'w') as f:
|
||||
f.write(access_token)
|
||||
# Modifiy a Flask Response to set a cookie containing the access JWT.
|
||||
set_access_cookies(response, access_token)
|
||||
return response
|
||||
except (RuntimeError, KeyError):
|
||||
return response
|
||||
|
||||
@info.route('/infos', methods=['GET'])
|
||||
@jwt_required()
|
||||
def get_infos():
|
||||
''' Retreive informations '''
|
||||
# Access the identity of the current user with get_jwt_identity
|
||||
current_user = get_jwt_identity()
|
||||
content = {}
|
||||
# load data from JSON database
|
||||
with open(current_app.config['DB_PATH'], 'r') as f:
|
||||
data = json.load(f)
|
||||
content['manufacturer'] = data['INFOS']['manufacturer']
|
||||
content['operator'] = data['INFOS']['control']['operator']
|
||||
content['provider'] = data['INFOS']['control']['service_provider']
|
||||
content['signal_dbm'] = data['INFOS']['control']['signal_dbm']
|
||||
content['signal_qos'] = data['INFOS']['control']['signal_qos']
|
||||
content['sim_inserted'] = data['INFOS']['control']['sim_inserted']
|
||||
content['call_ready'] = data['INFOS']['control']['call_ready']
|
||||
return jsonify(content), status.HTTP_200_OK
|
||||
@@ -0,0 +1,6 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : log views and models
|
||||
|
||||
from .views import log
|
||||
@@ -0,0 +1,112 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : log routes
|
||||
|
||||
#########################################################
|
||||
# Importation de modules externes #
|
||||
|
||||
import sys, re, os
|
||||
import logging as log
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from flask import Flask, Blueprint, request, abort, jsonify, current_app
|
||||
from flask_api import status
|
||||
from flask_jwt_extended import create_access_token
|
||||
from flask_jwt_extended import get_jwt
|
||||
from flask_jwt_extended import set_access_cookies
|
||||
from flask_jwt_extended import get_jwt_identity
|
||||
from flask_jwt_extended import jwt_required
|
||||
|
||||
import json
|
||||
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
#########################################################
|
||||
# Class et Methods #
|
||||
|
||||
log = Blueprint('log', __name__, url_prefix='/api/configurateur')
|
||||
|
||||
@log.errorhandler(HTTPException)
|
||||
def handle_exception(e):
|
||||
''' return JSON instead of HTML for HTTP errors '''
|
||||
response = e.get_response()
|
||||
# replace the body with JSON
|
||||
response.data = json.dumps({
|
||||
'code': e.code,
|
||||
'name': e.name,
|
||||
'description': e.description,
|
||||
})
|
||||
response.content_type = "application/json"
|
||||
return response
|
||||
|
||||
@log.after_request
|
||||
def refresh_expiring_tokens(response):
|
||||
''' Using an 'after_request' callback, we refresh any token that is within
|
||||
30 minutes of expiring.'''
|
||||
try:
|
||||
exp_timestamp = get_jwt()['exp']
|
||||
now = datetime.now(timezone.utc)
|
||||
target_timestamp = datetime.timestamp(now + current_app.config['DELTA'])
|
||||
if target_timestamp > exp_timestamp:
|
||||
current_app.logger.warning("On doit recréer un token ....")
|
||||
access_token = create_access_token(identity=get_jwt_identity())
|
||||
# refresh token in storage place
|
||||
if os.path.exists(os.path.join("/tmp", current_app.config['PROJECT'])):
|
||||
with open(os.path.join("/tmp", current_app.config['PROJECT'], get_jwt_identity()['id']), 'w') as f:
|
||||
f.write(access_token)
|
||||
# Modifiy a Flask Response to set a cookie containing the access JWT.
|
||||
set_access_cookies(response, access_token)
|
||||
return response
|
||||
except (RuntimeError, KeyError):
|
||||
return response
|
||||
|
||||
@log.route('/conf_logs', methods=['GET'])
|
||||
@jwt_required()
|
||||
def get_conf_logs():
|
||||
''' Retreive conf logs '''
|
||||
# Access the identity of the current user with get_jwt_identity
|
||||
current_user = get_jwt_identity()
|
||||
|
||||
lines = []
|
||||
logfile = os.path.join(current_app.config['LOG_FOLDER'], current_app.config['PROJECT'] + '.log')
|
||||
try:
|
||||
with open(logfile) as f:
|
||||
current_app.logger.debug("conf log file: {}".format(logfile))
|
||||
for idx, line in enumerate(f.readlines()):
|
||||
try:
|
||||
date_time, head, gravity, msg = line.split(' - ', 3)
|
||||
content = {'datetime': date_time, 'header': head, 'gravity': gravity, 'msg':msg}
|
||||
lines.append(content)
|
||||
except ValueError as e:
|
||||
lines[-1]['msg'] = lines[-1]['msg'] + line
|
||||
except FileNotFoundError as e:
|
||||
current_app.logger.error("Fichier de log ({}) manquant".format(logfile))
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="Fichier log manquant")
|
||||
|
||||
return jsonify(lines), status.HTTP_200_OK
|
||||
|
||||
@log.route('/app_logs', methods=['GET'])
|
||||
@jwt_required()
|
||||
def get_app_logs():
|
||||
''' Retreive app logs '''
|
||||
# Access the identity of the current user with get_jwt_identity
|
||||
current_user = get_jwt_identity()
|
||||
|
||||
lines = []
|
||||
logfile = os.path.join(current_app.config['LOG_FOLDER'], current_app.config['APP_NAME'] + '.log')
|
||||
try:
|
||||
with open(logfile) as f:
|
||||
current_app.logger.debug("app log file: {}".format(logfile))
|
||||
for idx, line in enumerate(f.readlines()):
|
||||
try:
|
||||
date_time, head, gravity, msg = line.split(' - ', 3)
|
||||
content = {'datetime': date_time, 'header': head, 'gravity': gravity, 'msg':msg}
|
||||
lines.append(content)
|
||||
except ValueError as e:
|
||||
lines[-1]['msg'] = lines[-1]['msg'] + line
|
||||
except FileNotFoundError as e:
|
||||
current_app.logger.error("Fichier de log ({}) manquant".format(logfile))
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="Fichier log manquant")
|
||||
|
||||
return jsonify(lines), status.HTTP_200_OK
|
||||
@@ -0,0 +1,21 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@scle.fr
|
||||
# @brief : Client UNIX Socket Manager
|
||||
|
||||
#########################################################
|
||||
# Importation de modules externes #
|
||||
|
||||
import sys, re, os
|
||||
import socket
|
||||
|
||||
#########################################################
|
||||
# Corps principal du programme #
|
||||
|
||||
#########################################################
|
||||
# Decorators #
|
||||
|
||||
#########################################################
|
||||
# Instantiation #
|
||||
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
@@ -0,0 +1,6 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : params views and models
|
||||
|
||||
from .views import params
|
||||
@@ -0,0 +1,149 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : Params routes
|
||||
|
||||
#########################################################
|
||||
# Importation de modules externes #
|
||||
|
||||
import sys, re, os
|
||||
import logging as log
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from flask import Flask, Blueprint, request, abort, jsonify, current_app
|
||||
from flask_api import status
|
||||
from flask_jwt_extended import create_access_token
|
||||
from flask_jwt_extended import get_jwt
|
||||
from flask_jwt_extended import set_access_cookies
|
||||
from flask_jwt_extended import unset_jwt_cookies
|
||||
from flask_jwt_extended import get_jwt_identity
|
||||
from flask_jwt_extended import jwt_required
|
||||
|
||||
import json
|
||||
import shutil
|
||||
import hashlib
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
from ConfBack.manager import sock
|
||||
|
||||
#########################################################
|
||||
# Class et Methods #
|
||||
|
||||
params = Blueprint('params', __name__, url_prefix='/api/configurateur')
|
||||
|
||||
@params.errorhandler(HTTPException)
|
||||
def handle_exception(e):
|
||||
''' return JSON instead of HTML for HTTP errors '''
|
||||
response = e.get_response()
|
||||
# replace the body with JSON
|
||||
response.data = json.dumps({
|
||||
'code': e.code,
|
||||
'name': e.name,
|
||||
'description': e.description,
|
||||
})
|
||||
response.content_type = "application/json"
|
||||
return response
|
||||
|
||||
@params.after_request
|
||||
def refresh_expiring_tokens(response):
|
||||
''' Using an 'after_request' callback, we refresh any token that is within
|
||||
30 minutes of expiring.'''
|
||||
try:
|
||||
exp_timestamp = get_jwt()['exp']
|
||||
now = datetime.now(timezone.utc)
|
||||
target_timestamp = datetime.timestamp(now + current_app.config['DELTA'])
|
||||
if target_timestamp > exp_timestamp:
|
||||
current_app.logger.warning("On doit recréer un token JWT ....")
|
||||
access_token = create_access_token(identity=get_jwt_identity())
|
||||
# refresh token in storage place
|
||||
if os.path.exists(os.path.join("/tmp", current_app.config['PROJECT'])):
|
||||
with open(os.path.join("/tmp", current_app.config['PROJECT'], get_jwt_identity()['id']), 'w') as f:
|
||||
f.write(access_token)
|
||||
# Modifiy a Flask Response to set a cookie containing the access JWT.
|
||||
set_access_cookies(response, access_token)
|
||||
return response
|
||||
except (RuntimeError, KeyError):
|
||||
return response
|
||||
|
||||
@params.route('/params', methods=['GET'])
|
||||
@jwt_required()
|
||||
def retreive_params():
|
||||
''' Récupération des paramètres de l'intercom
|
||||
'''
|
||||
current_app.logger.info("Récupération des paramètres de l'intercom")
|
||||
current_user = get_jwt_identity()
|
||||
# load data from JSON database
|
||||
try:
|
||||
with open(current_app.config['DB_PATH'], 'r') as f:
|
||||
data = json.load(f)
|
||||
if 'OPERATION' and 'PIN_ACTIF' and 'CODE_PIN' and 'NUM_AUTORISE' and 'TONE_DURATION' and 'DTMF_CODE' and 'DTMF_DURATION' in data:
|
||||
content = {'operation': data['OPERATION'], 'pin_actif': data['PIN_ACTIF'], 'code_pin': data['CODE_PIN'], 'num_autorized': data['NUM_AUTORISE'], 'tone_duration': data['TONE_DURATION'], 'dtmf_code': data['DTMF_CODE'], 'dtmf_duration': data['DTMF_DURATION']}
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="paramètres manquant en base de données")
|
||||
except FileNotFoundError as e:
|
||||
current_app.logger.error("Fichier ({}) manquant".format(current_app.config['DB_PATH']))
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="Fichier manquant")
|
||||
|
||||
return content, status.HTTP_200_OK
|
||||
|
||||
@params.route('/update_params', methods=['POST'])
|
||||
@jwt_required()
|
||||
def update_params():
|
||||
''' Mise à jour des paramètres de l'intercom
|
||||
'''
|
||||
current_app.logger.info("Mise à jour des paramètres de l'intercom")
|
||||
current_user = get_jwt_identity()
|
||||
# recuperation des attributs JSON de la requete
|
||||
data_req = request.get_json()
|
||||
current_app.logger.debug("request: {}".format(data_req))
|
||||
# load data from JSON database
|
||||
try:
|
||||
with open(current_app.config['DB_PATH'], 'r') as f:
|
||||
data = json.load(f)
|
||||
except FileNotFoundError as e:
|
||||
current_app.logger.error("Fichier ({}) manquant".format(current_app.config['DB_PATH']))
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="Fichier manquant")
|
||||
|
||||
if 'operation' in data_req:
|
||||
data['OPERATION'] = data_req['operation']
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="paramètre manquant")
|
||||
if 'pin_actif' in data_req:
|
||||
data['PIN_ACTIF'] = data_req['pin_actif']
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="paramètre manquant")
|
||||
if 'code_pin' in data_req:
|
||||
data['CODE_PIN'] = data_req['code_pin']
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="paramètre manquant")
|
||||
if 'num_autorized' in data_req:
|
||||
data['NUM_AUTORISE'] = data_req['num_autorized']
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="paramètre manquant")
|
||||
if 'tone_duration' in data_req:
|
||||
data['TONE_DURATION'] = int(data_req['tone_duration'])
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="paramètre manquant")
|
||||
if 'dtmf_code' in data_req:
|
||||
data['DTMF_CODE'] = data_req['dtmf_code']
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="paramètre manquant")
|
||||
if 'dtmf_duration' in data_req:
|
||||
data['DTMF_DURATION'] = int(data_req['dtmf_duration'])
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="paramètre manquant")
|
||||
|
||||
with open(current_app.config['DB_PATH'], 'w') as f:
|
||||
json.dump(data, f)
|
||||
|
||||
try:
|
||||
# send order to KineIntercom process
|
||||
sock.send(b"RELOAD_DB\n")
|
||||
except:
|
||||
current_app.logger.error("Erreur d'envoi de l'ordre au processus KineIntercom")
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="Erreur d'envoi de l'ordre au processus")
|
||||
|
||||
content = {'message':'maj parameters successful!'}
|
||||
|
||||
return content, status.HTTP_200_OK
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : schedule views and models
|
||||
|
||||
from .views import schedule
|
||||
@@ -0,0 +1,121 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
# @author : vincent.benoit@benserv.fr
|
||||
# @brief : Scheduler routes
|
||||
|
||||
#########################################################
|
||||
# Importation de modules externes #
|
||||
|
||||
import sys, re, os
|
||||
import logging as log
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from flask import Flask, Blueprint, request, abort, jsonify, current_app
|
||||
from flask_api import status
|
||||
from flask_jwt_extended import create_access_token
|
||||
from flask_jwt_extended import get_jwt
|
||||
from flask_jwt_extended import set_access_cookies
|
||||
from flask_jwt_extended import unset_jwt_cookies
|
||||
from flask_jwt_extended import get_jwt_identity
|
||||
from flask_jwt_extended import jwt_required
|
||||
|
||||
import json
|
||||
import shutil
|
||||
import hashlib
|
||||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
#########################################################
|
||||
# Class et Methods #
|
||||
|
||||
schedule = Blueprint('schedule', __name__, url_prefix='/api/configurateur')
|
||||
|
||||
@schedule.errorhandler(HTTPException)
|
||||
def handle_exception(e):
|
||||
''' return JSON instead of HTML for HTTP errors '''
|
||||
response = e.get_response()
|
||||
# replace the body with JSON
|
||||
response.data = json.dumps({
|
||||
'code': e.code,
|
||||
'name': e.name,
|
||||
'description': e.description,
|
||||
})
|
||||
response.content_type = "application/json"
|
||||
return response
|
||||
|
||||
@schedule.after_request
|
||||
def refresh_expiring_tokens(response):
|
||||
''' Using an 'after_request' callback, we refresh any token that is within
|
||||
30 minutes of expiring.'''
|
||||
try:
|
||||
exp_timestamp = get_jwt()['exp']
|
||||
now = datetime.now(timezone.utc)
|
||||
target_timestamp = datetime.timestamp(now + current_app.config['DELTA'])
|
||||
if target_timestamp > exp_timestamp:
|
||||
current_app.logger.warning("On doit recréer un token JWT ....")
|
||||
access_token = create_access_token(identity=get_jwt_identity())
|
||||
# refresh token in storage place
|
||||
if os.path.exists(os.path.join("/tmp", current_app.config['PROJECT'])):
|
||||
with open(os.path.join("/tmp", current_app.config['PROJECT'], get_jwt_identity()['id']), 'w') as f:
|
||||
f.write(access_token)
|
||||
# Modifiy a Flask Response to set a cookie containing the access JWT.
|
||||
set_access_cookies(response, access_token)
|
||||
return response
|
||||
except (RuntimeError, KeyError):
|
||||
return response
|
||||
|
||||
@schedule.route('/scheduler', methods=['GET'])
|
||||
@jwt_required()
|
||||
def retreive_scheduler():
|
||||
''' Récupération des horaires
|
||||
'''
|
||||
current_app.logger.info("Récupération des horaires")
|
||||
current_user = get_jwt_identity()
|
||||
# load data from JSON database
|
||||
try:
|
||||
with open(current_app.config['DB_PATH'], 'r') as f:
|
||||
data = json.load(f)
|
||||
content = []
|
||||
if 'HORAIRES' in data:
|
||||
for day in data['HORAIRES']:
|
||||
h = []
|
||||
for hour in data['HORAIRES'][day]:
|
||||
h.append(hour)
|
||||
content.append({'name': day, 'horaires':h})
|
||||
#current_app.logger.debug("{}".format(content))
|
||||
else:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="horaire manquant en base de données")
|
||||
except FileNotFoundError as e:
|
||||
current_app.logger.error("Fichier ({}) manquant".format(current_app.config['DB_PATH']))
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="Fichier manquant")
|
||||
|
||||
return content, status.HTTP_200_OK
|
||||
|
||||
@schedule.route('/update_schedulers', methods=['POST'])
|
||||
@jwt_required()
|
||||
def update_scheduler():
|
||||
''' Mise à jour des horaires
|
||||
'''
|
||||
current_app.logger.info("Mise à jour des horaires")
|
||||
current_user = get_jwt_identity()
|
||||
# recuperation des attributs JSON de la requete
|
||||
data_req = request.get_json()
|
||||
# load data from JSON database
|
||||
try:
|
||||
with open(current_app.config['DB_PATH'], 'r') as f:
|
||||
data_db = json.load(f)
|
||||
except FileNotFoundError as e:
|
||||
current_app.logger.error("Fichier ({}) manquant".format(current_app.config['DB_PATH']))
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="Fichier manquant")
|
||||
|
||||
for day in data_db['HORAIRES']:
|
||||
for d in data_req:
|
||||
if 'name' in d and d['name'] == day:
|
||||
data_db['HORAIRES'][day] = d['horaires']
|
||||
elif 'name' not in d:
|
||||
abort(status.HTTP_406_NOT_ACCEPTABLE, description="erreur des données de la requete")
|
||||
|
||||
with open(current_app.config['DB_PATH'], 'w') as f:
|
||||
json.dump(data_db, f)
|
||||
content = {'message':'maj parameters successful!'}
|
||||
return content, status.HTTP_200_OK
|
||||
|
||||
Reference in New Issue
Block a user