From dd9e49e35073dc48382cd15963351e1dbd4f633e Mon Sep 17 00:00:00 2001 From: Chris Knoll Date: Tue, 13 Feb 2024 19:09:15 -0500 Subject: [PATCH] Optimize Permission handling on ui (#2912) * Change permission structure to optimized for for reads. * Update permission check to match WildCardPermission logic. --- js/pages/configuration/configuration.html | 5 +++ js/pages/configuration/configuration.js | 18 +++++++++ js/services/AuthAPI.js | 47 +++++++++++++++-------- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/js/pages/configuration/configuration.html b/js/pages/configuration/configuration.html index ebbaf5493..831dcf859 100644 --- a/js/pages/configuration/configuration.html +++ b/js/pages/configuration/configuration.html @@ -135,6 +135,11 @@ +
+ + + +
diff --git a/js/pages/configuration/configuration.js b/js/pages/configuration/configuration.js index 76ac15225..a13723d96 100644 --- a/js/pages/configuration/configuration.js +++ b/js/pages/configuration/configuration.js @@ -260,6 +260,24 @@ define([ buttonClass, } } + + runDiagnostics() { + + const startTime = performance.now(); + + // get the list of isPermitted functions, except the literal isPermitted + for (const key in authApi) { + if (typeof authApi[key] === 'function' && key.startsWith('isPermitted') && key != 'isPermitted') { + authApi[key](); // Invoke the function + } + } + + const endTime = performance.now(); + + const elapsedTime = endTime - startTime; + console.log(`Script execution time: ${elapsedTime} milliseconds`); + + } } return commonUtils.build('ohdsi-configuration', Configuration, view); diff --git a/js/services/AuthAPI.js b/js/services/AuthAPI.js index 098589973..cd88bbb32 100644 --- a/js/services/AuthAPI.js +++ b/js/services/AuthAPI.js @@ -78,7 +78,7 @@ define(function(require, exports) { url: config.api.url + 'user/me', method: 'GET', success: function (info, textStatus, jqXHR) { - permissions(info.permissions.map(p => p.permission)); + permissions(info.permissionIdx); // read from permission index of User info subject(info.login); authProvider(jqXHR.getResponseHeader('x-auth-provider')); fullName(info.name ? info.name : info.login); @@ -176,32 +176,44 @@ define(function(require, exports) { } } + // adapted from https://github.com/apache/shiro/blob/fa518ec985fd192497cd04e2569041b2f469aead/core/src/main/java/org/apache/shiro/authz/permission/WildcardPermission.java#L201 + var checkPermission = function(permission, etalon) { - // etalon may be like '*:read,write:etc' - if (!etalon || !permission) { + // etalon may be like '*:read,write:etc', and is a permission assigned to the user. + // permission is the permission to check + if (!etalon || !permission) { // both must be non-null to perform a check return false; } - if (permission == etalon) { + if (permission == etalon) { // quick check: if equal on both sides, then permission is granted. return true; } var etalonLevels = etalon.split(':'); var permissionLevels = permission.split(':'); - if (etalonLevels.length != permissionLevels.length) { - return false; + var i = 0; + for (let permissionLevel of permissionLevels) { + // If this etalon has less parts than the permission, everything after the number of parts contained + // in this etalon is automatically implied, so return true + if (etalonLevels.length - 1 < i) { + return true; + } else { + var etalonPart = etalonLevels[i].split(','); + var permissionPart = permissionLevel.split(','); + if (!etalonPart.includes("*") && !permissionPart.every(pp => etalonPart.includes(pp))) { + return false; + } + } + i++; } - - for (var i = 0; i < permissionLevels.length; i++) { - var pLevel = permissionLevels[i]; - var eLevels = etalonLevels[i].split(','); - - if (eLevels.indexOf('*') < 0 && eLevels.indexOf(pLevel) < 0) { + // If etalon has more parts than the permission, return true if rest of eLevels contains wildcard + for (; i < etalonLevels.length; i++) { // loop through remaining etalonLevels + var etalonPart = etalonLevels[i].split(','); + if (!etalonPart.includes("*")) { return false; } } - return true; }; @@ -210,7 +222,11 @@ define(function(require, exports) { return true; } - var etalons = permissions(); + if (!permissions()) return false; + + firstPerm = permission.split(":")[0]; + + var etalons = [...(permissions()["*"] || []), ...(permissions()[firstPerm]||[])]; if (!etalons) { return false; } @@ -498,7 +514,7 @@ define(function(require, exports) { const setAuthParams = (tokenHeader, permissionsStr = '') => { !!tokenHeader && token(tokenHeader); - !!permissionsStr && permissions(permissionsStr.split('|')); + !!permissionsStr && permissions(permissionsStr); }; var resetAuthParams = function () { @@ -622,6 +638,7 @@ define(function(require, exports) { TOKEN_HEADER, runAs, executeWithRefresh, + }; return api;