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. 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 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 created using the **setup.py** script which will create the database file and
schema within it, and add the first user account (with administrative schema within it, and add the first user account (with administrative
privileges) and a default server group for them. A **settings** table is also 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 :maxdepth: 2
getting_started getting_started
external_database
connecting connecting
managing_cluster_objects managing_cluster_objects
managing_database_objects managing_database_objects
@ -31,4 +32,4 @@ of database objects.
.. note:: Postgres, PostgreSQL and the Slonik Logo are trademarks or .. note:: Postgres, PostgreSQL and the Slonik Logo are trademarks or
registered trademarks of the `PostgreSQL Community Association of Canada 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. the first time after starting the application.
* Once you set the master password, all the existing saved passwords will be * Once you set the master password, all the existing saved passwords will be
re-encrypted using the master password. re-encrypted using the master password.
* The server passwords which are saved in the SQLite DB file are encrypted and * The server passwords which are saved in the SQLite DB file or External
decrypted using the master password. Database are encrypted and decrypted using the master password.
.. image:: images/master_password_set.png .. image:: images/master_password_set.png
:alt: Set master password :alt: Set master password

View File

@ -11,6 +11,7 @@ notes for it.
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
release_notes_6_16
release_notes_6_15 release_notes_6_15
release_notes_6_14 release_notes_6_14
release_notes_6_13 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 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) * 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. * 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>* *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. * Make sure the query changes are committed.
Account locking by failed login attempts: 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. 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) # for the particular session. (in minutes)
MAX_SESSION_IDLE_TIME = 60 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 # User account and settings storage
########################################################################## ##########################################################################

View File

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

View File

@ -14,7 +14,8 @@ Revises: ef590e979b0d
Create Date: 2017-11-14 19:09:04.674575 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 identifiers, used by Alembic.
revision = '02b9dccdcfcb' revision = '02b9dccdcfcb'
@ -24,12 +25,8 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('server', sa.Column('bgcolor', sa.String(length=10)))
'ALTER TABLE server ADD COLUMN bgcolor TEXT(10)' op.add_column('server', sa.Column('fgcolor', sa.String(length=10)))
)
db.engine.execute(
'ALTER TABLE server ADD COLUMN fgcolor TEXT(10)'
)
def downgrade(): def downgrade():

View File

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

View File

@ -14,8 +14,8 @@ Revises: 15c88f765bc8
Create Date: 2022-01-04 13:08:05.484598 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 identifiers, used by Alembic.
revision = '1586db67b98e' revision = '1586db67b98e'
@ -25,12 +25,10 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('process', sa.Column('server_id', sa.Integer(),
'ALTER TABLE process ADD COLUMN server_id INTEGER DEFAULT 0' server_default='0'))
) op.add_column('server', sa.Column('cloud_status', sa.Integer(),
db.engine.execute( server_default='0'))
'ALTER TABLE server ADD COLUMN cloud_status INTEGER DEFAULT 0'
)
def downgrade(): def downgrade():

View File

@ -16,8 +16,8 @@ Revises: 6650c52670c2
Create Date: 2021-11-24 17:33:12.533825 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 identifiers, used by Alembic.
revision = '15c88f765bc8' revision = '15c88f765bc8'
@ -27,15 +27,13 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute(""" op.create_table(
CREATE TABLE user_mfa( 'user_mfa', sa.Column('user_id', sa.Integer(), nullable=False),
user_id INTEGER NOT NULL, sa.Column('mfa_auth', sa.String(length=256), nullable=False),
mfa_auth VARCHAR(256) NOT NULL, sa.Column('options', sa.String()),
options TEXT, sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
PRIMARY KEY (user_id, mfa_auth), sa.PrimaryKeyConstraint('user_id', 'mfa_auth'))
FOREIGN KEY(user_id) REFERENCES user (id)
)
""")
# ### end Alembic commands ### # ### 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 Revision ID: 35f29b1701bd
Revises: ec1cac3399c9 Revises: ec1cac3399c9
Create Date: 2019-04-26 16:38:08.368471 Create Date: 2019-04-26 16:38:08.368471
""" """
import base64 from alembic import op
import os import sqlalchemy as sa
import sys
from pgadmin.model import db, Server
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '35f29b1701bd' revision = '35f29b1701bd'
@ -21,33 +24,12 @@ depends_on = None
def upgrade(): def upgrade():
op.add_column('user', sa.Column('masterpass_check', sa.String(length=256)))
db.engine.execute("create table user_old as select * from user") with op.batch_alter_table("user") as batch_op:
batch_op.create_check_constraint(
db.engine.execute("DROP TABLE user") "ck_active_range",
"active IN (true, false)"
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")
def downgrade(): 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 Revision ID: 398697dc9550
Revises: a091c9611d20 Revises: a091c9611d20
Create Date: 2020-09-07 15:17:59.473879 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 identifiers, used by Alembic.
revision = '398697dc9550' revision = '398697dc9550'
@ -16,39 +24,49 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute(""" macro_table = op.create_table(
CREATE TABLE macros ( 'macros',
id INTEGER NOT NULL, sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
alt BOOLEAN NOT NULL, sa.Column('alt', sa.Boolean(), nullable=False),
control BOOLEAN NOT NULL, sa.Column('control', sa.Boolean(), nullable=False),
key VARCHAR(128) NOT NULL, sa.Column('key', sa.String(length=128), nullable=False),
key_code INTEGER NOT NULL, sa.Column('key_code', sa.Integer(), nullable=False),
PRIMARY KEY(id) sa.PrimaryKeyConstraint('id'))
);
""")
db.engine.execute(""" op.create_table(
CREATE TABLE user_macros ( 'user_macros',
mid INTEGER NOT NULL, sa.Column('mid', sa.Integer(), nullable=False),
uid INTEGER NOT NULL, sa.Column('uid', sa.Integer(), nullable=False),
name VARCHAR(1024) NOT NULL, sa.Column('name', sa.String(length=1024), nullable=False),
sql TEXT NOT NULL, sa.Column('sql', sa.String()),
PRIMARY KEY(mid, uid), sa.ForeignKeyConstraint(['mid'], ['macros.id']),
FOREIGN KEY(mid) REFERENCES macros (id), sa.ForeignKeyConstraint(['uid'], ['user.id']),
FOREIGN KEY(uid) REFERENCES user (id) sa.PrimaryKeyConstraint('mid', 'uid'))
);
""")
db.engine.execute(""" op.bulk_insert(macro_table, [
INSERT INTO macros (id, alt, control, key, key_code) VALUES (1, 0, 1, '1', 49), {'alt': 0, 'control': 1, 'key': '1', 'key_code': 49},
(2, 0, 1, '2', 50), (3, 0, 1, '3', 51), (4, 0, 1, '4', 52), {'alt': 0, 'control': 1, 'key': '2', 'key_code': 50},
(5, 0, 1, '5', 53), (6, 0, 1, '6', 54), (7, 0, 1, '7', 55), {'alt': 0, 'control': 1, 'key': '3', 'key_code': 51},
(8, 0, 1, '8', 56), (9, 0, 1, '9', 57), (10, 0, 1, '0', 48), {'alt': 0, 'control': 1, 'key': '4', 'key_code': 52},
(11, 1, 0, 'F1', 112), (12, 1, 0, 'F2', 113), (13, 1, 0, 'F3', 114), {'alt': 0, 'control': 1, 'key': '5', 'key_code': 53},
(14, 1, 0, 'F4', 115), (15, 1, 0, 'F5', 116), (16, 1, 0, 'F6', 117), {'alt': 0, 'control': 1, 'key': '6', 'key_code': 54},
(17, 1, 0, 'F7', 118), (18, 1, 0, 'F8', 119), (19, 1, 0, 'F9', 120), {'alt': 0, 'control': 1, 'key': '7', 'key_code': 55},
(20, 1, 0, 'F10', 121), (21, 1, 0, 'F11', 122), (22, 1, 0, 'F12', 123); {'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(): 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 Revision ID: 3c1e4b6eda55
Revises: 09d53fca90c7 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 identifiers, used by Alembic.
revision = '3c1e4b6eda55' revision = '3c1e4b6eda55'
@ -17,9 +25,7 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('server', sa.Column('hostaddr', sa.String(length=1024)))
'ALTER TABLE server ADD COLUMN hostaddr TEXT(1024)'
)
def downgrade(): def downgrade():

View File

@ -7,14 +7,13 @@
# #
########################################################################## ##########################################################################
"""empty message """
Revision ID: 3ce25f562f3b Revision ID: 3ce25f562f3b
Revises: 6650c52670c2 Revises: 6650c52670c2
Create Date: 2021-12-01 11:52:09.037749 Create Date: 2021-12-01 11:52:09.037749
""" """
from pgadmin.model import db
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '3ce25f562f3b' revision = '3ce25f562f3b'
@ -24,18 +23,8 @@ depends_on = None
def upgrade(): def upgrade():
# Rename user table to user_old and again user_old to user to change # After using alembic the old logic is not required.
# the foreign key refernce of user_old table which is not exists pass
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")
def downgrade(): 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 Revision ID: 493cd3e39c0c
Revises: 7c56ea250085 Revises: 7c56ea250085
@ -8,8 +15,6 @@ Create Date: 2018-06-18 11:26:33.285037
""" """
from alembic import op from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '493cd3e39c0c' revision = '493cd3e39c0c'
@ -19,9 +24,8 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('server', sa.Column('connect_timeout', sa.Integer(),
'ALTER TABLE server ADD COLUMN connect_timeout INTEGER DEFAULT 0' server_default='0'))
)
def downgrade(): 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) """Added service field option in server table (RM#3140)
Revision ID: 50aad68f99c2 Revision ID: 50aad68f99c2
@ -6,8 +13,8 @@ Revises: 02b9dccdcfcb
Create Date: 2018-03-07 11:53:57.584280 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 identifiers, used by Alembic.
revision = '50aad68f99c2' revision = '50aad68f99c2'
@ -17,69 +24,10 @@ depends_on = None
def upgrade(): def upgrade():
# To Save previous data, create temp table op.add_column('server', sa.Column('service', sa.String()))
with op.batch_alter_table("server") as batch_op:
db.engine.execute("create table server_old as select * from server") batch_op.alter_column('host', nullable=True)
batch_op.alter_column('maintenance_db', nullable=True)
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'
)
def downgrade(): def downgrade():

View File

@ -17,10 +17,7 @@ Create Date: 2021-07-10 18:12:38.821602
from alembic import op from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
from pgadmin import db
revision = '6650c52670c2' revision = '6650c52670c2'
down_revision = 'c465fee44968' down_revision = 'c465fee44968'
branch_labels = None branch_labels = None
@ -28,12 +25,10 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('user', sa.Column('locked', sa.Boolean(),
'ALTER TABLE user ADD COLUMN locked BOOLEAN DEFAULT FALSE' server_default='false'))
) op.add_column('user', sa.Column('login_attempts', sa.Integer(),
db.engine.execute( server_default='0'))
'ALTER TABLE user ADD COLUMN login_attempts int DEFAULT 0'
)
def downgrade(): 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 """Change server port constraint to allow port below 1024 RM#3307
Revision ID: 7c56ea250085 Revision ID: 7c56ea250085
@ -7,9 +14,6 @@ Create Date: 2018-06-04 14:23:31.472645
""" """
from alembic import op from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '7c56ea250085' revision = '7c56ea250085'
@ -19,75 +23,12 @@ depends_on = None
def upgrade(): def upgrade():
# To Save previous data, create temp table with op.batch_alter_table("server") as batch_op:
batch_op.drop_constraint('ck_port_range')
db.engine.execute("create table server_old as select * from server") batch_op.create_check_constraint(
"ck_port_range",
db.engine.execute("DROP TABLE server") "port >= 1 AND port <= 65535"
# 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)
) )
""")
# 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(): 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 Revision ID: 7fedf8531802
Revises: aff1436e3c8c Revises: aff1436e3c8c
@ -8,7 +15,6 @@ Create Date: 2020-02-26 11:24:54.353288
""" """
from alembic import op from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '7fedf8531802' revision = '7fedf8531802'
@ -18,35 +24,25 @@ depends_on = None
def upgrade(): 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") op.execute(
user_table.update().values(username=user_table.c.email)
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")
def downgrade(): 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 Revision ID: 81c7ffeffeee
Revises: 398697dc9550 Revises: 398697dc9550
@ -7,8 +14,8 @@ Create Date: 2020-11-02 09:46:51.250338
""" """
from alembic import op from alembic import op
import sqlalchemy as sa from sqlalchemy.orm.session import Session
from pgadmin.model import db, Preferences from pgadmin.model import Preferences
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
@ -23,22 +30,22 @@ def upgrade():
Delete older preferences open new tab for Query tool, Debugger, Delete older preferences open new tab for Query tool, Debugger,
and Schema diff. 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() 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() 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( name='schema_diff_new_browser_tab').order_by(
Preferences.id.desc()).first() Preferences.id.desc()).first()
if qt_open_tab_setting: if qt_open_tab_setting:
db.session.delete(qt_open_tab_setting) session.delete(qt_open_tab_setting)
if debugger_tab_setting: if debugger_tab_setting:
db.session.delete(debugger_tab_setting) session.delete(debugger_tab_setting)
if schema_diff_tab_setting: if schema_diff_tab_setting:
db.session.delete(schema_diff_tab_setting) session.delete(schema_diff_tab_setting)
db.session.commit()
def downgrade(): 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 Revision ID: 84700139beb0
Revises: d39482714a2e Revises: d39482714a2e
Create Date: 2020-06-24 15:53:56.489518 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 identifiers, used by Alembic.
revision = '84700139beb0' revision = '84700139beb0'
@ -17,15 +24,13 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute(""" op.create_table(
CREATE TABLE "database" ( 'database',
"id" INTEGER NOT NULL, sa.Column('id', sa.Integer(), nullable=False),
"schema_res" TEXT, sa.Column('schema_res', sa.String()),
"server" INTEGER NOT NULL, sa.Column('server', sa.Integer(), nullable=False),
PRIMARY KEY("id","server"), sa.ForeignKeyConstraint(['server'], ['server.id'], ),
FOREIGN KEY("server") REFERENCES "server"("id") sa.PrimaryKeyConstraint('id', 'server'))
);
""")
def downgrade(): 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 Revision ID: a091c9611d20
Revises: 84700139beb0 Revises: 84700139beb0
Create Date: 2020-07-14 17:20:22.705737 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 identifiers, used by Alembic.
revision = 'a091c9611d20' revision = 'a091c9611d20'
@ -17,55 +24,54 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('server', sa.Column('shared', sa.Boolean()))
'ALTER TABLE server ADD COLUMN shared 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(""" # Named constraint
CREATE TABLE sharedserver ( with op.batch_alter_table("sharedserver") as batch_op:
id INTEGER NOT NULL, batch_op.create_check_constraint('ck_shared_server_port',
user_id INTEGER NOT NULL, 'port >= 1024 AND port <= 65535')
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)
);
""")
def downgrade(): 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 Revision ID: a39bd015b644
Revises: 81c7ffeffeee Revises: 81c7ffeffeee
Create Date: 2021-01-12 15:46:49.283021 Create Date: 2021-01-12 15:46:49.283021
""" """
from pgadmin.model import db from alembic import op
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'a39bd015b644' revision = 'a39bd015b644'
@ -17,84 +23,10 @@ depends_on = None
def upgrade(): def upgrade():
with op.batch_alter_table("sharedserver") as batch_op:
# To Save previous data, create temp table batch_op.drop_constraint('ck_shared_server_port')
batch_op.alter_column('port', nullable=True)
db.engine.execute("create table sharedserver_old as " batch_op.alter_column('maintenance_db', nullable=True)
"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")
def downgrade(): 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 """Added columns for SSH tunneling
Revision ID: a68b374fe373 Revision ID: a68b374fe373
@ -8,7 +15,6 @@ Create Date: 2018-04-05 13:59:57.588355
""" """
from alembic import op from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'a68b374fe373' revision = 'a68b374fe373'
@ -18,24 +24,14 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('server', sa.Column('use_ssh_tunnel', sa.Integer(),
'ALTER TABLE server ADD COLUMN use_ssh_tunnel INTEGER DEFAULT 0' server_default='0'))
) op.add_column('server', sa.Column('tunnel_host', sa.String()))
db.engine.execute( op.add_column('server', sa.Column('tunnel_port', sa.String()))
'ALTER TABLE server ADD COLUMN tunnel_host TEXT' op.add_column('server', sa.Column('tunnel_username', sa.String()))
) op.add_column('server', sa.Column('tunnel_authentication', sa.Integer(),
db.engine.execute( server_default='0'))
'ALTER TABLE server ADD COLUMN tunnel_port TEXT' op.add_column('server', sa.Column('tunnel_identity_file', sa.String()))
)
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'
)
def downgrade(): 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 """Change the not null constraints for port, username as it should not
compulsory when service is provided. RM #4642 compulsory when service is provided. RM #4642
@ -8,8 +15,6 @@ Create Date: 2019-09-09 15:41:30.084753
""" """
from alembic import op from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'a77a0932a568' revision = 'a77a0932a568'
@ -19,74 +24,11 @@ depends_on = None
def upgrade(): def upgrade():
# To Save previous data, create temp table # Port and Username can be null if service is provided.
db.engine.execute("create table server_old as select * from server") with op.batch_alter_table("server") as batch_op:
batch_op.drop_constraint('ck_port_range')
db.engine.execute("DROP TABLE server") batch_op.alter_column('port', nullable=True)
batch_op.alter_column('username', nullable=True)
# 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")
def downgrade(): def downgrade():

View File

@ -13,7 +13,8 @@ Revises: 493cd3e39c0c
Create Date: 2018-07-26 11:19:50.879849 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 identifiers, used by Alembic.
revision = 'aa86fb60b73d' revision = 'aa86fb60b73d'
@ -23,9 +24,7 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('server', sa.Column('tunnel_password', sa.String(length=64)))
'ALTER TABLE server ADD COLUMN tunnel_password TEXT(64)'
)
def downgrade(): 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. """ Update the default timeout to 10 seconds instead on 0.
0 indicates wait indefinitely which causes trouble when network connection 0 indicates wait indefinitely which causes trouble when network connection
to server is lost. to server is lost.
@ -8,7 +15,8 @@ Revises: a77a0932a568
Create Date: 2019-10-28 12:47:36.828709 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 identifiers, used by Alembic.
revision = 'aff1436e3c8c' revision = 'aff1436e3c8c'
@ -18,8 +26,15 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( # get metadata from current connection
'UPDATE server SET connect_timeout=10 WHERE connect_timeout=0 OR connect_timeout IS NULL' 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 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 identifiers, used by Alembic.
revision = 'b5b87fdfcb30' revision = 'b5b87fdfcb30'
@ -24,9 +25,8 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('process', sa.Column('process_state', sa.Integer(),
'ALTER TABLE process ADD COLUMN process_state INTEGER DEFAULT 0' server_default='0'))
)
def downgrade(): 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 Revision ID: c465fee44968
Revises: d0bc9f32b2b9 Revises: d0bc9f32b2b9
Create Date: 2021-06-04 14:42:12.843116 Create Date: 2021-06-04 14:42:12.843116
""" """
from pgadmin.model import db, User from alembic import op
from sqlalchemy.sql import text import sqlalchemy as sa
import uuid import uuid
@ -19,46 +26,20 @@ depends_on = None
def upgrade(): 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(): def downgrade():
# pgAdmin only upgrades, downgrade not implemented. # 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 Revision ID: c6974f64df08
Revises: a39bd015b644 Revises: a39bd015b644
Create Date: 2021-04-22 10:06:21.282770 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. # revision identifiers, used by Alembic.
@ -18,9 +25,7 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('sharedserver', sa.Column('osid', sa.Integer()))
'ALTER TABLE sharedserver ADD COLUMN osid INTEGER'
)
def downgrade(): def downgrade():

View File

@ -14,8 +14,9 @@ Revises: aa86fb60b73d
Create Date: 2018-08-29 15:33:57.855491 Create Date: 2018-08-29 15:33:57.855491
""" """
from alembic import op
from pgadmin.model import db from sqlalchemy.orm.session import Session
from pgadmin.model import DebuggerFunctionArguments
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'ca00ec32581b' revision = 'ca00ec32581b'
@ -25,9 +26,11 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( session = Session(bind=op.get_bind())
'DELETE FROM debugger_function_arguments'
) debugger_records = session.query(DebuggerFunctionArguments).all()
if debugger_records:
session.delete(debugger_records)
def downgrade(): 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 Revision ID: d0bc9f32b2b9
Revises: c6974f64df08 Revises: c6974f64df08
@ -8,7 +15,6 @@ Create Date: 2021-04-27 12:40:08.899712
""" """
from alembic import op from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'd0bc9f32b2b9' revision = 'd0bc9f32b2b9'
@ -18,9 +24,8 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('server', sa.Column('kerberos_conn', sa.Boolean(),
'ALTER TABLE server ADD COLUMN kerberos_conn INTEGER DEFAULT 0' server_default='false'))
)
def downgrade(): def downgrade():

View File

@ -16,7 +16,6 @@ Create Date: 2020-04-09 13:20:13.939775
""" """
from alembic import op from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'd39482714a2e' revision = 'd39482714a2e'
@ -26,22 +25,21 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('server', sa.Column('save_password', sa.Integer(),
'ALTER TABLE server ADD COLUMN save_password INTEGER DEFAULT 0' server_default='0'))
)
# If password is already exists for any existing server then change the # If password is already exists for any existing server then change the
# save_password column to 1 (True) else set 0 # save_password column to 1 (True) else set 0
db.engine.execute( # get metadata from current connection
""" meta = sa.MetaData(bind=op.get_bind())
UPDATE server SET save_password = ( # define table representation
CASE WHEN password IS NOT NULL AND password != '' THEN meta.reflect(only=('server',))
1 server_table = sa.Table('server', meta)
ELSE
0 op.execute(
END server_table.update().values(save_password=sa.case(
) (server_table.c.password != 'NULL' and
""" server_table.c.password != '', 1), else_=0)
) ))
def downgrade(): 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 Revision ID: d85a62333272
Revises: 3c1e4b6eda55 Revises: 3c1e4b6eda55
Create Date: 2017-07-07 16:03:23.842734 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 identifiers, used by Alembic.
revision = 'd85a62333272' revision = 'd85a62333272'
@ -17,9 +24,7 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('server', sa.Column('db_res', sa.String()))
'ALTER TABLE server ADD COLUMN db_res TEXT'
)
def downgrade(): 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 Revision ID: ec1cac3399c9
Revises: b5b87fdfcb30 Revises: b5b87fdfcb30
Create Date: 2019-03-07 16:05:28.874203 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 identifiers, used by Alembic.
revision = 'ec1cac3399c9' revision = 'ec1cac3399c9'
@ -15,27 +23,19 @@ down_revision = 'b5b87fdfcb30'
branch_labels = None branch_labels = None
depends_on = 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(): def upgrade():
db.engine.execute(""" op.create_table(
CREATE TABLE query_history ( 'query_history',
srno INTEGER NOT NULL, sa.Column('srno', sa.Integer(), nullable=False),
uid INTEGER NOT NULL, sa.Column('uid', sa.Integer(), nullable=False),
sid INTEGER NOT NULL, sa.Column('sid', sa.Integer(), nullable=False),
dbname TEXT NOT NULL, sa.Column('dbname', sa.String(), nullable=False),
query_info TEXT NOT NULL, sa.Column('query_info', sa.String(), nullable=False),
last_updated_flag TEXT NOT NULL, sa.Column('last_updated_flag', sa.String(), nullable=False),
PRIMARY KEY (srno, uid, sid, dbname), sa.ForeignKeyConstraint(['sid'], ['server.id']),
FOREIGN KEY(uid) REFERENCES user (id), sa.ForeignKeyConstraint(['uid'], ['user.id']),
FOREIGN KEY(sid) REFERENCES server (id) sa.PrimaryKeyConstraint('srno', 'uid', 'sid', 'dbname'))
)""")
def downgrade(): 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 identifiers, used by Alembic.
revision = 'ece2e76bf60e' revision = 'ece2e76bf60e'
@ -25,9 +26,7 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('process', sa.Column('utility_pid', sa.Integer()))
'ALTER TABLE process ADD COLUMN utility_pid INTEGER'
)
def downgrade(): 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 Revision ID: ef590e979b0d
Revises: d85a62333272 Revises: d85a62333272
@ -8,7 +15,6 @@ Create Date: 2017-08-23 18:37:14.836988
""" """
from alembic import op from alembic import op
import sqlalchemy as sa import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'ef590e979b0d' revision = 'ef590e979b0d'
@ -18,28 +24,13 @@ depends_on = None
def upgrade(): def upgrade():
db.engine.execute( op.add_column('server', sa.Column('passfile', sa.String()))
'ALTER TABLE server ADD COLUMN passfile TEXT' op.add_column('server', sa.Column('sslcert', sa.String()))
) op.add_column('server', sa.Column('sslkey', sa.String()))
db.engine.execute( op.add_column('server', sa.Column('sslrootcert', sa.String()))
'ALTER TABLE server ADD COLUMN sslcert TEXT' op.add_column('server', sa.Column('sslcrl', sa.String()))
) op.add_column('server', sa.Column('sslcompression', sa.Integer(),
db.engine.execute( server_default='0'))
'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'
)
def downgrade(): 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. """Encrypt the existing user password.
Revision ID: f195f9a4923d Revision ID: f195f9a4923d
@ -10,6 +17,8 @@ import config
from flask import current_app from flask import current_app
from flask_security import Security, SQLAlchemyUserDatastore from flask_security import Security, SQLAlchemyUserDatastore
from flask_security.utils import verify_and_update_password 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 from pgadmin.model import Keys, db, User, Role
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
@ -21,8 +30,9 @@ depends_on = None
def upgrade(): def upgrade():
app = current_app app = current_app
db.session.flush() session = Session(bind=op.get_bind())
current_salt = Keys.query.filter_by(name = 'SECURITY_PASSWORD_SALT').first().value current_salt = session.query(Keys).filter_by(
name='SECURITY_PASSWORD_SALT').first().value
app.config.update(dict(SECURITY_PASSWORD_SALT=current_salt)) app.config.update(dict(SECURITY_PASSWORD_SALT=current_salt))
app.config['SECURITY_PASSWORD_HASH'] = config.SECURITY_PASSWORD_HASH app.config['SECURITY_PASSWORD_HASH'] = config.SECURITY_PASSWORD_HASH
@ -32,7 +42,7 @@ def upgrade():
else: else:
app.config['SECURITY_PASSWORD_SALT'] = current_salt 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)\ User.id, User.email, User.password, User.active, User.confirmed_at)\
.all() .all()
# This will upgrade the plaintext password of all the user as per the # 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: if user.password is not None:
verify_and_update_password(user.password, user) verify_and_update_password(user.password, user)
db.session.commit()
def downgrade(): def downgrade():
# pgAdmin only upgrades, downgrade not implemented. # pgAdmin only upgrades, downgrade not implemented.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@
########################################################################## ##########################################################################
from .user_info import user_info 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 .db_upgrade import db_upgrade
from .data_directory import create_app_data_directory from .data_directory import create_app_data_directory
from .db_table_check import check_db_tables 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(): def get_version():
try: try:
version = Version.query.filter_by(name='ConfigDB').first() 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: except Exception:
return -1 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""" """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, server_id=sid,
database_id=did, database_id=did,
schema_id=scid, schema_id=scid,
function_id=func_id function_id=func_id
).count() ).count())
args_data = [] args_data = []
@ -1819,13 +1819,13 @@ def set_arguments_sqlite(sid, did, scid, func_id):
try: try:
for i in range(0, len(data)): for i in range(0, len(data)):
dbg_func_args_exists = DebuggerFunctionArguments.query.filter_by( dbg_func_args_exists = int(
server_id=data[i]['server_id'], DebuggerFunctionArguments.query.filter_by(
database_id=data[i]['database_id'], server_id=data[i]['server_id'],
schema_id=data[i]['schema_id'], database_id=data[i]['database_id'],
function_id=data[i]['function_id'], schema_id=data[i]['schema_id'],
arg_id=data[i]['arg_id'] function_id=data[i]['function_id'],
).count() arg_id=data[i]['arg_id']).count())
# handle the Array list sent from the client # handle the Array list sent from the client
array_string = '' array_string = ''

View File

@ -97,28 +97,55 @@ def setup_db(app):
print("pgAdmin 4 - Application Initialisation") print("pgAdmin 4 - Application Initialisation")
print("======================================\n") print("======================================\n")
with app.app_context(): def run_migration_for_sqlite():
# Run migration for the first time i.e. create database with app.app_context():
from config import SQLITE_PATH # Run migration for the first time i.e. create database
if not os.path.exists(SQLITE_PATH): from config import SQLITE_PATH
db_upgrade(app) if not os.path.exists(SQLITE_PATH):
else:
version = Version.query.filter_by(name='ConfigDB').first()
schema_version = version.value
# Run migration if current schema version is greater than the
# schema version stored in version table
if CURRENT_SCHEMA_VERSION >= schema_version:
db_upgrade(app) db_upgrade(app)
else:
# Update schema version to the latest
if CURRENT_SCHEMA_VERSION > schema_version:
version = Version.query.filter_by(name='ConfigDB').first() version = Version.query.filter_by(name='ConfigDB').first()
version.value = CURRENT_SCHEMA_VERSION schema_version = version.value
db.session.commit()
if os.name != 'nt': # Run migration if current schema version is greater than the
os.chmod(config.SQLITE_PATH, 0o600) # 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(): def clear_servers():