1246 lines
45 KiB
JavaScript
1246 lines
45 KiB
JavaScript
/*
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
this work for additional information regarding copyright ownership.
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
(the "License"); you may not use this file except in compliance with
|
|
the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
solrAdminApp.controller('SecurityController', function ($scope, $timeout, $cookies, $window, Constants, System, Security) {
|
|
$scope.resetMenu("security", Constants.IS_ROOT_PAGE);
|
|
|
|
$scope.params = [];
|
|
$scope.filteredPredefinedPermissions = [];
|
|
|
|
var strongPasswordRegex = /^(?=.*[0-9])(?=.*[!@#$%^&*\-_()[\]])[a-zA-Z0-9!@#$%^&*\-_()[\]]{8,30}$/;
|
|
|
|
function toList(str) {
|
|
if (Array.isArray(str)) {
|
|
return str; // already a list
|
|
}
|
|
return str.trim().split(",").map(s => s.trim()).filter(s => s !== "");
|
|
}
|
|
|
|
function asList(listOrStr) {
|
|
return Array.isArray(listOrStr) ? listOrStr : (listOrStr ? [listOrStr] : []);
|
|
}
|
|
|
|
function transposeUserRoles(userRoles) {
|
|
var roleUsers = {};
|
|
for (var u in userRoles) {
|
|
var roleList = asList(userRoles[u]);
|
|
for (var i in roleList) {
|
|
var role = roleList[i];
|
|
if (!roleUsers[role]) roleUsers[role] = []
|
|
roleUsers[role].push(u);
|
|
}
|
|
}
|
|
|
|
var roles = [];
|
|
for (var r in roleUsers) {
|
|
roles.push({"name":r, "users":Array.from(new Set(roleUsers[r]))});
|
|
}
|
|
return roles.sort((a, b) => (a.name > b.name) ? 1 : -1);
|
|
}
|
|
|
|
/**
|
|
* Check if user's roles are compatible with permission's roles
|
|
* @param roles list of roles for a permission, where at least one is required
|
|
* @param rolesForUser list of roles for user
|
|
* @return true if user has one of the required roles, or permission has a wildcard role
|
|
*/
|
|
function roleMatch(roles, rolesForUser) {
|
|
if (roles.includes("*"))
|
|
return true
|
|
for (let r in rolesForUser) {
|
|
if (roles.includes(rolesForUser[r]))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function permRow(perm, i) {
|
|
var roles = asList(perm.role);
|
|
var paths = asList(perm.path);
|
|
|
|
var collectionNames = "";
|
|
var collections = [];
|
|
if ("collection" in perm) {
|
|
if (perm["collection"] == null) {
|
|
collectionNames = "null";
|
|
} else {
|
|
collections = asList(perm.collection);
|
|
collectionNames = collections.sort().join(", ");
|
|
}
|
|
} else {
|
|
// no collection property on the perm, so the default "*" applies
|
|
collectionNames = "";
|
|
collections.push("*");
|
|
}
|
|
|
|
var method = asList(perm.method);
|
|
|
|
// perms don't always have an index ?!?
|
|
var index = "index" in perm ? perm["index"] : ""+i;
|
|
|
|
return { "index": index, "name": perm.name, "collectionNames": collectionNames, "collections": collections,
|
|
"roles": roles, "paths": paths, "method": method, "params": perm.params };
|
|
}
|
|
|
|
function checkError(data) {
|
|
var cause = null;
|
|
if ("errorMessages" in data && Array.isArray(data["errorMessages"]) && data["errorMessages"].length > 0) {
|
|
cause = "?";
|
|
if ("errorMessages" in data["errorMessages"][0] && Array.isArray(data["errorMessages"][0]["errorMessages"]) && data["errorMessages"][0]["errorMessages"].length > 0) {
|
|
cause = data["errorMessages"][0]["errorMessages"][0];
|
|
}
|
|
}
|
|
return cause;
|
|
}
|
|
|
|
function truncateTo(str, maxLen, delim) {
|
|
// allow for a little on either side of maxLen for better display
|
|
var varLen = Math.min(Math.round(maxLen * 0.1), 15);
|
|
if (str.length <= maxLen + varLen) {
|
|
return str;
|
|
}
|
|
|
|
var total = str.split(delim).length;
|
|
var at = str.indexOf(delim, maxLen - varLen);
|
|
str = (at !== -1 && at < maxLen + varLen) ? str.substring(0, at) : str.substring(0, maxLen);
|
|
var trimmed = str.split(delim).length;
|
|
var diff = total - trimmed;
|
|
str += " ... "+(diff > 1 ? "(+"+diff+" more)" : "");
|
|
return str;
|
|
}
|
|
|
|
$scope.closeErrorDialog = function () {
|
|
delete $scope.securityAPIError;
|
|
delete $scope.securityAPIErrorDetails;
|
|
};
|
|
|
|
$scope.displayList = function(listOrStr) {
|
|
if (!listOrStr) return "";
|
|
var str = Array.isArray(listOrStr) ? listOrStr.sort().join(", ") : (""+listOrStr).trim();
|
|
return truncateTo(str, 160, ", ");
|
|
};
|
|
|
|
$scope.displayParams = function(obj) {
|
|
if (!obj) return "";
|
|
if (Array.isArray(obj)) return obj.sort().join(", ");
|
|
|
|
var display = "";
|
|
for (const [key, value] of Object.entries(obj)) {
|
|
if (display.length > 0) display += "; ";
|
|
display += (key + "=" + (Array.isArray(value)?value.sort().join(","):value+""));
|
|
}
|
|
return truncateTo(display, 160, "; ");
|
|
};
|
|
|
|
$scope.displayRoles = function(obj) {
|
|
return (!obj || (Array.isArray(obj) && obj.length === 0)) ? "null" : $scope.displayList(obj);
|
|
};
|
|
|
|
// TODO: Use new permissions.js
|
|
$scope.predefinedPermissions = ["collection-admin-edit", "collection-admin-read", "core-admin-read", "core-admin-edit", "zk-read",
|
|
"read", "update", "all", "config-edit", "config-read", "schema-read", "schema-edit", "security-edit", "security-read",
|
|
"metrics-read", "health", "filestore-read", "filestore-write", "package-edit", "package-read"].sort();
|
|
|
|
$scope.predefinedPermissionCollection = {"read":"*", "update":"*", "config-edit":"*", "config-read":"*", "schema-edit":"*", "schema-read":"*"};
|
|
|
|
$scope.errorHandler = function (e) {
|
|
var error = e.data && e.data.error ? e.data.error : null;
|
|
if (error && error.msg) {
|
|
$scope.securityAPIError = error.msg;
|
|
$scope.securityAPIErrorDetails = e.data.errorDetails;
|
|
} else if (e.data && e.data.message) {
|
|
$scope.securityAPIError = e.data.message;
|
|
$scope.securityAPIErrorDetails = JSON.stringify(e.data);
|
|
}
|
|
};
|
|
|
|
$scope.showHelp = function (id) {
|
|
if ($scope.helpId && ($scope.helpId === id || id === '')) {
|
|
delete $scope.helpId;
|
|
} else {
|
|
$scope.helpId = id;
|
|
}
|
|
};
|
|
|
|
$scope.wrapSchemeCmd = function(cmd, data) {
|
|
var schemeCmd = {};
|
|
schemeCmd[cmd] = $scope.multiAuthWithBasic ? { "basic": data } : data;
|
|
return schemeCmd;
|
|
};
|
|
|
|
$scope.findEditableAuthz = function(data) {
|
|
var authz = data.authorization;
|
|
if (!authz) {
|
|
return null;
|
|
}
|
|
|
|
var authzClass = authz["class"];
|
|
if (authzClass.endsWith(".RuleBasedAuthorizationPlugin")) {
|
|
return authz;
|
|
}
|
|
|
|
// go dig around in the schemes list looking for the editable one ...
|
|
if (authzClass.endsWith(".MultiAuthRuleBasedAuthorizationPlugin")) {
|
|
if ("schemes" in authz) {
|
|
for (var i in authz.schemes) {
|
|
if (authz.schemes[i]["class"].endsWith(".RuleBasedAuthorizationPlugin")) {
|
|
return authz.schemes[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
$scope.validatePermConfig = function() {
|
|
$scope.hasPermWarnings = false;
|
|
$scope.permWarnings = [];
|
|
|
|
var namedPerms = $scope.permissionsTable.filter(p => $scope.predefinedPermissions.includes(p.name));
|
|
// look for named perms with -edit but w/o a -read
|
|
for (var n in namedPerms) {
|
|
var perm = namedPerms[n];
|
|
if (perm.name.endsWith("-edit")) {
|
|
// see if there is a "-read" too
|
|
var pfx = perm.name.substring(0, perm.name.indexOf("-edit"));
|
|
const readPermName = pfx + "-read";
|
|
var readPerm = namedPerms.find(p => p.name === readPermName);
|
|
if (!readPerm) {
|
|
$scope.permWarnings.push(readPermName+" is not protected! In general, if you protect "+perm.name+", you should also protect "+readPermName);
|
|
}
|
|
}
|
|
}
|
|
|
|
var hasAll = namedPerms.find(p => p.name === "all");
|
|
if (hasAll) {
|
|
if ($scope.permissionsTable[$scope.permissionsTable.length-1].name !== "all") {
|
|
$scope.permWarnings.push("The 'all' permission should always be the last permission in your config so that more specific permissions are applied first.");
|
|
}
|
|
} else {
|
|
$scope.permWarnings.push("The 'all' permission is not configured! In general, you should assign the 'all' permission to an admin role and list it as the last permission in your config.");
|
|
}
|
|
|
|
$scope.hasPermWarnings = $scope.permWarnings.length > 0;
|
|
};
|
|
|
|
$scope.refresh = function () {
|
|
$scope.hideAll();
|
|
|
|
$scope.tls = false;
|
|
$scope.blockUnknown = "false"; // default setting
|
|
$scope.realmName = "solr";
|
|
$scope.forwardCredentials = "false";
|
|
$scope.multiAuthWithBasic = false;
|
|
|
|
$scope.currentUser = sessionStorage.getItem("auth.username");
|
|
|
|
$scope.userFilter = "";
|
|
$scope.userFilterOption = "";
|
|
$scope.userFilterText = "";
|
|
$scope.userFilterOptions = [];
|
|
|
|
$scope.permFilter = "";
|
|
$scope.permFilterOption = "";
|
|
$scope.permFilterOptions = [];
|
|
$scope.permFilterTypes = ["", "name", "role", "path", "collection"];
|
|
|
|
System.get(function(data) {
|
|
$scope.tls = data.security ? data.security["tls"] : false;
|
|
$scope.authenticationPlugin = data.security ? data.security["authenticationPlugin"] : null;
|
|
$scope.authorizationPlugin = data.security ? data.security["authorizationPlugin"] : null;
|
|
$scope.isSecurityAdminEnabled = $scope.authenticationPlugin != null;
|
|
$scope.isCloudMode = data.mode.match( /solrcloud/i ) != null;
|
|
$scope.zkHost = $scope.isCloudMode ? data["zkHost"] : "";
|
|
$scope.solrHome = data["solr_home"];
|
|
$scope.refreshSecurityPanel();
|
|
}, function(e) {
|
|
if (e.status === 401 || e.status === 403) {
|
|
$scope.isSecurityAdminEnabled = true;
|
|
$scope.hasSecurityEditPerm = false;
|
|
$scope.hideAll();
|
|
}
|
|
});
|
|
};
|
|
|
|
$scope.hideAll = function () {
|
|
// add more dialogs here
|
|
delete $scope.validationError;
|
|
$scope.showUserDialog = false;
|
|
$scope.showPermDialog = false;
|
|
delete $scope.helpId;
|
|
};
|
|
|
|
$scope.refreshSecurityPanel = function() {
|
|
|
|
// determine if the authorization plugin supports CRUD permissions
|
|
$scope.managePermissionsEnabled =
|
|
($scope.authorizationPlugin === "org.apache.solr.security.RuleBasedAuthorizationPlugin" ||
|
|
$scope.authorizationPlugin === "org.apache.solr.security.ExternalRoleRuleBasedAuthorizationPlugin" ||
|
|
$scope.authorizationPlugin === "org.apache.solr.security.MultiAuthRuleBasedAuthorizationPlugin");
|
|
|
|
// don't allow CRUD on roles if using external
|
|
$scope.manageUserRolesEnabled = false;
|
|
|
|
Security.get({path: "authorization"}, function (data) {
|
|
//console.log(">> authorization: "+JSON.stringify(data));
|
|
|
|
if (!data.authorization) {
|
|
$scope.isSecurityAdminEnabled = false;
|
|
$scope.hasSecurityEditPerm = false;
|
|
return;
|
|
}
|
|
|
|
var authz = $scope.findEditableAuthz(data);
|
|
//console.log(">> authz: "+JSON.stringify(authz));
|
|
|
|
if (authz) {
|
|
$scope.manageUserRolesEnabled = true;
|
|
}
|
|
|
|
if ($scope.manageUserRolesEnabled) {
|
|
$scope.userRoles = authz["user-role"];
|
|
$scope.roles = transposeUserRoles($scope.userRoles);
|
|
$scope.filteredRoles = $scope.roles;
|
|
$scope.roleNames = $scope.roles.map(r => r.name).sort();
|
|
$scope.roleNamesWithWildcard = ["*"].concat($scope.roleNames);
|
|
if (!$scope.permFilterTypes.includes("user")) {
|
|
$scope.permFilterTypes.push("user"); // can only filter perms by user if we have a role to user mapping
|
|
}
|
|
} else {
|
|
$scope.userRoles = {};
|
|
$scope.roles = [];
|
|
$scope.filteredRoles = [];
|
|
$scope.roleNames = [];
|
|
}
|
|
|
|
$scope.permissionsConfig = data.authorization["permissions"];
|
|
$scope.permissionsTable = [];
|
|
for (p in $scope.permissionsConfig) {
|
|
$scope.permissionsTable.push(permRow($scope.permissionsConfig[p], parseInt(p)+1));
|
|
}
|
|
$scope.filteredPerms = $scope.permissionsTable;
|
|
|
|
// check for issues with perm config
|
|
$scope.validatePermConfig();
|
|
|
|
// use the current user's roles (obtained from System.get) to check if they have the security permissions
|
|
// Note: the backend will check too so this is only for display purposes
|
|
$scope.hasSecurityEditPerm = $scope.isPermitted(permissions.SECURITY_EDIT_PERM);
|
|
$scope.hasSecurityReadPerm = $scope.hasSecurityEditPerm || $scope.isPermitted(permissions.SECURITY_READ_PERM);
|
|
|
|
// authentication
|
|
if ($scope.authenticationPlugin === "org.apache.solr.security.BasicAuthPlugin" || $scope.authenticationPlugin === "org.apache.solr.security.MultiAuthPlugin") {
|
|
$scope.manageUsersEnabled = true;
|
|
|
|
Security.get({path: "authentication"}, function (data) {
|
|
// console.log(">> authentication: "+JSON.stringify(data));
|
|
|
|
if (!data.authentication) {
|
|
$scope.manageUsersEnabled = false;
|
|
$scope.users = [];
|
|
$scope.filteredUsers = $scope.users;
|
|
return;
|
|
}
|
|
|
|
// find the "basic" scheme if using multi-auth
|
|
var authn = data.authentication;
|
|
if ("schemes" in data.authentication) {
|
|
for (var a in data.authentication.schemes) {
|
|
if (data.authentication.schemes[a]["scheme"] === "basic") {
|
|
authn = data.authentication.schemes[a];
|
|
$scope.multiAuthWithBasic = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//console.log(">> authn: "+JSON.stringify(authn));
|
|
|
|
$scope.blockUnknown = authn["blockUnknown"] === true ? "true" : "false";
|
|
$scope.forwardCredentials = authn["forwardCredentials"] === true ? "true" : "false";
|
|
|
|
if ("realm" in authn) {
|
|
$scope.realmName = authn["realm"];
|
|
}
|
|
|
|
var users = [];
|
|
if (authn.credentials) {
|
|
for (var u in authn.credentials) {
|
|
var roles = $scope.userRoles[u];
|
|
if (!roles) roles = [];
|
|
users.push({"username":u, "roles":roles});
|
|
}
|
|
}
|
|
|
|
$scope.users = users.sort((a, b) => (a.username > b.username) ? 1 : -1);
|
|
$scope.filteredUsers = $scope.users.slice(0,100); // only display first 100
|
|
}, $scope.errorHandler);
|
|
} else {
|
|
$scope.users = [];
|
|
$scope.filteredUsers = $scope.users;
|
|
$scope.manageUsersEnabled = false;
|
|
}
|
|
}, $scope.errorHandler);
|
|
};
|
|
|
|
$scope.validatePassword = function() {
|
|
var password = $scope.upsertUser.password.trim();
|
|
var password2 = $scope.upsertUser.password2 ? $scope.upsertUser.password2.trim() : "";
|
|
if (password !== password2) {
|
|
$scope.validationError = "Passwords do not match!";
|
|
return false;
|
|
}
|
|
|
|
if (password.length < 15 && !password.match(strongPasswordRegex)) {
|
|
$scope.validationError = "Password not strong enough! Must have length >= 15 or contain at least one lowercase letter, one uppercase letter, one digit, and one of these special characters: !@#$%^&*_-[]()";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
$scope.updateUserRoles = function() {
|
|
var setUserRoles = {};
|
|
var roles = [];
|
|
if ($scope.upsertUser.selectedRoles) {
|
|
roles = roles.concat($scope.upsertUser.selectedRoles);
|
|
}
|
|
if ($scope.upsertUser.newRole && $scope.upsertUser.newRole.trim() !== "") {
|
|
var newRole = $scope.upsertUser.newRole.trim();
|
|
if (newRole !== "null" && newRole !== "*" && newRole.length <= 30) {
|
|
roles.push(newRole);
|
|
} // else, no new role for you!
|
|
}
|
|
var userRoles = Array.from(new Set(roles));
|
|
setUserRoles[$scope.upsertUser.username] = userRoles.length > 0 ? userRoles : null;
|
|
var cmdJson = $scope.wrapSchemeCmd("set-user-role", setUserRoles);
|
|
Security.post({path: "authorization"}, cmdJson, function (data) {
|
|
$scope.toggleUserDialog();
|
|
$scope.refreshSecurityPanel();
|
|
});
|
|
};
|
|
|
|
$scope.doUpsertUser = function() {
|
|
if (!$scope.upsertUser) {
|
|
delete $scope.validationError;
|
|
$scope.showUserDialog = false;
|
|
return;
|
|
}
|
|
|
|
if (!$scope.upsertUser.username || $scope.upsertUser.username.trim() === "") {
|
|
$scope.validationError = "Username is required!";
|
|
return;
|
|
}
|
|
|
|
// keep username to a reasonable length? but allow for email addresses
|
|
var username = $scope.upsertUser.username.trim();
|
|
if (username.length > 30) {
|
|
$scope.validationError = "Username must be 30 characters or less!";
|
|
return;
|
|
}
|
|
|
|
var doSetUser = false;
|
|
if ($scope.userDialogMode === 'add') {
|
|
if ($scope.users) {
|
|
var existing = $scope.users.find(u => u.username === username);
|
|
if (existing) {
|
|
$scope.validationError = "User '"+username+"' already exists!";
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!$scope.upsertUser.password) {
|
|
$scope.validationError = "Password is required!";
|
|
return;
|
|
}
|
|
|
|
if (!$scope.validatePassword()) {
|
|
return;
|
|
}
|
|
doSetUser = true;
|
|
} else {
|
|
if ($scope.upsertUser.password) {
|
|
if ($scope.validatePassword()) {
|
|
doSetUser = true;
|
|
} else {
|
|
return; // update to password is invalid
|
|
}
|
|
} // else no update to password
|
|
}
|
|
|
|
if ($scope.upsertUser.newRole && $scope.upsertUser.newRole.trim() !== "") {
|
|
var newRole = $scope.upsertUser.newRole.trim();
|
|
if (newRole === "null" || newRole === "*" || newRole.length > 30) {
|
|
$scope.validationError = "Invalid new role: "+newRole;
|
|
return;
|
|
}
|
|
}
|
|
|
|
delete $scope.validationError;
|
|
|
|
if (doSetUser) {
|
|
var setUserJson = {};
|
|
setUserJson[username] = $scope.upsertUser.password.trim();
|
|
var cmdJson = $scope.wrapSchemeCmd("set-user", setUserJson);
|
|
Security.post({path: "authentication"}, cmdJson, function (data) {
|
|
var errorCause = checkError(data);
|
|
if (errorCause != null) {
|
|
$scope.securityAPIError = "create user "+username+" failed due to: "+errorCause;
|
|
$scope.securityAPIErrorDetails = JSON.stringify(data);
|
|
return;
|
|
}
|
|
// TODO: shouldn't need this extra GET, but sometimes the config back from the server doesn't have our new user
|
|
// and doing this seems to avoid what looks like a race?
|
|
Security.get({path: "authentication"}, function (data2) {
|
|
$scope.updateUserRoles();
|
|
});
|
|
});
|
|
} else {
|
|
$scope.updateUserRoles();
|
|
}
|
|
};
|
|
|
|
$scope.confirmDeleteUser = function() {
|
|
if (window.confirm("Confirm delete the '"+$scope.upsertUser.username+"' user?")) {
|
|
// remove all roles for the user and the delete the user
|
|
var removeRoles = {};
|
|
removeRoles[$scope.upsertUser.username] = null;
|
|
var cmdJson = $scope.wrapSchemeCmd("set-user-role", removeRoles);
|
|
Security.post({path: "authorization"}, cmdJson, function (data) {
|
|
var deleteUserCmd = $scope.wrapSchemeCmd("delete-user", [$scope.upsertUser.username]);
|
|
Security.post({path: "authentication"}, deleteUserCmd, function (data2) {
|
|
$scope.toggleUserDialog();
|
|
$scope.refreshSecurityPanel();
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
$scope.showAddUserDialog = function() {
|
|
$scope.userDialogMode = "add";
|
|
$scope.userDialogHeader = "Add New User";
|
|
$scope.userDialogAction = "Add User";
|
|
$scope.upsertUser = {};
|
|
$scope.toggleUserDialog();
|
|
};
|
|
|
|
$scope.toggleUserDialog = function() {
|
|
if ($scope.showUserDialog) {
|
|
delete $scope.upsertUser;
|
|
delete $scope.validationError;
|
|
$scope.showUserDialog = false;
|
|
return;
|
|
}
|
|
|
|
$scope.hideAll();
|
|
$('#user-dialog').css({left: 132, top: 132});
|
|
$scope.showUserDialog = true;
|
|
};
|
|
|
|
$scope.onPredefinedChanged = function() {
|
|
if (!$scope.upsertPerm) {
|
|
return;
|
|
}
|
|
|
|
if ($scope.upsertPerm.name && $scope.upsertPerm.name.trim() !== "") {
|
|
delete $scope.selectedPredefinedPermission;
|
|
} else {
|
|
$scope.upsertPerm.name = "";
|
|
}
|
|
|
|
if ($scope.selectedPredefinedPermission && $scope.selectedPredefinedPermission in $scope.predefinedPermissionCollection) {
|
|
$scope.upsertPerm.collection = $scope.predefinedPermissionCollection[$scope.selectedPredefinedPermission];
|
|
}
|
|
|
|
$scope.isPermFieldDisabled = ($scope.upsertPerm.name === "" && $scope.selectedPredefinedPermission);
|
|
};
|
|
|
|
$scope.showAddPermDialog = function() {
|
|
$scope.permDialogMode = "add";
|
|
$scope.permDialogHeader = "Add New Permission";
|
|
$scope.permDialogAction = "Add Permission";
|
|
$scope.upsertPerm = {};
|
|
$scope.upsertPerm.name = "";
|
|
$scope.upsertPerm.index = "";
|
|
$scope.upsertPerm["method"] = {"get":"true", "post":"true", "put":"true", "delete":"true"};
|
|
$scope.isPermFieldDisabled = false;
|
|
delete $scope.selectedPredefinedPermission;
|
|
|
|
$scope.params = [{"name":"", "value":""}];
|
|
|
|
var permissionNames = $scope.permissionsConfig.map(p => p.name);
|
|
$scope.filteredPredefinedPermissions = $scope.predefinedPermissions.filter(p => !permissionNames.includes(p));
|
|
|
|
$scope.togglePermDialog();
|
|
};
|
|
|
|
$scope.togglePermDialog = function() {
|
|
if ($scope.showPermDialog) {
|
|
delete $scope.upsertPerm;
|
|
delete $scope.validationError;
|
|
$scope.showPermDialog = false;
|
|
$scope.isPermFieldDisabled = false;
|
|
delete $scope.selectedPredefinedPermission;
|
|
return;
|
|
}
|
|
|
|
$scope.hideAll();
|
|
|
|
var leftPos = $scope.permDialogMode === "add" ? 500 : 100;
|
|
var topPos = $('#permissions').offset().top - 320;
|
|
if (topPos < 0) topPos = 0;
|
|
$('#add-permission-dialog').css({left: leftPos, top: topPos});
|
|
|
|
$scope.showPermDialog = true;
|
|
};
|
|
|
|
$scope.getMethods = function() {
|
|
var methods = [];
|
|
if ($scope.upsertPerm.method.get === "true") {
|
|
methods.push("GET");
|
|
}
|
|
if ($scope.upsertPerm.method.put === "true") {
|
|
methods.push("PUT");
|
|
}
|
|
if ($scope.upsertPerm.method.post === "true") {
|
|
methods.push("POST");
|
|
}
|
|
if ($scope.upsertPerm.method.delete === "true") {
|
|
methods.push("DELETE");
|
|
}
|
|
return methods;
|
|
};
|
|
|
|
$scope.confirmDeletePerm = function() {
|
|
var permName = $scope.selectedPredefinedPermission ? $scope.selectedPredefinedPermission : $scope.upsertPerm.name.trim();
|
|
if (window.confirm("Confirm delete the '"+permName+"' permission?")) {
|
|
var index = parseInt($scope.upsertPerm.index);
|
|
Security.post({path: "authorization"}, { "delete-permission": index }, function (data) {
|
|
$scope.togglePermDialog();
|
|
$scope.refreshSecurityPanel();
|
|
});
|
|
}
|
|
};
|
|
|
|
$scope.doUpsertPermission = function() {
|
|
if (!$scope.upsertPerm) {
|
|
$scope.upsertPerm = {};
|
|
}
|
|
|
|
var isAdd = $scope.permDialogMode === "add";
|
|
var name = $scope.selectedPredefinedPermission ? $scope.selectedPredefinedPermission : $scope.upsertPerm.name.trim();
|
|
|
|
if (isAdd) {
|
|
if (!name) {
|
|
$scope.validationError = "Either select a predefined permission or provide a name for a custom permission";
|
|
return;
|
|
}
|
|
var permissionNames = $scope.permissionsConfig.map(p => p.name);
|
|
if (permissionNames.includes(name)) {
|
|
$scope.validationError = "Permission '"+name+"' already exists!";
|
|
return;
|
|
}
|
|
|
|
if (name === "*") {
|
|
$scope.validationError = "Invalid permission name!";
|
|
return;
|
|
}
|
|
}
|
|
|
|
var role = null;
|
|
if ($scope.manageUserRolesEnabled) {
|
|
role = $scope.upsertPerm.selectedRoles;
|
|
if (!role || role.length === 0) {
|
|
role = null;
|
|
} else if (role.includes("*")) {
|
|
role = ["*"];
|
|
}
|
|
} else if ($scope.upsertPerm.manualRoles && $scope.upsertPerm.manualRoles.trim() !== "") {
|
|
var manualRoles = $scope.upsertPerm.manualRoles.trim();
|
|
role = (manualRoles === "null") ? null : toList(manualRoles);
|
|
}
|
|
|
|
var setPermJson = {"name": name, "role": role };
|
|
|
|
if ($scope.selectedPredefinedPermission) {
|
|
$scope.params = [{"name":"","value":""}];
|
|
} else {
|
|
// collection
|
|
var coll = null;
|
|
if ($scope.upsertPerm.collection != null && $scope.upsertPerm.collection !== "null") {
|
|
if ($scope.upsertPerm.collection === "*") {
|
|
coll = "*";
|
|
} else {
|
|
coll = $scope.upsertPerm.collection && $scope.upsertPerm.collection.trim() !== "" ? toList($scope.upsertPerm.collection) : "";
|
|
}
|
|
}
|
|
setPermJson["collection"] = coll;
|
|
|
|
// path
|
|
if (!$scope.upsertPerm.path || (Array.isArray($scope.upsertPerm.path) && $scope.upsertPerm.path.length === 0)) {
|
|
$scope.validationError = "Path is required for custom permissions!";
|
|
return;
|
|
}
|
|
|
|
setPermJson["path"] = toList($scope.upsertPerm.path);
|
|
|
|
if ($scope.upsertPerm.method) {
|
|
var methods = $scope.getMethods();
|
|
if (methods.length === 0) {
|
|
$scope.validationError = "Must specify at least one request method for a custom permission!";
|
|
return;
|
|
}
|
|
|
|
if (methods.length < 4) {
|
|
setPermJson["method"] = methods;
|
|
} // else no need to specify, rule applies to all methods
|
|
}
|
|
|
|
// params
|
|
var params = {};
|
|
if ($scope.params && $scope.params.length > 0) {
|
|
for (i in $scope.params) {
|
|
var p = $scope.params[i];
|
|
var name = p.name.trim();
|
|
if (name !== "" && p.value) {
|
|
if (name in params) {
|
|
params[name].push(p.value);
|
|
} else {
|
|
params[name] = [p.value];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
setPermJson["params"] = params;
|
|
}
|
|
|
|
var indexUpdated = false;
|
|
if ($scope.upsertPerm.index) {
|
|
var indexOrBefore = isAdd ? "before" : "index";
|
|
var indexInt = parseInt($scope.upsertPerm.index);
|
|
if (indexInt < 1) indexInt = 1;
|
|
if (indexInt >= $scope.permissionsConfig.length) indexInt = null;
|
|
if (indexInt != null) {
|
|
setPermJson[indexOrBefore] = indexInt;
|
|
}
|
|
indexUpdated = (!isAdd && indexInt !== parseInt($scope.upsertPerm.originalIndex));
|
|
}
|
|
|
|
if (indexUpdated) {
|
|
// changing position is a delete + re-add in new position
|
|
Security.post({path: "authorization"}, { "delete-permission": parseInt($scope.upsertPerm.originalIndex) }, function (remData) {
|
|
if (setPermJson.index) {
|
|
var before = setPermJson.index;
|
|
delete setPermJson.index;
|
|
setPermJson["before"] = before;
|
|
}
|
|
|
|
// add perm back in new position
|
|
Security.post({path: "authorization"}, { "set-permission": setPermJson }, function (data) {
|
|
var errorCause = checkError(data);
|
|
if (errorCause != null) {
|
|
$scope.securityAPIError = "set-permission "+name+" failed due to: "+errorCause;
|
|
$scope.securityAPIErrorDetails = JSON.stringify(data);
|
|
return;
|
|
}
|
|
$scope.togglePermDialog();
|
|
// avoids a weird race with not getting the latest config after an update
|
|
Security.get({path: "authorization"}, function (ignore) {
|
|
$scope.refreshSecurityPanel();
|
|
});
|
|
});
|
|
});
|
|
} else {
|
|
var action = isAdd ? "set-permission" : "update-permission";
|
|
var postBody = {};
|
|
postBody[action] = setPermJson;
|
|
|
|
// if they have the "all" permission in the last position, then keep it there when adding a new permission
|
|
if (!setPermJson["before"] && !setPermJson["index"] && $scope.permissionsTable && $scope.permissionsTable.length > 0 && $scope.permissionsTable[$scope.permissionsTable.length-1].name === "all") {
|
|
setPermJson["before"] = $scope.permissionsTable.length;
|
|
}
|
|
|
|
Security.post({path: "authorization"}, postBody, function (data) {
|
|
var errorCause = checkError(data);
|
|
if (errorCause != null) {
|
|
$scope.securityAPIError = action+" "+name+" failed due to: "+errorCause;
|
|
$scope.securityAPIErrorDetails = JSON.stringify(data);
|
|
return;
|
|
}
|
|
|
|
$scope.togglePermDialog();
|
|
// avoids a weird race with not getting the latest config after an update
|
|
Security.get({path: "authorization"}, function (ignore) {
|
|
$scope.refreshSecurityPanel();
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
$scope.applyUserFilter = function() {
|
|
$scope.userFilterText = "";
|
|
$scope.userFilterOption = "";
|
|
$scope.userFilterOptions = [];
|
|
$scope.filteredUsers = $scope.users; // reset the filtered when the filter type changes
|
|
|
|
if ($scope.userFilter === "name" || $scope.userFilter === "path") {
|
|
// no-op: filter is text input
|
|
} else if ($scope.userFilter === "role") {
|
|
$scope.userFilterOptions = $scope.roleNames;
|
|
} else if ($scope.userFilter === "perm") {
|
|
$scope.userFilterOptions = $scope.permissionsConfig.map(p => p.name).sort();
|
|
} else {
|
|
$scope.userFilter = "";
|
|
}
|
|
};
|
|
|
|
$scope.onUserFilterTextChanged = function() {
|
|
// don't fire until we have at least 2 chars ...
|
|
if ($scope.userFilterText && $scope.userFilterText.trim().length >= 2) {
|
|
$scope.userFilterOption = $scope.userFilterText.toLowerCase();
|
|
$scope.onUserFilterOptionChanged();
|
|
} else {
|
|
$scope.filteredUsers = $scope.users;
|
|
}
|
|
};
|
|
|
|
function pathMatch(paths, filter) {
|
|
for (p in paths) {
|
|
if (paths[p].includes(filter)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
$scope.onUserFilterOptionChanged = function() {
|
|
var filter = $scope.userFilterOption ? $scope.userFilterOption.trim() : "";
|
|
if (filter.length === 0) {
|
|
$scope.filteredUsers = $scope.users;
|
|
return;
|
|
}
|
|
|
|
if ($scope.userFilter === "name") {
|
|
$scope.filteredUsers = $scope.users.filter(u => u.username.toLowerCase().includes(filter));
|
|
} else if ($scope.userFilter === "role") {
|
|
$scope.filteredUsers = $scope.users.filter(u => u.roles.includes(filter));
|
|
} else if ($scope.userFilter === "path") {
|
|
var rolesForPath = Array.from(new Set($scope.permissionsTable.filter(p => p.roles && pathMatch(p.paths, filter)).flatMap(p => p.roles)));
|
|
var usersForPath = Array.from(new Set($scope.roles.filter(r => r.users && r.users.length > 0 && rolesForPath.includes(r.name)).flatMap(r => r.users)));
|
|
$scope.filteredUsers = $scope.users.filter(u => usersForPath.includes(u.username));
|
|
} else if ($scope.userFilter === "perm") {
|
|
var rolesForPerm = Array.from(new Set($scope.permissionsTable.filter(p => p.name === filter).flatMap(p => p.roles)));
|
|
var usersForPerm = Array.from(new Set($scope.roles.filter(r => r.users && r.users.length > 0 && rolesForPerm.includes(r.name)).flatMap(r => r.users)));
|
|
$scope.filteredUsers = $scope.users.filter(u => usersForPerm.includes(u.username));
|
|
} else {
|
|
// reset
|
|
$scope.userFilter = "";
|
|
$scope.userFilterOption = "";
|
|
$scope.userFilterText = "";
|
|
$scope.filteredUsers = $scope.users;
|
|
}
|
|
};
|
|
|
|
$scope.applyPermFilter = function() {
|
|
$scope.permFilterText = "";
|
|
$scope.permFilterOption = "";
|
|
$scope.permFilterOptions = [];
|
|
$scope.filteredPerms = $scope.permissionsTable;
|
|
|
|
if ($scope.permFilter === "name" || $scope.permFilter === "path") {
|
|
// no-op: filter is text input
|
|
} else if ($scope.permFilter === "role") {
|
|
var roles = $scope.manageUserRolesEnabled ? $scope.roleNames : Array.from(new Set($scope.permissionsTable.flatMap(p => p.roles))).sort();
|
|
$scope.permFilterOptions = ["*", "null"].concat(roles);
|
|
} else if ($scope.permFilter === "user") {
|
|
$scope.permFilterOptions = Array.from(new Set($scope.roles.flatMap(r => r.users))).sort();
|
|
} else if ($scope.permFilter === "collection") {
|
|
$scope.permFilterOptions = Array.from(new Set($scope.permissionsTable.flatMap(p => p.collections))).sort();
|
|
$scope.permFilterOptions.push("null");
|
|
} else {
|
|
// no perm filtering
|
|
$scope.permFilter = "";
|
|
}
|
|
};
|
|
|
|
$scope.onPermFilterTextChanged = function() {
|
|
// don't fire until we have at least 2 chars ...
|
|
if ($scope.permFilterText && $scope.permFilterText.trim().length >= 2) {
|
|
$scope.permFilterOption = $scope.permFilterText.trim().toLowerCase();
|
|
$scope.onPermFilterOptionChanged();
|
|
} else {
|
|
$scope.filteredPerms = $scope.permissionsTable;
|
|
}
|
|
};
|
|
|
|
$scope.onPermFilterOptionChanged = function() {
|
|
var filterCriteria = $scope.permFilterOption ? $scope.permFilterOption.trim() : "";
|
|
if (filterCriteria.length === 0) {
|
|
$scope.filteredPerms = $scope.permissionsTable;
|
|
return;
|
|
}
|
|
|
|
if ($scope.permFilter === "name") {
|
|
$scope.filteredPerms = $scope.permissionsTable.filter(p => p.name.toLowerCase().includes(filterCriteria));
|
|
} else if ($scope.permFilter === "role") {
|
|
if (filterCriteria === "null") {
|
|
$scope.filteredPerms = $scope.permissionsTable.filter(p => p.roles.length === 0);
|
|
} else {
|
|
$scope.filteredPerms = $scope.permissionsTable.filter(p => p.roles.includes(filterCriteria));
|
|
}
|
|
} else if ($scope.permFilter === "path") {
|
|
$scope.filteredPerms = $scope.permissionsTable.filter(p => pathMatch(p.paths, filterCriteria));
|
|
} else if ($scope.permFilter === "user") {
|
|
// get the user's roles and then find all the permissions mapped to each role
|
|
var rolesForUser = $scope.roles.filter(r => r.users.includes(filterCriteria)).map(r => r.name);
|
|
$scope.filteredPerms = $scope.permissionsTable.filter(p => p.roles.length > 0 && roleMatch(p.roles, rolesForUser));
|
|
} else if ($scope.permFilter === "collection") {
|
|
function collectionMatch(collNames, colls, filter) {
|
|
return (filter === "null") ?collNames === "null" : colls.includes(filter);
|
|
}
|
|
$scope.filteredPerms = $scope.permissionsTable.filter(p => collectionMatch(p.collectionNames, p.collections, filterCriteria));
|
|
} else {
|
|
// reset
|
|
$scope.permFilter = "";
|
|
$scope.permFilterOption = "";
|
|
$scope.permFilterText = "";
|
|
$scope.filteredPerms = $scope.permissionsTable;
|
|
}
|
|
};
|
|
|
|
$scope.editUser = function(row) {
|
|
if (!row || !$scope.hasSecurityEditPerm) {
|
|
return;
|
|
}
|
|
|
|
var userId = row.username;
|
|
$scope.userDialogMode = "edit";
|
|
$scope.userDialogHeader = "Edit User: "+userId;
|
|
$scope.userDialogAction = "Update";
|
|
var userRoles = userId in $scope.userRoles ? $scope.userRoles[userId] : [];
|
|
if (!Array.isArray(userRoles)) {
|
|
userRoles = [userRoles];
|
|
}
|
|
|
|
$scope.upsertUser = { username: userId, selectedRoles: userRoles };
|
|
$scope.toggleUserDialog();
|
|
};
|
|
|
|
function buildMethods(m) {
|
|
return {"get":""+m.includes("GET"), "post":""+m.includes("POST"), "put":""+m.includes("PUT"), "delete":""+m.includes("DELETE")};
|
|
}
|
|
|
|
$scope.editPerm = function(row) {
|
|
if (!$scope.managePermissionsEnabled || !$scope.hasSecurityEditPerm || !row) {
|
|
return;
|
|
}
|
|
|
|
var name = row.name;
|
|
$scope.permDialogMode = "edit";
|
|
$scope.permDialogHeader = "Edit Permission: "+name;
|
|
$scope.permDialogAction = "Update";
|
|
|
|
var perm = $scope.permissionsTable.find(p => p.name === name);
|
|
var isPredefined = $scope.predefinedPermissions.includes(name);
|
|
if (isPredefined) {
|
|
$scope.selectedPredefinedPermission = name;
|
|
$scope.upsertPerm = { };
|
|
$scope.filteredPredefinedPermissions = [];
|
|
$scope.filteredPredefinedPermissions.push(name);
|
|
if ($scope.selectedPredefinedPermission && $scope.selectedPredefinedPermission in $scope.predefinedPermissionCollection) {
|
|
$scope.upsertPerm.collection = $scope.predefinedPermissionCollection[$scope.selectedPredefinedPermission];
|
|
}
|
|
$scope.isPermFieldDisabled = true;
|
|
} else {
|
|
$scope.upsertPerm = { name: name, collection: perm.collectionNames, path: perm.paths };
|
|
$scope.params = [];
|
|
if (perm.params) {
|
|
for (const [key, value] of Object.entries(perm.params)) {
|
|
if (Array.isArray(value)) {
|
|
for (i in value) {
|
|
$scope.params.push({"name":key, "value":value[i]});
|
|
}
|
|
} else {
|
|
$scope.params.push({"name":key, "value":value});
|
|
}
|
|
}
|
|
}
|
|
if ($scope.params.length === 0) {
|
|
$scope.params = [{"name":"","value":""}];
|
|
}
|
|
|
|
$scope.upsertPerm["method"] = perm.method.length === 0 ? {"get":"true", "post":"true", "put":"true", "delete":"true"} : buildMethods(perm.method);
|
|
$scope.isPermFieldDisabled = false;
|
|
delete $scope.selectedPredefinedPermission;
|
|
}
|
|
|
|
$scope.upsertPerm.index = perm["index"];
|
|
$scope.upsertPerm.originalIndex = perm["index"];
|
|
|
|
// roles depending on authz plugin support
|
|
if ($scope.manageUserRolesEnabled) {
|
|
$scope.upsertPerm["selectedRoles"] = asList(perm.roles);
|
|
} else {
|
|
$scope.upsertPerm["manualRoles"] = asList(perm.roles).sort().join(", ");
|
|
}
|
|
|
|
$scope.togglePermDialog();
|
|
};
|
|
|
|
$scope.applyRoleFilter = function() {
|
|
$scope.roleFilterText = "";
|
|
$scope.roleFilterOption = "";
|
|
$scope.roleFilterOptions = [];
|
|
$scope.filteredRoles = $scope.roles; // reset the filtered when the filter type changes
|
|
|
|
if ($scope.roleFilter === "name" || $scope.roleFilter === "path") {
|
|
// no-op: filter is text input
|
|
} else if ($scope.roleFilter === "user") {
|
|
$scope.roleFilterOptions = Array.from(new Set($scope.roles.flatMap(r => r.users))).sort();
|
|
} else if ($scope.roleFilter === "perm") {
|
|
$scope.roleFilterOptions = $scope.permissionsConfig.map(p => p.name).sort();
|
|
} else {
|
|
$scope.roleFilter = "";
|
|
}
|
|
};
|
|
|
|
$scope.onRoleFilterTextChanged = function() {
|
|
// don't fire until we have at least 2 chars ...
|
|
if ($scope.roleFilterText && $scope.roleFilterText.trim().length >= 2) {
|
|
$scope.roleFilterOption = $scope.roleFilterText.toLowerCase();
|
|
$scope.onRoleFilterOptionChanged();
|
|
} else {
|
|
$scope.filteredRoles = $scope.roles;
|
|
}
|
|
};
|
|
|
|
$scope.onRoleFilterOptionChanged = function() {
|
|
var filter = $scope.roleFilterOption ? $scope.roleFilterOption.trim() : "";
|
|
if (filter.length === 0) {
|
|
$scope.filteredRoles = $scope.roles;
|
|
return;
|
|
}
|
|
|
|
if ($scope.roleFilter === "name") {
|
|
$scope.filteredRoles = $scope.roles.filter(r => r.name.toLowerCase().includes(filter));
|
|
} else if ($scope.roleFilter === "user") {
|
|
$scope.filteredRoles = $scope.roles.filter(r => r.users.includes(filter));
|
|
} else if ($scope.roleFilter === "path") {
|
|
var rolesForPath = Array.from(new Set($scope.permissionsTable.filter(p => p.roles && pathMatch(p.paths, filter)).flatMap(p => p.roles)));
|
|
$scope.filteredRoles = $scope.roles.filter(r => rolesForPath.includes(r.name));
|
|
} else if ($scope.roleFilter === "perm") {
|
|
var rolesForPerm = Array.from(new Set($scope.permissionsTable.filter(p => p.name === filter).flatMap(p => p.roles)));
|
|
$scope.filteredRoles = $scope.roles.filter(r => rolesForPerm.includes(r.name));
|
|
} else {
|
|
// reset
|
|
$scope.roleFilter = "";
|
|
$scope.roleFilterOption = "";
|
|
$scope.roleFilterText = "";
|
|
$scope.filteredRoles = $scope.roles;
|
|
}
|
|
};
|
|
|
|
$scope.showAddRoleDialog = function() {
|
|
$scope.roleDialogMode = "add";
|
|
$scope.roleDialogHeader = "Add New Role";
|
|
$scope.roleDialogAction = "Add Role";
|
|
$scope.upsertRole = {};
|
|
$scope.userNames = $scope.users.map(u => u.username);
|
|
$scope.grantPermissionNames = Array.from(new Set($scope.predefinedPermissions.concat($scope.permissionsConfig.map(p => p.name)))).sort();
|
|
$scope.toggleRoleDialog();
|
|
};
|
|
|
|
$scope.toggleRoleDialog = function() {
|
|
if ($scope.showRoleDialog) {
|
|
delete $scope.upsertRole;
|
|
delete $scope.validationError;
|
|
delete $scope.userNames;
|
|
$scope.showRoleDialog = false;
|
|
return;
|
|
}
|
|
$scope.hideAll();
|
|
$('#role-dialog').css({left: 680, top: 139});
|
|
$scope.showRoleDialog = true;
|
|
};
|
|
|
|
$scope.doUpsertRole = function() {
|
|
if (!$scope.upsertRole) {
|
|
delete $scope.validationError;
|
|
$scope.showRoleDialog = false;
|
|
return;
|
|
}
|
|
|
|
if (!$scope.upsertRole.name || $scope.upsertRole.name.trim() === "") {
|
|
$scope.validationError = "Role name is required!";
|
|
return;
|
|
}
|
|
|
|
// keep role name to a reasonable length? but allow for email addresses
|
|
var name = $scope.upsertRole.name.trim();
|
|
if (name.length > 30) {
|
|
$scope.validationError = "Role name must be 30 characters or less!";
|
|
return;
|
|
}
|
|
|
|
if (name === "null" || name === "*") {
|
|
$scope.validationError = "Role name '"+name+"' is invalid!";
|
|
return;
|
|
}
|
|
|
|
if ($scope.roleDialogMode === "add") {
|
|
if ($scope.roleNames.includes(name)) {
|
|
$scope.validationError = "Role '"+name+"' already exists!";
|
|
return;
|
|
}
|
|
}
|
|
|
|
var usersForRole = [];
|
|
if ($scope.upsertRole.selectedUsers && $scope.upsertRole.selectedUsers.length > 0) {
|
|
usersForRole = usersForRole.concat($scope.upsertRole.selectedUsers);
|
|
}
|
|
usersForRole = Array.from(new Set(usersForRole));
|
|
if (usersForRole.length === 0) {
|
|
$scope.validationError = "Must assign new role '"+name+"' to at least one user.";
|
|
return;
|
|
}
|
|
|
|
var perms = [];
|
|
if ($scope.upsertRole.grantedPerms && Array.isArray($scope.upsertRole.grantedPerms) && $scope.upsertRole.grantedPerms.length > 0) {
|
|
perms = $scope.upsertRole.grantedPerms;
|
|
}
|
|
|
|
// go get the latest role mappings ...
|
|
Security.get({path: "authorization"}, function (data) {
|
|
var authz = $scope.findEditableAuthz(data);
|
|
if (!authz) {
|
|
$scope.validationError = "User roles not editable via the UI!";
|
|
return;
|
|
}
|
|
|
|
var userRoles = authz["user-role"];
|
|
var setUserRoles = {};
|
|
for (u in usersForRole) {
|
|
var user = usersForRole[u];
|
|
var currentRoles = user in userRoles ? asList(userRoles[user]) : [];
|
|
// add the new role for this user if needed
|
|
if (!currentRoles.includes(name)) {
|
|
currentRoles.push(name);
|
|
}
|
|
setUserRoles[user] = currentRoles;
|
|
}
|
|
|
|
var cmdJson = $scope.wrapSchemeCmd("set-user-role", setUserRoles);
|
|
Security.post({path: "authorization"}, cmdJson, function (data2) {
|
|
|
|
var errorCause = checkError(data2);
|
|
if (errorCause != null) {
|
|
$scope.securityAPIError = "set-user-role for "+username+" failed due to: "+errorCause;
|
|
$scope.securityAPIErrorDetails = JSON.stringify(data2);
|
|
return;
|
|
}
|
|
|
|
if (perms.length === 0) {
|
|
// close dialog and refresh the tables ...
|
|
$scope.toggleRoleDialog();
|
|
$scope.refreshSecurityPanel();
|
|
return;
|
|
}
|
|
|
|
var currentPerms = data.authorization["permissions"];
|
|
for (i in perms) {
|
|
var permName = perms[i];
|
|
var existingPerm = currentPerms.find(p => p.name === permName);
|
|
|
|
if (existingPerm) {
|
|
var roleList = [];
|
|
if (existingPerm.role) {
|
|
if (Array.isArray(existingPerm.role)) {
|
|
roleList = existingPerm.role;
|
|
} else {
|
|
roleList.push(existingPerm.role);
|
|
}
|
|
}
|
|
if (!roleList.includes(name)) {
|
|
roleList.push(name);
|
|
}
|
|
existingPerm.role = roleList;
|
|
Security.post({path: "authorization"}, { "update-permission": existingPerm }, function (data3) {
|
|
$scope.refreshSecurityPanel();
|
|
});
|
|
} else {
|
|
// new perm ... must be a predefined ...
|
|
if ($scope.predefinedPermissions.includes(permName)) {
|
|
var setPermission = {name: permName, role:[name]};
|
|
Security.post({path: "authorization"}, { "set-permission": setPermission }, function (data3) {
|
|
$scope.refreshSecurityPanel();
|
|
});
|
|
} // else ignore it
|
|
}
|
|
}
|
|
$scope.toggleRoleDialog();
|
|
});
|
|
});
|
|
|
|
};
|
|
|
|
$scope.editRole = function(row) {
|
|
if (!row || !$scope.hasSecurityEditPerm) {
|
|
return;
|
|
}
|
|
|
|
var roleName = row.name;
|
|
$scope.roleDialogMode = "edit";
|
|
$scope.roleDialogHeader = "Edit Role: "+roleName;
|
|
$scope.roleDialogAction = "Update";
|
|
var role = $scope.roles.find(r => r.name === roleName);
|
|
var perms = $scope.permissionsTable.filter(p => p.roles.includes(roleName)).map(p => p.name);
|
|
$scope.upsertRole = { name: roleName, selectedUsers: role.users, grantedPerms: perms };
|
|
$scope.userNames = $scope.users.map(u => u.username);
|
|
$scope.grantPermissionNames = Array.from(new Set($scope.predefinedPermissions.concat($scope.permissionsConfig.map(p => p.name)))).sort();
|
|
$scope.toggleRoleDialog();
|
|
};
|
|
|
|
$scope.onBlockUnknownChange = function() {
|
|
var cmdJson = $scope.wrapSchemeCmd("set-property", { "blockUnknown": $scope.blockUnknown === "true" });
|
|
Security.post({path: "authentication"}, cmdJson, function (data) {
|
|
$scope.refreshSecurityPanel();
|
|
});
|
|
};
|
|
|
|
$scope.onForwardCredsChange = function() {
|
|
var cmdJson = $scope.wrapSchemeCmd("set-property", { "forwardCredentials": $scope.forwardCredentials === "true" });
|
|
Security.post({path: "authentication"}, cmdJson, function (data) {
|
|
$scope.refreshSecurityPanel();
|
|
});
|
|
};
|
|
|
|
$scope.removeParam= function(index) {
|
|
if ($scope.params.length === 1) {
|
|
$scope.params = [{"name":"","value":""}];
|
|
} else {
|
|
$scope.params.splice(index, 1);
|
|
}
|
|
};
|
|
|
|
$scope.addParam = function(index) {
|
|
$scope.params.splice(index+1, 0, {"name":"","value":""});
|
|
};
|
|
|
|
$scope.refresh();
|
|
})
|