mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Add authentication and the basis of the browser module.
A user authentication module based on flask-security is added, which allows users to login and change/recover passwords etc. Custom templates are included for the user/password UIs. A new setup script will initialise the user (and later settings) DB, adding the first user and granting them an Administrator role. A redirects blueprint module is added to handle simple URL redirects. A browser module is added and currently renders a skeleton page with a menu bar, gravatar and jumbotron. NOTE FOR LATER: Currently this code might make the nice basis for any web app that needs user management and plugins. Hmmm....
This commit is contained in:
parent
7fa40d7671
commit
10515431c7
@ -1,7 +1,18 @@
|
||||
Flask==0.10.1
|
||||
Flask-Gravatar==0.4.1
|
||||
Flask-Login==0.2.11
|
||||
Flask-Mail==0.9.1
|
||||
Flask-Principal==0.4.0
|
||||
Flask-SQLAlchemy==2.0
|
||||
Flask-Security==1.7.4
|
||||
Flask-WTF==0.11
|
||||
Jinja2==2.7.3
|
||||
MarkupSafe==0.23
|
||||
SQLAlchemy==0.9.8
|
||||
WTForms==2.0.2
|
||||
Werkzeug==0.9.6
|
||||
blinker==1.3
|
||||
itsdangerous==0.24
|
||||
passlib==1.6.2
|
||||
psycopg2==2.5.2
|
||||
wsgiref==0.1.2
|
||||
|
@ -10,6 +10,7 @@
|
||||
##########################################################################
|
||||
|
||||
from logging import *
|
||||
import os
|
||||
|
||||
##########################################################################
|
||||
# Application settings
|
||||
@ -73,11 +74,48 @@ CSRF_ENABLED = True
|
||||
|
||||
# Secret key for signing CSRF data. Override this in config_local.py if
|
||||
# running on a web server
|
||||
CSRF_SESSION_KEY = 'SuperSecret'
|
||||
CSRF_SESSION_KEY = 'SuperSecret1'
|
||||
|
||||
# Secret key for signing cookies. Override this in config_local.py if
|
||||
# running on a web server
|
||||
SECRET_KEY = 'SuperSecret'
|
||||
SECRET_KEY = 'SuperSecret2'
|
||||
|
||||
# Salt used when hashing passwords. Override this in config_local.py if
|
||||
# running on a web server
|
||||
SECURITY_PASSWORD_SALT = 'SuperSecret3'
|
||||
|
||||
# Hashing algorithm used for password storage
|
||||
SECURITY_PASSWORD_HASH = 'pbkdf2_sha512'
|
||||
|
||||
##########################################################################
|
||||
# User account and settings storage
|
||||
##########################################################################
|
||||
|
||||
# The default path to the SQLite database used to store user accounts and
|
||||
# settings. This default places the file in the same directory as this
|
||||
# config file, but generates an absolute path for use througout the app.
|
||||
SQLITE_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'pgadmin4.db')
|
||||
|
||||
##########################################################################
|
||||
# Mail server settings
|
||||
##########################################################################
|
||||
|
||||
# These settings are used when running in web server mode for confirming
|
||||
# and resetting passwords etc.
|
||||
MAIL_SERVER = 'smtp.gmail.com'
|
||||
MAIL_PORT = 465
|
||||
MAIL_USE_SSL = True
|
||||
MAIL_USERNAME = 'username'
|
||||
MAIL_PASSWORD = 'SuperSecret'
|
||||
|
||||
##########################################################################
|
||||
# Mail content settings
|
||||
##########################################################################
|
||||
|
||||
# These settings define the content of password reset emails
|
||||
SECURITY_EMAIL_SUBJECT_PASSWORD_RESET = "Password reset instructions for %s" % APP_NAME
|
||||
SECURITY_EMAIL_SUBJECT_PASSWORD_NOTICE = "Your %s password has been reset" % APP_NAME
|
||||
SECURITY_EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE = "Your password for %s has been changed" % APP_NAME
|
||||
|
||||
##########################################################################
|
||||
# Local config settings
|
||||
|
@ -10,8 +10,13 @@
|
||||
"""The main pgAdmin module. This handles the application initialisation tasks,
|
||||
such as setup of logging, dynamic loading of modules etc."""
|
||||
|
||||
import inspect, logging, os
|
||||
from flask import Flask
|
||||
from flask.ext.sqlalchemy import SQLAlchemy
|
||||
from flask.ext.security import Security, SQLAlchemyUserDatastore, login_required
|
||||
from flask_mail import Mail
|
||||
from settings_model import db, Role, User
|
||||
|
||||
import inspect, logging, os
|
||||
|
||||
# Configuration settings
|
||||
import config
|
||||
@ -56,7 +61,26 @@ def create_app(app_name=config.APP_NAME):
|
||||
app.logger.info('Starting %s v%s...', config.APP_NAME, config.APP_VERSION)
|
||||
app.logger.info('################################################################################')
|
||||
|
||||
# Register all the modules
|
||||
##########################################################################
|
||||
# Setup authentication
|
||||
##########################################################################
|
||||
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + config.SQLITE_PATH.replace('\\', '/')
|
||||
app.config['SECURITY_RECOVERABLE'] = True
|
||||
app.config['SECURITY_CHANGEABLE'] = True
|
||||
|
||||
# Create database connection object and mailer
|
||||
db.init_app(app)
|
||||
mail = Mail(app)
|
||||
|
||||
# Setup Flask-Security
|
||||
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
|
||||
security = Security(app, user_datastore)
|
||||
|
||||
##########################################################################
|
||||
# Load plugin modules
|
||||
##########################################################################
|
||||
|
||||
path = os.path.dirname(os.path.realpath(__file__))
|
||||
files = os.listdir(path)
|
||||
for f in files:
|
||||
@ -76,7 +100,6 @@ def create_app(app_name=config.APP_NAME):
|
||||
app.logger.info('Registering blueprint module: %s' % f)
|
||||
app.register_blueprint(module.views.blueprint)
|
||||
|
||||
# All done!
|
||||
app.logger.debug('URL map: %s' % app.url_map)
|
||||
|
||||
return app
|
||||
|
||||
|
0
web/pgadmin/browser/__init__.py
Normal file
0
web/pgadmin/browser/__init__.py
Normal file
46
web/pgadmin/browser/templates/index.html
Normal file
46
web/pgadmin/browser/templates/index.html
Normal file
@ -0,0 +1,46 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">pgAdmin 4</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">File <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="{{ url_for('security.change_password') }}">Change Password</a></li>
|
||||
<li><a href="{{ url_for('utils.test') }}">Test URL</a></li>
|
||||
<li><a href="{{ url_for('utils.ping') }}">Ping</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="{{ url_for('security.logout') }}">Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="#"><img src="{{ username | gravatar }}" width="18" height="18"> {{ username }}</a></li>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="jumbotron">
|
||||
<div class="container">
|
||||
<h1>pgAdmin 4</h1>
|
||||
<p>Welcome to pgAdmin 4.</p>
|
||||
<p><a class="btn btn-primary btn-lg" href="http://www.pgadmin.org/" role="button">Learn more »</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include 'messages.html' %}
|
||||
{% endblock %}
|
12
web/pgadmin/browser/templates/messages.html
Normal file
12
web/pgadmin/browser/templates/messages.html
Normal file
@ -0,0 +1,12 @@
|
||||
{%- with messages = get_flashed_messages(with_categories=true) -%}
|
||||
{% if messages %}
|
||||
<div style="position: fixed; top: 70px; right: 20px; width: 400px; z-index: 9999">
|
||||
{% for category, message in messages %}
|
||||
<div class="alert alert-{{ category }} alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- endwith %}
|
37
web/pgadmin/browser/views.py
Normal file
37
web/pgadmin/browser/views.py
Normal file
@ -0,0 +1,37 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2014, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""A blueprint module implementing the core pgAdmin browser."""
|
||||
MODULE_NAME = 'browser'
|
||||
|
||||
import config
|
||||
from flask import Blueprint, current_app, render_template
|
||||
from flaskext.gravatar import Gravatar
|
||||
from flask.ext.security import login_required
|
||||
from flask.ext.login import current_user
|
||||
|
||||
# Initialise the module
|
||||
blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', static_url_path='', template_folder='templates', url_prefix='/' + MODULE_NAME)
|
||||
|
||||
##########################################################################
|
||||
# A test page
|
||||
##########################################################################
|
||||
@blueprint.route("/")
|
||||
@login_required
|
||||
def index():
|
||||
"""Render and process the main browser window."""
|
||||
gravatar = Gravatar(current_app,
|
||||
size=100,
|
||||
rating='g',
|
||||
default='retro',
|
||||
force_default=False,
|
||||
use_ssl=False,
|
||||
base_url=None)
|
||||
|
||||
return render_template('index.html', username=current_user.email)
|
0
web/pgadmin/redirects/__init__.py
Normal file
0
web/pgadmin/redirects/__init__.py
Normal file
24
web/pgadmin/redirects/views.py
Normal file
24
web/pgadmin/redirects/views.py
Normal file
@ -0,0 +1,24 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2014, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""A blueprint module providing URL redirects."""
|
||||
MODULE_NAME = 'redirects'
|
||||
|
||||
import config
|
||||
from flask import Blueprint, redirect, url_for
|
||||
from flask.ext.security import login_required
|
||||
|
||||
# Initialise the module
|
||||
blueprint = Blueprint(MODULE_NAME, __name__)
|
||||
|
||||
@blueprint.route('/')
|
||||
@login_required
|
||||
def index():
|
||||
"""Redirect users hitting the root to the browser"""
|
||||
return redirect(url_for('browser.index'))
|
0
web/pgadmin/static/css/bootstrap-theme.css
vendored
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap-theme.css
vendored
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap-theme.css.map
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap-theme.css.map
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap-theme.min.css
vendored
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap-theme.min.css
vendored
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap.css
vendored
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap.css
vendored
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap.css.map
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap.css.map
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap.min.css
vendored
Executable file → Normal file
0
web/pgadmin/static/css/bootstrap.min.css
vendored
Executable file → Normal file
0
web/pgadmin/static/css/main.css
Executable file → Normal file
0
web/pgadmin/static/css/main.css
Executable file → Normal file
@ -1,2 +1 @@
|
||||
/* Overrides/fixes for pgAdmin specific styling in Bootstrap */
|
||||
|
||||
|
0
web/pgadmin/static/fonts/glyphicons-halflings-regular.eot
Executable file → Normal file
0
web/pgadmin/static/fonts/glyphicons-halflings-regular.eot
Executable file → Normal file
0
web/pgadmin/static/fonts/glyphicons-halflings-regular.svg
Executable file → Normal file
0
web/pgadmin/static/fonts/glyphicons-halflings-regular.svg
Executable file → Normal file
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
0
web/pgadmin/static/fonts/glyphicons-halflings-regular.ttf
Executable file → Normal file
0
web/pgadmin/static/fonts/glyphicons-halflings-regular.ttf
Executable file → Normal file
0
web/pgadmin/static/fonts/glyphicons-halflings-regular.woff
Executable file → Normal file
0
web/pgadmin/static/fonts/glyphicons-halflings-regular.woff
Executable file → Normal file
BIN
web/pgadmin/static/img/logo-256.png
Normal file
BIN
web/pgadmin/static/img/logo-256.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
BIN
web/pgadmin/static/img/logo-right-256.png
Normal file
BIN
web/pgadmin/static/img/logo-right-256.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
0
web/pgadmin/static/js/main.js
Executable file → Normal file
0
web/pgadmin/static/js/main.js
Executable file → Normal file
0
web/pgadmin/static/js/vendor/bootstrap.js
vendored
Executable file → Normal file
0
web/pgadmin/static/js/vendor/bootstrap.js
vendored
Executable file → Normal file
0
web/pgadmin/static/js/vendor/bootstrap.min.js
vendored
Executable file → Normal file
0
web/pgadmin/static/js/vendor/bootstrap.min.js
vendored
Executable file → Normal file
0
web/pgadmin/static/js/vendor/jquery-1.11.1.min.js
vendored
Executable file → Normal file
0
web/pgadmin/static/js/vendor/jquery-1.11.1.min.js
vendored
Executable file → Normal file
0
web/pgadmin/static/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js
vendored
Executable file → Normal file
0
web/pgadmin/static/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js
vendored
Executable file → Normal file
0
web/pgadmin/static/js/vendor/npm.js
vendored
Executable file → Normal file
0
web/pgadmin/static/js/vendor/npm.js
vendored
Executable file → Normal file
13
web/pgadmin/templates/security/change_password.html
Normal file
13
web/pgadmin/templates/security/change_password.html
Normal file
@ -0,0 +1,13 @@
|
||||
{% extends "security/panel.html" %}
|
||||
{% block panel_title %}pgAdmin Password Change{% endblock %}
|
||||
{% block panel_body %}
|
||||
<form action="{{ url_for_security('change_password') }}" method="POST" name="change_password_form">
|
||||
{{ change_password_form.hidden_tag() }}
|
||||
<fieldset>
|
||||
{{ render_field_with_errors(change_password_form.password, "password") }}
|
||||
{{ render_field_with_errors(change_password_form.new_password, "password") }}
|
||||
{{ render_field_with_errors(change_password_form.new_password_confirm, "password") }}
|
||||
<input class="btn btn-lg btn-success btn-block" type="submit" value="Change Password">
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
10
web/pgadmin/templates/security/fields.html
Normal file
10
web/pgadmin/templates/security/fields.html
Normal file
@ -0,0 +1,10 @@
|
||||
{% macro render_field_with_errors(field, type) %}
|
||||
<div class="form-group{% if field.errors %} has-error{% endif %}">
|
||||
<input class="form-control" placeholder="{{ field.label.text }}" name="{{ field.name }}" type="{{ type }}">
|
||||
</div>
|
||||
{% if field.errors %}
|
||||
{% for error in field.errors %}
|
||||
<span class="help-block">{{ error }}</span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
12
web/pgadmin/templates/security/forgot_password.html
Normal file
12
web/pgadmin/templates/security/forgot_password.html
Normal file
@ -0,0 +1,12 @@
|
||||
{% extends "security/panel.html" %}
|
||||
{% block panel_title %}Recover pgAdmin Password{% endblock %}
|
||||
{% block panel_body %}
|
||||
<p>Enter the email address for the user account you wish to recover the password for:</p>
|
||||
<form action="{{ url_for_security('forgot_password') }}" method="POST" name="forgot_password_form">
|
||||
{{ forgot_password_form.hidden_tag() }}
|
||||
<fieldset>
|
||||
{{ render_field_with_errors(forgot_password_form.email, "text") }}
|
||||
<input class="btn btn-lg btn-success btn-block" type="submit" value="Recover Password">
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
13
web/pgadmin/templates/security/login_user.html
Normal file
13
web/pgadmin/templates/security/login_user.html
Normal file
@ -0,0 +1,13 @@
|
||||
{% extends "security/panel.html" %}
|
||||
{% block panel_title %}pgAdmin Login{% endblock %}
|
||||
{% block panel_body %}
|
||||
<form action="{{ url_for_security('login') }}" method="POST" name="login_user_form">
|
||||
{{ login_user_form.hidden_tag() }}
|
||||
<fieldset>
|
||||
{{ render_field_with_errors(login_user_form.email, "text") }}
|
||||
{{ render_field_with_errors(login_user_form.password, "password") }}
|
||||
<input class="btn btn-lg btn-success btn-block" type="submit" value="Login">
|
||||
</fieldset>
|
||||
</form>
|
||||
<span class="help-block">Forgotten your <a href="{{ url_for('security.forgot_password') }}">password</a>?</span>
|
||||
{% endblock %}
|
12
web/pgadmin/templates/security/messages.html
Normal file
12
web/pgadmin/templates/security/messages.html
Normal file
@ -0,0 +1,12 @@
|
||||
{%- with messages = get_flashed_messages(with_categories=true) -%}
|
||||
{% if messages %}
|
||||
<div style="position: fixed; top: 20px; right: 20px; width: 400px; z-index: 9999">
|
||||
{% for category, message in messages %}
|
||||
<div class="alert alert-{{ category }} alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- endwith %}
|
21
web/pgadmin/templates/security/panel.html
Normal file
21
web/pgadmin/templates/security/panel.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% extends "base.html" %}
|
||||
{% from "security/fields.html" import render_field_with_errors %}
|
||||
{% block body %}
|
||||
<div class="container">
|
||||
{% include "security/messages.html" %}
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-md-offset-4">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% block panel_title %}{% endblock %}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% block panel_body %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'security/watermark.html' %}
|
||||
{% endblock %}
|
12
web/pgadmin/templates/security/reset_password.html
Normal file
12
web/pgadmin/templates/security/reset_password.html
Normal file
@ -0,0 +1,12 @@
|
||||
{% extends "security/panel.html" %}
|
||||
{% block panel_title %}pgAdmin Password Reset{% endblock %}
|
||||
{% block panel_body %}
|
||||
<form action="{{ url_for_security('reset_password', token=reset_password_token) }}" method="POST" name="reset_password_form">
|
||||
{{ reset_password_form.hidden_tag() }}
|
||||
<fieldset>
|
||||
{{ render_field_with_errors(reset_password_form.password, "password") }}
|
||||
{{ render_field_with_errors(reset_password_form.password_confirm, "password") }}
|
||||
<input class="btn btn-lg btn-success btn-block" type="submit" value="Reset Password">
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
5
web/pgadmin/templates/security/watermark.html
Normal file
5
web/pgadmin/templates/security/watermark.html
Normal file
@ -0,0 +1,5 @@
|
||||
{% block watermark %}
|
||||
<div style="position: fixed; bottom: 0; right: 0;">
|
||||
<img src="img/logo-right-256.png" alt="pgAdmin 4">
|
||||
</div>
|
||||
{% endblock %}
|
@ -12,6 +12,7 @@ MODULE_NAME = 'utils'
|
||||
|
||||
import config
|
||||
from flask import Blueprint, render_template
|
||||
from flask.ext.security import login_required
|
||||
from time import time, ctime
|
||||
|
||||
# Initialise the module
|
||||
@ -21,6 +22,7 @@ blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', static_url
|
||||
# A test page
|
||||
##########################################################################
|
||||
@blueprint.route("/test")
|
||||
@login_required
|
||||
def test():
|
||||
"""Generate a simple test page to demonstrate that output can be rendered."""
|
||||
output = """
|
||||
|
37
web/settings_model.py
Normal file
37
web/settings_model.py
Normal file
@ -0,0 +1,37 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2014, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""Defines the models for the configuration database."""
|
||||
|
||||
from flask.ext.sqlalchemy import SQLAlchemy
|
||||
from flask.ext.security import UserMixin, RoleMixin
|
||||
|
||||
db = SQLAlchemy()
|
||||
|
||||
# Define models
|
||||
roles_users = db.Table('roles_users',
|
||||
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
|
||||
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
|
||||
|
||||
class Role(db.Model, RoleMixin):
|
||||
"""Define a security role"""
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
name = db.Column(db.String(80), unique=True)
|
||||
description = db.Column(db.String(255))
|
||||
|
||||
class User(db.Model, UserMixin):
|
||||
"""Define a user object"""
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
email = db.Column(db.String(255), unique=True)
|
||||
password = db.Column(db.String(255))
|
||||
active = db.Column(db.Boolean())
|
||||
active = db.Column(db.Boolean())
|
||||
confirmed_at = db.Column(db.DateTime())
|
||||
roles = db.relationship('Role', secondary=roles_users,
|
||||
backref=db.backref('users', lazy='dynamic'))
|
74
web/setup.py
Normal file
74
web/setup.py
Normal file
@ -0,0 +1,74 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2014, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""Perform the initial setup of the application, by creating the auth
|
||||
and settings database."""
|
||||
|
||||
from flask import Flask
|
||||
from flask.ext.sqlalchemy import SQLAlchemy
|
||||
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
|
||||
|
||||
# Configuration settings
|
||||
import config
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(config)
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + config.SQLITE_PATH.replace('\\', '/')
|
||||
db.init_app(app)
|
||||
|
||||
print "pgAdmin 4 - Application Initialisation"
|
||||
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 "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, tell the user and exit.
|
||||
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: ")
|
||||
|
||||
pprompt = lambda: (getpass.getpass(), getpass.getpass('Retype password: '))
|
||||
|
||||
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)
|
||||
security = Security(app, user_datastore)
|
||||
|
||||
with app.app_context():
|
||||
password = encrypt_password(p1)
|
||||
|
||||
db.create_all()
|
||||
user_datastore.create_role(name='Administrators', description='pgAdmin Administrators Role')
|
||||
user_datastore.create_user(email=email, password=password)
|
||||
user_datastore.add_role_to_user(email, 'Administrators')
|
||||
db.session.commit()
|
||||
|
||||
# Done!
|
||||
print ""
|
||||
print "The configuration database has been created at %s" % config.SQLITE_PATH
|
Loading…
Reference in New Issue
Block a user