Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use custom IdM identity service in Flowable for user's groups resolution. #198

Merged
merged 6 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2015-2016 ForgeRock AS.
* Portions Copyright 2023 Wren Security.
* Portions Copyright 2023-2024 Wren Security.
*/

define([
Expand Down Expand Up @@ -99,14 +99,14 @@ define([
cssClass: "btn-primary",
action: function(dialogRef) {
var id = $("#candidateUsersSelect").val(),
label = $("#candidateUsersSelect option:selected").text(),
selectedUser = _.find(candidateUsers, { _id: id }),
callback = function () {
_this.render([_this.model.id], _.bind(function () {
messagesManager.messages.addMessage({"message": $.t("templates.taskInstance.assignedSuccess")});
}, this));
};

obj.assignTask(_this.model, id, label, callback);
obj.assignTask(_this.model, selectedUser, callback);
dialogRef.close();
}
}
Expand All @@ -118,18 +118,17 @@ define([
* sets the assignee attribute on a taskinstance
*
* @param model {a taskinstance model}
* @id {the new assignee id to be set}
* @label {the username text to be displayed in the nonCandidateWarning}
* @user {object representing the new assignee user to be set}
* @successCallback
* @returns {nothing}
* @constructor
*/
obj.assignTask = function(model, id, label, successCallback) {
obj.assignTask = function(model, user, successCallback) {
var assignNow = function () {
model.set("assignee",id);
model.set("assignee", user._id);

if (id === "noUserAssigned") {
model.set("assignee",null);
if (user._id === "noUserAssigned") {
model.set("assignee", null);
}

model.save().then(successCallback);
Expand All @@ -139,8 +138,8 @@ define([
* before changing assignee alert the "assigner" that the user
* being assigned does not exist in the list of candidate users
*/
if (id !== "noUserAssigned" && !_.includes(model.get("candidates").candidateUsers, id)) {
UIUtils.jqConfirm($.t("templates.taskInstance.nonCanditateWarning",{ userName: label }), _.bind(function() {
if (user._id !== "noUserAssigned" && !_.includes(model.get("candidates").candidateUsers, user.userName)) {
UIUtils.jqConfirm($.t("templates.taskInstance.nonCanditateWarning",{ userName: user.userName }), _.bind(function() {
assignNow();
}, this));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ define([
displayName = (item.displayName) ? item.displayName : item.givenName + " " + item.sn;


return '<divclass="option">' +
return '<div class="option">' +
'<span class="user-title">' +
'<span class="user-fullname">' + escape(displayName) + userName + '</span>' +
'</span>' +
Expand All @@ -176,7 +176,7 @@ define([
if (!query.length) {
queryFilter = "userName sw \"\" &_pageSize=10";
} else {
queryFilter = "givenName sw \"" +query +"\" or sn sw \"" +query +"\" or userName sw \"" +query +"\"";
queryFilter = "givenName sw \"" + query +"\" or sn sw \"" + query +"\" or userName sw \"" + query +"\"";
}

ResourceDelegate.searchResource(queryFilter, "managed/user").then(function(search) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2011-2016 ForgeRock AS.
* Portions Copyright 2023 Wren Security.
* Portions Copyright 2023-2024 Wren Security.
*/

define([
Expand Down Expand Up @@ -262,8 +262,8 @@ define([
task = this.getTaskFromCacheById($(target).closest("tr").find("input[name=taskId]").val());

if (task) {
for (i = 0; i < task.usersToAssign.users.length; i++) {
user = task.usersToAssign.users[i];
for (i = 0; i < task.usersToAssign.length; i++) {
user = task.usersToAssign[i];

if ($(target).find("option[value='"+ user.username +"']").length === 0 && user.username !== conf.loggedUser.get("userName")) {
$(target).append('<option value="'+ user.username +'">'+ user.displayableName +'</option');
Expand Down
51 changes: 14 additions & 37 deletions openidm-zip/src/main/resources/bin/defaults/script/router-authz.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Portions Copyrighted 2024 Wren Security
*/

/*
Expand Down Expand Up @@ -124,49 +126,24 @@ function join (arr, delim) {
}

function isUserCandidateForTask(taskInstanceId) {

var userCandidateTasksQueryParams = {
const params = {
"_queryId": "filtered-query",
"taskId": taskInstanceId,
"taskCandidateUser": context.security.authenticationId
},
userCandidateTasks = openidm.query("workflow/taskinstance", userCandidateTasksQueryParams).result,
userGroupCandidateTasksQueryParams,
userGroupCandidateTasks,
i,roles,role;

for (i = 0; i < userCandidateTasks.length; i++) {
if (taskInstanceId === userCandidateTasks[i]._id) {
return true;
}
}

roles = "";
for (i = 0; i < context.security.authorization.roles.length; i++) {
role = context.security.authorization.roles[i];
if (i === 0) {
roles = role;
} else {
roles = roles + "," + role;
}
}

userGroupCandidateTasksQueryParams = {
"_queryId": "filtered-query",
"taskCandidateGroup": ((typeof roles === "string") ? roles : join(roles, ","))
};
userGroupCandidateTasks = openidm.query("workflow/taskinstance", userGroupCandidateTasksQueryParams).result;
for (i = 0; i < userGroupCandidateTasks.length; i++) {
if (taskInstanceId === userGroupCandidateTasks[i]._id) {
return true;
}
}

return false;
const tasks = openidm.query("workflow/taskinstance", params).result;
return tasks.length > 0;
}

function canUpdateTask() {
var taskInstanceId = request.resourcePath.split("/")[2];
return isMyTask() || isUserCandidateForTask(taskInstanceId);
const taskInstanceId = request.resourcePath.split("/")[2];
const params = {
"_queryId": "filtered-query",
"taskId": taskInstanceId,
"taskCandidateOrAssigned": context.security.authenticationId
}
const tasks = openidm.query("workflow/taskinstance", params).result;
return tasks.length > 0;
}

function isProcessOnUsersList(processFilter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Portions Copyrighted 2024 Wren Security
*/

if (request.method !== "action") {
if (request.method !== "query") {
throw {
"code" : 403,
"message" : "Access denied"
Expand All @@ -34,124 +36,71 @@ if (!request.additionalParameters || !request.additionalParameters.taskId) {
}

(function () {
var getUserById = function(userId) {
var user = openidm.read("managed/user/"+userId);
if (!user) {
user = openidm.read("repo/internal/user/"+userId);
}
return user;
},
getUserByName = function(userName) {
var getUserByUserName = function(userName) {
var params = {
"_queryId": "for-userName",
"uid": userName
},
result = openidm.query("managed/user", params),
user = false;
user = null;

if (result.result && result.result.length === 1) {
user = result.result[0];
}
if (!user) {
user = openidm.read("repo/internal/user/"+userName);
}
return user;
},
getDisplayableOf = function(user) {
if (user.givenName || user.familyName) {
return user.givenName + " " + user.familyName;
if (user.givenName || user.sn) {
return user.givenName + " " + user.sn;
} else {
return user.userName ? user.userName : user._id;
}
},
taskDefinitionQueryParams,
taskDefinition,
taskCandidateUserArray,
candidateUserTaskDefinition,
taskCandidateGroupArray,
candidateGroupTaskDefinition,
i,j,
usersToAdd = {},
availableUsersToAssign,
candidateUsers = [],
candidateUser,
candidateGroups = [],
candidateGroup,
params,
result,
user,
username,
assigneeUserName,
task = openidm.read("workflow/taskinstance/" + request.additionalParameters.taskId);

if (!task) {
throw "Task Not Found";
throw "Task ID " + request.additionalParameters.taskId + " Not Found";
}

taskDefinitionQueryParams = {
"_queryId": "query-taskdefinition",
"processDefinitionId": task.processDefinitionId,
"taskDefinitionKey": task.taskDefinitionKey
};
taskDefinition = openidm.query("workflow/taskdefinition", taskDefinitionQueryParams);

taskCandidateUserArray = taskDefinition.taskCandidateUser.toArray();
for (i = 0; i < taskCandidateUserArray.length; i++) {
candidateUserTaskDefinition = taskCandidateUserArray[i];
candidateUsers.push(candidateUserTaskDefinition.expressionText);
}

taskCandidateGroupArray = taskDefinition.taskCandidateGroup.toArray();
for (i = 0; i < taskCandidateGroupArray.length; i++) {
candidateGroupTaskDefinition = taskCandidateGroupArray[i];
candidateGroups.push(candidateGroupTaskDefinition.expressionText);
}


for (i = 0; i < candidateGroups.length; i++) {
candidateGroup = candidateGroups[i];
result = openidm.query("managed/role/" + candidateGroup + "/members", {"_queryFilter": "true"}, ["*"]);

if (result.result && result.result.length > 0) {
for (j = 0; j < result.result.length; j++) {
user = result.result[j];
// Collect candidate users
candidateUsers = task.candidates.candidateUsers;
candidateUsers.forEach(user => {
usersToAdd[candidateUser] = user;
});

// Collect users from candidate groups
candidateGroups = task.candidates.candidateGroups;
candidateGroups.forEach(group => {
result = openidm.query("managed/role/" + group + "/members", { "_queryFilter": "true" }, ["_id", "userName", "givenName", "sn"]);
if (result.result) {
result.result.forEach(user => {
usersToAdd[user.userName] = user;
}
}

result = openidm.query("repo/internal/user", params);

if (result.result && result.result.length > 0) {
for (j = 0; j < result.result.length; j++) {
user = result.result[j];
username = user.userName ? user.userName : user._id;
usersToAdd[username] = user;
}
});
}
}

for (i = 0; i < candidateUsers.length; i++) {
candidateUser = candidateUsers[i];
usersToAdd[candidateUser] = user;
}

});

availableUsersToAssign = { users : [] };
availableUsersToAssign = [];
for (username in usersToAdd) {
if (usersToAdd.hasOwnProperty(username)) {
user = getUserByName(username);
if (user) {
availableUsersToAssign.users.push({_id: user._id, username: username, displayableName: getDisplayableOf(user)});
}
user = getUserByUserName(username);
if (user) {
availableUsersToAssign.push({ _id: user._id, username: username, displayableName: getDisplayableOf(user) });
}
}

assigneeUserName = task.assignee;
if (assigneeUserName && assigneeUserName !== '') {
user = getUserByName(assigneeUserName);
if (user) {
availableUsersToAssign.assignee = {_id: user._id, username: assigneeUserName, displayableName: getDisplayableOf(user)};
}
// Add internal users
internalUsers = openidm.query("repo/internal/user", { "_queryFilter": "true" });
if (internalUsers.result) {
internalUsers.result.forEach(user => {
availableUsersToAssign.push({ _id: user._id, username: user.userName, displayableName: getDisplayableOf(user) });
});
}

return availableUsersToAssign;
Expand Down
Loading
Loading