123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- from array import array
- from msilib.schema import Class
- from re import I
- import threading
- from tkinter.ttk import Separator
- from typing import Type
- from xmlrpc.client import boolean
- from flask import session,Flask,request, jsonify
- from flask_restful import Resource, Api
- import flask_restful
- from itsdangerous import json
- from sqlalchemy import delete
- from utility.app_logging import logger_name
- import logging
- import persistence
- import Model.isp_model as isp_model
- import Model.model_manager as model_manager
- from werkzeug.security import check_password_hash
- import anytree
- import View.view_privilege as privileges
- from datetime import timedelta
- from flask_session import Session
- import View.view_error_management as view_error_management
- logger = logging.getLogger(logger_name + ".VIEW")
- __app__ = Flask("OpenIsp")
- __app__.secret_key = "aseqzdwxc"
- __app__.permanent_session_lifetime = timedelta(minutes=2)
- __app__.config["SESSION_PERMANENT"] = False
- __app__.config["SESSION_TYPE"] = "filesystem"
- __resource_array__ : array
- __id_counter__ : int = 1
- from werkzeug.serving import make_server
- class ServerThread(threading.Thread):
- def __init__(self, app,ip,port):
- threading.Thread.__init__(self)
- self.server = make_server(ip, port, app)
- self.ctx = app.app_context()
- self.ctx.push()
- def run(self):
- logger.info('starting server')
- self.server.serve_forever()
- def shutdown(self):
- self.server.shutdown()
- __server_process__ : ServerThread
- def get_roles_ids() :
- return session["roles_ids"]
- def init() :
- @__app__.before_request
- def before_request_func():
- print(request.headers.__dict__)
- global __id_counter__
- logger.debug("before_request is running!")
- if not "client_id" in session :
- session["client_id"] = str(__id_counter__)
- logger.debug("client_id is " + session["client_id"])
- __id_counter__ = __id_counter__ + 1
- if not request.path == "/api/login" and not "username" in session :
- logger.warning("Unauthorized client with id " + session["client_id"] + " try to access application")
- resp = jsonify({'message' : 'Unauthorized'})
- resp.status_code = 401
- return resp
- if "username" in session :
- logger.debug("request from " + session["username"])
- from flask.logging import default_handler
- __app__.logger.removeHandler(default_handler)
- privileges.init()
- view_error_management.define_error_management(__app__)
- @__app__.route('/api/login',methods = ['POST'])
- def login():
- _json = request.json
- _username = _json['username']
- _password = _json['password']
- with persistence.get_Session_Instance() as sess :
- Item = sess.query(isp_model.user_account).filter(isp_model.user_account.nickname == _username).first()
- if not isinstance(Item,isp_model.user_account) :
- logger.warning("user tried to login with unknown account name : " + _username)
- resp = jsonify({'message' : 'Bad Request - user account not found'})
- resp.status_code = 400
- return resp
- if not check_password_hash(Item.password,_password) :
- logger.warning("user with account name '" + _username + "' tried to login with invalid password")
- resp = jsonify({'message' : 'Bad Request - invalid password for this account'})
- resp.status_code = 400
- return resp
- session["username"] = _username
- session["account_data"] = model_manager.ModelObjectToJsonString(Item)
- session["roles_ids"] = [privileges.inventory_read_only_role.id]
- logger.info("account " + _username + " logged IN successfully with id : " + session["client_id"])
- resp = jsonify({'message' : 'login successful'})
- resp.status_code = 200
- return resp
- @__app__.route('/api/logout',methods = ['POST'])
- def logout():
- logger.info("account " + session["username"] + " logged OUT with id : " + session["client_id"])
- session.clear()
- return jsonify('logout')
- @__app__.route('/routes',methods = ['GET'])
- @privileges.manager.require_authorization(required_role=privileges.inventory_admin_role,ids_getter=get_roles_ids)
- def routes():
- routes = []
- for route in __app__.url_map.iter_rules():
- routes.append('%s' % route)
- return jsonify(routes)
- def run() :
- global __server_process__
- __server_process__ = ServerThread(__app__,"0.0.0.0",8000)
- __server_process__.start()
- logger.info('View server started')
- def stop() :
- global __server_process__
- __server_process__.shutdown()
- logger.info('View server stopped')
- class ResourceNode(anytree.NodeMixin) :
- def __init__(self, url_key : str, resource = None, parent=None, children=None):
- super(ResourceNode, self).__init__()
- self.url_key = url_key
- self.parent = parent
- if children:
- self.children = children
- if resource :
- self.resource = resource
- # we check if the resource class has an http API method
- get = getattr(self, "get", None)
- post = getattr(self, "post", None)
- delete = getattr(self, "delete", None)
- update = getattr(self, "update", None)
- patch = getattr(self, "patch", None)
- if not callable(get) and not callable(post) \
- and not callable(delete) and not callable(update) \
- and not callable(patch) :
- raise BaseException("class does have an api class")
- url_slice = None
- resource = None
- def add_resource_tree(node : ResourceNode) :
- if not node.is_root() :
- raise BaseException("node is not a root node")
- logger.debug("adding resource tree for API")
- logger.debug(anytree.RenderTree(node, style=anytree.AsciiStyle()).by_attr("url_slice"))
- for node in anytree.PreOrderIter(node) :
- logger.debug("iterating though node " + node.url_key)
- if node.resource is not None :
- logger.debug("resource found")
- url = ""
- parent : ResourceNode
- for parent in node.ancestors :
- url = url + node.separator + parent.url_key
- print("url built for the node : " + url)
- __api__.add_resource(node.resource, url)
- __resource_array__.append(node)
- #node.ancestors ( all parent )
- def delete_resource_tree(node : ResourceNode, cascade : boolean = True) :
- if not cascade and not node.is_leaf() :
- raise BaseException("cannot delete only a node when it's not a leaf !")
- raise BaseException("Not implemented yet") #TODO
|