def __init__(self, monitor_id, wait_time, run_interval=False, custom_logger=None): """ Super constructor invoked from implementing sub-classes of this class providing interfaces start, track_success and track_error """ # set meta flags self.active = False self.finished = False self.started = False # store parameters self.monitor_id = monitor_id self.wait_time = wait_time self.run_interval = run_interval # init logger if custom_logger is not None: self.logger = custom_logger else: self.logger = Logger(self.__class__.__name__)
from flask import Flask from pbu import Logger from config import load_config, get_log_folder, is_debug, get_port import api.static_api as static_api # API endpoint modules from frappyflaskauth import register_endpoints as register_user_endpoints, check_login_state from frappyflaskdataset import register_endpoints as register_data_endpoints from frappyflaskcontent import register_endpoints as register_content_endpoints # storage modules from frappymongouser import UserStore, UserTokenStore from frappymongodataset import DataStore from frappymongocontent import ContentStore if __name__ == "__main__": logger = Logger("MAIN", log_folder=get_log_folder()) logger.info("==========================================") logger.info(" Starting application") logger.info("==========================================") # load config from .env file config = load_config() # ---- database and stores ---- # fetch mongo config from config import get_mongodb_config mongo_url, mongo_db = get_mongodb_config() # initialise stores stores = { "user":
from flask import Flask from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from config import load_config, get_log_folder, get_mysql_config from pbu import Logger from storage.shared import db from api.cli_commands import ComputeMetricsCommand # load config from .env file config = load_config() # ---- database and stores ---- host, db_name, username, password = get_mysql_config() uri = 'mysql://{0}:{1}@{2}/{3}'.format(username, password, host, db_name) app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = uri db.init_app(app) migrate = Migrate() migrate.init_app(app, db) manager = Manager(app) manager.add_command('db', MigrateCommand) manager.add_command('metrics', ComputeMetricsCommand) if __name__ == '__main__': logger = Logger("DB", log_folder=get_log_folder()) manager.run()
def check_login_state(permission=None, allow_api_key=False): """ Main function to be called from API endpoints to check if a user is logged in. This will extract the authorization token from the header, check it against the currently stored active sessions and handle any AuthenticationErrors that might occur by returning a 401 to the callee. If the request is authenticated, the associated user will be returned. :return: the authenticated user, if authentication was successful. :raise: AuthenticationError in case the login failed for whatever reason """ try: token = extract_token() if token is not None and token.startswith("Token "): # API key auth if allow_api_key is False: logger = Logger("user_api") logger.error( "API key access not allowed for the current endpoint.") abort(403) # not enabled for this endpoint # check api key if token[6:] not in api_key_cache: raise AuthenticationError( "Invalid authorization header") # api key not registered user = api_key_cache[token[6:]] else: # fetch user the regular way user = perform_login_check(token) if permission is None or permission in user.permissions: return user except AuthenticationError as ae: logger = Logger("user_api") logger.exception(ae) abort(401) raise ae logger = Logger("user_api") logger.error("User {} doesn't have required privileges: {}".format( user.username, permission)) abort(403) raise AuthenticationError("Insufficient privileges")
class BasicMonitor(ABC): """ Abstract base class (ABC) for all monitors containing base functionality for lifecycle and meta information. """ def __init__(self, monitor_id, wait_time, run_interval=False, custom_logger=None): """ Super constructor invoked from implementing sub-classes of this class providing interfaces start, track_success and track_error """ # set meta flags self.active = False self.finished = False self.started = False # store parameters self.monitor_id = monitor_id self.wait_time = wait_time self.run_interval = run_interval # init logger if custom_logger is not None: self.logger = custom_logger else: self.logger = Logger(self.__class__.__name__) @abstractmethod def running(self): """ Abstract main method of each inverter. `running` needs to be implemented by every non-abstract sub-class of this class. """ pass def to_json(self): """ Creates a dictionary with some base meta attributes about this monitor. Sub classes should invoke this method when serialising to json and then add any additional parameters as necessary to the result of this methods invoke. :return: a dictionary with basic information, such as site_id and overall active status """ return { "active": self.active, "started": self.started, "finished": self.finished, "id": self.monitor_id, "waitTime": self.wait_time, "runInterval": self.run_interval, } def wait(self, exec_duration=0): """ Executes a wait for a certain amount of time depending on the configuration of the monitor. Additionally, it takes into account the execution time of the last loop, if run_interval is True. :param exec_duration: the execution time of the last execution loop (only relevant for run_interval=True) """ if self.run_interval: time.sleep(max(1, self.wait_time - exec_duration)) else: time.sleep(self.wait_time) def wait_till_midnight(self): """ This method will just wait until the next midnight event. If the monitor is started at 6:30pm, this method will simply wait for 5h and 30min. """ # localise current date local_date = datetime.now() # extract time local_time = local_date.time() # compute wait time until midnight wait_time = ((23 - local_time.hour) * 60 * 60) + ( (59 - local_time.minute) * 60) + (60 - local_time.second) # wait till midnight self.logger.info( "Waiting {} seconds for monitor {} until midnight".format( wait_time, self.monitor_id)) time.sleep(wait_time) def start(self): """ Starts the monitor, updating a flag and triggering `running()` """ if self.active: # already started return # start monitor self.active = True try: if self.started: # only restart if the previous thread has finished or after error self.logger.info("Restarting monitor for {}".format( self.monitor_id)) self.running() else: # first time start self.started = True self.logger.info("Starting monitor for {}".format( self.monitor_id)) self.running() self.finished = True except BaseException as ex: self.logger.exception( "Exception during monitor execution for monitor {}: {}".format( self.monitor_id, str(ex))) # is currently not active due to error self.active = False # wait for one execution loop to avoid error spamming time.sleep(self.wait_time) self.start() def stop(self): """ Sets the active flag to false, which will terminate the `running()` loop. """ # set a flag, let the monitor handle this self.logger.info("Stopping {} for {}".format(self.__class__.__name__, self.monitor_id)) self.active = False
from flask import Flask, request, abort, jsonify from pbu import Logger, JSON from config import get_log_folder, get_port, get_auth_token, get_enabled_log_levels from logging import LogRecord def extract_auth_token(): key = "Authorization" if key in request.headers: return request.headers[key] return None if __name__ == '__main__': # initialise logger logger = Logger("MAIN", log_folder=get_log_folder(), enable_logger_name=True, enabled_log_levels=get_enabled_log_levels()) logger.info("==========================================") logger.info(" Starting Log Server") logger.info("==========================================") # create flask app app = Flask(__name__) # load from config, if required auth_token = get_auth_token() # declare API handler for incoming log messages @app.route("/api/log", methods=["POST"]) def log_message(): if auth_token is not None and auth_token != extract_auth_token(): logger.warn("Incoming request with invalid authentication")