Skip to content
6 changes: 6 additions & 0 deletions web/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,12 @@
# "Unauthorised use is strictly forbidden."
LOGIN_BANNER = ""

##########################################################################
# Admin options
##########################################################################
ADMIN_CAN_SEE_ALL_SERVERS = False


##########################################################################
# Log settings
##########################################################################
Expand Down
51 changes: 31 additions & 20 deletions web/pgadmin/browser/server_groups/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
import config
from pgadmin.utils.preferences import Preferences
from pgadmin.utils.server_access import get_server_group, \
get_server_groups_for_user
get_server_groups_for_user, \
get_servers_from_group


def get_icon_css_class(group_id, group_user_id,
Expand Down Expand Up @@ -69,25 +70,44 @@ def csssnippets(self):
@staticmethod
def has_shared_server(gid):
"""
To check whether given server group contains shared server or not
To check whether given server group contains shared servers
:param gid:
:return: True if servergroup contains shared server else false
:return: True if servergroup contains shared servers else false
"""
servers = Server.query.filter_by(servergroup_id=gid)
pref = Preferences.module('browser')
hide_shared_server = pref.preference('hide_shared_server').get()

servers = get_servers_from_group(gid, hide_shared_server)
for s in servers:
if s.shared:
return True

return False

@staticmethod
def has_not_shared_server(gid):
"""
To check whether given server group contains NOT shared servers
:param gid:
:return: True if servergroup contains NOT shared servers else false
"""
pref = Preferences.module('browser')
hide_shared_server = pref.preference('hide_shared_server').get()

servers = get_servers_from_group(gid, hide_shared_server)
for s in servers:
if not s.shared:
return True

return False

def get_nodes(self, *arg, **kwargs):
"""Return a JSON document listing the server groups for the user"""

if config.SERVER_MODE:
groups = ServerGroupView.get_all_server_groups()
else:
groups = ServerGroup.query.filter_by(
user_id=current_user.id
).order_by("id")
pref = Preferences.module('browser')
hide_shared_server = pref.preference('hide_shared_server').get()

groups = ServerGroupView.get_all_server_groups().order_by("id")

for idx, group in enumerate(groups):
icon_class, is_shared = get_icon_css_class(group.id, group.user_id)
Expand Down Expand Up @@ -387,16 +407,7 @@ def get_all_server_groups():
pref = Preferences.module('browser')
hide_shared_server = pref.preference('hide_shared_server').get()

server_groups = get_server_groups_for_user()

if hide_shared_server:
groups = []
for group in server_groups:
if group.user_id != current_user.id and \
ServerGroupModule.has_shared_server(group.id):
continue
groups.append(group)
return groups
server_groups = get_server_groups_for_user(only_owned=hide_shared_server)

return server_groups

Expand Down
11 changes: 9 additions & 2 deletions web/pgadmin/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,13 @@ class ServerGroup(db.Model, UserScopedMixin):
name = db.Column(db.String(128), nullable=False)
__table_args__ = (db.UniqueConstraint('user_id', 'name'),)

servers = db.relationship(
'Server',
back_populates='servergroup',
lazy='select',
cascade=CASCADE_STR
)

@property
def serialize(self):
"""Return object data in easily serializable format"""
Expand Down Expand Up @@ -293,9 +300,9 @@ class Server(db.Model, UserScopedMixin):
role = db.Column(db.String(64), nullable=True)
comment = db.Column(db.String(1024), nullable=True)
discovery_id = db.Column(db.String(128), nullable=True)
servers = db.relationship(
servergroup = db.relationship(
'ServerGroup',
backref=db.backref('server', cascade=CASCADE_STR),
back_populates='servers',
lazy='joined'
)
db_res = db.Column(db.Text(), nullable=True)
Expand Down
6 changes: 3 additions & 3 deletions web/pgadmin/tools/schema_diff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,10 @@ def servers():
"connected": connected
}

if server.servers.name in res:
res[server.servers.name].append(server_info)
if server.servergroup.name in res:
res[server.servergroup.name].append(server_info)
else:
res[server.servers.name] = [server_info]
res[server.servergroup.name] = [server_info]

except Exception as e:
app.logger.exception(e)
Expand Down
2 changes: 1 addition & 1 deletion web/pgadmin/tools/sqleditor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2420,7 +2420,7 @@ def get_new_connection_data(sgid=None, sid=None):
manager = driver.connection_manager(server.id)
conn = manager.connection()
connected = conn.connected()
server_group_data[server.servers.name].append({
server_group_data[server.servergroup.name].append({
'label': server.name,
"value": server.id,
'image': server_icon_and_background(connected, manager,
Expand Down
80 changes: 40 additions & 40 deletions web/pgadmin/utils/server_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ def get_server(sid, only_owned=False):
if not config.SERVER_MODE:
return Server.query.filter_by(id=sid).first()

# Administrators can access all servers if ADMIN_CAN_SEE_ALL_SERVERS is True
if _is_admin() and config.ADMIN_CAN_SEE_ALL_SERVERS:
return Server.query.filter_by(id=sid).first()

if only_owned:
return Server.query.filter_by(
id=sid, user_id=current_user.id).first()
Expand All @@ -64,17 +68,25 @@ def get_server(sid, only_owned=False):
)
).first()

if server is not None:
return server
return server

# Administrators can access all servers
if _is_admin():
return Server.query.filter_by(id=sid).first()

return None
def get_servers_from_group(gid, only_owned=False):
"""Fetch servers from a group

Args:
gid: Server group ID.
only_owned: If True, only return servers owned by the current
user.
"""
query = get_user_server_query().filter(Server.servergroup_id == gid)

if only_owned:
query = query.filter(Server.user_id == current_user.id)

return query

def get_server_group(gid):
def get_server_group(gid,only_owned=False):
"""Fetch a server group by ID, verifying user access.

Returns the group if:
Expand All @@ -88,64 +100,52 @@ def get_server_group(gid):
if not config.SERVER_MODE:
return ServerGroup.query.filter_by(id=gid).first()

sg = ServerGroup.query.filter(
ServerGroup.id == gid,
or_(
ServerGroup.user_id == current_user.id,
ServerGroup.id.in_(
db.session.query(Server.servergroup_id).filter(
Server.shared
)
)
)
).first()

if sg is not None:
return sg

if _is_admin():
if _is_admin() and config.ADMIN_CAN_SEE_ALL_SERVERS:
return ServerGroup.query.filter_by(id=gid).first()
Comment thread
lkmatsumura marked this conversation as resolved.

return None
sg = get_server_groups_for_user(only_owned=only_owned).filter_by(id=gid).first()

return sg


def get_server_groups_for_user():
def get_server_groups_for_user(only_owned=False):
"""Return server groups visible to the current user.

Includes groups owned by the user plus groups containing shared
servers (Server.shared=True, visible to all authenticated users).
Administrators see all groups.
Administrators see all groups if ADMIN_CAN_SEE_ALL_SERVERS is True.
"""
if not config.SERVER_MODE:
return ServerGroup.query.filter_by(
user_id=current_user.id
).all()
)

if _is_admin():
return ServerGroup.query.all()
if _is_admin() and config.ADMIN_CAN_SEE_ALL_SERVERS:
return ServerGroup.query

return ServerGroup.query.filter(
or_(
ServerGroup.user_id == current_user.id,
ServerGroup.id.in_(
db.session.query(Server.servergroup_id).filter(
Server.shared
)
)
sg = ServerGroup.query.filter(
ServerGroup.user_id == current_user.id
)
).all()

if not only_owned:
sg = sg.union(
ServerGroup.query.join(ServerGroup.servers)
.filter(Server.shared)
)

return sg


def get_user_server_query():
"""Return a base query for servers accessible to the current user.

Includes owned servers + shared servers (visible to all users).
Administrators see all servers.
Administrators see all servers if ADMIN_CAN_SEE_ALL_SERVERS is True.
"""
if not config.SERVER_MODE:
return Server.query

if _is_admin():
if _is_admin() and config.ADMIN_CAN_SEE_ALL_SERVERS:
return Server.query

return Server.query.filter(
Expand Down