def test_redirect_view(self): app = Flask(__name__) app.config['SECRET_KEY'] = 'foo' paranoid = Paranoid(app) paranoid.redirect_view = 'custom_redirect' @app.route('/') def index(): return 'foobar' @app.route('/redirect') def custom_redirect(): return 'foo' client = app.test_client(use_cookies=True) self.assertEqual(paranoid.redirect_view, 'custom_redirect') rv = client.get('/', headers={'User-Agent': 'foo'}) self.assertEqual(rv.status_code, 200) rv = client.get('/', headers={'User-Agent': 'bar'}) self.assertEqual(rv.status_code, 302) self.assertTrue(rv.headers['Location'].endswith('/redirect')) self.assertIn(self._delete_cookie('session'), rv.headers.getlist('Set-Cookie')) self.assertNotIn(self._delete_cookie('remember_token'), rv.headers.getlist('Set-Cookie'))
def init_app(app): """ Application extensions initialization. """ extensions = ( logging, cross_origin_resource_sharing, db, login_manager, marshmallow, api, oauth2, mail, edm, ) for extension in extensions: extension.init_app(app) # minify(app=app) paranoid = Paranoid(app) paranoid.redirect_view = '/' # Initialize Stripe payment stripe.api_key = app.config.get('STRIPE_SECRET_KEY')
def test_flask_login(self): app = Flask(__name__) app.config['SECRET_KEY'] = 'foo' paranoid = Paranoid(app) paranoid.redirect_view = 'https://foo.com/foobarbaz' @app.route('/') def index(): return 'foobar' client = app.test_client(use_cookies=True) sys.modules['flask_login'] = '******' self.assertEqual(paranoid.redirect_view, 'https://foo.com/foobarbaz') rv = client.get('/', headers={'User-Agent': 'foo'}) self.assertEqual(rv.status_code, 200) rv = client.get('/', headers={'User-Agent': 'bar'}) del sys.modules['flask_login'] self.assertEqual(rv.status_code, 302) self.assertEqual(rv.headers['Location'], 'https://foo.com/foobarbaz') self.assertIn(self._delete_cookie('session'), rv.headers.getlist('Set-Cookie')) self.assertIn(self._delete_cookie('remember_token', httponly=False), rv.headers.getlist('Set-Cookie'))
def init_app(app): """ Application extensions initialization. """ global _CONFIG_PATH_CHOICES _CONFIG_PATH_CHOICES = sorted(app.config.keys()) extensions = ( # The extensions in this block need to remain in this order for proper setup logging, sentry, db, api, config, # The remaining extensions oauth2, cross_origin_resource_sharing, login_manager, marshmallow, edm, submission, tus, mail, stripe, ) for extension in extensions: extension.init_app(app) # minify(app=app) paranoid = Paranoid(app) paranoid.redirect_view = '/'
def test_callback(self): app = Flask(__name__) app.config['SECRET_KEY'] = 'foo' paranoid = Paranoid() paranoid.init_app(app) paranoid.redirect_view = 'custom_redirect' @app.route('/') def index(): return 'foobar' @paranoid.on_invalid_session def custom_callback(): return 'foo' client = app.test_client(use_cookies=True) self.assertEqual(paranoid.redirect_view, custom_callback) rv = client.get('/', headers={'User-Agent': 'foo'}) self.assertEqual(rv.status_code, 200) rv = client.get('/', headers={'User-Agent': 'bar'}) self.assertEqual(rv.status_code, 200) self.assertEqual(rv.get_data(as_text=True), 'foo') self.assertIn(self._delete_cookie('session'), rv.headers.getlist('Set-Cookie')) self.assertNotIn(self._delete_cookie('remember_token'), rv.headers.getlist('Set-Cookie'))
def test_401(self): app = Flask(__name__) app.config['SECRET_KEY'] = 'foo' Paranoid(app) @app.route('/') def index(): return 'foobar' client = app.test_client(use_cookies=True) rv = client.get('/', headers={'User-Agent': 'foo'}) self.assertEqual(rv.status_code, 200) rv = client.get('/', headers={'User-Agent': 'foo'}) self.assertEqual(rv.status_code, 200) rv = client.get('/', headers={'User-Agent': 'bar'}) self.assertEqual(rv.status_code, 401) self.assertIn(self._delete_cookie('session'), rv.headers.getlist('Set-Cookie')) self.assertNotIn(self._delete_cookie('remember_token'), rv.headers.getlist('Set-Cookie'))
app.register_blueprint(userAPI.users_blueprint) Models.database.create_all() # a = Models.Admin.query.get(1) # try: # x = Models.Admin('Henry123','password123',96279135,'superuser') # Models.database.session.add(x) # Models.database.session.commit() # except: # Models.database.session.rollback() # print(Models.roles.query.filter_by(type='admin').first()) # s = Models.Admin.query.filter_by(username='******').first() # print(a.adminid) csrf = CSRFProtect(app) #session protection paranoid = Paranoid(app) paranoid.redirect_view = 'localhost:5000/register' db = mysql_connect.read_config_file() # session expiry, still need error emssage @app.before_request def before_request(): # print(psutil.net_io_counters()) session.permanent = True app.permanent_session_lifetime = datetime.timedelta(minutes=1) # session.modified = True g.user = current_user # @app.errorhandler(403)
def create_app(app_name=None): # Configuration settings import config if not app_name: app_name = config.APP_NAME # Only enable password related functionality in server mode. if config.SERVER_MODE is True: # Some times we need to access these config params where application # context is not available (we can't use current_app.config in those # cases even with current_app.app_context()) # So update these params in config itself. # And also these updated config values will picked up by application # since we are updating config before the application instance is # created. config.SECURITY_RECOVERABLE = True config.SECURITY_CHANGEABLE = True # Now we'll open change password page in alertify dialog # we don't want it to redirect to main page after password # change operation so we will open the same password change page again. config.SECURITY_POST_CHANGE_VIEW = 'browser.change_password' """Create the Flask application, startup logging and dynamically load additional modules (blueprints) that are found in this directory.""" app = PgAdmin(__name__, static_url_path='/static') # Removes unwanted whitespace from render_template function app.jinja_env.trim_blocks = True app.config.from_object(config) app.config.update(dict(PROPAGATE_EXCEPTIONS=True)) ########################################################################## # Setup logging and log the application startup ########################################################################## # Add SQL level logging, and set the base logging level logging.addLevelName(25, 'SQL') app.logger.setLevel(logging.DEBUG) app.logger.handlers = [] # We also need to update the handler on the webserver in order to see # request. Setting the level prevents werkzeug from setting up it's own # stream handler thus ensuring all the logging goes through the pgAdmin # logger. logger = logging.getLogger('werkzeug') logger.setLevel(logging.INFO) # Set SQLITE_PATH to TEST_SQLITE_PATH while running test cases if ( 'PGADMIN_TESTING_MODE' in os.environ and os.environ['PGADMIN_TESTING_MODE'] == '1' ): config.SQLITE_PATH = config.TEST_SQLITE_PATH # Ensure the various working directories exist from pgadmin.setup import create_app_data_directory, db_upgrade create_app_data_directory(config) # File logging fh = logging.FileHandler(config.LOG_FILE, encoding='utf-8') fh.setLevel(config.FILE_LOG_LEVEL) fh.setFormatter(logging.Formatter(config.FILE_LOG_FORMAT)) app.logger.addHandler(fh) logger.addHandler(fh) # Console logging ch = logging.StreamHandler() ch.setLevel(config.CONSOLE_LOG_LEVEL) ch.setFormatter(logging.Formatter(config.CONSOLE_LOG_FORMAT)) app.logger.addHandler(ch) logger.addHandler(ch) # Log the startup app.logger.info('########################################################') app.logger.info('Starting %s v%s...', config.APP_NAME, config.APP_VERSION) app.logger.info('########################################################') app.logger.debug("Python syspath: %s", sys.path) ########################################################################## # Setup i18n ########################################################################## # Initialise i18n babel = Babel(app) app.logger.debug('Available translations: %s' % babel.list_translations()) @babel.localeselector def get_locale(): """Get the language for the user.""" language = 'en' if config.SERVER_MODE is False: # Get the user language preference from the miscellaneous module if current_user.is_authenticated: user_id = current_user.id else: user = user_datastore.get_user(config.DESKTOP_USER) if user is not None: user_id = user.id user_language = Preferences.raw_value( 'miscellaneous', 'user_language', None, user_id ) if user_language is not None: language = user_language else: # If language is available in get request then return the same # otherwise check the session or cookie data = request.form if 'language' in data: language = data['language'] or language setattr(session, 'PGADMIN_LANGUAGE', language) elif hasattr(session, 'PGADMIN_LANGUAGE'): language = getattr(session, 'PGADMIN_LANGUAGE', language) elif hasattr(request.cookies, 'PGADMIN_LANGUAGE'): language = getattr( request.cookies, 'PGADMIN_LANGUAGE', language ) return language ########################################################################## # Setup authentication ########################################################################## app.config['SQLALCHEMY_DATABASE_URI'] = u'sqlite:///{0}?timeout={1}' \ .format(config.SQLITE_PATH.replace(u'\\', u'/'), getattr(config, 'SQLITE_TIMEOUT', 500) ) # Create database connection object and mailer db.init_app(app) ########################################################################## # Upgrade the schema (if required) ########################################################################## with app.app_context(): # Run migration for the first time i.e. create database from config import SQLITE_PATH if not os.path.exists(SQLITE_PATH): db_upgrade(app) else: version = Version.query.filter_by(name='ConfigDB').first() schema_version = version.value # Run migration if current schema version is greater than the # schema version stored in version table if CURRENT_SCHEMA_VERSION >= schema_version: db_upgrade(app) # Update schema version to the latest if CURRENT_SCHEMA_VERSION > schema_version: version = Version.query.filter_by(name='ConfigDB').first() version.value = CURRENT_SCHEMA_VERSION db.session.commit() Mail(app) import pgadmin.utils.paths as paths paths.init_app(app) # Setup Flask-Security user_datastore = SQLAlchemyUserDatastore(db, User, Role) security = Security(None, user_datastore) ########################################################################## # Setup security ########################################################################## with app.app_context(): config.CSRF_SESSION_KEY = Keys.query.filter_by( name='CSRF_SESSION_KEY').first().value config.SECRET_KEY = Keys.query.filter_by( name='SECRET_KEY').first().value config.SECURITY_PASSWORD_SALT = Keys.query.filter_by( name='SECURITY_PASSWORD_SALT').first().value # Update the app.config with proper security keyes for signing CSRF data, # signing cookies, and the SALT for hashing the passwords. app.config.update(dict({ 'CSRF_SESSION_KEY': config.CSRF_SESSION_KEY, 'SECRET_KEY': config.SECRET_KEY, 'SECURITY_PASSWORD_SALT': config.SECURITY_PASSWORD_SALT, 'SESSION_COOKIE_DOMAIN': config.SESSION_COOKIE_DOMAIN })) security.init_app(app, user_datastore) # register custom unauthorised handler. app.login_manager.unauthorized_handler(pga_unauthorised) app.session_interface = create_session_interface(app) # Make the Session more secure against XSS & CSRF when running in web mode if config.SERVER_MODE: paranoid = Paranoid(app) paranoid.redirect_view = 'browser.index' ########################################################################## # Load all available server drivers ########################################################################## driver.init_app(app) ########################################################################## # Register language to the preferences after login ########################################################################## @user_logged_in.connect_via(app) def register_language(sender, user): # After logged in, set the language in the preferences if we get from # the login page data = request.form if 'language' in data: language = data['language'] # Set the user language preference misc_preference = Preferences.module('miscellaneous') user_languages = misc_preference.preference( 'user_language' ) if user_languages and language: language = user_languages.set(language) ########################################################################## # Register any local servers we can discover ########################################################################## @user_logged_in.connect_via(app) def on_user_logged_in(sender, user): # Keep hold of the user ID user_id = user.id # Get the first server group for the user servergroup_id = 1 servergroups = ServerGroup.query.filter_by( user_id=user_id ).order_by("id") if servergroups.count() > 0: servergroup = servergroups.first() servergroup_id = servergroup.id '''Add a server to the config database''' def add_server(user_id, servergroup_id, name, superuser, port, discovery_id, comment): # Create a server object if needed, and store it. servers = Server.query.filter_by( user_id=user_id, discovery_id=svr_discovery_id ).order_by("id") if servers.count() > 0: return svr = Server(user_id=user_id, servergroup_id=servergroup_id, name=name, host='localhost', port=port, maintenance_db='postgres', username=superuser, ssl_mode='prefer', comment=svr_comment, discovery_id=discovery_id) db.session.add(svr) db.session.commit() # Figure out what servers are present if winreg is not None: arch_keys = set() proc_arch = os.environ['PROCESSOR_ARCHITECTURE'].lower() try: proc_arch64 = os.environ['PROCESSOR_ARCHITEW6432'].lower() except Exception as e: proc_arch64 = None if proc_arch == 'x86' and not proc_arch64: arch_keys.add(0) elif proc_arch == 'x86' or proc_arch == 'amd64': arch_keys.add(winreg.KEY_WOW64_32KEY) arch_keys.add(winreg.KEY_WOW64_64KEY) for arch_key in arch_keys: for server_type in ('PostgreSQL', 'EnterpriseDB'): try: root_key = winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\" + server_type + "\Services", 0, winreg.KEY_READ | arch_key ) for i in xrange(0, winreg.QueryInfoKey(root_key)[0]): inst_id = winreg.EnumKey(root_key, i) inst_key = winreg.OpenKey(root_key, inst_id) svr_name = winreg.QueryValueEx( inst_key, 'Display Name' )[0] svr_superuser = winreg.QueryValueEx( inst_key, 'Database Superuser' )[0] svr_port = winreg.QueryValueEx(inst_key, 'Port')[0] svr_discovery_id = inst_id svr_comment = gettext( "Auto-detected %s installation with the data " "directory at %s" % ( winreg.QueryValueEx( inst_key, 'Display Name' )[0], winreg.QueryValueEx( inst_key, 'Data Directory' )[0] ) ) add_server( user_id, servergroup_id, svr_name, svr_superuser, svr_port, svr_discovery_id, svr_comment ) inst_key.Close() except Exception as e: pass else: # We use the postgres-winreg.ini file on non-Windows try: from configparser import ConfigParser except ImportError: from ConfigParser import ConfigParser # Python 2 registry = ConfigParser() try: registry.read('/etc/postgres-reg.ini') sections = registry.sections() # Loop the sections, and get the data from any that are PG or PPAS for section in sections: if ( section.startswith('PostgreSQL/') or section.startswith('EnterpriseDB/') ): svr_name = registry.get(section, 'Description') svr_superuser = registry.get(section, 'Superuser') svr_port = registry.getint(section, 'Port') svr_discovery_id = section description = registry.get(section, 'Description') data_directory = registry.get(section, 'DataDirectory') if hasattr(str, 'decode'): description = description.decode('utf-8') data_directory = data_directory.decode('utf-8') svr_comment = gettext(u"Auto-detected %s installation " u"with the data directory at %s" % ( description, data_directory ) ) add_server(user_id, servergroup_id, svr_name, svr_superuser, svr_port, svr_discovery_id, svr_comment) except Exception as e: pass @user_logged_in.connect_via(app) @user_logged_out.connect_via(app) def force_session_write(app, user): session.force_write = True ########################################################################## # Load plugin modules ########################################################################## for module in app.find_submodules('pgadmin'): app.logger.info('Registering blueprint module: %s' % module) app.register_blueprint(module) ########################################################################## # Handle the desktop login ########################################################################## @app.before_request def before_request(): """Login the default user if running in desktop mode""" # Check the auth key is valid, if it's set, and we're not in server # mode, and it's not a help file request. if not config.SERVER_MODE and app.PGADMIN_KEY != '': if ( ('key' not in request.args or request.args['key'] != app.PGADMIN_KEY) and request.cookies.get('PGADMIN_KEY') != app.PGADMIN_KEY and request.endpoint != 'help.static' ): abort(401) if not config.SERVER_MODE and not current_user.is_authenticated: user = user_datastore.get_user(config.DESKTOP_USER) # Throw an error if we failed to find the desktop user, to give # the sysadmin a hint. We'll continue to try to login anyway as # that'll through a nice 500 error for us. if user is None: app.logger.error( 'The desktop user %s was not found in the configuration ' 'database.' % config.DESKTOP_USER ) abort(401) login_user(user) @app.after_request def after_request(response): if 'key' in request.args: domain = dict() if config.COOKIE_DEFAULT_DOMAIN and \ config.COOKIE_DEFAULT_DOMAIN != 'localhost': domain['domain'] = config.COOKIE_DEFAULT_DOMAIN response.set_cookie('PGADMIN_KEY', value=request.args['key'], path=config.COOKIE_DEFAULT_PATH, **domain) return response ########################################################################## # Minify output ########################################################################## # HTMLMIN doesn't work with Python 2.6. if not config.DEBUG and sys.version_info >= (2, 7): from flask_htmlmin import HTMLMIN HTMLMIN(app) @app.context_processor def inject_blueprint(): """Inject a reference to the current blueprint, if any.""" return { 'current_app': current_app, 'current_blueprint': current_blueprint } ########################################################################## # All done! ########################################################################## return app
# try: # x = AdminModels.Admin('testUser', 'password123', 96279135) # AdminModels.database.session.add(x) # AdminModels.database.session.commit() # except: # AdminModels.database.session.rollback() # csp = { # 'default-src': ['\'self\'','https://fonts.googleapis.com/css'], # 'img-src': '\'self\' data:', # 'style-src': '\'unsafe-inline\' \'self\'', # 'script-src': '\'self\' \'unsafe-inline\'' # # } # talisman = Talisman(app) paranoid = Paranoid(app) paranoid.redirect_view = 'https://google.com' @app.before_request def before_request(): if current_user.is_authenticated: last_login = session['last_login'] time = datetime.datetime.now() - last_login print(time.seconds) if time.seconds > 900: # 30minutes logout_user() session.clear() resp = make_response(redirect(url_for('login'))) if resp.headers['Location'] == '/': return resp
def create_app(): app = Flask(__name__) app.config['SECRET_KEY'] = 'top-secret!' csrf.init_app(app) login_manager = LoginManager(app) @login_manager.user_loader def load_user(id): return User(id) login_manager.session_protection = 'strong' paranoid = Paranoid(app) paranoid.redirect_view = '/login' @paranoid.on_invalid_session def invalid_session(): return 'Please login', 401 # http://localhost:5000/login - this will be the login page, we need to use both GET and POST requests @app.route('/login', methods=['GET', 'POST']) def login(): # Output message if something goes wrong... msg = '' # Check if 'username' and 'password' POST requests exist (user submitted form) if request.method == 'POST' and 'username' in request.form and 'password' in request.form and 'two_factor_auth' in request.form: # Create variables for easy access username = request.form['username'] password = request.form['password'] hashedPassword = hashlib.md5(password.encode('utf-8')).hexdigest() two_factor_auth = request.form['two_factor_auth'] # Check if account exists using dict account = {} if username in accounts and accounts[username][ 'password'] == hashedPassword: if accounts[username]['two_factor_auth'] == two_factor_auth: # Fetch one record from dict and return result account['username'] = username account['password'] = hashedPassword account['two_factor_auth'] = two_factor_auth # Account exists in accounts dict in out database # Create session data, we can access this data in other routes session['logged_in'] = True login_user(User(username)) msg = 'Success!' else: msg = 'Failure: Incorrect two-factor authentication' else: # Account doesnt exist or username/password incorrect msg = 'Failure: Incorrect username or password' return render_template('index.html', msg=msg) # http://localhost:5000/register - this will be the registration page, we need to use both GET and POST requests @app.route('/register', methods=['GET', 'POST']) def register(): # Output message if something goes wrong... msg = '' # Check if 'username' and 'password' POST requests exist (user submitted form) if request.method == 'POST' and 'username' in request.form and 'password' in request.form and 'two_factor_auth' in request.form: # Create variables for easy access username = request.form['username'] password = request.form['password'] hashedPassword = hashlib.md5(password.encode('utf-8')).hexdigest() two_factor_auth = request.form['two_factor_auth'] # Check if account exists using dict account = {} if username in accounts: if accounts[username][ 'password'] == hashedPassword and accounts[username][ 'two_factor_auth'] == two_factor_auth: # Fetch one record from dict and return result account['username'] = username account['password'] = hashedPassword account['two_factor_auth'] = two_factor_auth # If account exists in accounts dict in out database if bool(account): msg = 'Failure: Account already exists!' elif not re.match(r'[A-Za-z0-9]+', username): msg = 'Failure: Username must contain only characters and numbers!' elif not re.match(r'[0-9]+', two_factor_auth): msg = 'Failure: Enter phone number for 2fa' elif not username or not password: msg = 'Failure: Please fill out the form!' else: # Account doesn't exists and the form data is valid, now insert new account into dict # Hash password hashedPassword = hashlib.md5( password.encode('utf-8')).hexdigest() accounts[username] = { 'password': hashedPassword, 'two_factor_auth': two_factor_auth } msg = 'Success!' elif request.method == 'POST': # Form is empty... (no POST data) msg = 'Failure: Please fill out the form!' # Show registration form with message (if any) return render_template('register.html', msg=msg) # http://localhost:5000/spell_check - this will be the home page, only accessible for loggedin users @app.route('/spell_check', methods=['GET', 'POST']) def spell_check(): msg = '' inputtext = '' # Check if user is loggedin if 'logged_in' in session: if request.method == 'POST' and 'inputtext' in request.form: inputtext = request.form['inputtext'] # Put inputtext into file f = open('input.txt', 'w') f.write(inputtext) f.close() output = subprocess.getoutput( './spell_check input.txt wordlist.txt') msg = ', '.join(output.split()) # User is loggedin show them the home page return render_template('spell_check.html', msg=msg, output=inputtext) # User is not loggedin redirect to login page return redirect(url_for('login')) return app
return anonymous_token # Initiate LoginManager object login_manager = LoginManager(application) login_manager.anonymous_user = AnonymousUser login_manager.session_protection = 'strong' # Import and register blueprint modules # (prevent circular imports) for module_name, url_prefix in BLUEPRINTS_NAME_WITH_URL_PREFIX: module = importlib.import_module('blueprints.%s' % module_name) application.register_blueprint(module.blueprint, url_prefix=url_prefix) # Initiate Paranoid object paranoid = Paranoid(application) paranoid.redirect_view = BLUEPRINTS_ROOT_HANDLER # Import UserStore from models from models import UserStore @login_manager.user_loader def load_user(user_id): """ Return SignedInUser object linked to User entity by uid. """ return SignedInUser(UserStore.read(user_id)) # Initiate SocketIO object
app.config.from_object(ProductionConfig) else: print("Unkown configuration name") raise db = SQLAlchemy(app) migrate = Migrate(app, db) login = LoginManager(app) login.login_view = "auth.login" admin_app = Admin( app, name="Flask quickstart", template_mode="bootstrap3", base_template="admin/my_base.html", ) mail = Mail(app) paranoid = Paranoid(app) paranoid.redirect_view = "main.index" # blog related pagedown = PageDown(app) markdown = Markdown(app) # upload related images = UploadSet("images", IMAGES) documents = UploadSet("documents", DOCUMENTS) configure_uploads(app, (images, documents)) patch_request_class(app, 16 * 1024 * 1024) from app.auth import auth_blueprint app.register_blueprint(auth_blueprint, url_prefix="/auth")
def create_app(test_config=None): app = Flask(__name__, static_folder='static') if test_config is None: # load the instance config, if it exists, when not testing app.config.from_pyfile('sql/md.cfg', silent=False) else: # load the test config if passed in app.config.from_mapping(test_config) # Initiate database connection pool params = configuration.mdconfig() pool_params = configuration.mdconfig(section='psycopg2') app.config['POSTGRESQL_POOL'] = pool.ThreadedConnectionPool( pool_params['min_pool_conn'], pool_params['max_pool_conn'], user=params['user'], password=params['password'], host=params['host'], port=params['port'], database=params['database']) mail.init_app(app) csrf.init_app(app) paranoid = Paranoid(app) paranoid.redirect_view = 'md.index' # cors # for swaggerUI # https://idratherbewriting.com/learnapidoc/pubapis_swagger.html CORS(app, resources={r"/api/*": {"origins": "*"}}) # errors app.register_error_handler(403, forbidden_error) app.register_error_handler(404, not_found_error) app.register_error_handler(500, internal_error) app.register_error_handler(405, not_allowed_error) app.register_error_handler(413, reques_entity_too_large_error) # define custom jinja filters app.jinja_env.filters['match'] = configuration.match app.jinja_env.filters['match_multiline'] = configuration.match_multiline # ensure the instance folder exists try: os.makedirs(app.instance_path) except OSError: pass from . import db db.init_app(app) from . import auth app.register_blueprint(auth.bp) from . import md app.register_blueprint(md.bp) from . import ajax app.register_blueprint(ajax.bp) from . import api csrf.exempt(api.bp) app.register_blueprint(api.bp) from . import static_route app.register_blueprint(static_route.bp) from . import upload app.register_blueprint(upload.bp) # from . import error # app.register_blueprint(error.bp) app.add_url_rule('/', endpoint='index') if app.debug: print(app.config) return app
def create_app(app_name=None): # Configuration settings import config if not app_name: app_name = config.APP_NAME """Create the Flask application, startup logging and dynamically load additional modules (blueprints) that are found in this directory.""" app = PgAdmin(__name__, static_url_path='/static') # Removes unwanted whitespace from render_template function app.jinja_env.trim_blocks = True app.config.from_object(config) app.config.update(dict(PROPAGATE_EXCEPTIONS=True)) ########################################################################## # Setup logging and log the application startup ########################################################################## # Add SQL level logging, and set the base logging level logging.addLevelName(25, 'SQL') app.logger.setLevel(logging.DEBUG) app.logger.handlers = [] # We also need to update the handler on the webserver in order to see # request. Setting the level prevents werkzeug from setting up it's own # stream handler thus ensuring all the logging goes through the pgAdmin # logger. logger = logging.getLogger('werkzeug') logger.setLevel(logging.INFO) # Set SQLITE_PATH to TEST_SQLITE_PATH while running test cases if "PGADMIN_TESTING_MODE" in os. environ and \ os.environ["PGADMIN_TESTING_MODE"] == "1": config.SQLITE_PATH = config.TEST_SQLITE_PATH # Ensure the various working directories exist from pgadmin.setup import create_app_data_directory, db_upgrade create_app_data_directory(config) # File logging fh = logging.FileHandler(config.LOG_FILE, encoding='utf-8') fh.setLevel(config.FILE_LOG_LEVEL) fh.setFormatter(logging.Formatter(config.FILE_LOG_FORMAT)) app.logger.addHandler(fh) logger.addHandler(fh) # Console logging ch = logging.StreamHandler() ch.setLevel(config.CONSOLE_LOG_LEVEL) ch.setFormatter(logging.Formatter(config.CONSOLE_LOG_FORMAT)) app.logger.addHandler(ch) logger.addHandler(ch) # Log the startup app.logger.info('########################################################') app.logger.info('Starting %s v%s...', config.APP_NAME, config.APP_VERSION) app.logger.info('########################################################') app.logger.debug("Python syspath: %s", sys.path) ########################################################################## # Setup i18n ########################################################################## # Initialise i18n babel = Babel(app) app.logger.debug('Available translations: %s' % babel.list_translations()) @babel.localeselector def get_locale(): """Get the language for the user.""" language = 'en' if config.SERVER_MODE is False: # Get the user language preference from the miscellaneous module misc_preference = Preferences.module('miscellaneous', False) if misc_preference: user_languages = misc_preference.preference('user_language') if user_languages: language = user_languages.get() or language else: # If language is available in get request then return the same # otherwise check the session or cookie data = request.form if 'language' in data: language = data['language'] or language setattr(session, 'PGADMIN_LANGUAGE', language) elif hasattr(session, 'PGADMIN_LANGUAGE'): language = getattr(session, 'PGADMIN_LANGUAGE', language) elif hasattr(request.cookies, 'PGADMIN_LANGUAGE'): language = getattr(request.cookies, 'PGADMIN_LANGUAGE', language) return language ########################################################################## # Setup authentication ########################################################################## app.config[ 'SQLALCHEMY_DATABASE_URI'] = u'sqlite:///{0}?timeout={1}'.format( config.SQLITE_PATH.replace(u'\\', u'/'), getattr(config, 'SQLITE_TIMEOUT', 500)) # Only enable password related functionality in server mode. if config.SERVER_MODE is True: # TODO: Figure out how to disable /logout and /login app.config['SECURITY_RECOVERABLE'] = True app.config['SECURITY_CHANGEABLE'] = True # Create database connection object and mailer db.init_app(app) ########################################################################## # Upgrade the schema (if required) ########################################################################## db_upgrade(app) Mail(app) import pgadmin.utils.paths as paths paths.init_app(app) # Setup Flask-Security user_datastore = SQLAlchemyUserDatastore(db, User, Role) security = Security(None, user_datastore) ########################################################################## # Setup security ########################################################################## with app.app_context(): config.CSRF_SESSION_KEY = Keys.query.filter_by( name='CSRF_SESSION_KEY').first().value config.SECRET_KEY = Keys.query.filter_by( name='SECRET_KEY').first().value config.SECURITY_PASSWORD_SALT = Keys.query.filter_by( name='SECURITY_PASSWORD_SALT').first().value # Update the app.config with proper security keyes for signing CSRF data, # signing cookies, and the SALT for hashing the passwords. app.config.update(dict(CSRF_SESSION_KEY=config.CSRF_SESSION_KEY)) app.config.update(dict(SECRET_KEY=config.SECRET_KEY)) app.config.update( dict(SECURITY_PASSWORD_SALT=config.SECURITY_PASSWORD_SALT)) security.init_app(app) app.session_interface = create_session_interface(app) # Make the Session more secure against XSS & CSRF when running in web mode if config.SERVER_MODE: paranoid = Paranoid(app) paranoid.redirect_view = 'browser.index' ########################################################################## # Load all available server drivers ########################################################################## driver.init_app(app) ########################################################################## # Register language to the preferences after login ########################################################################## @user_logged_in.connect_via(app) def register_language(sender, user): # After logged in, set the language in the preferences if we get from # the login page data = request.form if 'language' in data: language = data['language'] # Set the user language preference misc_preference = Preferences.module('miscellaneous') user_languages = misc_preference.preference('user_language') if user_languages and language: language = user_languages.set(language) ########################################################################## # Register any local servers we can discover ########################################################################## @user_logged_in.connect_via(app) def on_user_logged_in(sender, user): # Keep hold of the user ID user_id = user.id # Get the first server group for the user servergroup_id = 1 servergroups = ServerGroup.query.filter_by( user_id=user_id).order_by("id") if servergroups.count() > 0: servergroup = servergroups.first() servergroup_id = servergroup.id '''Add a server to the config database''' def add_server(user_id, servergroup_id, name, superuser, port, discovery_id, comment): # Create a server object if needed, and store it. servers = Server.query.filter_by( user_id=user_id, discovery_id=svr_discovery_id).order_by("id") if servers.count() > 0: return svr = Server(user_id=user_id, servergroup_id=servergroup_id, name=name, host='localhost', port=port, maintenance_db='postgres', username=superuser, ssl_mode='prefer', comment=svr_comment, discovery_id=discovery_id) db.session.add(svr) db.session.commit() # Figure out what servers are present if winreg is not None: arch_keys = set() proc_arch = os.environ['PROCESSOR_ARCHITECTURE'].lower() try: proc_arch64 = os.environ['PROCESSOR_ARCHITEW6432'].lower() except: proc_arch64 = None if proc_arch == 'x86' and not proc_arch64: arch_keys.add(0) elif proc_arch == 'x86' or proc_arch == 'amd64': arch_keys.add(winreg.KEY_WOW64_32KEY) arch_keys.add(winreg.KEY_WOW64_64KEY) for arch_key in arch_keys: for server_type in ('PostgreSQL', 'EnterpriseDB'): try: root_key = winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\" + server_type + "\Services", 0, winreg.KEY_READ | arch_key) for i in xrange(0, winreg.QueryInfoKey(root_key)[0]): inst_id = winreg.EnumKey(root_key, i) inst_key = winreg.OpenKey(root_key, inst_id) svr_name = winreg.QueryValueEx( inst_key, 'Display Name')[0] svr_superuser = winreg.QueryValueEx( inst_key, 'Database Superuser')[0] svr_port = winreg.QueryValueEx(inst_key, 'Port')[0] svr_discovery_id = inst_id svr_comment = gettext( "Auto-detected %s installation with the data directory at %s" % (winreg.QueryValueEx(inst_key, 'Display Name')[0], winreg.QueryValueEx(inst_key, 'Data Directory')[0])) add_server(user_id, servergroup_id, svr_name, svr_superuser, svr_port, svr_discovery_id, svr_comment) inst_key.Close() except: pass else: # We use the postgres-winreg.ini file on non-Windows try: from configparser import ConfigParser except ImportError: from ConfigParser import ConfigParser # Python 2 registry = ConfigParser() try: registry.read('/etc/postgres-reg.ini') sections = registry.sections() # Loop the sections, and get the data from any that are PG or PPAS for section in sections: if section.startswith('PostgreSQL/') or section.startswith( 'EnterpriseDB/'): svr_name = registry.get(section, 'Description') svr_superuser = registry.get(section, 'Superuser') svr_port = registry.getint(section, 'Port') svr_discovery_id = section description = registry.get(section, 'Description') data_directory = registry.get(section, 'DataDirectory') if hasattr(str, 'decode'): description = description.decode('utf-8') data_directory = data_directory.decode('utf-8') svr_comment = gettext( u"Auto-detected %s installation with the data directory at %s" % (description, data_directory)) add_server(user_id, servergroup_id, svr_name, svr_superuser, svr_port, svr_discovery_id, svr_comment) except: pass ########################################################################## # Load plugin modules ########################################################################## for module in app.find_submodules('pgadmin'): app.logger.info('Registering blueprint module: %s' % module) app.register_blueprint(module) ########################################################################## # Handle the desktop login ########################################################################## @app.before_request def before_request(): """Login the default user if running in desktop mode""" # Check the auth key is valid, if it's set, and we're not in server # mode, and it's not a help file request. if not config.SERVER_MODE and app.PGADMIN_KEY != '': if ((not 'key' in request.args or request.args['key'] != app.PGADMIN_KEY) and request.cookies.get('PGADMIN_KEY') != app.PGADMIN_KEY and request.endpoint != 'help.static'): abort(401) if not config.SERVER_MODE: user = user_datastore.get_user(config.DESKTOP_USER) # Throw an error if we failed to find the desktop user, to give # the sysadmin a hint. We'll continue to try to login anyway as # that'll through a nice 500 error for us. if user is None: app.logger.error( 'The desktop user %s was not found in the configuration database.' % config.DESKTOP_USER) abort(401) login_user(user) @app.after_request def after_request(response): if 'key' in request.args: response.set_cookie('PGADMIN_KEY', value=request.args['key']) return response ########################################################################## # Minify output ########################################################################## # HTMLMIN doesn't work with Python 2.6. if not config.DEBUG and sys.version_info >= (2, 7): HTMLMIN(app) @app.context_processor def inject_blueprint(): """Inject a reference to the current blueprint, if any.""" return { 'current_app': current_app, 'current_blueprint': current_blueprint } ########################################################################## # All done! ########################################################################## return app
from flask import Flask from config import Config from flask_sqlalchemy import SQLAlchemy from flask_bcrypt import Bcrypt from flask_paranoid import Paranoid import pymysql from werkzeug.utils import secure_filename from flask_mail import Mail, Message pymysql.install_as_MySQLdb() S2T = Flask(__name__) S2T.debug = True paranoid = Paranoid(S2T) paranoid.redirect_view = '/' S2T.config.from_object(Config) db = SQLAlchemy(S2T) bcrypt = Bcrypt(S2T) '''Change when in production''' #S2T.config['SERVER_NAME'] = '127.0.0.1:5000' S2T.config['SERVER_NAME'] = 'sohjunqi.pythonanywhere.com' '''Temp folder for conversions''' S2T.config['TEMP_FOLDER'] = 'tran_temp' '''Storage folder''' S2T.config['STORAGE_FOLDER'] = 'transcripts' ''''Profile pictures folder''' S2T.config['PROFILE_FOLDER'] = 'profiles'
from flask_login import LoginManager from flask_paranoid import Paranoid from typing import Callable from TexDBook.src.python.core.init_app import app, default_init_app from TexDBook.src.python.util.flask.flask_utils_types import JsonOrMessage from TexDBook.src.python.util.flask.rest_api import json, rest_api from TexDBook.src.python.util.oop import override from TexDBook.src.python.util.password import sha256 init_app = default_init_app login_manager = LoginManager() # type: LoginManager login_manager.init_app(app) paranoid = Paranoid() # type: Paranoid paranoid.init_app(app) # @override(Paranoid) # def write_token_to_session(_super, self, token): # print("writing token: " + token) # print(paranoid.create_token()) # print(paranoid.get_token_from_session()) # print(request.headers.get("User-Agent")) # print(request.headers.get("X-Forwarded-For")) # print(request.remote_addr) # return _super(self, token) @override(Paranoid) def create_token(_super, self):
from waitress import serve # Local modules from app import _create_app from app.db.firebase import CrudDB, Authentication # Utilities from werkzeug.exceptions import HTTPException # Handler errors web import requests import uuid import random import pdb # Creation of the application IMPORTANT app = _create_app() paranoid = Paranoid(app) # Session hash @app.route('/', methods=['GET', 'POST']) @paranoid.on_invalid_session def index(): """ Funtion manager to show the home of the app """ if not session.get('user_session'): flash('Please log in first!') return redirect(url_for('login'))
def create_app(config_class=Config): app = Flask(__name__) app.config.from_object(config_class) db.init_app(app) migrate.init_app(app, db) login.init_app(app) mail.init_app(app) bootstrap.init_app(app) moment.init_app(app) babel.init_app(app) cache.init_app(app) app.redis = Redis.from_url(app.config['REDIS_URL']) app.task_queue = rq.Queue('syncboom-tasks', connection=app.redis) paranoid = Paranoid(app) paranoid.redirect_view = '/' app.before_request(app_before_request) from app.errors import bp as errors_bp app.register_blueprint(errors_bp) from app.auth import bp as auth_bp app.register_blueprint(auth_bp, url_prefix='/auth') from app.main import bp as main_bp app.register_blueprint(main_bp) from app.mapping import bp as mapping_bp app.register_blueprint(mapping_bp, url_prefix='/mapping') if not app.debug and not app.testing: if app.config['MAIL_SERVER']: auth = None if app.config['MAIL_USERNAME'] or app.config['MAIL_PASSWORD']: auth = (app.config['MAIL_USERNAME'], app.config['MAIL_PASSWORD']) secure = None if app.config['MAIL_USE_TLS']: secure = () mail_handler = SMTPHandler( mailhost=(app.config['MAIL_SERVER'], app.config['MAIL_PORT']), fromaddr='no-reply@' + app.config['MAIL_SERVER'], toaddrs=app.config['ADMINS'], subject='[SyncBoom] Failure', credentials=auth, secure=secure) mail_handler.setLevel(logging.ERROR) app.logger.addHandler(mail_handler) if app.config['LOG_TO_STDOUT']: stream_handler = logging.StreamHandler() stream_handler.setLevel(logging.INFO) app.logger.addHandler(stream_handler) else: if not os.path.exists('logs'): os.mkdir('logs') file_handler = RotatingFileHandler('logs/syncboom.log', maxBytes=10240, backupCount=10) file_handler.setFormatter( logging.Formatter('%(asctime)s %(levelname)s: %(message)s ' '[in %(pathname)s:%(lineno)d]')) file_handler.setLevel(logging.INFO) app.logger.addHandler(file_handler) app.logger.setLevel(logging.INFO) # Serve local Bootstrap files when in debug mode app.config["BOOTSTRAP_SERVE_LOCAL"] = app.debug @app.after_request def set_secure_headers(response): secure_headers.flask(response) return response return app
import os from flask_cors import CORS from flask_restful import Api from flask import Flask from flask_security import (Security, SQLAlchemyUserDatastore) from flask_paranoid import Paranoid app = Flask(__name__) CORS(app) paranoid = Paranoid(app) paranoid.redirect_view = '/' app_settings = os.getenv('APP_SETTINGS', 'config.DevelopmentConfig') travis = os.getenv('TRAVIS', None) if travis: app_settings = 'config-sample.TestingConfig' app.config.from_object(app_settings) from database import (db) from classes.user.model import (User, Role) from classes.user.forms import (UserRegisterForm, UserLoginForm) #from classes.upload.hive_data import (HiveData) api = Api(app) #hive_data = HiveData(influxDB) if not app.debug and not app.testing and not app.config['SSL_DISABLE']:
def create_app(app_name=None): # Configuration settings import config if not app_name: app_name = config.APP_NAME # Only enable password related functionality in server mode. if config.SERVER_MODE is True: # Some times we need to access these config params where application # context is not available (we can't use current_app.config in those # cases even with current_app.app_context()) # So update these params in config itself. # And also these updated config values will picked up by application # since we are updating config before the application instance is # created. config.SECURITY_RECOVERABLE = True config.SECURITY_CHANGEABLE = True # Now we'll open change password page in alertify dialog # we don't want it to redirect to main page after password # change operation so we will open the same password change page again. config.SECURITY_POST_CHANGE_VIEW = 'browser.change_password' """Create the Flask application, startup logging and dynamically load additional modules (blueprints) that are found in this directory.""" app = PgAdmin(__name__, static_url_path='/static') # Removes unwanted whitespace from render_template function app.jinja_env.trim_blocks = True app.config.from_object(config) app.config.update(dict(PROPAGATE_EXCEPTIONS=True)) ########################################################################## # Setup logging and log the application startup ########################################################################## # Add SQL level logging, and set the base logging level logging.addLevelName(25, 'SQL') app.logger.setLevel(logging.DEBUG) app.logger.handlers = [] # We also need to update the handler on the webserver in order to see # request. Setting the level prevents werkzeug from setting up it's own # stream handler thus ensuring all the logging goes through the pgAdmin # logger. logger = logging.getLogger('werkzeug') logger.setLevel(logging.INFO) # Set SQLITE_PATH to TEST_SQLITE_PATH while running test cases if ( 'PGADMIN_TESTING_MODE' in os.environ and os.environ['PGADMIN_TESTING_MODE'] == '1' ): config.SQLITE_PATH = config.TEST_SQLITE_PATH # Ensure the various working directories exist from pgadmin.setup import create_app_data_directory, db_upgrade create_app_data_directory(config) # File logging fh = logging.FileHandler(config.LOG_FILE, encoding='utf-8') fh.setLevel(config.FILE_LOG_LEVEL) fh.setFormatter(logging.Formatter(config.FILE_LOG_FORMAT)) app.logger.addHandler(fh) logger.addHandler(fh) # Console logging ch = logging.StreamHandler() ch.setLevel(config.CONSOLE_LOG_LEVEL) ch.setFormatter(logging.Formatter(config.CONSOLE_LOG_FORMAT)) app.logger.addHandler(ch) logger.addHandler(ch) # Log the startup app.logger.info('########################################################') app.logger.info('Starting %s v%s...', config.APP_NAME, config.APP_VERSION) app.logger.info('########################################################') app.logger.debug("Python syspath: %s", sys.path) ########################################################################## # Setup i18n ########################################################################## # Initialise i18n babel = Babel(app) app.logger.debug('Available translations: %s' % babel.list_translations()) @babel.localeselector def get_locale(): """Get the language for the user.""" language = 'en' if config.SERVER_MODE is False: # Get the user language preference from the miscellaneous module if current_user.is_authenticated: user_id = current_user.id else: user = user_datastore.get_user(config.DESKTOP_USER) if user is not None: user_id = user.id user_language = Preferences.raw_value( 'miscellaneous', 'user_language', None, user_id ) if user_language is not None: language = user_language else: # If language is available in get request then return the same # otherwise check the session or cookie data = request.form if 'language' in data: language = data['language'] or language setattr(session, 'PGADMIN_LANGUAGE', language) elif hasattr(session, 'PGADMIN_LANGUAGE'): language = getattr(session, 'PGADMIN_LANGUAGE', language) elif hasattr(request.cookies, 'PGADMIN_LANGUAGE'): language = getattr( request.cookies, 'PGADMIN_LANGUAGE', language ) return language ########################################################################## # Setup authentication ########################################################################## app.config['SQLALCHEMY_DATABASE_URI'] = u'sqlite:///{0}?timeout={1}' \ .format(config.SQLITE_PATH.replace(u'\\', u'/'), getattr(config, 'SQLITE_TIMEOUT', 500) ) # Create database connection object and mailer db.init_app(app) ########################################################################## # Upgrade the schema (if required) ########################################################################## with app.app_context(): # Run migration for the first time i.e. create database from config import SQLITE_PATH if not os.path.exists(SQLITE_PATH): db_upgrade(app) else: version = Version.query.filter_by(name='ConfigDB').first() schema_version = version.value # Run migration if current schema version is greater than the # schema version stored in version table if CURRENT_SCHEMA_VERSION >= schema_version: db_upgrade(app) # Update schema version to the latest if CURRENT_SCHEMA_VERSION > schema_version: version = Version.query.filter_by(name='ConfigDB').first() version.value = CURRENT_SCHEMA_VERSION db.session.commit() Mail(app) import pgadmin.utils.paths as paths paths.init_app(app) # Setup Flask-Security user_datastore = SQLAlchemyUserDatastore(db, User, Role) security = Security(None, user_datastore) ########################################################################## # Setup security ########################################################################## with app.app_context(): config.CSRF_SESSION_KEY = Keys.query.filter_by( name='CSRF_SESSION_KEY').first().value config.SECRET_KEY = Keys.query.filter_by( name='SECRET_KEY').first().value config.SECURITY_PASSWORD_SALT = Keys.query.filter_by( name='SECURITY_PASSWORD_SALT').first().value # Update the app.config with proper security keyes for signing CSRF data, # signing cookies, and the SALT for hashing the passwords. app.config.update(dict({ 'CSRF_SESSION_KEY': config.CSRF_SESSION_KEY, 'SECRET_KEY': config.SECRET_KEY, 'SECURITY_PASSWORD_SALT': config.SECURITY_PASSWORD_SALT, 'SESSION_COOKIE_DOMAIN': config.SESSION_COOKIE_DOMAIN })) security.init_app(app, user_datastore) # register custom unauthorised handler. app.login_manager.unauthorized_handler(pga_unauthorised) # Set the permanent session lifetime to the specified value in config file. app.permanent_session_lifetime = timedelta( days=config.SESSION_EXPIRATION_TIME) app.session_interface = create_session_interface( app, config.SESSION_SKIP_PATHS ) # Make the Session more secure against XSS & CSRF when running in web mode if config.SERVER_MODE: paranoid = Paranoid(app) paranoid.redirect_view = 'browser.index' ########################################################################## # Load all available server drivers ########################################################################## driver.init_app(app) ########################################################################## # Register language to the preferences after login ########################################################################## @user_logged_in.connect_via(app) def register_language(sender, user): # After logged in, set the language in the preferences if we get from # the login page data = request.form if 'language' in data: language = data['language'] # Set the user language preference misc_preference = Preferences.module('miscellaneous') user_languages = misc_preference.preference( 'user_language' ) if user_languages and language: language = user_languages.set(language) ########################################################################## # Register any local servers we can discover ########################################################################## @user_logged_in.connect_via(app) def on_user_logged_in(sender, user): # Keep hold of the user ID user_id = user.id # Get the first server group for the user servergroup_id = 1 servergroups = ServerGroup.query.filter_by( user_id=user_id ).order_by("id") if servergroups.count() > 0: servergroup = servergroups.first() servergroup_id = servergroup.id '''Add a server to the config database''' def add_server(user_id, servergroup_id, name, superuser, port, discovery_id, comment): # Create a server object if needed, and store it. servers = Server.query.filter_by( user_id=user_id, discovery_id=svr_discovery_id ).order_by("id") if servers.count() > 0: return svr = Server(user_id=user_id, servergroup_id=servergroup_id, name=name, host='localhost', port=port, maintenance_db='postgres', username=superuser, ssl_mode='prefer', comment=svr_comment, discovery_id=discovery_id) db.session.add(svr) db.session.commit() # Figure out what servers are present if winreg is not None: arch_keys = set() proc_arch = os.environ['PROCESSOR_ARCHITECTURE'].lower() try: proc_arch64 = os.environ['PROCESSOR_ARCHITEW6432'].lower() except Exception as e: proc_arch64 = None if proc_arch == 'x86' and not proc_arch64: arch_keys.add(0) elif proc_arch == 'x86' or proc_arch == 'amd64': arch_keys.add(winreg.KEY_WOW64_32KEY) arch_keys.add(winreg.KEY_WOW64_64KEY) for arch_key in arch_keys: for server_type in ('PostgreSQL', 'EnterpriseDB'): try: root_key = winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\" + server_type + "\Services", 0, winreg.KEY_READ | arch_key ) for i in xrange(0, winreg.QueryInfoKey(root_key)[0]): inst_id = winreg.EnumKey(root_key, i) inst_key = winreg.OpenKey(root_key, inst_id) svr_name = winreg.QueryValueEx( inst_key, 'Display Name' )[0] svr_superuser = winreg.QueryValueEx( inst_key, 'Database Superuser' )[0] svr_port = winreg.QueryValueEx(inst_key, 'Port')[0] svr_discovery_id = inst_id svr_comment = gettext( "Auto-detected %s installation with the data " "directory at %s" % ( winreg.QueryValueEx( inst_key, 'Display Name' )[0], winreg.QueryValueEx( inst_key, 'Data Directory' )[0] ) ) add_server( user_id, servergroup_id, svr_name, svr_superuser, svr_port, svr_discovery_id, svr_comment ) inst_key.Close() except Exception as e: pass else: # We use the postgres-winreg.ini file on non-Windows try: from configparser import ConfigParser except ImportError: from ConfigParser import ConfigParser # Python 2 registry = ConfigParser() try: registry.read('/etc/postgres-reg.ini') sections = registry.sections() # Loop the sections, and get the data from any that are PG or PPAS for section in sections: if ( section.startswith('PostgreSQL/') or section.startswith('EnterpriseDB/') ): svr_name = registry.get(section, 'Description') svr_superuser = registry.get(section, 'Superuser') # getint function throws exception if value is blank. # Ex: Port= # In such case we should handle the exception and continue # to read the next section of the config file. try: svr_port = registry.getint(section, 'Port') except ValueError: continue svr_discovery_id = section description = registry.get(section, 'Description') data_directory = registry.get(section, 'DataDirectory') if hasattr(str, 'decode'): description = description.decode('utf-8') data_directory = data_directory.decode('utf-8') svr_comment = gettext(u"Auto-detected %s installation " u"with the data directory at %s" % ( description, data_directory ) ) add_server(user_id, servergroup_id, svr_name, svr_superuser, svr_port, svr_discovery_id, svr_comment) except Exception as e: pass @user_logged_in.connect_via(app) @user_logged_out.connect_via(app) def force_session_write(app, user): session.force_write = True @user_logged_out.connect_via(app) def clear_current_user_connections(app, user): from config import PG_DEFAULT_DRIVER from pgadmin.utils.driver import get_driver _driver = get_driver(PG_DEFAULT_DRIVER) _driver.gc_own() ########################################################################## # Load plugin modules ########################################################################## for module in app.find_submodules('pgadmin'): app.logger.info('Registering blueprint module: %s' % module) app.register_blueprint(module) ########################################################################## # Handle the desktop login ########################################################################## @app.before_request def before_request(): """Login the default user if running in desktop mode""" # Check the auth key is valid, if it's set, and we're not in server # mode, and it's not a help file request. if not config.SERVER_MODE and app.PGADMIN_KEY != '': if ( ('key' not in request.args or request.args['key'] != app.PGADMIN_KEY) and request.cookies.get('PGADMIN_KEY') != app.PGADMIN_KEY and request.endpoint != 'help.static' ): abort(401) if not config.SERVER_MODE and not current_user.is_authenticated: user = user_datastore.get_user(config.DESKTOP_USER) # Throw an error if we failed to find the desktop user, to give # the sysadmin a hint. We'll continue to try to login anyway as # that'll through a nice 500 error for us. if user is None: app.logger.error( 'The desktop user %s was not found in the configuration ' 'database.' % config.DESKTOP_USER ) abort(401) login_user(user) @app.after_request def after_request(response): if 'key' in request.args: domain = dict() if config.COOKIE_DEFAULT_DOMAIN and \ config.COOKIE_DEFAULT_DOMAIN != 'localhost': domain['domain'] = config.COOKIE_DEFAULT_DOMAIN response.set_cookie('PGADMIN_KEY', value=request.args['key'], path=config.COOKIE_DEFAULT_PATH, **domain) return response ########################################################################## # Cache busting ########################################################################## # Version number to be added to all static file url requests # This is used by url_for function when generating urls # This will solve caching issues when application is upgrading # This is called - Cache Busting @app.url_defaults def add_internal_version(endpoint, values): extensions = config.APP_VERSION_EXTN # Add the internal version only if it is set if config.APP_VERSION_PARAM is not None and \ config.APP_VERSION_PARAM != '': # If there is a filename, add the version if 'filename' in values \ and values['filename'].endswith(extensions): values[config.APP_VERSION_PARAM] = config.APP_VERSION_INT else: # Sometimes there may be direct endpoint for some files # There will be only one rule for such endpoints urls = [url for url in app.url_map.iter_rules(endpoint)] if len(urls) == 1 and urls[0].rule.endswith(extensions): values[config.APP_VERSION_PARAM] = \ config.APP_VERSION_INT # Strip away internal version param before sending further to app as it was # required for cache busting only @app.url_value_preprocessor def strip_version_number(endpoint, values): if values and config.APP_VERSION_PARAM in values: values.pop(config.APP_VERSION_PARAM) ########################################################################## # Minify output ########################################################################## # HTMLMIN doesn't work with Python 2.6. if not config.DEBUG and sys.version_info >= (2, 7): from flask_htmlmin import HTMLMIN HTMLMIN(app) @app.context_processor def inject_blueprint(): """Inject a reference to the current blueprint, if any.""" return { 'current_app': current_app, 'current_blueprint': current_blueprint } ########################################################################## # All done! ########################################################################## return app
def create_app(test_config=None): app = Flask(__name__, static_folder='static') if test_config is None: # load the instance config, if it exists, when not testing app.config.from_pyfile('sql/md.cfg', silent=False) # app.config.from_object('config.Config') # app.config.update( # SECRET_KEY = os.urandom(24), # SESSION_COOKIE_SECURE = False, # WTF_CSRF_TIME_LIMIT = None # ) else: # load the test config if passed in app.config.from_mapping(test_config) # # config flaskmail # params = config.mdconfig(section='email_auth') # flask_params = config.mdconfig(section='flask') # app.config.update( # # FLASK SETTINGS # DEBUG = flask_params['debug'], # # EMAIL SETTINGS # MAIL_SERVER = params['mail_server'], # MAIL_PORT = params['mail_port'], # MAIL_USE_TLS = params['mail_use_tls'], # MAIL_USERNAME = params['mail_username'], # MAIL_PASSWORD = params['mail_password'], # MAIL_DEFAULT_SENDER = params['mail_default_sender'], # # CSRF tokens config # WTF_CSRF_TIME_LIMIT = None # ) mail.init_app(app) csrf.init_app(app) paranoid = Paranoid(app) paranoid.redirect_view = '/MD/auth/login' # cors # for swaggerUI # https://idratherbewriting.com/learnapidoc/pubapis_swagger.html CORS(app, resources={r"/api/*": {"origins": "*"}}) # errors app.register_error_handler(403, forbidden_error) app.register_error_handler(404, not_found_error) app.register_error_handler(500, internal_error) app.register_error_handler(405, not_allowed_error) app.register_error_handler(413, reques_entity_too_large_error) # define custom jinja filters app.jinja_env.filters['match'] = config.match # if test_config is None: # # load the instance config, if it exists, when not testing # app.config.from_pyfile('config.py', silent=True) # else: # # load the test config if passed in # app.config.from_mapping(test_config) # ensure the instance folder exists try: os.makedirs(app.instance_path) except OSError: pass from . import db db.init_app(app) from . import auth app.register_blueprint(auth.bp) from . import md app.register_blueprint(md.bp) from . import ajax app.register_blueprint(ajax.bp) from . import api csrf.exempt(api.bp) app.register_blueprint(api.bp) from . import static_route app.register_blueprint(static_route.bp) from . import upload app.register_blueprint(upload.bp) # from . import error # app.register_blueprint(error.bp) app.add_url_rule('/', endpoint='index') # a simple page that says hello # @app.route('/factory_test') # def hello(): # return 'Flask factory ok!' # if not app.debug: # # logging into a file # # (from https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-vii-error-handling) # if not os.path.exists('logs'): # os.mkdir('logs') # file_handler = RotatingFileHandler('logs/mobidetails.log', maxBytes=10240, # backupCount=10) # file_handler.setFormatter(logging.Formatter( # '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]')) # file_handler.setLevel(logging.INFO) # app.logger.addHandler(file_handler) # app.logger.setLevel(logging.INFO) # app.logger.info('Mobidetails startup') if app.debug: print(app.config) return app
# Initiate LoginManager object login_manager = LoginManager(application) login_manager.anonymous_user = AnonymousUser login_manager.session_protection = 'strong' # Import and register blueprint modules # (prevent circular imports) for module_name, url_prefix in [('root', '/'), ('poll', '/poll/'), ('live', '/live/')]: module = importlib.import_module('blueprints.%s' % module_name) application.register_blueprint(module.blueprint, url_prefix=url_prefix) # Initiate Paranoid object paranoid = Paranoid(application) paranoid.redirect_view = 'root.get_home' # Initiate CSRF object csrf = CSRFProtect(application) # Import User and UserStore from models from models.entity.user import User from models.user_store import UserStore @login_manager.user_loader def load_user(user_id): """ Return SignedInUser object linked to User entity by uid. """
from flask_login import LoginManager from flask_mail import Mail from flask_migrate import Migrate from flask_paranoid import Paranoid from flask_sqlalchemy import SQLAlchemy from flask_talisman import Talisman from flask_wtf.csrf import CSRFProtect from sqlalchemy import event from sqlalchemy.engine import Engine database = SQLAlchemy() migrate = Migrate() csrf = CSRFProtect() login = LoginManager() paranoid = Paranoid() talisman = Talisman() bootstrap = Bootstrap() mail = Mail() @event.listens_for(Engine, "connect") def set_sqlite_pragma(dbapi_connection, connection_record): cursor = dbapi_connection.cursor() cursor.execute("PRAGMA foreign_keys=ON") cursor.close() def create_application(instance_path): if instance_path:
# This enables app to be executed by command: # - export FLASK_APP=app.py # - flask run app = Flask(__name__, template_folder="./templates") # app.secret_key = "CS9163Assignment02WebsiteFlaskSessionSecretKey" # app.WTF_CSRF_SECRET_KEY = "CS9163Assignment02WebsiteFlaskWTFCSRFToken" app.secret_key = get_secret_key("flask_session_secret_key", "DefaultCS9163Assignment04SecretKey") app.WTF_CSRF_SECRET_KEY = get_secret_key("flask_wtf_csrf_token", "DefaultCS9163Assignment04SecretKey") # Random secret_key does work, but this will lose all existed sessions # when current flask application restarts. # app.secret_key = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(32)) # app.WTF_CSRF_SECRET_KEY = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(32)) app.config.update( SQLALCHEMY_DATABASE_URI='sqlite:///sqlite3/cs9163.sqlite3' ) app.config.update( SESSION_COOKIE_HTTPONLY=True, SESSION_COOKIE_SAMESITE='Lax', PERMANENT_SESSION_LIFETIME=600 ) csrf = CSRFProtect(app) paranoid = Paranoid(app) configure_routes(app) paranoid.redirect_view = ROOT_URL + '/login' if __name__ == "__main__": app.run(debug=True)
def create_app(app_name=None): # Configuration settings import config if not app_name: app_name = config.APP_NAME # Check if app is created for CLI operations or Web cli_mode = False if app_name.endswith('-cli'): cli_mode = True # Only enable password related functionality in server mode. if config.SERVER_MODE is True: # Some times we need to access these config params where application # context is not available (we can't use current_app.config in those # cases even with current_app.app_context()) # So update these params in config itself. # And also these updated config values will picked up by application # since we are updating config before the application instance is # created. config.SECURITY_RECOVERABLE = True config.SECURITY_CHANGEABLE = True # Now we'll open change password page in alertify dialog # we don't want it to redirect to main page after password # change operation so we will open the same password change page again. config.SECURITY_POST_CHANGE_VIEW = 'browser.change_password' """Create the Flask application, startup logging and dynamically load additional modules (blueprints) that are found in this directory.""" app = PgAdmin(__name__, static_url_path='/static') # Removes unwanted whitespace from render_template function app.jinja_env.trim_blocks = True app.config.from_object(config) app.config.update(dict(PROPAGATE_EXCEPTIONS=True)) ########################################################################## # Setup logging and log the application startup ########################################################################## # We won't care about errors in the logging system, we are more # interested in application errors. logging.raiseExceptions = False # Add SQL level logging, and set the base logging level logging.addLevelName(25, 'SQL') app.logger.setLevel(logging.DEBUG) app.logger.handlers = [] # We also need to update the handler on the webserver in order to see # request. Setting the level prevents werkzeug from setting up it's own # stream handler thus ensuring all the logging goes through the pgAdmin # logger. logger = logging.getLogger('werkzeug') logger.setLevel(config.CONSOLE_LOG_LEVEL) # Set SQLITE_PATH to TEST_SQLITE_PATH while running test cases if ('PGADMIN_TESTING_MODE' in os.environ and os.environ['PGADMIN_TESTING_MODE'] == '1'): config.SQLITE_PATH = config.TEST_SQLITE_PATH config.MASTER_PASSWORD_REQUIRED = False config.UPGRADE_CHECK_ENABLED = False if not cli_mode: # Ensure the various working directories exist from pgadmin.setup import create_app_data_directory create_app_data_directory(config) # File logging fh = logging.FileHandler(config.LOG_FILE, encoding='utf-8') fh.setLevel(config.FILE_LOG_LEVEL) fh.setFormatter(logging.Formatter(config.FILE_LOG_FORMAT)) app.logger.addHandler(fh) logger.addHandler(fh) # Console logging ch = logging.StreamHandler() ch.setLevel(config.CONSOLE_LOG_LEVEL) ch.setFormatter(logging.Formatter(config.CONSOLE_LOG_FORMAT)) app.logger.addHandler(ch) logger.addHandler(ch) # Log the startup app.logger.info('########################################################') app.logger.info('Starting %s v%s...', config.APP_NAME, config.APP_VERSION) app.logger.info('########################################################') app.logger.debug("Python syspath: %s", sys.path) ########################################################################## # Setup i18n ########################################################################## # Initialise i18n babel = Babel(app) app.logger.debug('Available translations: %s' % babel.list_translations()) @babel.localeselector def get_locale(): """Get the language for the user.""" language = 'en' if config.SERVER_MODE is False: # Get the user language preference from the miscellaneous module if current_user.is_authenticated: user_id = current_user.id else: user = user_datastore.get_user(config.DESKTOP_USER) if user is not None: user_id = user.id user_language = Preferences.raw_value('misc', 'user_language', 'user_language', user_id) if user_language is not None: language = user_language else: # If language is available in get request then return the same # otherwise check the session or cookie data = request.form if 'language' in data: language = data['language'] or language setattr(session, 'PGADMIN_LANGUAGE', language) elif hasattr(session, 'PGADMIN_LANGUAGE'): language = getattr(session, 'PGADMIN_LANGUAGE', language) elif hasattr(request.cookies, 'PGADMIN_LANGUAGE'): language = getattr(request.cookies, 'PGADMIN_LANGUAGE', language) return language ########################################################################## # Setup authentication ########################################################################## app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///{0}?timeout={1}' \ .format(config.SQLITE_PATH.replace('\\', '/'), getattr(config, 'SQLITE_TIMEOUT', 500) ) # Override USER_DOES_NOT_EXIST and INVALID_PASSWORD messages from flask. app.config['SECURITY_MSG_USER_DOES_NOT_EXIST'] = \ app.config['SECURITY_MSG_INVALID_PASSWORD'] = \ (gettext("Incorrect username or password."), "error") # Create database connection object and mailer db.init_app(app) ########################################################################## # Upgrade the schema (if required) ########################################################################## with app.app_context(): # Run migration for the first time i.e. create database from config import SQLITE_PATH from pgadmin.setup import db_upgrade # If version not available, user must have aborted. Tables are not # created and so its an empty db if not os.path.exists(SQLITE_PATH) or get_version() == -1: # If running in cli mode then don't try to upgrade, just raise # the exception if not cli_mode: db_upgrade(app) else: if not os.path.exists(SQLITE_PATH): raise FileNotFoundError('SQLite database file "' + SQLITE_PATH + '" does not exists.') raise RuntimeError('Specified SQLite database file ' 'is not valid.') else: schema_version = get_version() # Run migration if current schema version is greater than the # schema version stored in version table if CURRENT_SCHEMA_VERSION >= schema_version: db_upgrade(app) # Update schema version to the latest if CURRENT_SCHEMA_VERSION > schema_version: set_version(CURRENT_SCHEMA_VERSION) db.session.commit() if os.name != 'nt': os.chmod(config.SQLITE_PATH, 0o600) Mail(app) # Don't bother paths when running in cli mode if not cli_mode: import pgadmin.utils.paths as paths paths.init_app(app) # Setup Flask-Security user_datastore = SQLAlchemyUserDatastore(db, User, Role) security = Security(None, user_datastore) ########################################################################## # Setup security ########################################################################## with app.app_context(): config.CSRF_SESSION_KEY = Keys.query.filter_by( name='CSRF_SESSION_KEY').first().value config.SECRET_KEY = Keys.query.filter_by( name='SECRET_KEY').first().value config.SECURITY_PASSWORD_SALT = Keys.query.filter_by( name='SECURITY_PASSWORD_SALT').first().value # Update the app.config with proper security keyes for signing CSRF data, # signing cookies, and the SALT for hashing the passwords. app.config.update( dict({ 'CSRF_SESSION_KEY': config.CSRF_SESSION_KEY, 'SECRET_KEY': config.SECRET_KEY, 'SECURITY_PASSWORD_SALT': config.SECURITY_PASSWORD_SALT, 'SESSION_COOKIE_DOMAIN': config.SESSION_COOKIE_DOMAIN, # CSRF Token expiration till session expires 'WTF_CSRF_TIME_LIMIT': getattr(config, 'CSRF_TIME_LIMIT', None), 'WTF_CSRF_METHODS': ['GET', 'POST', 'PUT', 'DELETE'], })) security.init_app(app, user_datastore) # register custom unauthorised handler. app.login_manager.unauthorized_handler(pga_unauthorised) # Set the permanent session lifetime to the specified value in config file. app.permanent_session_lifetime = timedelta( days=config.SESSION_EXPIRATION_TIME) if not cli_mode: app.session_interface = create_session_interface( app, config.SESSION_SKIP_PATHS) # Make the Session more secure against XSS & CSRF when running in web mode if config.SERVER_MODE and config.ENHANCED_COOKIE_PROTECTION: paranoid = Paranoid(app) paranoid.redirect_view = 'browser.index' ########################################################################## # Load all available server drivers ########################################################################## driver.init_app(app) authenticate.init_app(app) ########################################################################## # Register language to the preferences after login ########################################################################## @user_logged_in.connect_via(app) def register_language(sender, user): # After logged in, set the language in the preferences if we get from # the login page data = request.form if 'language' in data: language = data['language'] # Set the user language preference misc_preference = Preferences.module('misc') user_languages = misc_preference.preference('user_language') if user_languages and language: language = user_languages.set(language) ########################################################################## # Register any local servers we can discover ########################################################################## @user_logged_in.connect_via(app) def on_user_logged_in(sender, user): # Keep hold of the user ID user_id = user.id # Get the first server group for the user servergroup_id = 1 servergroups = ServerGroup.query.filter_by( user_id=user_id).order_by("id") if servergroups.count() > 0: servergroup = servergroups.first() servergroup_id = servergroup.id '''Add a server to the config database''' def add_server(user_id, servergroup_id, name, superuser, port, discovery_id, comment): # Create a server object if needed, and store it. servers = Server.query.filter_by( user_id=user_id, discovery_id=svr_discovery_id).order_by("id") if servers.count() > 0: return svr = Server(user_id=user_id, servergroup_id=servergroup_id, name=name, host='localhost', port=port, maintenance_db='postgres', username=superuser, ssl_mode='prefer', comment=svr_comment, discovery_id=discovery_id) db.session.add(svr) db.session.commit() # Figure out what servers are present if winreg is not None: arch_keys = set() proc_arch = os.environ['PROCESSOR_ARCHITECTURE'].lower() try: proc_arch64 = os.environ['PROCESSOR_ARCHITEW6432'].lower() except Exception: proc_arch64 = None if proc_arch == 'x86' and not proc_arch64: arch_keys.add(0) elif proc_arch == 'x86' or proc_arch == 'amd64': arch_keys.add(winreg.KEY_WOW64_32KEY) arch_keys.add(winreg.KEY_WOW64_64KEY) for arch_key in arch_keys: for server_type in ('PostgreSQL', 'EnterpriseDB'): try: root_key = winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\" + server_type + "\\Services", 0, winreg.KEY_READ | arch_key) for i in range(0, winreg.QueryInfoKey(root_key)[0]): inst_id = winreg.EnumKey(root_key, i) inst_key = winreg.OpenKey(root_key, inst_id) svr_name = winreg.QueryValueEx( inst_key, 'Display Name')[0] svr_superuser = winreg.QueryValueEx( inst_key, 'Database Superuser')[0] svr_port = winreg.QueryValueEx(inst_key, 'Port')[0] svr_discovery_id = inst_id svr_comment = gettext( "Auto-detected {0} installation with the data " "directory at {1}").format( winreg.QueryValueEx( inst_key, 'Display Name')[0], winreg.QueryValueEx( inst_key, 'Data Directory')[0]) add_server(user_id, servergroup_id, svr_name, svr_superuser, svr_port, svr_discovery_id, svr_comment) inst_key.Close() except Exception: pass else: # We use the postgres-winreg.ini file on non-Windows from configparser import ConfigParser registry = ConfigParser() try: registry.read('/etc/postgres-reg.ini') sections = registry.sections() # Loop the sections, and get the data from any that are PG or PPAS for section in sections: if (section.startswith('PostgreSQL/') or section.startswith('EnterpriseDB/')): svr_name = registry.get(section, 'Description') svr_superuser = registry.get(section, 'Superuser') # getint function throws exception if value is blank. # Ex: Port= # In such case we should handle the exception and continue # to read the next section of the config file. try: svr_port = registry.getint(section, 'Port') except ValueError: continue svr_discovery_id = section description = registry.get(section, 'Description') data_directory = registry.get(section, 'DataDirectory') svr_comment = gettext( "Auto-detected {0} installation " "with the data directory at {1}").format( description, data_directory) add_server(user_id, servergroup_id, svr_name, svr_superuser, svr_port, svr_discovery_id, svr_comment) except Exception: pass @user_logged_in.connect_via(app) @user_logged_out.connect_via(app) def force_session_write(app, user): session.force_write = True @user_logged_in.connect_via(app) def store_crypt_key(app, user): # in desktop mode, master password is used to encrypt/decrypt # and is stored in the keyManager memory if config.SERVER_MODE and 'password' in request.form: current_app.keyManager.set(request.form['password']) @user_logged_out.connect_via(app) def current_user_cleanup(app, user): from config import PG_DEFAULT_DRIVER from pgadmin.utils.driver import get_driver from flask import current_app # remove key current_app.keyManager.reset() for mdl in current_app.logout_hooks: try: mdl.on_logout(user) except Exception as e: current_app.logger.exception(e) _driver = get_driver(PG_DEFAULT_DRIVER) _driver.gc_own() ########################################################################## # Load plugin modules ########################################################################## for module in app.find_submodules('pgadmin'): app.logger.info('Registering blueprint module: %s' % module) app.register_blueprint(module) app.register_logout_hook(module) @app.before_request def limit_host_addr(): """ This function validate the hosts from ALLOWED_HOSTS before allowing HTTP request to avoid Host Header Injection attack :return: None/JSON response with 403 HTTP status code """ client_host = str(request.host).split(':')[0] valid = True allowed_hosts = config.ALLOWED_HOSTS if len(allowed_hosts) != 0: regex = re.compile( r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?:/\d{1,2}|)') # Create separate list for ip addresses and host names ip_set = list(filter(lambda ip: regex.match(ip), allowed_hosts)) host_set = list( filter(lambda ip: not regex.match(ip), allowed_hosts)) is_ip = regex.match(client_host) if is_ip: ip_address = [] for ip in ip_set: ip_address.extend(list(ipaddress.ip_network(ip))) valid = ip_address.__contains__( ipaddress.ip_address(client_host)) else: valid = host_set.__contains__(client_host) if not valid: return make_json_response(status=403, success=0, errormsg=_("403 FORBIDDEN")) ########################################################################## # Handle the desktop login ########################################################################## @app.before_request def before_request(): """Login the default user if running in desktop mode""" # Check the auth key is valid, if it's set, and we're not in server # mode, and it's not a help file request. if not config.SERVER_MODE and app.PGADMIN_INT_KEY != '' and ( ('key' not in request.args or request.args['key'] != app.PGADMIN_INT_KEY) and request.cookies.get('PGADMIN_INT_KEY') != app.PGADMIN_INT_KEY and request.endpoint != 'help.static'): abort(401) if not config.SERVER_MODE and not current_user.is_authenticated: user = user_datastore.get_user(config.DESKTOP_USER) # Throw an error if we failed to find the desktop user, to give # the sysadmin a hint. We'll continue to try to login anyway as # that'll through a nice 500 error for us. if user is None: app.logger.error( 'The desktop user %s was not found in the configuration ' 'database.' % config.DESKTOP_USER) abort(401) login_user(user) # if the server is restarted the in memory key will be lost # but the user session may still be active. Logout the user # to get the key again when login if config.SERVER_MODE and current_user.is_authenticated and \ current_app.keyManager.get() is None and \ request.endpoint not in ('security.login', 'security.logout'): logout_user() @app.after_request def after_request(response): if 'key' in request.args: domain = dict() if config.COOKIE_DEFAULT_DOMAIN and \ config.COOKIE_DEFAULT_DOMAIN != 'localhost': domain['domain'] = config.COOKIE_DEFAULT_DOMAIN response.set_cookie('PGADMIN_INT_KEY', value=request.args['key'], path=config.COOKIE_DEFAULT_PATH, secure=config.SESSION_COOKIE_SECURE, httponly=config.SESSION_COOKIE_HTTPONLY, samesite=config.SESSION_COOKIE_SAMESITE, **domain) SecurityHeaders.set_response_headers(response) return response ########################################################################## # Cache busting ########################################################################## # Version number to be added to all static file url requests # This is used by url_for function when generating urls # This will solve caching issues when application is upgrading # This is called - Cache Busting @app.url_defaults def add_internal_version(endpoint, values): extensions = config.APP_VERSION_EXTN # Add the internal version only if it is set if config.APP_VERSION_PARAM is not None and \ config.APP_VERSION_PARAM != '': # If there is a filename, add the version if 'filename' in values \ and values['filename'].endswith(extensions): values[config.APP_VERSION_PARAM] = config.APP_VERSION_INT else: # Sometimes there may be direct endpoint for some files # There will be only one rule for such endpoints urls = [url for url in app.url_map.iter_rules(endpoint)] if len(urls) == 1 and urls[0].rule.endswith(extensions): values[config.APP_VERSION_PARAM] = \ config.APP_VERSION_INT # Strip away internal version param before sending further to app as it was # required for cache busting only @app.url_value_preprocessor def strip_version_number(endpoint, values): if values and config.APP_VERSION_PARAM in values: values.pop(config.APP_VERSION_PARAM) ########################################################################## # Minify output. Not required in desktop mode ########################################################################## if not config.DEBUG and config.SERVER_MODE: from flask_compress import Compress Compress(app) from pgadmin.misc.themes import themes themes(app) @app.context_processor def inject_blueprint(): """ Inject a reference to the current blueprint, if any. """ return { 'current_app': current_app, 'current_blueprint': current_blueprint, } @app.errorhandler(Exception) def all_exception_handler(e): current_app.logger.error(e, exc_info=True) return internal_server_error(errormsg=str(e)) # Exclude HTTPexception from above handler (all_exception_handler) # HTTPException are user defined exceptions and those should be returned # as is @app.errorhandler(HTTPException) def http_exception_handler(e): current_app.logger.error(e, exc_info=True) return e # Intialize the key manager app.keyManager = KeyManager() ########################################################################## # Protection against CSRF attacks ########################################################################## with app.app_context(): pgCSRFProtect.init_app(app) ########################################################################## # All done! ########################################################################## return app
app.config['SESSION_COOKIE_HTTPONLY'] = True app.config['REMEMBER_COOKIE_HTTPONLY'] = True #=============================== # Security options and functions #=============================== from flask_cors import CORS cors = CORS(app, origins=['http://localhost:3000', 'http://localhost:3001'], headers=['Content-Type'], expose_headers=['Access-Control-Allow-Origin'], supports_credentials=True) from flask_paranoid import Paranoid Paranoid(app) #=============================== # Database options and functions #=============================== from .models.auth import User, UserRole, Role from .models.blog import Post, Category from .database import database @app.before_request def before_request(): database.connect() database.create_tables([User, Role, UserRole, Category, Post], safe=True)