From 17347250130a57e6046fc7768376c7d01e205b06 Mon Sep 17 00:00:00 2001 From: Anup Dahal Date: Thu, 30 Oct 2025 13:12:10 +0545 Subject: [PATCH 1/5] Feat : addtional permissions check to manage a resource permissions --- .../client/js/plugins/Share/Share.jsx | 8 +++- .../Share/components/Permissions/index.jsx | 8 ++-- .../client/js/utils/ResourceUtils.js | 46 +++++++++++++++++-- .../js/utils/__tests__/ResourceUtils-test.js | 3 +- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/geonode_mapstore_client/client/js/plugins/Share/Share.jsx b/geonode_mapstore_client/client/js/plugins/Share/Share.jsx index e998f2b3d3..db2d9c279d 100644 --- a/geonode_mapstore_client/client/js/plugins/Share/Share.jsx +++ b/geonode_mapstore_client/client/js/plugins/Share/Share.jsx @@ -28,6 +28,8 @@ import { } from '@js/selectors/resource'; import { canAccessPermissions, + canManageAnonymousPermissions, + canManageRegisteredMemberPermissions, getDownloadUrlInfo, getResourceTypesInfo } from '@js/utils/ResourceUtils'; @@ -43,11 +45,13 @@ const getEmbedUrl = (resource) => { function Share({ enabled, onClose, - resource, + resource, resourceType }) { const embedUrl = getEmbedUrl(resource); const downloadUrl = getDownloadUrlInfo(resource)?.url; + const manageAnonymousPermissions = canManageAnonymousPermissions(resource); + const manageRegisteredMemberPermissions = canManageRegisteredMemberPermissions(resource); return ( - {canAccessPermissions(resource) && } + {canAccessPermissions(resource) && } {(resourceType === 'document' && !!downloadUrl) && } collapsible={false} />} {embedUrl && } />} diff --git a/geonode_mapstore_client/client/js/plugins/Share/components/Permissions/index.jsx b/geonode_mapstore_client/client/js/plugins/Share/components/Permissions/index.jsx index d19cd4b812..91253fad64 100644 --- a/geonode_mapstore_client/client/js/plugins/Share/components/Permissions/index.jsx +++ b/geonode_mapstore_client/client/js/plugins/Share/components/Permissions/index.jsx @@ -94,7 +94,9 @@ const Permissions = ({ resourceType, permissionsLoading, compactPermissions, - onChangePermissions + onChangePermissions, + manageAnonymousPermissions, + manageRegisteredMemberPermissions }) => { const enableGeoLimits = resourceType === ResourceTypes.DATASET; const isMounted = useIsMounted(); @@ -106,11 +108,11 @@ const Permissions = ({ let responseOptions; if (resourceIndex !== -1) { responseOptions = getResourcePermissions( - data[resourceIndex].allowed_perms.compact + data[resourceIndex].allowed_perms.compact , compactPermissions?.groups ,manageAnonymousPermissions, manageRegisteredMemberPermissions ); } else { // set a default permission object - responseOptions = getResourcePermissions(data[0].allowed_perms.compact); + responseOptions = getResourcePermissions(data[0].allowed_perms.compact, compactPermissions?.groups ,manageAnonymousPermissions, manageRegisteredMemberPermissions); } isMounted(() => setPermissionsObject(responseOptions)); }); diff --git a/geonode_mapstore_client/client/js/utils/ResourceUtils.js b/geonode_mapstore_client/client/js/utils/ResourceUtils.js index 8b077e7d6a..3f2f909edb 100644 --- a/geonode_mapstore_client/client/js/utils/ResourceUtils.js +++ b/geonode_mapstore_client/client/js/utils/ResourceUtils.js @@ -8,7 +8,7 @@ import uuid from 'uuid'; import url from 'url'; -import { isEmpty, uniqBy, omit, orderBy, isString, isObject } from 'lodash'; +import { isEmpty, uniqBy, omit, orderBy, isString, isObject, has } from 'lodash'; import { isImageServerUrl } from '@mapstore/framework/utils/ArcGISUtils'; import { getConfigProp, convertFromLegacy, normalizeConfig } from '@mapstore/framework/utils/ConfigUtils'; @@ -474,13 +474,51 @@ export const setAvailableResourceTypes = (value) => { availableResourceTypes = value; }; +export const canManageAnonymousPermissions = (resource) => { + return resourceHasPermission(resource, 'can_manage_anonymous_permissions'); +}; + +export const canManageRegisteredMemberPermissions = (resource) => { + return resourceHasPermission(resource, 'can_manage_registered_member_permissions'); +} + +/** + * Get the current permission for a specific group. + * @param {*} groupName + * @param {*} groups + */ +export const getPermissionForGroup = (groupName, groups) => { + const group = groups?.find(g => g.name === groupName); + return group?.permissions; +}; + +/** + * Filters permission options for a group if management is disabled. + * If management is disabled, it restricts the options to only the current permission. + * @param {object} options The permissions options object. + * @param {array} groups The list of groups with their current permissions. + * @param {string} groupName The name of the group to filter ('anonymous' or 'registered-members'). + * @param {boolean} canManage The flag indicating if the user can manage permissions. + */ +const filterGroupPermissions = (options, groups, groupName, canManage) => { + if (!canManage && options[groupName]) { + const permissionValue = getPermissionForGroup(groupName, groups); + const currentPermission = options[groupName].find(p => p.name === permissionValue); + if (currentPermission) { + options[groupName] = [currentPermission]; + } + } +}; + /** * Extracts lists of permissions into an object for use in the Share plugin select elements * @param {Object} options Permission Object to extract permissions from * @returns An object containing permissions for each type of user/group */ -export const getResourcePermissions = (options) => { - const permissionsOptions = {}; +export const getResourcePermissions = (options , groups, manageAnonymousPermissions=false, manageRegisteredMemberPermissions=false) => { + filterGroupPermissions(options, groups, 'anonymous', manageAnonymousPermissions); + filterGroupPermissions(options, groups, 'registered-members', manageRegisteredMemberPermissions); + let permissionsOptions = {}; Object.keys(options).forEach((key) => { const permissions = options[key]; let selectOptions = []; @@ -885,4 +923,4 @@ export const canManageResourceSettings = (resource) => { export const canAccessPermissions = (resource) => { const { perms } = resource || {}; return perms?.includes('change_resourcebase_permissions'); -}; +}; \ No newline at end of file diff --git a/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js b/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js index 0c196fba42..4c7cfbb0ff 100644 --- a/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js +++ b/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js @@ -111,7 +111,8 @@ describe('Test Resource Utils', () => { } } }]; - const permissionOptions = getResourcePermissions(data[0].allowed_perms.compact); + const groups = []; + const permissionOptions = getResourcePermissions(data[0].allowed_perms.compact, groups); expect(permissionOptions).toEqual({ test1: [ { value: 'none', labelId: `gnviewer.nonePermission`, label: 'None' }, From 04ccaaceab193bc9d907d75e18434db206c93551 Mon Sep 17 00:00:00 2001 From: Anup Dahal Date: Thu, 30 Oct 2025 13:20:45 +0545 Subject: [PATCH 2/5] Removed unsed import --- geonode_mapstore_client/client/js/utils/ResourceUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode_mapstore_client/client/js/utils/ResourceUtils.js b/geonode_mapstore_client/client/js/utils/ResourceUtils.js index 3f2f909edb..1364a9cf71 100644 --- a/geonode_mapstore_client/client/js/utils/ResourceUtils.js +++ b/geonode_mapstore_client/client/js/utils/ResourceUtils.js @@ -8,7 +8,7 @@ import uuid from 'uuid'; import url from 'url'; -import { isEmpty, uniqBy, omit, orderBy, isString, isObject, has } from 'lodash'; +import { isEmpty, uniqBy, omit, orderBy, isString, isObject } from 'lodash'; import { isImageServerUrl } from '@mapstore/framework/utils/ArcGISUtils'; import { getConfigProp, convertFromLegacy, normalizeConfig } from '@mapstore/framework/utils/ConfigUtils'; From 0ef7d87b4cb6867a9f65585de92e8aa9745b9b36 Mon Sep 17 00:00:00 2001 From: Anup Dahal Date: Tue, 11 Nov 2025 14:07:05 +0545 Subject: [PATCH 3/5] Updated logic of DetailsShare for Permissions --- .../components/DetailsShare.jsx | 19 +++++--- .../client/js/utils/ResourceUtils.js | 43 +++++++++---------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsShare.jsx b/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsShare.jsx index bc5a658f19..79c0716c4e 100644 --- a/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsShare.jsx +++ b/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsShare.jsx @@ -21,7 +21,8 @@ import { import { updateResourceCompactPermissions } from "@js/actions/gnresource"; import { getCompactPermissions, - getViewedResourceType + getViewedResourceType, + getResourceData, } from "@js/selectors/resource"; import { getCurrentResourcePermissionsLoading } from "@js/selectors/resourceservice"; import { @@ -30,6 +31,8 @@ import { permissionsCompactToLists, permissionsListsToCompact, resourceToPermissionEntry, + canManageAnonymousPermissions, + canManageRegisteredMemberPermissions, ResourceTypes } from "@js/utils/ResourceUtils"; import GeoLimits from "./GeoLimits"; @@ -94,12 +97,14 @@ const Permissions = ({ permissionsLoading, compactPermissions, onChangePermissions, - manageAnonymousPermissions, - manageRegisteredMemberPermissions + resource }) => { + console.log(resource,'resource in permission'); const enableGeoLimits = resourceType === ResourceTypes.DATASET; const isMounted = useIsMounted(); const [permissionsObject, setPermissionsObject] = useState({}); + const manageAnonymousPermissions = canManageAnonymousPermissions(resource); + const manageRegisteredMemberPermissions = canManageRegisteredMemberPermissions(resource); useEffect(() => { getResourceTypes().then((data) => { @@ -146,12 +151,14 @@ export default connect( [ getCompactPermissions, getCurrentResourcePermissionsLoading, - getViewedResourceType + getViewedResourceType, + getResourceData, ], - (compactPermissions, permissionsLoading, type) => ({ + (compactPermissions, permissionsLoading, type, resource) => ({ compactPermissions, permissionsLoading, - resourceType: type + resourceType: type, + resource }) ), { diff --git a/geonode_mapstore_client/client/js/utils/ResourceUtils.js b/geonode_mapstore_client/client/js/utils/ResourceUtils.js index 362112a7e9..e99eda5854 100644 --- a/geonode_mapstore_client/client/js/utils/ResourceUtils.js +++ b/geonode_mapstore_client/client/js/utils/ResourceUtils.js @@ -484,32 +484,27 @@ export const canManageRegisteredMemberPermissions = (resource) => { return resourceHasPermission(resource, 'can_manage_registered_member_permissions'); } -/** - * Get the current permission for a specific group. - * @param {*} groupName - * @param {*} groups - */ -export const getPermissionForGroup = (groupName, groups) => { - const group = groups?.find(g => g.name === groupName); - return group?.permissions; -}; - /** * Filters permission options for a group if management is disabled. * If management is disabled, it restricts the options to only the current permission. * @param {object} options The permissions options object. * @param {array} groups The list of groups with their current permissions. - * @param {string} groupName The name of the group to filter ('anonymous' or 'registered-members'). - * @param {boolean} canManage The flag indicating if the user can manage permissions. + * @param {array} groupNames Array of group names to filter ('anonymous' or 'registered-members'). + * @returns {object} Filtered permissions options */ -const filterGroupPermissions = (options, groups, groupName, canManage) => { - if (!canManage && options[groupName]) { - const permissionValue = getPermissionForGroup(groupName, groups); - const currentPermission = options[groupName].find(p => p.name === permissionValue); - if (currentPermission) { - options[groupName] = [currentPermission]; - } - } +const filterGroupPermissions = (options, groups, groupNames) => { + return groupNames.length + ? Object.fromEntries(Object.keys(options) + .map((key) => { + if (groupNames.some(name => name === key)) { + const group = groups?.find(g => g.name === key); + const permissionValue = group?.permissions; + const currentPermission = options[key].find(p => p.name === permissionValue); + return currentPermission ? [key, currentPermission] : [key, options[key]]; + } + return [key, options[key]]; + })) + : options; }; /** @@ -517,9 +512,11 @@ const filterGroupPermissions = (options, groups, groupName, canManage) => { * @param {Object} options Permission Object to extract permissions from * @returns An object containing permissions for each type of user/group */ -export const getResourcePermissions = (options , groups, manageAnonymousPermissions=false, manageRegisteredMemberPermissions=false) => { - filterGroupPermissions(options, groups, 'anonymous', manageAnonymousPermissions); - filterGroupPermissions(options, groups, 'registered-members', manageRegisteredMemberPermissions); +export const getResourcePermissions = (_options , groups, manageAnonymousPermissions=false, manageRegisteredMemberPermissions=false) => { + const options = filterGroupPermissions(_options, groups, [ + ...(manageAnonymousPermissions ? [] : ['anonymous']), + ...(manageRegisteredMemberPermissions? [] : ['registered-members']), + ]); let permissionsOptions = {}; Object.keys(options).forEach((key) => { const permissions = options[key]; From c71665a6887c7ce78235d75561c1abf23e4d2821 Mon Sep 17 00:00:00 2001 From: Anup Dahal Date: Tue, 11 Nov 2025 14:14:37 +0545 Subject: [PATCH 4/5] Fixed linting issues --- .../js/plugins/ResourceDetails/components/DetailsShare.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsShare.jsx b/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsShare.jsx index 79c0716c4e..45b1ea9fdb 100644 --- a/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsShare.jsx +++ b/geonode_mapstore_client/client/js/plugins/ResourceDetails/components/DetailsShare.jsx @@ -99,7 +99,6 @@ const Permissions = ({ onChangePermissions, resource }) => { - console.log(resource,'resource in permission'); const enableGeoLimits = resourceType === ResourceTypes.DATASET; const isMounted = useIsMounted(); const [permissionsObject, setPermissionsObject] = useState({}); From 8e263ca994f83eaeaffb34b133a2ba2340f14b08 Mon Sep 17 00:00:00 2001 From: Anup Dahal Date: Tue, 11 Nov 2025 15:06:56 +0545 Subject: [PATCH 5/5] Fixed typo --- geonode_mapstore_client/client/js/utils/ResourceUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode_mapstore_client/client/js/utils/ResourceUtils.js b/geonode_mapstore_client/client/js/utils/ResourceUtils.js index e99eda5854..75e4541523 100644 --- a/geonode_mapstore_client/client/js/utils/ResourceUtils.js +++ b/geonode_mapstore_client/client/js/utils/ResourceUtils.js @@ -500,7 +500,7 @@ const filterGroupPermissions = (options, groups, groupNames) => { const group = groups?.find(g => g.name === key); const permissionValue = group?.permissions; const currentPermission = options[key].find(p => p.name === permissionValue); - return currentPermission ? [key, currentPermission] : [key, options[key]]; + return currentPermission ? [key, [currentPermission]] : [key, options[key]]; } return [key, options[key]]; }))