Added support for storing configurations of pgAdmin in an external database. #1832

This commit is contained in:
Akshay Joshi 2022-10-20 16:18:41 +05:30 committed by GitHub
parent d50e9f7fc2
commit e17c50d304
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 963 additions and 1062 deletions

View File

@ -44,7 +44,7 @@ the **Flask-Security** module to manage application security and users, and
provides options for self-service password reset and password changes etc.
Whether in desktop or server mode, each user's settings are stored in a SQLite
database which is also used to store the user accounts. This is initially
OR external database which is also used to store the user accounts. This is initially
created using the **setup.py** script which will create the database file and
schema within it, and add the first user account (with administrative
privileges) and a default server group for them. A **settings** table is also

View File

@ -0,0 +1,63 @@
.. _external_database:
****************************************************
`External database for pgAdmin configuration`:index:
****************************************************
The configurations used by pgAdmin are stored in the SQLite database.
There are many settings stored in this database, like preferences,
user accounts, auto-discovered servers, and many more.
In SQLite, the database is stored in a single file that may be located anywhere
in the directory, which means it is not prepared for failure (no HA support).
In addition, it is not designed to handle many connections reading/writing data
concurrently.
pgAdmin added support for storing configurations in an external database to
prevent this.
Added the 'CONFIG_DATABASE_URI' parameter in the :ref:`config.py <config_py>`
file.
Use SQLite Database
*******************
To use SQLite Database, make sure CONFIG_DATABASE_URI is empty string, such as
''.
Use External Database
*********************
If you want to use an external database, make sure the CONFIG_DATABASE_URI
format is "dialect+driver://username:password@host:port/database".
**Note** It is recommended to create the database in advance.
Use PostgreSQL Database
***********************
Following are the formats to use PostgreSQL as an external database.
Basic syntax:
.. code-block:: bash
postgresql://username:password@host:port/database
Using specific schema (It is recommended to create the schema in advance):
.. code-block:: bash
postgresql://username:password@host:port/database?options=-csearch_path=<schema name>
Using default pgpass path for the service account:
.. code-block:: bash
postgresql://username@host:port?options=-csearch_path=<schema name>
Specifying pgpass file path:
.. code-block:: bash
postgresql://username@host:port?passfile=<path of the pgpass file>&options=-csearch_path=<schema name>

View File

@ -16,6 +16,7 @@ of database objects.
:maxdepth: 2
getting_started
external_database
connecting
managing_cluster_objects
managing_database_objects
@ -31,4 +32,4 @@ of database objects.
.. note:: Postgres, PostgreSQL and the Slonik Logo are trademarks or
registered trademarks of the `PostgreSQL Community Association of Canada
<https://www.postgres.ca/>`_, and used with their permission.
<https://www.postgres.ca/>`_, and used with their permission.

View File

@ -11,8 +11,8 @@ passwords. This is applicable only for desktop mode users.
the first time after starting the application.
* Once you set the master password, all the existing saved passwords will be
re-encrypted using the master password.
* The server passwords which are saved in the SQLite DB file are encrypted and
decrypted using the master password.
* The server passwords which are saved in the SQLite DB file or External
Database are encrypted and decrypted using the master password.
.. image:: images/master_password_set.png
:alt: Set master password

View File

@ -11,6 +11,7 @@ notes for it.
.. toctree::
:maxdepth: 1
release_notes_6_16
release_notes_6_15
release_notes_6_14
release_notes_6_13

View File

@ -0,0 +1,26 @@
************
Version 6.16
************
Release date: 2022-11-17
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v6.15.
Supported Database Servers
**************************
**PostgreSQL**: 10, 11, 12, 13, 14 and 15
**EDB Advanced Server**: 10, 11, 12, 13, 14 and 15
New features
************
| `Issue #1832 <https://github.com/pgadmin-org/pgadmin4/issues/1832>`_ - Added support for storing configurations of pgAdmin in an external database.
Housekeeping
************
Bug fixes
*********

View File

@ -26,7 +26,9 @@ When Administrator itself gets locked, following steps may be considered to rest
OR
By updating SQLite DB (pgAdmin4.db):
By updating configuration database
SQLite DB (pgAdmin4.db):
* Locate the pgAdmin4.db file and open it using any DB Browser (or DB Browser for SQLite)
* After opening the DB file, head towards 'Execute SQL' section.
@ -34,6 +36,13 @@ By updating SQLite DB (pgAdmin4.db):
*UPDATE USER SET LOCKED = false, LOGIN_ATTEMPTS = 0 WHERE USERNAME = <YOUR_EMAIL_ID>*
External database:
* Connect to the database.
* Run below query -
*UPDATE USER SET LOCKED = false, LOGIN_ATTEMPTS = 0 WHERE USERNAME = <YOUR_EMAIL_ID>*
* Make sure the query changes are committed.
Account locking by failed login attempts:
@ -47,4 +56,4 @@ exceeded.
MAX_LOGIN_ATTEMPTS is defaulted to 3 unsuccessful login attempts, after which the account would be locked.
The only way to restore the user account is by contacting the Administrator and ask to unlock it.
The only way to restore the user account is by contacting the Administrator and ask to unlock it.

View File

@ -306,6 +306,23 @@ PG_DEFAULT_DRIVER = 'psycopg2'
# for the particular session. (in minutes)
MAX_SESSION_IDLE_TIME = 60
##########################################################################
# External Database Settings
#
# All configuration settings are stored by default in the SQLite database.
# In order to use external databases like PostgreSQL sets the value of
# CONFIG_DATABASE_URI like below:
# dialect+driver://username:password@host:port/database
#
# PostgreSQL:
# postgresql://username:password@host:port/database
# Specify Schema Name
# postgresql://username:password@host:port/database?options=-csearch_path=pgadmin
# Using PGPASS file
# postgresql://username@host:port?options=-csearch_path=pgadmin
##########################################################################
CONFIG_DATABASE_URI = ''
##########################################################################
# User account and settings storage
##########################################################################

View File

@ -24,8 +24,9 @@ logger = logging.getLogger('alembic.env')
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from flask import current_app
config.set_main_option('sqlalchemy.url',
current_app.config.get('SQLALCHEMY_DATABASE_URI'))
db_url_escaped = \
current_app.config.get('SQLALCHEMY_DATABASE_URI').replace('%', '%%')
config.set_main_option('sqlalchemy.url', db_url_escaped)
target_metadata = current_app.extensions['migrate'].db.metadata
# other values from the config, defined by the needs of env.py,
@ -87,6 +88,7 @@ def run_migrations_online():
finally:
connection.close()
if context.is_offline_mode():
run_migrations_offline()
else:

View File

@ -14,7 +14,8 @@ Revises: ef590e979b0d
Create Date: 2017-11-14 19:09:04.674575
"""
from pgadmin.model import db
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '02b9dccdcfcb'
@ -24,12 +25,8 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN bgcolor TEXT(10)'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN fgcolor TEXT(10)'
)
op.add_column('server', sa.Column('bgcolor', sa.String(length=10)))
op.add_column('server', sa.Column('fgcolor', sa.String(length=10)))
def downgrade():

View File

@ -16,11 +16,11 @@ Create Date: 2017-03-13 12:27:30.543908
"""
import base64
import os
import sys
import config
import sqlalchemy as sa
from alembic import op
from pgadmin.model import db, Server
from pgadmin.setup import get_version
from pgadmin.setup import get_version_for_migration
# revision identifiers, used by Alembic.
@ -31,211 +31,147 @@ depends_on = None
def upgrade():
version = get_version()
version = get_version_for_migration(op)
# Changes introduced in schema version 2
if version < 2:
# Create the 'server' table
db.metadata.create_all(db.engine, tables=[Server.__table__])
if version < 3:
db.engine.execute(
'ALTER TABLE server ADD COLUMN comment TEXT(1024)'
)
op.add_column('server', sa.Column('comment', sa.String(length=1024)))
if version < 4:
db.engine.execute(
'ALTER TABLE server ADD COLUMN password TEXT(64)'
)
op.add_column('server', sa.Column('password', sa.String(length=64)))
if version < 5:
db.engine.execute('ALTER TABLE server ADD COLUMN role text(64)')
op.add_column('server', sa.Column('role', sa.String(length=64)))
if version < 6:
# To Save previous data, create temp table
db.engine.execute("create table server_old as select * from server")
db.engine.execute("DROP TABLE server")
db.engine.execute("""
CREATE TABLE server (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
servergroup_id INTEGER NOT NULL,
name VARCHAR(128) NOT NULL,
host VARCHAR(128) NOT NULL,
port INTEGER NOT NULL CHECK (port >= 1024 AND port <= 65534),
maintenance_db VARCHAR(64) NOT NULL,
username VARCHAR(64) NOT NULL,
ssl_mode VARCHAR(16) NOT NULL CHECK (
ssl_mode IN (
'allow', 'prefer', 'require', 'disable', 'verify-ca', 'verify-full'
)),
comment VARCHAR(1024), password TEXT(64), role text(64),
PRIMARY KEY (id),
FOREIGN KEY(user_id) REFERENCES user (id),
FOREIGN KEY(servergroup_id) REFERENCES servergroup (id)
)""")
db.engine.execute("""
INSERT INTO server (
id, user_id, servergroup_id, name, host, port, maintenance_db, username,
ssl_mode, comment, password, role
) SELECT
id, user_id, servergroup_id, name, host, port, maintenance_db, username,
ssl_mode, comment, password, role
FROM server_old""")
db.engine.execute("DROP TABLE server_old")
with op.batch_alter_table("server") as batch_op:
batch_op.create_check_constraint(
"ck_port_range",
"port >= 1024 AND port <= 65535"
)
batch_op.create_check_constraint(
"ck_ssl_mode",
"ssl_mode IN ('allow', 'prefer', 'require', 'disable', \
'verify-ca', 'verify-full')"
)
if version < 8:
db.engine.execute("""
CREATE TABLE module_preference(
id INTEGER PRIMARY KEY,
name VARCHAR(256) NOT NULL
)""")
op.create_table(
'module_preference',
sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
sa.Column('name', sa.String(length=256), nullable=False),
sa.PrimaryKeyConstraint('id'))
db.engine.execute("""
CREATE TABLE preference_category(
id INTEGER PRIMARY KEY,
mid INTEGER,
name VARCHAR(256) NOT NULL,
op.create_table(
'preference_category',
sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
sa.Column('mid', sa.Integer(),),
sa.Column('name', sa.String(length=256), nullable=False),
sa.ForeignKeyConstraint(['mid'], ['module_preference.id'], ),
sa.PrimaryKeyConstraint('id'))
FOREIGN KEY(mid) REFERENCES module_preference(id)
)""")
op.create_table(
'preferences',
sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
sa.Column('cid', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=256), nullable=False),
sa.ForeignKeyConstraint(['cid'], ['preference_category.id'], ),
sa.PrimaryKeyConstraint('id'))
db.engine.execute("""
CREATE TABLE preferences (
id INTEGER PRIMARY KEY,
cid INTEGER NOT NULL,
name VARCHAR(256) NOT NULL,
FOREIGN KEY(cid) REFERENCES preference_category (id)
)""")
db.engine.execute("""
CREATE TABLE user_preferences (
pid INTEGER,
uid INTEGER,
value VARCHAR(1024) NOT NULL,
PRIMARY KEY (pid, uid),
FOREIGN KEY(pid) REFERENCES preferences (pid),
FOREIGN KEY(uid) REFERENCES user (id)
)""")
op.create_table(
'user_preferences',
sa.Column('pid', sa.Integer(), nullable=False),
sa.Column('uid', sa.Integer(), nullable=False),
sa.Column('value', sa.String(length=1024), nullable=False),
sa.ForeignKeyConstraint(['pid'], ['preferences.id'], ),
sa.ForeignKeyConstraint(['uid'], ['user.id'], ),
sa.PrimaryKeyConstraint('pid', 'uid'))
if version < 9:
db.engine.execute("""
CREATE TABLE IF NOT EXISTS debugger_function_arguments (
server_id INTEGER ,
database_id INTEGER ,
schema_id INTEGER ,
function_id INTEGER ,
arg_id INTEGER ,
is_null INTEGER NOT NULL CHECK (is_null >= 0 AND is_null <= 1) ,
is_expression INTEGER NOT NULL CHECK (is_expression >= 0 AND is_expression <= 1) ,
use_default INTEGER NOT NULL CHECK (use_default >= 0 AND use_default <= 1) ,
value TEXT,
PRIMARY KEY (server_id, database_id, schema_id, function_id, arg_id)
)""")
op.create_table(
'debugger_function_arguments',
sa.Column('server_id', sa.Integer(), nullable=False),
sa.Column('database_id', sa.Integer(), nullable=False),
sa.Column('schema_id', sa.Integer(), nullable=False),
sa.Column('function_id', sa.Integer(), nullable=False),
sa.Column('arg_id', sa.Integer(), nullable=False),
sa.Column('is_null', sa.Integer(), nullable=False),
sa.Column('is_expression', sa.Integer(), nullable=False),
sa.Column('use_default', sa.Integer()),
sa.Column('value', sa.String(), nullable=False),
sa.CheckConstraint('is_null >= 0 AND is_null <= 1'),
sa.CheckConstraint('is_expression >= 0 AND is_expression <= 1'),
sa.CheckConstraint('use_default >= 0 AND use_default <= 1'),
sa.PrimaryKeyConstraint('server_id', 'database_id', 'schema_id',
'function_id', 'arg_id'))
if version < 10:
db.engine.execute("""
CREATE TABLE process(
user_id INTEGER NOT NULL,
pid TEXT NOT NULL,
desc TEXT NOT NULL,
command TEXT NOT NULL,
arguments TEXT,
start_time TEXT,
end_time TEXT,
logdir TEXT,
exit_code INTEGER,
acknowledge TEXT,
PRIMARY KEY(pid),
FOREIGN KEY(user_id) REFERENCES user (id)
)""")
op.create_table(
'process',
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('pid', sa.String(), nullable=False),
sa.Column('desc', sa.String(), nullable=False),
sa.Column('command', sa.String(), nullable=False),
sa.Column('arguments', sa.String()),
sa.Column('start_time', sa.String()),
sa.Column('end_time', sa.String()),
sa.Column('logdir', sa.String()),
sa.Column('exit_code', sa.Integer()),
sa.Column('acknowledge', sa.String()),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('pid'))
if version < 11:
db.engine.execute("""
UPDATE role
SET name = 'Administrator',
description = 'pgAdmin Administrator Role'
WHERE name = 'Administrators'
""")
# get metadata from current connection
meta = sa.MetaData(bind=op.get_bind())
# define table representation
meta.reflect(only=('role',))
role_table = sa.Table('role', meta)
db.engine.execute("""
INSERT INTO role ( name, description )
VALUES ('User', 'pgAdmin User Role')
""")
op.execute(
role_table.update().where(role_table.c.name == 'Administrators')
.values(name='Administrator',
description='pgAdmin Administrator Role'))
if version < 12:
db.engine.execute("create table server_old as select * from server")
db.engine.execute("DROP TABLE server")
db.engine.execute("""
CREATE TABLE server (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
servergroup_id INTEGER NOT NULL,
name VARCHAR(128) NOT NULL,
host VARCHAR(128) NOT NULL,
port INTEGER NOT NULL CHECK (port >= 1024 AND port <= 65535),
maintenance_db VARCHAR(64) NOT NULL,
username VARCHAR(64) NOT NULL,
ssl_mode VARCHAR(16) NOT NULL CHECK (
ssl_mode IN (
'allow', 'prefer', 'require', 'disable', 'verify-ca', 'verify-full'
)),
comment VARCHAR(1024), password TEXT(64), role text(64),
PRIMARY KEY (id),
FOREIGN KEY(user_id) REFERENCES user (id),
FOREIGN KEY(servergroup_id) REFERENCES servergroup (id)
)""")
db.engine.execute("""
INSERT INTO server (
id, user_id, servergroup_id, name, host, port, maintenance_db, username,
ssl_mode, comment, password, role
) SELECT
id, user_id, servergroup_id, name, host, port, maintenance_db, username,
ssl_mode, comment, password, role
FROM server_old""")
db.engine.execute("DROP TABLE server_old")
op.bulk_insert(role_table,
[{'name': 'User', 'description': 'pgAdmin User Role'}])
if version < 13:
db.engine.execute("""
ALTER TABLE SERVER
ADD COLUMN discovery_id TEXT
""")
op.add_column('server', sa.Column('discovery_id', sa.String()))
if version < 14:
db.engine.execute("""
CREATE TABLE keys (
name TEST NOT NULL,
value TEXT NOT NULL,
PRIMARY KEY (name))
""")
sql = "INSERT INTO keys (name, value) VALUES ('CSRF_SESSION_KEY', '%s')" % base64.urlsafe_b64encode(
os.urandom(32)).decode()
db.engine.execute(sql)
keys_table = op.create_table(
'keys',
sa.Column('name', sa.String(), nullable=False),
sa.Column('value', sa.String(), nullable=False),
sa.PrimaryKeyConstraint('name'))
secret_key = base64.urlsafe_b64encode(os.urandom(32)).decode()
if hasattr(config, 'SECRET_KEY'):
sql = "INSERT INTO keys (name, value) VALUES ('SECRET_KEY', '%s')" % config.SECRET_KEY
else:
sql = "INSERT INTO keys (name, value) VALUES ('SECRET_KEY', '%s')" % base64.urlsafe_b64encode(
os.urandom(32)).decode()
db.engine.execute(sql)
secret_key = config.SECRET_KEY
# If SECURITY_PASSWORD_SALT is not in the config, but we're upgrading, then it must (unless the
# user edited the main config - which they shouldn't have done) have been at it's default
# value, so we'll use that. Otherwise, use whatever we can find in the config.
# If SECURITY_PASSWORD_SALT is not in the config, but we're upgrading,
# then it must (unless the user edited the main config - which they
# shouldn't have done) have been at it's default value, so we'll use
# that. Otherwise, use whatever we can find in the config.
security_password_salt = 'SuperSecret3'
if hasattr(config, 'SECURITY_PASSWORD_SALT'):
sql = "INSERT INTO keys (name, value) VALUES ('SECURITY_PASSWORD_SALT', '%s')" % config.SECURITY_PASSWORD_SALT
else:
sql = "INSERT INTO keys (name, value) VALUES ('SECURITY_PASSWORD_SALT', 'SuperSecret3')"
db.engine.execute(sql)
security_password_salt = config.SECURITY_PASSWORD_SALT
db.engine.execute(
'UPDATE version set value="%s" WHERE name = "ConfigDB"' % config.SETTINGS_SCHEMA_VERSION
)
op.bulk_insert(keys_table,
[{'name': 'CSRF_SESSION_KEY', 'value':
base64.urlsafe_b64encode(os.urandom(32)).decode()},
{'name': 'SECRET_KEY', 'value': secret_key},
{'name': 'SECURITY_PASSWORD_SALT',
'value': security_password_salt}])
# get metadata from current connection
meta = sa.MetaData(bind=op.get_bind())
# define table representation
meta.reflect(only=('version',))
version_table = sa.Table('version', meta)
op.execute(
version_table.update().where(version_table.c.name == 'ConfigDB')
.values(value=config.SETTINGS_SCHEMA_VERSION))
# ### end Alembic commands ###

View File

@ -14,8 +14,8 @@ Revises: 15c88f765bc8
Create Date: 2022-01-04 13:08:05.484598
"""
from pgadmin.model import db
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '1586db67b98e'
@ -25,12 +25,10 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE process ADD COLUMN server_id INTEGER DEFAULT 0'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN cloud_status INTEGER DEFAULT 0'
)
op.add_column('process', sa.Column('server_id', sa.Integer(),
server_default='0'))
op.add_column('server', sa.Column('cloud_status', sa.Integer(),
server_default='0'))
def downgrade():

View File

@ -16,8 +16,8 @@ Revises: 6650c52670c2
Create Date: 2021-11-24 17:33:12.533825
"""
from pgadmin.model import db
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '15c88f765bc8'
@ -27,15 +27,13 @@ depends_on = None
def upgrade():
db.engine.execute("""
CREATE TABLE user_mfa(
user_id INTEGER NOT NULL,
mfa_auth VARCHAR(256) NOT NULL,
options TEXT,
PRIMARY KEY (user_id, mfa_auth),
FOREIGN KEY(user_id) REFERENCES user (id)
)
""")
op.create_table(
'user_mfa', sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('mfa_auth', sa.String(length=256), nullable=False),
sa.Column('options', sa.String()),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('user_id', 'mfa_auth'))
# ### end Alembic commands ###

View File

@ -1,17 +1,20 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: 35f29b1701bd
Revises: ec1cac3399c9
Create Date: 2019-04-26 16:38:08.368471
"""
import base64
import os
import sys
from pgadmin.model import db, Server
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '35f29b1701bd'
@ -21,33 +24,12 @@ depends_on = None
def upgrade():
db.engine.execute("create table user_old as select * from user")
db.engine.execute("DROP TABLE user")
db.engine.execute("""
CREATE TABLE user (
id INTEGER NOT NULL,
email VARCHAR(256) NOT NULL,
password VARCHAR(256),
active BOOLEAN NOT NULL,
confirmed_at DATETIME,
masterpass_check VARCHAR(256),
PRIMARY KEY (id),
UNIQUE (email),
CHECK (active IN (0, 1))
);
""")
db.engine.execute("""
INSERT INTO user (
id, email, password, active, confirmed_at
) SELECT
id, email, password, active, confirmed_at
FROM user_old""")
db.engine.execute("DROP TABLE user_old")
op.add_column('user', sa.Column('masterpass_check', sa.String(length=256)))
with op.batch_alter_table("user") as batch_op:
batch_op.create_check_constraint(
"ck_active_range",
"active IN (true, false)"
)
def downgrade():

View File

@ -1,12 +1,20 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: 398697dc9550
Revises: a091c9611d20
Create Date: 2020-09-07 15:17:59.473879
"""
from pgadmin.model import db
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '398697dc9550'
@ -16,39 +24,49 @@ depends_on = None
def upgrade():
db.engine.execute("""
CREATE TABLE macros (
id INTEGER NOT NULL,
alt BOOLEAN NOT NULL,
control BOOLEAN NOT NULL,
key VARCHAR(128) NOT NULL,
key_code INTEGER NOT NULL,
PRIMARY KEY(id)
);
""")
macro_table = op.create_table(
'macros',
sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
sa.Column('alt', sa.Boolean(), nullable=False),
sa.Column('control', sa.Boolean(), nullable=False),
sa.Column('key', sa.String(length=128), nullable=False),
sa.Column('key_code', sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('id'))
db.engine.execute("""
CREATE TABLE user_macros (
mid INTEGER NOT NULL,
uid INTEGER NOT NULL,
name VARCHAR(1024) NOT NULL,
sql TEXT NOT NULL,
PRIMARY KEY(mid, uid),
FOREIGN KEY(mid) REFERENCES macros (id),
FOREIGN KEY(uid) REFERENCES user (id)
);
""")
op.create_table(
'user_macros',
sa.Column('mid', sa.Integer(), nullable=False),
sa.Column('uid', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=1024), nullable=False),
sa.Column('sql', sa.String()),
sa.ForeignKeyConstraint(['mid'], ['macros.id']),
sa.ForeignKeyConstraint(['uid'], ['user.id']),
sa.PrimaryKeyConstraint('mid', 'uid'))
db.engine.execute("""
INSERT INTO macros (id, alt, control, key, key_code) VALUES (1, 0, 1, '1', 49),
(2, 0, 1, '2', 50), (3, 0, 1, '3', 51), (4, 0, 1, '4', 52),
(5, 0, 1, '5', 53), (6, 0, 1, '6', 54), (7, 0, 1, '7', 55),
(8, 0, 1, '8', 56), (9, 0, 1, '9', 57), (10, 0, 1, '0', 48),
(11, 1, 0, 'F1', 112), (12, 1, 0, 'F2', 113), (13, 1, 0, 'F3', 114),
(14, 1, 0, 'F4', 115), (15, 1, 0, 'F5', 116), (16, 1, 0, 'F6', 117),
(17, 1, 0, 'F7', 118), (18, 1, 0, 'F8', 119), (19, 1, 0, 'F9', 120),
(20, 1, 0, 'F10', 121), (21, 1, 0, 'F11', 122), (22, 1, 0, 'F12', 123);
""")
op.bulk_insert(macro_table, [
{'alt': 0, 'control': 1, 'key': '1', 'key_code': 49},
{'alt': 0, 'control': 1, 'key': '2', 'key_code': 50},
{'alt': 0, 'control': 1, 'key': '3', 'key_code': 51},
{'alt': 0, 'control': 1, 'key': '4', 'key_code': 52},
{'alt': 0, 'control': 1, 'key': '5', 'key_code': 53},
{'alt': 0, 'control': 1, 'key': '6', 'key_code': 54},
{'alt': 0, 'control': 1, 'key': '7', 'key_code': 55},
{'alt': 0, 'control': 1, 'key': '8', 'key_code': 56},
{'alt': 0, 'control': 1, 'key': '9', 'key_code': 57},
{'alt': 0, 'control': 1, 'key': '0', 'key_code': 48},
{'alt': 1, 'control': 0, 'key': 'F1', 'key_code': 112},
{'alt': 1, 'control': 0, 'key': 'F2', 'key_code': 113},
{'alt': 1, 'control': 0, 'key': 'F3', 'key_code': 114},
{'alt': 1, 'control': 0, 'key': 'F4', 'key_code': 115},
{'alt': 1, 'control': 0, 'key': 'F5', 'key_code': 116},
{'alt': 1, 'control': 0, 'key': 'F6', 'key_code': 117},
{'alt': 1, 'control': 0, 'key': 'F7', 'key_code': 118},
{'alt': 1, 'control': 0, 'key': 'F8', 'key_code': 119},
{'alt': 1, 'control': 0, 'key': 'F9', 'key_code': 120},
{'alt': 1, 'control': 0, 'key': 'F10', 'key_code': 121},
{'alt': 1, 'control': 0, 'key': 'F11', 'key_code': 122},
{'alt': 1, 'control': 0, 'key': 'F12', 'key_code': 123}
])
def downgrade():

View File

@ -1,5 +1,12 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: 3c1e4b6eda55
Revises: 09d53fca90c7
@ -7,7 +14,8 @@ Create Date: 2017-06-13 17:05:30.671859
"""
from pgadmin.model import db
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '3c1e4b6eda55'
@ -17,9 +25,7 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN hostaddr TEXT(1024)'
)
op.add_column('server', sa.Column('hostaddr', sa.String(length=1024)))
def downgrade():

View File

@ -7,14 +7,13 @@
#
##########################################################################
"""empty message
"""
Revision ID: 3ce25f562f3b
Revises: 6650c52670c2
Create Date: 2021-12-01 11:52:09.037749
"""
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = '3ce25f562f3b'
@ -24,18 +23,8 @@ depends_on = None
def upgrade():
# Rename user table to user_old and again user_old to user to change
# the foreign key refernce of user_old table which is not exists
db.engine.execute("ALTER TABLE user RENAME TO user_old")
db.engine.execute("ALTER TABLE user_old RENAME TO user")
# Rename server table to server_old and again server_old to server to change
# the foreign key refernce of server_old table which is not exists
db.engine.execute("ALTER TABLE server RENAME TO server_old")
db.engine.execute("ALTER TABLE server_old RENAME TO server")
# After using alembic the old logic is not required.
pass
def downgrade():

View File

@ -1,5 +1,12 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: 493cd3e39c0c
Revises: 7c56ea250085
@ -8,8 +15,6 @@ Create Date: 2018-06-18 11:26:33.285037
"""
from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = '493cd3e39c0c'
@ -19,9 +24,8 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN connect_timeout INTEGER DEFAULT 0'
)
op.add_column('server', sa.Column('connect_timeout', sa.Integer(),
server_default='0'))
def downgrade():

View File

@ -1,4 +1,11 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""Added service field option in server table (RM#3140)
Revision ID: 50aad68f99c2
@ -6,8 +13,8 @@ Revises: 02b9dccdcfcb
Create Date: 2018-03-07 11:53:57.584280
"""
from pgadmin.model import db
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '50aad68f99c2'
@ -17,69 +24,10 @@ depends_on = None
def upgrade():
# To Save previous data, create temp table
db.engine.execute("create table server_old as select * from server")
db.engine.execute("DROP TABLE server")
# With service file some fields won't be mandatory as user can provide
# them using service file. Removed NOT NULL constraint from few columns
db.engine.execute("""
CREATE TABLE server (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
servergroup_id INTEGER NOT NULL,
name VARCHAR(128) NOT NULL,
host VARCHAR(128),
port INTEGER NOT NULL CHECK(port >= 1024 AND port <= 65534),
maintenance_db VARCHAR(64),
username VARCHAR(64) NOT NULL,
password VARCHAR(64),
role VARCHAR(64),
ssl_mode VARCHAR(16) NOT NULL CHECK(ssl_mode IN
( 'allow' , 'prefer' , 'require' , 'disable' ,
'verify-ca' , 'verify-full' )
),
comment VARCHAR(1024),
discovery_id VARCHAR(128),
hostaddr TEXT(1024),
db_res TEXT,
passfile TEXT,
sslcert TEXT,
sslkey TEXT,
sslrootcert TEXT,
sslcrl TEXT,
sslcompression INTEGER DEFAULT 0,
bgcolor TEXT(10),
fgcolor TEXT(10),
PRIMARY KEY(id),
FOREIGN KEY(user_id) REFERENCES user(id),
FOREIGN KEY(servergroup_id) REFERENCES servergroup(id)
)
""")
# Copy old data again into table
db.engine.execute("""
INSERT INTO server (
id,user_id, servergroup_id, name, host, port, maintenance_db,
username, ssl_mode, comment, password, role, discovery_id,
hostaddr, db_res, passfile, sslcert, sslkey, sslrootcert, sslcrl,
bgcolor, fgcolor
) SELECT
id,user_id, servergroup_id, name, host, port, maintenance_db,
username, ssl_mode, comment, password, role, discovery_id,
hostaddr, db_res, passfile, sslcert, sslkey, sslrootcert, sslcrl,
bgcolor, fgcolor
FROM server_old""")
# Remove old data
db.engine.execute("DROP TABLE server_old")
# Add column for Service
db.engine.execute(
'ALTER TABLE server ADD COLUMN service TEXT'
)
op.add_column('server', sa.Column('service', sa.String()))
with op.batch_alter_table("server") as batch_op:
batch_op.alter_column('host', nullable=True)
batch_op.alter_column('maintenance_db', nullable=True)
def downgrade():

View File

@ -17,10 +17,7 @@ Create Date: 2021-07-10 18:12:38.821602
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
from pgadmin import db
revision = '6650c52670c2'
down_revision = 'c465fee44968'
branch_labels = None
@ -28,12 +25,10 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE user ADD COLUMN locked BOOLEAN DEFAULT FALSE'
)
db.engine.execute(
'ALTER TABLE user ADD COLUMN login_attempts int DEFAULT 0'
)
op.add_column('user', sa.Column('locked', sa.Boolean(),
server_default='false'))
op.add_column('user', sa.Column('login_attempts', sa.Integer(),
server_default='0'))
def downgrade():

View File

@ -1,4 +1,11 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""Change server port constraint to allow port below 1024 RM#3307
Revision ID: 7c56ea250085
@ -7,9 +14,6 @@ Create Date: 2018-06-04 14:23:31.472645
"""
from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = '7c56ea250085'
@ -19,75 +23,12 @@ depends_on = None
def upgrade():
# To Save previous data, create temp table
db.engine.execute("create table server_old as select * from server")
db.engine.execute("DROP TABLE server")
# Create table with new constraint definition
db.engine.execute("""
CREATE TABLE server (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
servergroup_id INTEGER NOT NULL,
name VARCHAR(128) NOT NULL,
host VARCHAR(128),
port INTEGER NOT NULL CHECK(port >= 1 AND port <= 65534),
maintenance_db VARCHAR(64),
username VARCHAR(64) NOT NULL,
password VARCHAR(64),
role VARCHAR(64),
ssl_mode VARCHAR(16) NOT NULL CHECK(ssl_mode IN
( 'allow' , 'prefer' , 'require' , 'disable' ,
'verify-ca' , 'verify-full' )
),
comment VARCHAR(1024),
discovery_id VARCHAR(128),
hostaddr TEXT(1024),
db_res TEXT,
passfile TEXT,
sslcert TEXT,
sslkey TEXT,
sslrootcert TEXT,
sslcrl TEXT,
sslcompression INTEGER DEFAULT 0,
bgcolor TEXT(10),
fgcolor TEXT(10),
service TEXT,
use_ssh_tunnel INTEGER DEFAULT 0,
tunnel_host TEXT,
tunnel_port TEXT,
tunnel_username TEXT,
tunnel_authentication INTEGER DEFAULT 0,
tunnel_identity_file TEXT,
PRIMARY KEY(id),
FOREIGN KEY(user_id) REFERENCES user(id),
FOREIGN KEY(servergroup_id) REFERENCES servergroup(id)
with op.batch_alter_table("server") as batch_op:
batch_op.drop_constraint('ck_port_range')
batch_op.create_check_constraint(
"ck_port_range",
"port >= 1 AND port <= 65535"
)
""")
# Copy old data again into table
db.engine.execute("""
INSERT INTO server (
id, user_id, servergroup_id, name, host, port, maintenance_db,
username, password, role, ssl_mode, comment, discovery_id, hostaddr,
db_res, passfile, sslcert, sslkey, sslrootcert, sslcrl,
sslcompression, bgcolor, fgcolor, service, use_ssh_tunnel,
tunnel_host, tunnel_port, tunnel_username, tunnel_authentication,
tunnel_identity_file
) SELECT
id, user_id, servergroup_id, name, host, port, maintenance_db,
username, password, role, ssl_mode, comment, discovery_id, hostaddr,
db_res, passfile, sslcert, sslkey, sslrootcert, sslcrl,
sslcompression, bgcolor, fgcolor, service, use_ssh_tunnel,
tunnel_host, tunnel_port, tunnel_username, tunnel_authentication,
tunnel_identity_file
FROM server_old""")
# Remove old data
db.engine.execute("DROP TABLE server_old")
def downgrade():

View File

@ -1,5 +1,12 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: 7fedf8531802
Revises: aff1436e3c8c
@ -8,7 +15,6 @@ Create Date: 2020-02-26 11:24:54.353288
"""
from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = '7fedf8531802'
@ -18,35 +24,25 @@ depends_on = None
def upgrade():
op.add_column('user', sa.Column('username', sa.String(length=256),
nullable=False, server_default=''))
op.add_column('user', sa.Column('auth_source', sa.String(length=256),
nullable=False, server_default='internal'))
with op.batch_alter_table("user") as batch_op:
batch_op.alter_column('email', nullable=True)
batch_op.drop_constraint('user_unique_constraint')
batch_op.create_unique_constraint('user_unique_constraint',
['username', 'auth_source'])
db.engine.execute("create table user_old as select * from user")
# For internal email is a user name, so update the existing records.
meta = sa.MetaData(bind=op.get_bind())
# define table representation
meta.reflect(only=('user',))
user_table = sa.Table('user', meta)
db.engine.execute("DROP TABLE user")
db.engine.execute("""
CREATE TABLE user (
id INTEGER NOT NULL,
username VARCHAR(256) NOT NULL,
email VARCHAR(256),
password VARCHAR(256),
active BOOLEAN NOT NULL,
confirmed_at DATETIME,
masterpass_check VARCHAR(256),
auth_source VARCHAR(256) NOT NULL DEFAULT 'internal',
PRIMARY KEY (id),
UNIQUE (username, auth_source),
CHECK (active IN (0, 1))
);
""")
db.engine.execute("""
INSERT INTO user (
id, username, email, password, active, confirmed_at, masterpass_check
) SELECT
id, email, email, password, active, confirmed_at, masterpass_check
FROM user_old""")
db.engine.execute("DROP TABLE user_old")
op.execute(
user_table.update().values(username=user_table.c.email)
)
def downgrade():

View File

@ -1,5 +1,12 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: 81c7ffeffeee
Revises: 398697dc9550
@ -7,8 +14,8 @@ Create Date: 2020-11-02 09:46:51.250338
"""
from alembic import op
import sqlalchemy as sa
from pgadmin.model import db, Preferences
from sqlalchemy.orm.session import Session
from pgadmin.model import Preferences
# revision identifiers, used by Alembic.
@ -23,22 +30,22 @@ def upgrade():
Delete older preferences open new tab for Query tool, Debugger,
and Schema diff.
"""
qt_open_tab_setting = Preferences.query.filter_by(
session = Session(bind=op.get_bind())
qt_open_tab_setting = session.query(Preferences).filter_by(
name='new_browser_tab').order_by(Preferences.id.desc()).first()
debugger_tab_setting = Preferences.query.filter_by(
debugger_tab_setting = session.query(Preferences).filter_by(
name='debugger_new_browser_tab').order_by(Preferences.id.desc()).first()
schema_diff_tab_setting = Preferences.query.filter_by(
schema_diff_tab_setting = session.query(Preferences).filter_by(
name='schema_diff_new_browser_tab').order_by(
Preferences.id.desc()).first()
if qt_open_tab_setting:
db.session.delete(qt_open_tab_setting)
session.delete(qt_open_tab_setting)
if debugger_tab_setting:
db.session.delete(debugger_tab_setting)
session.delete(debugger_tab_setting)
if schema_diff_tab_setting:
db.session.delete(schema_diff_tab_setting)
db.session.commit()
session.delete(schema_diff_tab_setting)
def downgrade():

View File

@ -1,13 +1,20 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: 84700139beb0
Revises: d39482714a2e
Create Date: 2020-06-24 15:53:56.489518
"""
from pgadmin.model import db
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '84700139beb0'
@ -17,15 +24,13 @@ depends_on = None
def upgrade():
db.engine.execute("""
CREATE TABLE "database" (
"id" INTEGER NOT NULL,
"schema_res" TEXT,
"server" INTEGER NOT NULL,
PRIMARY KEY("id","server"),
FOREIGN KEY("server") REFERENCES "server"("id")
);
""")
op.create_table(
'database',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('schema_res', sa.String()),
sa.Column('server', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['server'], ['server.id'], ),
sa.PrimaryKeyConstraint('id', 'server'))
def downgrade():

View File

@ -1,13 +1,20 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: a091c9611d20
Revises: 84700139beb0
Create Date: 2020-07-14 17:20:22.705737
"""
from pgadmin.model import db
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = 'a091c9611d20'
@ -17,55 +24,54 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN shared BOOLEAN'
)
op.add_column('server', sa.Column('shared', sa.Boolean()))
op.create_table(
'sharedserver',
sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('server_owner', sa.String(length=64)),
sa.Column('servergroup_id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('host', sa.String(length=128)),
sa.Column('port', sa.Integer(), nullable=False),
sa.Column('maintenance_db', sa.String(length=64)),
sa.Column('username', sa.String(length=64)),
sa.Column('password', sa.String(length=64)),
sa.Column('role', sa.String(length=64)),
sa.Column('ssl_mode', sa.String(length=16), nullable=False),
sa.Column('comment', sa.String(length=1024)),
sa.Column('discovery_id', sa.String(length=128)),
sa.Column('hostaddr', sa.String(length=1024)),
sa.Column('db_res', sa.String()),
sa.Column('passfile', sa.String()),
sa.Column('sslcert', sa.String()),
sa.Column('sslkey', sa.String()),
sa.Column('sslrootcert', sa.String()),
sa.Column('sslcrl', sa.String()),
sa.Column('sslcompression', sa.Integer(), server_default='0'),
sa.Column('bgcolor', sa.String(length=10)),
sa.Column('fgcolor', sa.String(length=10)),
sa.Column('service', sa.String()),
sa.Column('use_ssh_tunnel', sa.Integer(), server_default='0'),
sa.Column('tunnel_host', sa.String()),
sa.Column('tunnel_port', sa.String()),
sa.Column('tunnel_username', sa.String()),
sa.Column('tunnel_authentication', sa.Integer(), server_default='0'),
sa.Column('tunnel_identity_file', sa.String()),
sa.Column('shared', sa.Boolean(), nullable=False),
sa.Column('save_password', sa.Boolean(), nullable=False),
sa.Column('tunnel_password', sa.String(length=64)),
sa.Column('connect_timeout', sa.Integer()),
sa.CheckConstraint("ssl_mode IN ('allow', 'prefer', 'require', \
'disable', 'verify-ca', 'verify-full')"),
sa.ForeignKeyConstraint(['servergroup_id'], ['servergroup.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id'))
db.engine.execute("""
CREATE TABLE sharedserver (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
server_owner VARCHAR(64),
servergroup_id INTEGER NOT NULL,
name VARCHAR(128) NOT NULL,
host VARCHAR(128),
port INTEGER NOT NULL CHECK(port >= 1 AND port <= 65534),
maintenance_db VARCHAR(64),
username VARCHAR(64),
password VARCHAR(64),
role VARCHAR(64),
ssl_mode VARCHAR(16) NOT NULL CHECK(ssl_mode IN
( 'allow' , 'prefer' , 'require' , 'disable' ,
'verify-ca' , 'verify-full' )
),
comment VARCHAR(1024),
discovery_id VARCHAR(128),
hostaddr TEXT(1024),
db_res TEXT,
passfile TEXT,
sslcert TEXT,
sslkey TEXT,
sslrootcert TEXT,
sslcrl TEXT,
sslcompression INTEGER DEFAULT 0,
bgcolor TEXT(10),
fgcolor TEXT(10),
service TEXT,
use_ssh_tunnel INTEGER DEFAULT 0,
tunnel_host TEXT,
tunnel_port TEXT,
tunnel_username TEXT,
tunnel_authentication INTEGER DEFAULT 0,
tunnel_identity_file TEXT,
shared BOOLEAN NOT NULL,
save_password BOOLEAN NOT NULL,
tunnel_password VARCHAR(64),
connect_timeout INTEGER ,
PRIMARY KEY(id),
FOREIGN KEY(user_id) REFERENCES user(id),
FOREIGN KEY(servergroup_id) REFERENCES servergroup(id)
);
""")
# Named constraint
with op.batch_alter_table("sharedserver") as batch_op:
batch_op.create_check_constraint('ck_shared_server_port',
'port >= 1024 AND port <= 65535')
def downgrade():

View File

@ -1,13 +1,19 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: a39bd015b644
Revises: 81c7ffeffeee
Create Date: 2021-01-12 15:46:49.283021
"""
from pgadmin.model import db
from alembic import op
# revision identifiers, used by Alembic.
revision = 'a39bd015b644'
@ -17,84 +23,10 @@ depends_on = None
def upgrade():
# To Save previous data, create temp table
db.engine.execute("create table sharedserver_old as "
"select * from sharedserver")
db.engine.execute("DROP TABLE sharedserver")
# Create new table with removed not null constraints for port column.
db.engine.execute("""
CREATE TABLE sharedserver (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
server_owner VARCHAR(64),
servergroup_id INTEGER NOT NULL,
name VARCHAR(128) NOT NULL,
host VARCHAR(128),
port INTEGER,
maintenance_db VARCHAR(64),
username VARCHAR(64),
password VARCHAR(64),
role VARCHAR(64),
ssl_mode VARCHAR(16) NOT NULL CHECK(ssl_mode IN
( 'allow' , 'prefer' , 'require' , 'disable' ,
'verify-ca' , 'verify-full' )
),
comment VARCHAR(1024),
discovery_id VARCHAR(128),
hostaddr TEXT(1024),
db_res TEXT,
passfile TEXT,
sslcert TEXT,
sslkey TEXT,
sslrootcert TEXT,
sslcrl TEXT,
sslcompression INTEGER DEFAULT 0,
bgcolor TEXT(10),
fgcolor TEXT(10),
service TEXT,
use_ssh_tunnel INTEGER DEFAULT 0,
tunnel_host TEXT,
tunnel_port TEXT,
tunnel_username TEXT,
tunnel_authentication INTEGER DEFAULT 0,
tunnel_identity_file TEXT,
shared BOOLEAN NOT NULL,
save_password BOOLEAN NOT NULL,
tunnel_password VARCHAR(64),
connect_timeout INTEGER ,
PRIMARY KEY(id),
FOREIGN KEY(user_id) REFERENCES user(id),
FOREIGN KEY(servergroup_id) REFERENCES servergroup(id)
);
""")
# Copy old data again into table.
db.engine.execute("""
INSERT INTO sharedserver (
id, user_id, server_owner, servergroup_id, name, host, port,
maintenance_db, username, password, role, ssl_mode, comment,
discovery_id, hostaddr, db_res, passfile, sslcert, sslkey,
sslrootcert, sslcrl, sslcompression, bgcolor, fgcolor, service,
use_ssh_tunnel, tunnel_host, tunnel_port, tunnel_username,
tunnel_authentication, tunnel_identity_file, shared, save_password,
tunnel_password, connect_timeout
) SELECT
id, user_id, server_owner, servergroup_id, name, host, port,
maintenance_db, username, password, role, ssl_mode, comment,
discovery_id, hostaddr, db_res, passfile, sslcert, sslkey,
sslrootcert, sslcrl, sslcompression, bgcolor, fgcolor, service,
use_ssh_tunnel, tunnel_host, tunnel_port, tunnel_username,
tunnel_authentication, tunnel_identity_file, shared, save_password,
tunnel_password, connect_timeout
FROM sharedserver_old""")
# Drop older table.
db.engine.execute("DROP TABLE sharedserver_old")
with op.batch_alter_table("sharedserver") as batch_op:
batch_op.drop_constraint('ck_shared_server_port')
batch_op.alter_column('port', nullable=True)
batch_op.alter_column('maintenance_db', nullable=True)
def downgrade():

View File

@ -1,4 +1,11 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""Added columns for SSH tunneling
Revision ID: a68b374fe373
@ -8,7 +15,6 @@ Create Date: 2018-04-05 13:59:57.588355
"""
from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = 'a68b374fe373'
@ -18,24 +24,14 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN use_ssh_tunnel INTEGER DEFAULT 0'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN tunnel_host TEXT'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN tunnel_port TEXT'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN tunnel_username TEXT'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN tunnel_authentication INTEGER DEFAULT 0'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN tunnel_identity_file TEXT'
)
op.add_column('server', sa.Column('use_ssh_tunnel', sa.Integer(),
server_default='0'))
op.add_column('server', sa.Column('tunnel_host', sa.String()))
op.add_column('server', sa.Column('tunnel_port', sa.String()))
op.add_column('server', sa.Column('tunnel_username', sa.String()))
op.add_column('server', sa.Column('tunnel_authentication', sa.Integer(),
server_default='0'))
op.add_column('server', sa.Column('tunnel_identity_file', sa.String()))
def downgrade():

View File

@ -1,4 +1,11 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""Change the not null constraints for port, username as it should not
compulsory when service is provided. RM #4642
@ -8,8 +15,6 @@ Create Date: 2019-09-09 15:41:30.084753
"""
from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = 'a77a0932a568'
@ -19,74 +24,11 @@ depends_on = None
def upgrade():
# To Save previous data, create temp table
db.engine.execute("create table server_old as select * from server")
db.engine.execute("DROP TABLE server")
# Create table with drop constraint for port and username definition
db.engine.execute("""
CREATE TABLE server (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
servergroup_id INTEGER NOT NULL,
name VARCHAR(128) NOT NULL,
host VARCHAR(128),
port INTEGER,
maintenance_db VARCHAR(64) NOT NULL,
username VARCHAR(64),
password VARCHAR(64),
role VARCHAR(64),
ssl_mode VARCHAR(16) NOT NULL CHECK(ssl_mode IN
( 'allow' , 'prefer' , 'require' , 'disable' ,
'verify-ca' , 'verify-full' )
),
comment VARCHAR(1024),
discovery_id VARCHAR(128),
hostaddr TEXT(1024),
db_res TEXT,
passfile TEXT,
sslcert TEXT,
sslkey TEXT,
sslrootcert TEXT,
sslcrl TEXT,
sslcompression INTEGER DEFAULT 0,
bgcolor TEXT(10),
fgcolor TEXT(10),
service TEXT,
use_ssh_tunnel INTEGER DEFAULT 0,
tunnel_host TEXT,
tunnel_port TEXT,
tunnel_username TEXT,
tunnel_authentication INTEGER DEFAULT 0,
tunnel_identity_file TEXT, connect_timeout INTEGER DEFAULT 0, tunnel_password TEXT(64),
PRIMARY KEY(id),
FOREIGN KEY(user_id) REFERENCES user(id),
FOREIGN KEY(servergroup_id) REFERENCES servergroup(id)
)
""")
# Copy old data again into table
db.engine.execute("""
INSERT INTO server (
id, user_id, servergroup_id, name, host, port, maintenance_db,
username, password, role, ssl_mode, comment, discovery_id, hostaddr,
db_res, passfile, sslcert, sslkey, sslrootcert, sslcrl,
sslcompression, bgcolor, fgcolor, service, use_ssh_tunnel,
tunnel_host, tunnel_port, tunnel_username, tunnel_authentication,
tunnel_identity_file
) SELECT
id, user_id, servergroup_id, name, host, port, maintenance_db,
username, password, role, ssl_mode, comment, discovery_id, hostaddr,
db_res, passfile, sslcert, sslkey, sslrootcert, sslcrl,
sslcompression, bgcolor, fgcolor, service, use_ssh_tunnel,
tunnel_host, tunnel_port, tunnel_username, tunnel_authentication,
tunnel_identity_file
FROM server_old""")
# Remove old data
db.engine.execute("DROP TABLE server_old")
# Port and Username can be null if service is provided.
with op.batch_alter_table("server") as batch_op:
batch_op.drop_constraint('ck_port_range')
batch_op.alter_column('port', nullable=True)
batch_op.alter_column('username', nullable=True)
def downgrade():

View File

@ -13,7 +13,8 @@ Revises: 493cd3e39c0c
Create Date: 2018-07-26 11:19:50.879849
"""
from pgadmin.model import db
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'aa86fb60b73d'
@ -23,9 +24,7 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN tunnel_password TEXT(64)'
)
op.add_column('server', sa.Column('tunnel_password', sa.String(length=64)))
def downgrade():

View File

@ -1,4 +1,11 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
""" Update the default timeout to 10 seconds instead on 0.
0 indicates wait indefinitely which causes trouble when network connection
to server is lost.
@ -8,7 +15,8 @@ Revises: a77a0932a568
Create Date: 2019-10-28 12:47:36.828709
"""
from pgadmin.model import db
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'aff1436e3c8c'
@ -18,8 +26,15 @@ depends_on = None
def upgrade():
db.engine.execute(
'UPDATE server SET connect_timeout=10 WHERE connect_timeout=0 OR connect_timeout IS NULL'
# get metadata from current connection
meta = sa.MetaData(bind=op.get_bind())
# define table representation
meta.reflect(only=('server',))
server_table = sa.Table('server', meta)
op.execute(
server_table.update().where(server_table.c.connect_timeout == 0 or
server_table.c.connect_timeout is None)
.values(connect_timeout=10)
)

View File

@ -14,7 +14,8 @@ Revises: ece2e76bf60e
Create Date: 2018-10-24 12:37:59.487969
"""
from pgadmin.model import db
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'b5b87fdfcb30'
@ -24,9 +25,8 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE process ADD COLUMN process_state INTEGER DEFAULT 0'
)
op.add_column('process', sa.Column('process_state', sa.Integer(),
server_default='0'))
def downgrade():

View File

@ -1,13 +1,20 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: c465fee44968
Revises: d0bc9f32b2b9
Create Date: 2021-06-04 14:42:12.843116
"""
from pgadmin.model import db, User
from sqlalchemy.sql import text
from alembic import op
import sqlalchemy as sa
import uuid
@ -19,46 +26,20 @@ depends_on = None
def upgrade():
op.add_column('user', sa.Column('fs_uniquifier', sa.String(),
nullable=True))
db.engine.execute("create table user_old as select * from user")
meta = sa.MetaData(bind=op.get_bind())
# define table representation
meta.reflect(only=('user',))
user_table = sa.Table('user', meta)
db.engine.execute("DROP TABLE user")
op.execute(
user_table.update().values(fs_uniquifier=uuid.uuid4().hex)
)
with op.batch_alter_table("user") as batch_op:
batch_op.alter_column('fs_uniquifier', nullable=False)
db.engine.execute("""
CREATE TABLE user (
id INTEGER NOT NULL,
username VARCHAR(256) NOT NULL,
email VARCHAR(256),
password VARCHAR(256),
active BOOLEAN NOT NULL,
confirmed_at DATETIME,
masterpass_check VARCHAR(256),
auth_source VARCHAR(256) NOT NULL DEFAULT 'internal',
fs_uniquifier NOT NULL UNIQUE,
PRIMARY KEY (id),
UNIQUE (username, auth_source),
CHECK (active IN (0, 1))
);
""")
user_old = db.engine.execute(
'select id, username, email, password, active, '
'confirmed_at, masterpass_check, auth_source '
'from user_old')
statement = text("""
INSERT INTO user(id, username, email, password, active,
confirmed_at, masterpass_check, auth_source, fs_uniquifier)
VALUES(:id, :username, :email, :password, :active, :confirmed_at,
:masterpass_check, :auth_source, :fs_uniquifier)""")
db.engine.execute(statement, [
{
**row,
'fs_uniquifier': uuid.uuid4().hex
} for row in user_old
])
db.engine.execute("DROP TABLE user_old")
def downgrade():
# pgAdmin only upgrades, downgrade not implemented.

View File

@ -1,13 +1,20 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: c6974f64df08
Revises: a39bd015b644
Create Date: 2021-04-22 10:06:21.282770
"""
from pgadmin.model import db
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
@ -18,9 +25,7 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE sharedserver ADD COLUMN osid INTEGER'
)
op.add_column('sharedserver', sa.Column('osid', sa.Integer()))
def downgrade():

View File

@ -14,8 +14,9 @@ Revises: aa86fb60b73d
Create Date: 2018-08-29 15:33:57.855491
"""
from pgadmin.model import db
from alembic import op
from sqlalchemy.orm.session import Session
from pgadmin.model import DebuggerFunctionArguments
# revision identifiers, used by Alembic.
revision = 'ca00ec32581b'
@ -25,9 +26,11 @@ depends_on = None
def upgrade():
db.engine.execute(
'DELETE FROM debugger_function_arguments'
)
session = Session(bind=op.get_bind())
debugger_records = session.query(DebuggerFunctionArguments).all()
if debugger_records:
session.delete(debugger_records)
def downgrade():

View File

@ -1,5 +1,12 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: d0bc9f32b2b9
Revises: c6974f64df08
@ -8,7 +15,6 @@ Create Date: 2021-04-27 12:40:08.899712
"""
from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = 'd0bc9f32b2b9'
@ -18,9 +24,8 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN kerberos_conn INTEGER DEFAULT 0'
)
op.add_column('server', sa.Column('kerberos_conn', sa.Boolean(),
server_default='false'))
def downgrade():

View File

@ -16,7 +16,6 @@ Create Date: 2020-04-09 13:20:13.939775
"""
from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = 'd39482714a2e'
@ -26,22 +25,21 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN save_password INTEGER DEFAULT 0'
)
op.add_column('server', sa.Column('save_password', sa.Integer(),
server_default='0'))
# If password is already exists for any existing server then change the
# save_password column to 1 (True) else set 0
db.engine.execute(
"""
UPDATE server SET save_password = (
CASE WHEN password IS NOT NULL AND password != '' THEN
1
ELSE
0
END
)
"""
)
# get metadata from current connection
meta = sa.MetaData(bind=op.get_bind())
# define table representation
meta.reflect(only=('server',))
server_table = sa.Table('server', meta)
op.execute(
server_table.update().values(save_password=sa.case(
(server_table.c.password != 'NULL' and
server_table.c.password != '', 1), else_=0)
))
def downgrade():

View File

@ -1,13 +1,20 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: d85a62333272
Revises: 3c1e4b6eda55
Create Date: 2017-07-07 16:03:23.842734
"""
from pgadmin.model import db
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = 'd85a62333272'
@ -17,9 +24,7 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN db_res TEXT'
)
op.add_column('server', sa.Column('db_res', sa.String()))
def downgrade():

View File

@ -1,13 +1,21 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""empty message
"""
Revision ID: ec1cac3399c9
Revises: b5b87fdfcb30
Create Date: 2019-03-07 16:05:28.874203
"""
from pgadmin.model import db
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'ec1cac3399c9'
@ -15,27 +23,19 @@ down_revision = 'b5b87fdfcb30'
branch_labels = None
depends_on = None
srno = db.Column(db.Integer(), nullable=False, primary_key=True)
uid = db.Column(
db.Integer, db.ForeignKey('user.id'), nullable=False, primary_key=True
)
sid = db.Column(db.Integer(), nullable=False, primary_key=True)
did = db.Column(db.Integer(), nullable=False, primary_key=True)
query = db.Column(db.String(), nullable=False)
def upgrade():
db.engine.execute("""
CREATE TABLE query_history (
srno INTEGER NOT NULL,
uid INTEGER NOT NULL,
sid INTEGER NOT NULL,
dbname TEXT NOT NULL,
query_info TEXT NOT NULL,
last_updated_flag TEXT NOT NULL,
PRIMARY KEY (srno, uid, sid, dbname),
FOREIGN KEY(uid) REFERENCES user (id),
FOREIGN KEY(sid) REFERENCES server (id)
)""")
op.create_table(
'query_history',
sa.Column('srno', sa.Integer(), nullable=False),
sa.Column('uid', sa.Integer(), nullable=False),
sa.Column('sid', sa.Integer(), nullable=False),
sa.Column('dbname', sa.String(), nullable=False),
sa.Column('query_info', sa.String(), nullable=False),
sa.Column('last_updated_flag', sa.String(), nullable=False),
sa.ForeignKeyConstraint(['sid'], ['server.id']),
sa.ForeignKeyConstraint(['uid'], ['user.id']),
sa.PrimaryKeyConstraint('srno', 'uid', 'sid', 'dbname'))
def downgrade():

View File

@ -15,7 +15,8 @@ Create Date: 2018-10-18 14:45:13.483068
"""
from pgadmin.model import db
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'ece2e76bf60e'
@ -25,9 +26,7 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE process ADD COLUMN utility_pid INTEGER'
)
op.add_column('process', sa.Column('utility_pid', sa.Integer()))
def downgrade():

View File

@ -1,5 +1,12 @@
"""empty message
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""
Revision ID: ef590e979b0d
Revises: d85a62333272
@ -8,7 +15,6 @@ Create Date: 2017-08-23 18:37:14.836988
"""
from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = 'ef590e979b0d'
@ -18,28 +24,13 @@ depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN passfile TEXT'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN sslcert TEXT'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN sslkey TEXT'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN sslrootcert TEXT'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN sslcrl TEXT'
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN sslcompression '
'INTEGER default 0'
)
db.engine.execute(
'UPDATE server SET sslcompression=0'
)
op.add_column('server', sa.Column('passfile', sa.String()))
op.add_column('server', sa.Column('sslcert', sa.String()))
op.add_column('server', sa.Column('sslkey', sa.String()))
op.add_column('server', sa.Column('sslrootcert', sa.String()))
op.add_column('server', sa.Column('sslcrl', sa.String()))
op.add_column('server', sa.Column('sslcompression', sa.Integer(),
server_default='0'))
def downgrade():

View File

@ -1,4 +1,11 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2022, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""Encrypt the existing user password.
Revision ID: f195f9a4923d
@ -10,6 +17,8 @@ import config
from flask import current_app
from flask_security import Security, SQLAlchemyUserDatastore
from flask_security.utils import verify_and_update_password
from alembic import op
from sqlalchemy.orm.session import Session
from pgadmin.model import Keys, db, User, Role
# revision identifiers, used by Alembic.
@ -21,8 +30,9 @@ depends_on = None
def upgrade():
app = current_app
db.session.flush()
current_salt = Keys.query.filter_by(name = 'SECURITY_PASSWORD_SALT').first().value
session = Session(bind=op.get_bind())
current_salt = session.query(Keys).filter_by(
name='SECURITY_PASSWORD_SALT').first().value
app.config.update(dict(SECURITY_PASSWORD_SALT=current_salt))
app.config['SECURITY_PASSWORD_HASH'] = config.SECURITY_PASSWORD_HASH
@ -32,7 +42,7 @@ def upgrade():
else:
app.config['SECURITY_PASSWORD_SALT'] = current_salt
users = User.query.with_entities(
users = session.query(User).with_entities(
User.id, User.email, User.password, User.active, User.confirmed_at)\
.all()
# This will upgrade the plaintext password of all the user as per the
@ -41,8 +51,6 @@ def upgrade():
if user.password is not None:
verify_and_update_password(user.password, user)
db.session.commit()
def downgrade():
# pgAdmin only upgrades, downgrade not implemented.

View File

@ -16,7 +16,8 @@ Revises: 1586db67b98e
Create Date: 2022-10-11 11:25:00.000000
"""
from pgadmin.model import db
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = 'f79844e926ae'
@ -26,12 +27,8 @@ depends_on = None
def upgrade():
db.engine.execute("""
ALTER TABLE server ADD COLUMN passexec_cmd TEXT(256) null
""")
db.engine.execute("""
ALTER TABLE server ADD COLUMN passexec_expiration INT null
""")
op.add_column('server', sa.Column('passexec_cmd', sa.String(length=256)))
op.add_column('server', sa.Column('passexec_expiration', sa.Integer()))
# ### end Alembic commands ###

View File

@ -24,7 +24,6 @@ from flask import current_app
from flask_security import Security, SQLAlchemyUserDatastore
from flask_security.utils import hash_password
from pgadmin.model import db, User, Role
from pgadmin.setup import get_version
from pgadmin.setup import user_info
# revision identifiers, used by Alembic.
@ -36,80 +35,69 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
if get_version() != -1:
return
email, password = user_info()
op.create_table('version',
sa.Column('name', sa.String(length=32), nullable=False),
sa.Column('value', sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('name')
)
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('email', sa.String(length=256), nullable=False),
sa.Column('password', sa.String(length=256), nullable=True),
sa.Column('active', sa.Boolean(), nullable=False),
sa.Column('confirmed_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email')
)
op.create_table('role',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('description', sa.String(length=256), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
)
op.create_table('setting',
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('setting', sa.String(length=256), nullable=False),
sa.Column('value', sa.String(length=1024), nullable=True),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('user_id', 'setting')
)
op.create_table('roles_users',
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('role_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['role_id'], ['role.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], )
)
op.create_table('servergroup',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('user_id', 'name')
)
op.create_table('server',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('servergroup_id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('host', sa.String(length=128), nullable=False),
sa.Column('port', sa.Integer(), nullable=False),
sa.Column('maintenance_db', sa.String(length=64), nullable=False),
sa.Column('username', sa.String(length=64), nullable=False),
sa.Column('ssl_mode', sa.String(length=16), nullable=False),
sa.ForeignKeyConstraint(['servergroup_id'], ['servergroup.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
db.engine.execute("""
INSERT INTO "role"
VALUES(1, 'Administrators', 'pgAdmin Administrators Role')
""")
db.engine.execute("""
INSERT INTO "roles_users"
VALUES(1, 1);
""")
db.engine.execute("""
INSERT INTO "servergroup"
VALUES(1, 1, 'Servers')
""")
version_table = op.create_table(
'version', sa.Column('name', sa.String(length=32), nullable=False),
sa.Column('value', sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('name'))
user_table = op.create_table(
'user',
sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
sa.Column('email', sa.String(length=256), nullable=False),
sa.Column('password', sa.String(length=256), nullable=True),
sa.Column('active', sa.Boolean(), nullable=False),
sa.Column('confirmed_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id'))
with op.batch_alter_table("user") as batch_op:
batch_op.create_unique_constraint('user_unique_constraint', ['email'])
role_table = op.create_table(
'role',
sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('description', sa.String(length=256), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name'))
op.create_table(
'setting', sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('setting', sa.String(length=256), nullable=False),
sa.Column('value', sa.String(length=1024), nullable=True),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('user_id', 'setting'))
roles_users_table = op.create_table(
'roles_users', sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('role_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['role_id'], ['role.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ))
server_group_table = op.create_table(
'servergroup',
sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('user_id', 'name'))
op.create_table(
'server',
sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('servergroup_id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=False),
sa.Column('host', sa.String(length=128), nullable=False),
sa.Column('port', sa.Integer(), nullable=False),
sa.Column('maintenance_db', sa.String(length=64), nullable=False),
sa.Column('username', sa.String(length=64), nullable=False),
sa.Column('ssl_mode', sa.String(length=16), nullable=False),
sa.ForeignKeyConstraint(['servergroup_id'], ['servergroup.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id'))
current_salt = getattr(
config, 'SECURITY_PASSWORD_SALT', base64.urlsafe_b64encode(
@ -135,16 +123,23 @@ VALUES(1, 1, 'Servers')
setattr(config, 'SECRET_KEY', secret_key)
password = hash_password(password)
db.engine.execute("""
INSERT INTO "user"
VALUES(1, '%s',
'%s',
1, NULL)
""" % (email, password))
db.engine.execute("""
INSERT INTO "version"
VALUES('ConfigDB', 2);
""")
op.bulk_insert(user_table,
[{'email': email, 'password': password,
'active': 1, 'confirmed_at': None}])
op.bulk_insert(version_table,
[{'name': 'ConfigDB', 'value': 2}])
op.bulk_insert(role_table,
[{'name': 'Administrators',
'description': 'pgAdmin Administrators Role'}])
op.bulk_insert(roles_users_table,
[{'user_id': 1, 'role_id': 1}])
op.bulk_insert(server_group_table,
[{'user_id': 1, 'name': 'Servers'}])
# ### end Alembic commands ###

View File

@ -341,11 +341,14 @@ def create_app(app_name=None):
##########################################################################
# Setup authentication
##########################################################################
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///{0}?timeout={1}' \
.format(config.SQLITE_PATH.replace('\\', '/'),
getattr(config, 'SQLITE_TIMEOUT', 500)
)
if config.CONFIG_DATABASE_URI is not None and \
len(config.CONFIG_DATABASE_URI) > 0:
app.config['SQLALCHEMY_DATABASE_URI'] = config.CONFIG_DATABASE_URI
else:
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'] = \
@ -358,6 +361,9 @@ def create_app(app_name=None):
##########################################################################
# Upgrade the schema (if required)
##########################################################################
from config import SQLITE_PATH
from pgadmin.setup import db_upgrade
def backup_db_file():
"""
Create a backup of the current database file
@ -396,48 +402,76 @@ def create_app(app_name=None):
' database'.format(invalid_tb_names))
backup_db_file()
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:
upgrade_db()
def run_migration_for_sqlite():
with app.app_context():
# Run migration for the first time i.e. create database
# 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:
upgrade_db()
else:
if not os.path.exists(SQLITE_PATH):
raise FileNotFoundError(
'SQLite database file "' + SQLITE_PATH +
'" does not exists.')
raise RuntimeError(
'The configuration database file is not valid.')
else:
if not os.path.exists(SQLITE_PATH):
raise FileNotFoundError(
'SQLite database file "' + SQLITE_PATH +
'" does not exists.')
raise RuntimeError(
'The configuration database file is not valid.')
else:
schema_version = get_version()
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:
upgrade_db()
else:
# check all tables are present in the db.
is_db_error, invalid_tb_names = check_db_tables()
if is_db_error:
app.logger.error(
'Table(s) {0} are missing in the'
' database'.format(invalid_tb_names))
backup_db_file()
# Run migration if current schema version is greater than the
# schema version stored in version table
if CURRENT_SCHEMA_VERSION >= schema_version:
upgrade_db()
else:
# check all tables are present in the db.
is_db_error, invalid_tb_names = check_db_tables()
if is_db_error:
app.logger.error(
'Table(s) {0} are missing in the'
' database'.format(invalid_tb_names))
backup_db_file()
# Update schema version to the latest
if CURRENT_SCHEMA_VERSION > schema_version:
set_version(CURRENT_SCHEMA_VERSION)
db.session.commit()
# 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)
if os.name != 'nt':
os.chmod(config.SQLITE_PATH, 0o600)
def run_migration_for_others():
with app.app_context():
# Run migration for the first time i.e. create database
# If version not available, user must have aborted. Tables are not
# created and so its an empty db
try:
if get_version() == -1:
db_upgrade(app)
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()
except Exception as e:
app.logger.error(e)
# Run the migration as per specified by the user.
if config.CONFIG_DATABASE_URI is not None and \
len(config.CONFIG_DATABASE_URI) > 0:
run_migration_for_others()
else:
run_migration_for_sqlite()
Mail(app)
@ -553,7 +587,7 @@ def create_app(app_name=None):
user_id=user_id
).order_by("id")
if servergroups.count() > 0:
if int(servergroups.count()) > 0:
servergroup = servergroups.first()
servergroup_id = servergroup.id
@ -567,7 +601,7 @@ def create_app(app_name=None):
discovery_id=svr_discovery_id
).order_by("id")
if servers.count() > 0:
if int(servers.count()) > 0:
return
svr = Server(user_id=user_id,

View File

@ -347,7 +347,7 @@ def mfa_delete(auth_name: str) -> bool:
user_id=current_user.id, mfa_auth=auth_name
)
if auth.count() != 0:
if int(auth.count()) != 0:
auth.delete()
db.session.commit()

View File

@ -831,7 +831,8 @@ class ServerNode(PGChildNodeView):
# Delete the shared server from DB if server
# owner uncheck shared property
self.delete_shared_server(server.name, gid, server.id)
if arg == 'sslcompression':
if arg in ('sslcompression', 'use_ssh_tunnel',
'tunnel_authentication', 'kerberos_conn', 'shared'):
value = 1 if value else 0
self._update_server_details(server, sharedserver,
config_param_map, arg, value)
@ -1091,11 +1092,12 @@ class ServerNode(PGChildNodeView):
fgcolor=data.get('fgcolor', None),
service=data.get('service', None),
connect_timeout=data.get('connect_timeout', 0),
use_ssh_tunnel=data.get('use_ssh_tunnel', 0),
use_ssh_tunnel=1 if data.get('use_ssh_tunnel', False) else 0,
tunnel_host=data.get('tunnel_host', None),
tunnel_port=data.get('tunnel_port', 22),
tunnel_username=data.get('tunnel_username', None),
tunnel_authentication=data.get('tunnel_authentication', 0),
tunnel_authentication=1 if data.get('tunnel_authentication',
False) else 0,
tunnel_identity_file=data.get('tunnel_identity_file', None),
shared=data.get('shared', None),
passfile=data.get('passfile', None),

View File

@ -137,7 +137,10 @@ class BatchProcess(object):
if p is None:
raise LookupError(PROCESS_NOT_FOUND)
tmp_desc = loads(p.desc)
try:
tmp_desc = loads(bytes.fromhex(p.desc))
except Exception:
tmp_desc = loads(p.desc)
# ID
self.id = _id
@ -228,7 +231,7 @@ class BatchProcess(object):
csv_writer.writerow(_args)
args_val = args_csv_io.getvalue().strip(str('\r\n'))
tmp_desc = dumps(self.desc)
tmp_desc = dumps(self.desc).hex()
j = Process(
pid=int(uid),
@ -679,7 +682,11 @@ class BatchProcess(object):
:return: return value for details, type_desc and desc related
to process
"""
desc = loads(p.desc)
try:
desc = loads(bytes.fromhex(p.desc))
except Exception:
desc = loads(p.desc)
details = desc
type_desc = ''
current_storage_dir = None

View File

@ -169,8 +169,8 @@ class Server(db.Model):
db.CheckConstraint('sslcompression >= 0 AND sslcompression <= 1'),
nullable=False
)
bgcolor = db.Column(db.Text(10), nullable=True)
fgcolor = db.Column(db.Text(10), nullable=True)
bgcolor = db.Column(db.String(10), nullable=True)
fgcolor = db.Column(db.String(10), nullable=True)
service = db.Column(db.Text(), nullable=True)
connect_timeout = db.Column(db.Integer(), nullable=False)
use_ssh_tunnel = db.Column(
@ -437,8 +437,8 @@ class SharedServer(db.Model):
db.CheckConstraint('sslcompression >= 0 AND sslcompression <= 1'),
nullable=False
)
bgcolor = db.Column(db.Text(10), nullable=True)
fgcolor = db.Column(db.Text(10), nullable=True)
bgcolor = db.Column(db.String(10), nullable=True)
fgcolor = db.Column(db.String(10), nullable=True)
service = db.Column(db.Text(), nullable=True)
connect_timeout = db.Column(db.Integer(), nullable=False)
use_ssh_tunnel = db.Column(

View File

@ -8,7 +8,7 @@
##########################################################################
from .user_info import user_info
from .db_version import get_version, set_version
from .db_version import get_version, set_version, get_version_for_migration
from .db_upgrade import db_upgrade
from .data_directory import create_app_data_directory
from .db_table_check import check_db_tables

View File

@ -7,12 +7,27 @@
#
##########################################################################
from pgadmin.model import Version
from pgadmin.model import Version, db
from sqlalchemy.orm.session import Session
def get_version():
try:
version = Version.query.filter_by(name='ConfigDB').first()
except Exception:
db.session.rollback()
return -1
if version:
return version.value
else:
return -1
def get_version_for_migration(op):
try:
session = Session(bind=op.get_bind())
version = session.query(Version).filter_by(name='ConfigDB').first()
except Exception:
return -1

View File

@ -1730,12 +1730,12 @@ def get_arguments_sqlite(sid, did, scid, func_id):
"""
"""Get the count of the existing data available in sqlite database"""
dbg_func_args_count = DebuggerFunctionArguments.query.filter_by(
dbg_func_args_count = int(DebuggerFunctionArguments.query.filter_by(
server_id=sid,
database_id=did,
schema_id=scid,
function_id=func_id
).count()
).count())
args_data = []
@ -1819,13 +1819,13 @@ def set_arguments_sqlite(sid, did, scid, func_id):
try:
for i in range(0, len(data)):
dbg_func_args_exists = DebuggerFunctionArguments.query.filter_by(
server_id=data[i]['server_id'],
database_id=data[i]['database_id'],
schema_id=data[i]['schema_id'],
function_id=data[i]['function_id'],
arg_id=data[i]['arg_id']
).count()
dbg_func_args_exists = int(
DebuggerFunctionArguments.query.filter_by(
server_id=data[i]['server_id'],
database_id=data[i]['database_id'],
schema_id=data[i]['schema_id'],
function_id=data[i]['function_id'],
arg_id=data[i]['arg_id']).count())
# handle the Array list sent from the client
array_string = ''

View File

@ -97,28 +97,55 @@ def setup_db(app):
print("pgAdmin 4 - Application Initialisation")
print("======================================\n")
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:
def run_migration_for_sqlite():
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)
# Update schema version to the latest
if CURRENT_SCHEMA_VERSION > schema_version:
else:
version = Version.query.filter_by(name='ConfigDB').first()
version.value = CURRENT_SCHEMA_VERSION
db.session.commit()
schema_version = version.value
if os.name != 'nt':
os.chmod(config.SQLITE_PATH, 0o600)
# 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()
if os.name != 'nt':
os.chmod(config.SQLITE_PATH, 0o600)
def run_migration_for_others():
with app.app_context():
version = Version.query.filter_by(name='ConfigDB').first()
if version == -1:
db_upgrade(app)
else:
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()
# Run the migration as per specified by the user.
if config.CONFIG_DATABASE_URI is not None and \
len(config.CONFIG_DATABASE_URI) > 0:
run_migration_for_others()
else:
run_migration_for_sqlite()
def clear_servers():