diff --git a/web/config.py b/web/config.py index 4afea8460..a17157401 100644 --- a/web/config.py +++ b/web/config.py @@ -65,6 +65,17 @@ LOG_FILE = 'pgadmin4.log' # Server settings ########################################################################## +# The server mode determines whether or not we're running on a web server +# requiring user authentication, or desktop mode which uses an automatic +# default login. +# +# DO NOT DISABLE SERVER MODE IF RUNNING ON A WEBSERVER!! +SERVER_MODE = True + +# User ID (email address) to use for the default user in desktop mode. +# The default should be fine here, as it's not exposed in the app. +DESKTOP_USER = 'pgadmin4@pgadmin.org' + # The default port on which the app server will listen if not set in the # environment by the runtime DEFAULT_SERVER_PORT = 5050 diff --git a/web/pgAdmin4.py b/web/pgAdmin4.py index 81e347a7c..8c8b9467a 100644 --- a/web/pgAdmin4.py +++ b/web/pgAdmin4.py @@ -20,6 +20,27 @@ sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) import config from pgadmin import create_app +########################################################################## +# Sanity checks +########################################################################## + +# Check for local settings if running in server mode +if config.SERVER_MODE == True: + local_config = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'config_local.py') + if not os.path.isfile(local_config): + print "The configuration file %s does not exist.\n" % local_config + print "Before running this application, ensure that config_local.py has been created" + print "and sets values for SECRET_KEY, SECURITY_PASSWORD_SALT and CSRF_SESSION_KEY" + print "at bare minimum. See config.py for more information and a complete list of" + print "settings. Exiting..." + sys.exit(1) + +# Check if the database exists. If it does not, tell the user and exit. +if not os.path.isfile(config.SQLITE_PATH): + print "The configuration database %s does not exist.\n" % config.SQLITE_PATH + print "Please run 'python %s' to create it.\nExiting..." % os.path.join(os.path.dirname(os.path.realpath(__file__)), 'setup.py') + sys.exit(1) + ########################################################################## # Server starup ########################################################################## diff --git a/web/pgadmin/__init__.py b/web/pgadmin/__init__.py index 13cc2fca8..7b67a7644 100644 --- a/web/pgadmin/__init__.py +++ b/web/pgadmin/__init__.py @@ -10,9 +10,10 @@ """The main pgAdmin module. This handles the application initialisation tasks, such as setup of logging, dynamic loading of modules etc.""" -from flask import Flask +from flask import Flask, abort from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.security import Security, SQLAlchemyUserDatastore, login_required +from flask_security.utils import login_user from flask_mail import Mail from settings_model import db, Role, User @@ -66,8 +67,12 @@ def create_app(app_name=config.APP_NAME): ########################################################################## app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + config.SQLITE_PATH.replace('\\', '/') - app.config['SECURITY_RECOVERABLE'] = True - app.config['SECURITY_CHANGEABLE'] = True + + # Only enable password related functionality in server mode. + if config.SERVER_MODE == 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) @@ -100,6 +105,29 @@ def create_app(app_name=config.APP_NAME): app.logger.info('Registering blueprint module: %s' % f) app.register_blueprint(module.views.blueprint) + ########################################################################## + # Handle the desktop login + ########################################################################## + + @app.before_request + def before_request(): + """Login the default user if running in desktop mode""" + if config.SERVER_MODE == False: + 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) + + ########################################################################## # All done! + ########################################################################## + app.logger.debug('URL map: %s' % app.url_map) return app + diff --git a/web/pgadmin/browser/templates/index.html b/web/pgadmin/browser/templates/index.html index b01030a99..1c3e6e7ed 100644 --- a/web/pgadmin/browser/templates/index.html +++ b/web/pgadmin/browser/templates/index.html @@ -17,18 +17,23 @@ + + {% if config.SERVER_MODE %} + - + {% endif %} diff --git a/web/setup.py b/web/setup.py index 2e41c791f..8603c1412 100644 --- a/web/setup.py +++ b/web/setup.py @@ -16,7 +16,7 @@ from flask.ext.security import Security, SQLAlchemyUserDatastore from flask.ext.security.utils import encrypt_password from settings_model import db, Role, User -import getpass, os, sys +import getpass, os, random, sys, string # Configuration settings import config @@ -31,8 +31,8 @@ print "======================================\n" local_config = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'config_local.py') if not os.path.isfile(local_config): - print "%s does not exist.\n" % local_config - print "Before running this script, ensure that config_local.py has been created" + print "The configuration file %s does not exist.\n" % local_config + print "Before running this application, ensure that config_local.py has been created" print "and sets values for SECRET_KEY, SECURITY_PASSWORD_SALT and CSRF_SESSION_KEY" print "at bare minimum. See config.py for more information and a complete list of" print "settings. Exiting..." @@ -43,18 +43,26 @@ if os.path.isfile(config.SQLITE_PATH): print "The configuration database %s already exists and will not be overwritten.\nExiting..." % config.SQLITE_PATH sys.exit(1) -# Prompt the user for their default username and password. -print "Enter the email address and password to use for the initial pgAdmin user account:\n" -email = '' -while email == '': - email = raw_input("Email address: ") +if config.SERVER_MODE == False: + print "NOTE: Configuring authentication for DESKTOP mode." + email = config.DESKTOP_USER + p1 = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(32)]) -pprompt = lambda: (getpass.getpass(), getpass.getpass('Retype password: ')) +else: + print "NOTE: Configuring authentication for SERVER mode.\n" + + # Prompt the user for their default username and password. + print "Enter the email address and password to use for the initial pgAdmin user account:\n" + email = '' + while email == '': + email = raw_input("Email address: ") + + pprompt = lambda: (getpass.getpass(), getpass.getpass('Retype password: ')) -p1, p2 = pprompt() -while p1 != p2: - print('Passwords do not match. Try again') p1, p2 = pprompt() + while p1 != p2: + print('Passwords do not match. Try again') + p1, p2 = pprompt() # Setup Flask-Security user_datastore = SQLAlchemyUserDatastore(db, User, Role)