diff --git a/docs/en_US/images/permissions.png b/docs/en_US/images/permissions.png index d1b6eb08b..fc5fd483d 100644 Binary files a/docs/en_US/images/permissions.png and b/docs/en_US/images/permissions.png differ diff --git a/web/migrations/versions/c62bcc14c3d6_.py b/web/migrations/versions/c62bcc14c3d6_.py new file mode 100644 index 000000000..455ae4d55 --- /dev/null +++ b/web/migrations/versions/c62bcc14c3d6_.py @@ -0,0 +1,37 @@ + +"""empty message + +Revision ID: c62bcc14c3d6 +Revises: 1f0eddc8fc79 +Create Date: 2025-06-02 21:45:20.653669 + +""" +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = 'c62bcc14c3d6' +down_revision = '1f0eddc8fc79' +branch_labels = None +depends_on = None + +def upgrade(): + # Add 'change_password' permission to all roles except 'Administrator'. + meta = sa.MetaData() + meta.reflect(op.get_bind(), only=('role',)) + role_table = sa.Table('role', meta) + + perm = role_table.c.permissions + op.execute(role_table.update().where( + (role_table.c.name != 'Administrator') + ).values( + permissions=sa.case( + (perm == None, 'change_password'), + (perm == '', 'change_password'), + else_=perm + ',change_password' + )) + ) + +def downgrade(): + # pgAdmin only upgrades, downgrade not implemented. + pass diff --git a/web/pgadmin/model/__init__.py b/web/pgadmin/model/__init__.py index af1251f12..13f34aa8a 100644 --- a/web/pgadmin/model/__init__.py +++ b/web/pgadmin/model/__init__.py @@ -33,7 +33,7 @@ import config # ########################################################################## -SCHEMA_VERSION = 44 +SCHEMA_VERSION = 45 ########################################################################## # diff --git a/web/pgadmin/tools/user_management/PgAdminPermissions.py b/web/pgadmin/tools/user_management/PgAdminPermissions.py index 5a7fc594c..0055d8002 100644 --- a/web/pgadmin/tools/user_management/PgAdminPermissions.py +++ b/web/pgadmin/tools/user_management/PgAdminPermissions.py @@ -26,6 +26,7 @@ class AllPermissionTypes: tools_grant_wizard = 'tools_grant_wizard' storage_add_folder = 'storage_add_folder' storage_remove_folder = 'storage_remove_folder' + change_password = 'change_password' @staticmethod def list(): @@ -34,9 +35,10 @@ class AllPermissionTypes: class AllPermissionCategories: - object_explorer = 'Object Explorer' - tools = 'Tools' - storage_manager = 'Storage Manager' + object_explorer = gettext('Object Explorer') + tools = gettext('Tools') + storage_manager = gettext('Storage Manager') + miscellaneous = gettext('Miscellaneous') class PgAdminPermissions: @@ -118,6 +120,11 @@ class PgAdminPermissions: AllPermissionTypes.storage_remove_folder, gettext("Delete file/folder") ) + self.add_permission( + AllPermissionCategories.miscellaneous, + AllPermissionTypes.change_password, + gettext("Change password") + ) def add_permission(self, category: str, permission: str, label: str): self._all_permissions.append({ diff --git a/web/pgadmin/tools/user_management/static/js/index.js b/web/pgadmin/tools/user_management/static/js/index.js index 4bac23c85..abf4299ce 100644 --- a/web/pgadmin/tools/user_management/static/js/index.js +++ b/web/pgadmin/tools/user_management/static/js/index.js @@ -13,6 +13,7 @@ import gettext from 'sources/gettext'; import { showChangeUserPassword, showUrlDialog } from '../../../../static/js/Dialogs/index'; import { BROWSER_PANELS } from '../../../../browser/static/js/constants'; import Component from './Component'; +import withCheckPermission from '../../../../browser/static/js/withCheckPermission'; class UserManagement { static instance; @@ -30,9 +31,11 @@ class UserManagement { this.initialized = true; } - // This is a callback function to show change user dialog. + // This is a callback function to show change user dialog based on permission. change_password(url) { - showChangeUserPassword(url); + withCheckPermission({ permission: 'change_password' }, () => { + showChangeUserPassword(url); + })(); } // This is a callback function to show 2FA dialog.