This is an automated email from the ASF dual-hosted git repository.
andreapatricelli pushed a commit to branch 2_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/2_1_X by this push:
new acbd537 [SYNCOPE-1462] revisited UR management in enduser, fixed not
refreshing UR list
acbd537 is described below
commit acbd537d5312171f760ba407f2af8ad5f22cfa97
Author: Andrea Patricelli <[email protected]>
AuthorDate: Thu Jun 6 12:19:05 2019 +0200
[SYNCOPE-1462] revisited UR management in enduser, fixed not refreshing UR
list
---
.../META-INF/resources/app/css/editUser.css | 8 +-
.../resources/app/css/templates/dark/editUser.css | 2 +-
.../resources/META-INF/resources/app/index.html | 2 +-
.../resources/META-INF/resources/app/js/app.js | 13 ---
.../app/js/directives/autoCompleteTextField.js | 47 ++++++++
.../resources/app/js/directives/requestForms.js | 110 ------------------
.../resources/app/js/directives/requests.js | 98 ++++++----------
.../app/js/services/userRequestsService.js | 13 +--
.../resources/app/languages/de/static.json | 4 +-
.../resources/app/languages/en/static.json | 2 +-
.../resources/app/languages/it/static.json | 2 +-
.../resources/app/languages/ja/static.json | 2 +-
.../resources/app/views/autoCompleteTextField.html | 25 ++++
.../META-INF/resources/app/views/requestForms.html | 61 ----------
.../META-INF/resources/app/views/requests.html | 129 ++++++++++++---------
.../resources/app/views/user-request-forms.html | 48 --------
.../resources/app/views/user-requests.html | 2 +-
.../client/enduser/model/UserRequestWrapper.java | 46 ++++++++
.../enduser/resources/UserRequestsResource.java | 62 +++++++---
.../apache/syncope/common/lib/to/UserRequest.java | 20 ++++
.../core/flowable/api/UserRequestHandler.java | 9 ++
.../flowable/impl/FlowableUserRequestHandler.java | 48 ++++++--
.../syncope/core/logic/UserRequestLogic.java | 40 ++++---
.../rest/api/service/UserRequestService.java | 14 +++
.../rest/cxf/service/UserRequestServiceImpl.java | 5 +
25 files changed, 401 insertions(+), 411 deletions(-)
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css
b/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css
index 47d64d6..a0e86de 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css
+++ b/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css
@@ -62,7 +62,7 @@ under the License.
padding: 2%;
}
-#attribute {
+#attribute, #form-submit {
margin: auto;
max-width:480px;
padding: 10px;
@@ -379,6 +379,12 @@ div[role="tablist"] {
background-color: #f5f5f5;
border-color: #ddd;
}
+
+.search-box {
+ padding-bottom: 5px !important;
+ margin: 3%
+}
+
/* end default style
=============================================================================
*/
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/editUser.css
b/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/editUser.css
index dd0d351..1a34f70 100644
---
a/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/editUser.css
+++
b/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/editUser.css
@@ -92,4 +92,4 @@ span.k-dropdown,
.card-header {
background-color: #49553e;
-}
\ No newline at end of file
+}
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/index.html
b/client/enduser/src/main/resources/META-INF/resources/app/index.html
index 7122b50..7f124f5 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/index.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/index.html
@@ -145,7 +145,6 @@ under the License.
<script src="js/directives/captcha.js"></script>
<script src="js/directives/resources.js"></script>
<script src="js/directives/requests.js"></script>
- <script src="js/directives/requestForms.js"></script>
<script src="js/directives/formProperty.js"></script>
<script src="js/directives/groups.js"></script>
<script src="js/directives/auxClasses.js"></script>
@@ -157,6 +156,7 @@ under the License.
<script src="js/directives/modalWindow.js"></script>
<script src="js/directives/bpmnProcesses.js"></script>
<script src="js/directives/modalContent.js"></script>
+ <script src="js/directives/autoCompleteTextField.js"></script>
<script src="js/directives/ngEnter.js"></script>
<!--validator-->
<script src="js/validator/validationRules.js"></script>
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
index f95093e..5b67897 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
@@ -237,16 +237,6 @@ app.config(['$stateProvider', '$urlRouterProvider',
'$httpProvider', '$translate
}]
}
})
- .state('update.userRequestForms', {
- url: '/user-request-forms',
- templateUrl: 'views/user-request-forms.html',
- resolve: {
- 'authenticated': ['AuthService',
- function (AuthService) {
- return AuthService.islogged();
- }]
- }
- })
/* </Extensions> */
.state('update.finish', {
url: '/finish',
@@ -457,9 +447,6 @@ app.controller('ApplicationController', ['$scope',
'$rootScope', 'InfoService',
$scope.wizard.userRequests = {
"url": "/user-requests"
};
- $scope.wizard.userRequestForms = {
- "url": "/user-request-forms"
- };
/* </Extensions> */
$scope.wizardFirstStep = response.wizard.firstStep;
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/autoCompleteTextField.js
b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/autoCompleteTextField.js
new file mode 100644
index 0000000..82ec6be
--- /dev/null
+++
b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/autoCompleteTextField.js
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+'use strict';
+
+angular.module('self')
+ .directive('autoCompleteTextField', function () {
+ return {
+ restrict: 'E',
+ templateUrl: 'views/autoCompleteTextField.html',
+ scope: {
+ values: "=",
+ selected: "="
+ },
+ controller: function ($scope) {
+ $scope.complete = function (string) {
+ var output = [];
+ angular.forEach($scope.values, function (selected) {
+ if (selected.key.toLowerCase().indexOf(string.toLowerCase())
>= 0) {
+ output.push(selected.key);
+ }
+ });
+ $scope.filteredValues = output;
+ };
+
+ $scope.fillTextbox = function (selected) {
+ $scope.selected = selected;
+ $scope.filteredValues = null;
+ };
+ }
+ };
+ });
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/requestForms.js
b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/requestForms.js
deleted file mode 100644
index 4512257..0000000
---
a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/requestForms.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.
- */
-'use strict';
-
-angular.module('self')
- .directive('requestForms', ['UserRequestsService',
- function (UserRequestsService) {
- return {
- restrict: 'E',
- templateUrl: 'views/requestForms.html',
- scope: {
- user: "="
- },
- controller: function ($scope) {
- // Initialization
- $scope.query = {
- user: $scope.user.username,
- page: 1,
- size: 10
- };
-
- var calculatePages = function () {
- $scope.totalPages = Math.ceil($scope.forms.totalCount /
$scope.query.size);
- $scope.pages = _.range(1, $scope.totalPages + 1);
- };
-
- // <Pagination>
- $scope.reloadPage = function (page, size, successMsg) {
- // update query pagination parameters
- $scope.query.page = page;
- $scope.query.size = size;
- // recalculate pages
- calculatePages();
- if (page < 1 || page > $scope.totalPages) {
- return;
- }
- // get current page of items
-
- $scope.getUserRequestForms($scope.query, function (forms) {
- $scope.forms = forms;
- $scope.$parent.showSuccess(successMsg,
$scope.$parent.notification);
- });
- };
- // </Pagination>
-
- var init = function () {
- $scope.getUserRequestForms({
- user: $scope.user.username,
- page: 1,
- size: 10
- }, function (requestsForms) {
- $scope.forms = requestsForms;
- calculatePages();
- $scope.availableSizes = [{id: 1, value: 10}, {id: 2,
value: 25}, {id: 3, value: 50}];
- $scope.selectedSize = $scope.availableSizes[0];
- });
- };
-
- $scope.getUserRequestForms = function (query, callback) {
- UserRequestsService.getUserRequestForms(query).then(function
(response) {
- callback(response);
- }, function (response) {
- var errorMessage;
- // parse error response
- if (response !== undefined) {
- errorMessage = response.split("ErrorMessage{{")[1];
- errorMessage = errorMessage.split("}}")[0];
- }
- console.error("Error retrieving User Request Forms: ",
errorMessage);
- });
- };
-
- init();
-
- $scope.submit = function (form) {
- UserRequestsService.submitForm(form).then(function
(response) {
- console.debug("Form successfully submitted");
- $scope.$parent.showSuccess("Form successfully submitted",
$scope.$parent.notification);
- $scope.reloadPage($scope.query.page, $scope.query.size,
"Form successfully submitted");
- }, function (response) {
- var errorMessage;
- // parse error response
- if (response !== undefined) {
- errorMessage = response.split("ErrorMessage{{")[1];
- errorMessage = errorMessage.split("}}")[0];
- }
- console.error("Error retrieving User Request Forms: ",
errorMessage);
- $scope.$parent.showError("Error: " + (errorMessage ||
response), $scope.$parent.notification);
- });
-
- };
- }
- };
- }]);
\ No newline at end of file
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/requests.js
b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/requests.js
index 64d15a5..ac4e1a6 100644
---
a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/requests.js
+++
b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/requests.js
@@ -19,9 +19,8 @@
'use strict';
angular.module('self')
- .directive('requests', ['UserRequestsService', 'BpmnProcessService',
"$uibModal", "$document", '$filter',
- '$rootScope',
- function (UserRequestsService, BpmnProcessService, $uibModal,
$document, $filter, $rootScope) {
+ .directive('requests', ['UserRequestsService', 'BpmnProcessService',
'$rootScope',
+ function (UserRequestsService, BpmnProcessService, $rootScope) {
return {
restrict: 'E',
templateUrl: 'views/requests.html',
@@ -46,18 +45,14 @@ angular.module('self')
// update query pagination parameters
$scope.query.page = page;
$scope.query.size = size;
- // recalculate pages
- calculatePages();
- if (page < 1 || page > $scope.totalPages) {
- return;
- }
- // get current page of items
$scope.getUserRequests($scope.query, function (requests) {
$scope.requests = requests;
if (successMsg) {
$scope.$parent.showSuccess(successMsg,
$scope.$parent.notification);
}
+ // recalculate pages
+ calculatePages();
});
};
// </Pagination>
@@ -80,18 +75,19 @@ angular.module('self')
var init = function () {
$scope.requests = [];
+ $scope.availableSizes = [{id: 1, value: 10}, {id: 2, value:
25}, {id: 3, value: 50}];
+ $scope.selectedSize = $scope.availableSizes[0];
+ // date formatting
+ $scope.formatDate = $rootScope.formatDate;
+ // init requests
$scope.getUserRequests($scope.query, function (requests) {
$scope.requests = requests;
calculatePages();
- $scope.availableSizes = [{id: 1, value: 10}, {id: 2,
value: 25}, {id: 3, value: 50}];
- $scope.selectedSize = $scope.availableSizes[0];
- // date formatting
- $scope.formatDate = $rootScope.formatDate;
});
-
};
var initBpmnProcesses = function () {
+ $scope.selectedBpmnProcess = "";
$scope.bpmnProcesses = [];
BpmnProcessService.getBpmnProcesses().then(function
(response) {
$scope.bpmnProcesses = response;
@@ -112,15 +108,15 @@ angular.module('self')
init();
initBpmnProcesses();
- $scope.cancel = function (request, reason) {
- console.log("Cancel request ", request.executionId, reason);
- UserRequestsService.cancel(request.executionId,
reason).then(function (response) {
- var index = $scope.requests.result.indexOf(request);
+ $scope.cancel = function (requestWrapper, reason) {
+ console.log("Cancel request ",
requestWrapper.request.executionId, reason);
+
UserRequestsService.cancel(requestWrapper.request.executionId,
reason).then(function (response) {
+ var index = $scope.requests.result.indexOf(requestWrapper);
if (index > -1) {
$scope.requests.result.splice(index, 1);
$scope.requests.totalCount--;
- $scope.reloadPage($scope.query.page, $scope.query.size,
- "Process " + request.executionId + " successfully
canceled");
+ $scope.reloadPage($scope.query.page, $scope.query.size,
+ "Process " + requestWrapper.request.executionId
+ " successfully canceled");
}
}, function (response) {
var errorMessage;
@@ -129,49 +125,12 @@ angular.module('self')
errorMessage = response.split("ErrorMessage{{")[1];
errorMessage = errorMessage.split("}}")[0];
}
- console.error("Error canceling User Request: ",
request.executionId, errorMessage);
+ console.error("Error canceling User Request: ",
requestWrapper.executionId, errorMessage);
});
};
- $scope.openComponentModal = function (size, parentSelector) {
- $scope.selectedProcesses = [];
- var parentElem = parentSelector ?
-
angular.element($document[0].querySelector(parentSelector)) : undefined;
- var modalInstance = $uibModal.open({
- animation: true,
- ariaLabelledBy: 'modal-title',
- ariaDescribedBy: 'modal-body',
- component: 'modalWindow',
- appendTo: parentElem,
- size: size,
- windowClass: 'in',
- backdropClass: 'in',
- resolve: {
- bpmnProcesses: function () {
- return $scope.bpmnProcesses;
- },
- selectedProcesses: function () {
- return $scope.selectedProcesses;
- },
- modalHtml: function () {
- return '<bpmn-processes></bpmn-processes>';
- },
- title: function () {
- return
$filter('translate')(["SELECT_PROCESS"]).SELECT_PROCESS;
- }
- }
- });
-
- modalInstance.result.then(function () {
- for (var i = 0; i < $scope.selectedProcesses.length; i++) {
- startRequest(i);
- }
- }, function () {
- });
- };
-
- var startRequest = function (i) {
- var currentProc = $scope.selectedProcesses[i];
+ $scope.startRequest = function () {
+ var currentProc = $scope.selectedBpmnProcess;
UserRequestsService.start(currentProc).then(function
(response) {
console.log("Process " + currentProc + " successfully
started");
$scope.reloadPage($scope.query.page, $scope.query.size,
@@ -187,6 +146,25 @@ angular.module('self')
console.error("Error starting User Request: ",
errorMessage);
});
};
+
+ $scope.submitForm = function (form) {
+ UserRequestsService.submitForm(form).then(function
(response) {
+ console.debug("Form successfully submitted");
+ $scope.$parent.showSuccess("Form successfully submitted",
$scope.$parent.notification);
+ $scope.reloadPage($scope.query.page, $scope.query.size,
"Form successfully submitted");
+ }, function (response) {
+ var errorMessage;
+ // parse error response
+ if (response !== undefined) {
+ errorMessage = response.split("ErrorMessage{{")[1];
+ errorMessage = errorMessage.split("}}")[0];
+ }
+ console.error("Error retrieving User Request Forms: ",
errorMessage);
+ $scope.$parent.showError("Error: " + (errorMessage ||
response), $scope.$parent.notification);
+ });
+
+ };
+
}
};
}]);
\ No newline at end of file
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/js/services/userRequestsService.js
b/client/enduser/src/main/resources/META-INF/resources/app/js/services/userRequestsService.js
index b887784..b7ed879 100644
---
a/client/enduser/src/main/resources/META-INF/resources/app/js/services/userRequestsService.js
+++
b/client/enduser/src/main/resources/META-INF/resources/app/js/services/userRequestsService.js
@@ -27,18 +27,7 @@ angular.module('self')
userRequestsService.getUserRequests = function (query) {
return $http.get("../api/flowable/userRequests?user=" +
query.user
+ (query.page ? "&page=" + query.page + (query.size ?
"&size=" + query.size : "") : "")
- + (query.orderBy ? "&orderBy=" + query.orderby : ""))
- .then(function (response) {
- return response.data;
- }, function (response) {
- return $q.reject(response.data || response.statusText);
- });
- };
-
- userRequestsService.getUserRequestForms = function (query) {
- return $http.get("../api/flowable/userRequests/forms?user=" +
query.user
- + (query.page ? "&page=" + query.page + (query.size ?
"&size=" + query.size : "") : "")
- + (query.orderBy ? "&orderBy=" + query.orderby : ""))
+ + (query.orderBy ? "&orderBy=" + query.orderby : "") +
"&withForm=true")
.then(function (response) {
return response.data;
}, function (response) {
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/languages/de/static.json
b/client/enduser/src/main/resources/META-INF/resources/app/languages/de/static.json
index b685f6b..9d9eb38 100644
---
a/client/enduser/src/main/resources/META-INF/resources/app/languages/de/static.json
+++
b/client/enduser/src/main/resources/META-INF/resources/app/languages/de/static.json
@@ -57,10 +57,10 @@
"SELECT_PROCESS": "Wählen Sie einen oder mehrere Prozesse aus, um die
Anfragen zu starten",
"PAGE_SIZE": "Seitengröße",
"EXECUTION_ID": "Ausführungs-ID",
+ "TASK_ID": "Aufgaben-ID",
"START_TIME": "Startzeit",
"START": "Start",
"own": "Besitzen",
- "userRequests": "Anfragen",
- "userRequestForms": "Formen"
+ "userRequests": "Anfragen"
}
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/languages/en/static.json
b/client/enduser/src/main/resources/META-INF/resources/app/languages/en/static.json
index 31574e4..93d74c9 100644
---
a/client/enduser/src/main/resources/META-INF/resources/app/languages/en/static.json
+++
b/client/enduser/src/main/resources/META-INF/resources/app/languages/en/static.json
@@ -46,7 +46,6 @@
"virtualSchemas": "VirtualSchemas",
"resources": "Resources",
"userRequests": "Requests",
- "userRequestForms": "Forms",
"finish": "Finish",
"RESOURCES_PLACEHOLDER": "Click to select resources...",
"REALM": "Realm",
@@ -59,6 +58,7 @@
"SELECT_PROCESS": "Select one (or many) processes to start request(s)",
"PAGE_SIZE": "Page size",
"EXECUTION_ID": "Execution id",
+ "TASK_ID": "Task id",
"START_TIME": "Start time",
"START": "Start",
"own": "Own"
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/languages/it/static.json
b/client/enduser/src/main/resources/META-INF/resources/app/languages/it/static.json
index 3194dfc..b922737 100644
---
a/client/enduser/src/main/resources/META-INF/resources/app/languages/it/static.json
+++
b/client/enduser/src/main/resources/META-INF/resources/app/languages/it/static.json
@@ -46,7 +46,6 @@
"virtualSchemas": "VirtualSchemas",
"resources": "Risorse",
"userRequests": "Richieste",
- "userRequestForms": "Form",
"finish": "Fine",
"RESOURCES_PLACEHOLDER": "Clicca per selezionare risorse...",
"NEWUSER": "Nuovo utente",
@@ -59,6 +58,7 @@
"SELECT_PROCESS": "Selezionare uno (o più) processi per far partire una
richiesta(e)",
"PAGE_SIZE": "Elementi per pagina",
"EXECUTION_ID": "Id Esecuzione",
+ "TASK_ID": "Id Task",
"START_TIME": "Effettuata il",
"START": "Start",
"own": "Propri"
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/languages/ja/static.json
b/client/enduser/src/main/resources/META-INF/resources/app/languages/ja/static.json
index 51cd728..3d8d196 100644
---
a/client/enduser/src/main/resources/META-INF/resources/app/languages/ja/static.json
+++
b/client/enduser/src/main/resources/META-INF/resources/app/languages/ja/static.json
@@ -57,10 +57,10 @@
"SELECT_PROCESS": "プロセスを1つ(または複数)選択して、要求を開始します。",
"PAGE_SIZE": "ページサイズ",
"EXECUTION_ID": "実行ID",
+ "TASK_ID": "タスクID",
"START_TIME": "始まる時間",
"START": "開始",
"userRequests": "リクエスト",
- "userRequestForms": "フォーム",
"own": "自分"
}
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/views/autoCompleteTextField.html
b/client/enduser/src/main/resources/META-INF/resources/app/views/autoCompleteTextField.html
new file mode 100644
index 0000000..c09e683
--- /dev/null
+++
b/client/enduser/src/main/resources/META-INF/resources/app/views/autoCompleteTextField.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<div>
+ <input type="text" name="selected" id="selected" ng-model="selected"
ng-keyup="complete(selected)" class="form-control" />
+ <ul class="list-group">
+ <li class="list-group-item" ng-repeat="selected in filteredValues"
ng-click="fillTextbox(selected)">{{selected}}</li>
+ </ul>
+</div>
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/views/requestForms.html
b/client/enduser/src/main/resources/META-INF/resources/app/views/requestForms.html
deleted file mode 100644
index aa44b2c..0000000
---
a/client/enduser/src/main/resources/META-INF/resources/app/views/requestForms.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--
-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.
--->
-<div ng-repeat="form in forms.result">
- <uib-accordion ng-if="forms.result.length">
- <div uib-accordion-group heading="{{form.bpmnProcess| translate}}"
class="breadcrumb-header panel panel-default">
- <div id="attribute" class="form-group" ng-repeat="property in
form.properties">
- <label class="property-label" for="property.name">{{property.name}}
- <span ng-if="property.required">*</span>
- </label>
- <form-property property="property"></form-property>
- <validation-message name="{{property.name}}"/>
- </div>
- <div style="text-align: right">
- <button class="btn btn-secondary btn-default" type="button"
ng-click="submit(form)">{{ 'SUBMIT' | translate}}</button>
- </div>
- </div>
- </uib-accordion>
-</div>
-<div class="row">
- <div class="col-md-9" style="text-align: center">
- <!-- pager -->
- <ul ng-if="totalPages > 1" class="pagination">
- <li ng-class="{disabled:query.page === 1}">
- <a ng-click="reloadPage(1, query.size)">First</a>
- </li>
- <li ng-class="{disabled:query.page === 1}">
- <a ng-click="reloadPage(query.page - 1, query.size)">Previous</a>
- </li>
- <li ng-repeat="page in pages" ng-class="{active:query.page === page}">
- <a ng-click="reloadPage(page, query.size)">{{page}}</a>
- </li>
- <li ng-class="{disabled:query.page === totalPages}">
- <a ng-click="reloadPage(query.page + 1, query.size)">Next</a>
- </li>
- <li ng-class="{disabled:query.page === totalPages}">
- <a ng-click="reloadPage(totalPages, query.size)">Last</a>
- </li>
- </ul>
- </div>
- <div ng-if="totalPages > 1" class="form-group col-md-3 pagination-size-sm"
style="text-align: left">
- <select class="form-control" name="sizeSelect" id="sizeSelect"
- ng-options="option.value for option in availableSizes track by
option.id"
- ng-model="selectedSize" ng-change="reloadPage(query.page,
selectedSize.value)"></select>
- </div>
-</div>
\ No newline at end of file
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/views/requests.html
b/client/enduser/src/main/resources/META-INF/resources/app/views/requests.html
index 68c1da3..fc0f1f5 100644
---
a/client/enduser/src/main/resources/META-INF/resources/app/views/requests.html
+++
b/client/enduser/src/main/resources/META-INF/resources/app/views/requests.html
@@ -16,61 +16,82 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
-<div ng-repeat="request in requests.result">
- <uib-accordion ng-if="requests.result.length">
- <div uib-accordion-group heading="{{request.bpmnProcess| translate}}"
class="breadcrumb-header panel panel-default">
- <table class="table">
- <thead>
- <tr>
- <th>{{'EXECUTION_ID'| translate}}</th>
- <th>{{'START_TIME'| translate}}</th>
- </tr>
- </thead>
-
- <tbody>
- <tr>
- <td>{{request.executionId}}</td>
- <td>{{formatDate(request.startTime)}}</td>
- </tr>
- </tbody>
- </table>
- <div style="text-align: right">
- <a id="cancelRequest" class="btn btn-secondary btn-default"
ng-click="cancel(request)">
- <i class="fa fa-trash" aria-hidden="true"></i>
- </a>
- </div>
- </div>
- </uib-accordion>
-</div>
-<div class="row">
- <div class="col-md-9" style="text-align: center">
- <!-- pager -->
- <ul ng-if="totalPages > 1" class="pagination">
- <li ng-class="{disabled:query.page === 1}">
- <a ng-click="reloadPage(1, query.size)">First</a>
- </li>
- <li ng-class="{disabled:query.page === 1}">
- <a ng-click="reloadPage(query.page - 1, query.size)">Previous</a>
- </li>
- <li ng-repeat="page in pages" ng-class="{active:query.page === page}">
- <a ng-click="reloadPage(page, query.size)">{{page}}</a>
- </li>
- <li ng-class="{disabled:query.page === totalPages}">
- <a ng-click="reloadPage(query.page + 1, query.size)">Next</a>
- </li>
- <li ng-class="{disabled:query.page === totalPages}">
- <a ng-click="reloadPage(totalPages, query.size)">Last</a>
- </li>
- </ul>
+<div class="row panel panel-default card search-box">
+ <div class="col-md-10">
+ <auto-complete-text-field selected="selectedBpmnProcess"
values="bpmnProcesses"></auto-complete-text-field>
</div>
- <div ng-if="totalPages > 1" class="form-group col-md-3 pagination-size"
style="text-align: left">
- <select class="form-control" name="sizeSelect" id="sizeSelect"
- ng-options="option.value for option in availableSizes track by
option.id"
- ng-model="selectedSize" ng-change="reloadPage(query.page,
selectedSize.value)"></select>
+ <div class="col-md-2">
+ <button class="btn btn-secondary btn-default" type="button"
ng-click="startRequest()">{{ 'START' | translate}}</button>
</div>
</div>
-<div class="row" style="text-align: right">
- <button class="btn btn-default btn-sm" type="button"
ng-click="openComponentModal()">
- <i class="fa fa-plus" title="Start requests"></i>
- </button>
+
+<div ng-repeat="requestWrapper in requests.result">
+ <uib-accordion ng-if="requests.result.length">
+ <div uib-accordion-group heading="{{requestWrapper.request.bpmnProcess|
translate}}"
+ class="breadcrumb-header panel panel-default">
+ <div style="margin-left: 3%; margin-right: 3%">
+ <table class="table">
+ <thead>
+ <tr>
+ <th>{{'EXECUTION_ID'| translate}}</th>
+ <th>{{'TASK_ID'| translate}}</th>
+ <th>{{'START_TIME'| translate}}</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <tr>
+ <td>{{requestWrapper.request.executionId}}</td>
+ <td>{{requestWrapper.request.taskId}}</td>
+ <td>{{formatDate(requestWrapper.request.startTime)}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div ng-if="requestWrapper.request.hasForm && requestWrapper.form">
+ <div id="attribute" class="form-group" ng-repeat="property in
requestWrapper.form.properties">
+ <label class="property-label"
for="property.name">{{property.name}}
+ <span ng-if="property.required">*</span>
+ </label>
+ <form-property property="property"></form-property>
+ <validation-message name="{{property.name}}"/>
+ </div>
+ <div style="text-align: right" id="form-submit">
+ <button class="btn btn-secondary btn-default" type="button"
ng-click="submitForm(requestWrapper.form)">{{ 'SUBMIT' | translate}}</button>
+ </div>
+ </div>
+ <div style="text-align: right; margin-top: 3%">
+ <a id="cancelRequest" class="btn btn-secondary btn-default"
ng-click="cancel(requestWrapper)">
+ <i class="fa fa-trash" aria-hidden="true"></i>
+ </a>
+ </div>
+ </div>
+ </uib-accordion>
+ </div>
+ <div class="row">
+ <div class="col-md-9" style="text-align: center">
+ <!-- pager -->
+ <ul ng-if="totalPages > 1" class="pagination">
+ <li ng-class="{disabled:query.page === 1}">
+ <a ng-click="reloadPage(1, query.size)">First</a>
+ </li>
+ <li ng-class="{disabled:query.page === 1}">
+ <a ng-click="reloadPage(query.page - 1, query.size)">Previous</a>
+ </li>
+ <li ng-repeat="page in pages" ng-class="{active:query.page === page}">
+ <a ng-click="reloadPage(page, query.size)">{{page}}</a>
+ </li>
+ <li ng-class="{disabled:query.page === totalPages}">
+ <a ng-click="reloadPage(query.page + 1, query.size)">Next</a>
+ </li>
+ <li ng-class="{disabled:query.page === totalPages}">
+ <a ng-click="reloadPage(totalPages, query.size)">Last</a>
+ </li>
+ </ul>
+ </div>
+ <div ng-if="totalPages > 1" class="form-group col-md-3 pagination-size"
style="text-align: left">
+ <select class="form-control" name="sizeSelect" id="sizeSelect"
+ ng-options="option.value for option in availableSizes track by
option.id"
+ ng-model="selectedSize" ng-change="reloadPage(query.page,
selectedSize.value)"></select>
+ </div>
</div>
\ No newline at end of file
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/views/user-request-forms.html
b/client/enduser/src/main/resources/META-INF/resources/app/views/user-request-forms.html
deleted file mode 100644
index 4971143..0000000
---
a/client/enduser/src/main/resources/META-INF/resources/app/views/user-request-forms.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!--
-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.
--->
-<div>
- <request-forms user="user"></request-forms>
-</div>
-
-<div id="attribute" class="form-group row justify-content-between p-0">
- <div class="col-xs-3">
- <a id="cancel" class="btn btn-danger float-left nav-button" tabindex="0"
- ng-enter="logout()" ng-click="logout()">
- {{'CANCEL'| translate}}
- </a>
- </div>
- <div class="col-xs-9">
- <div id="navButtons" class="float-left"
- ng-class="(!createMode || (createMode && endReached)) ? 'col-xs-10' :
'col-xs-12'">
- <navigation-buttons-partial ng-show="createMode" base="create"
current="userRequestForms" wizard="{{wizard}}">
- </navigation-buttons-partial>
- <navigation-buttons-partial ng-show="!createMode" base="update"
current="userRequestForms" wizard="{{wizard}}">
- </navigation-buttons-partial>
- </div>
- <div class="float-right p-0"
- ng-class="(!createMode || (createMode && endReached)) ? 'col-xs-2' :
''"
- ng-show="!createMode || (createMode && endReached)">
- <button id="finish" type="button" tabindex="0"
- class="btn btn-secondary btn-default float-right nav-button"
- ng-enter="finish()" ng-click="finish()">
- {{'FINISH'| translate}}
- </button>
- </div>
- </div>
-</div>
\ No newline at end of file
diff --git
a/client/enduser/src/main/resources/META-INF/resources/app/views/user-requests.html
b/client/enduser/src/main/resources/META-INF/resources/app/views/user-requests.html
index 62c3e01..bc7aaa9 100644
---
a/client/enduser/src/main/resources/META-INF/resources/app/views/user-requests.html
+++
b/client/enduser/src/main/resources/META-INF/resources/app/views/user-requests.html
@@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
-<div id="attribute" class="form-group row upper-select ng-scope">
+<div>
<requests user="user"></requests>
</div>
diff --git
a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/model/UserRequestWrapper.java
b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/model/UserRequestWrapper.java
new file mode 100644
index 0000000..d96be15
--- /dev/null
+++
b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/model/UserRequestWrapper.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package org.apache.syncope.client.enduser.model;
+
+import org.apache.syncope.common.lib.BaseBean;
+import org.apache.syncope.common.lib.to.UserRequest;
+import org.apache.syncope.common.lib.to.UserRequestForm;
+
+public class UserRequestWrapper extends BaseBean {
+
+ private static final long serialVersionUID = -6221018606400361738L;
+
+ private final UserRequest request;
+
+ private final UserRequestForm form;
+
+ public UserRequestWrapper(final UserRequest request, final UserRequestForm
form) {
+ this.request = request;
+ this.form = form;
+ }
+
+ public UserRequest getRequest() {
+ return request;
+ }
+
+ public UserRequestForm getForm() {
+ return form;
+ }
+
+}
diff --git
a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserRequestsResource.java
b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserRequestsResource.java
index 812e408..6a25c5f 100644
---
a/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserRequestsResource.java
+++
b/ext/flowable/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserRequestsResource.java
@@ -18,16 +18,20 @@
*/
package org.apache.syncope.client.enduser.resources;
+import org.apache.syncope.client.enduser.model.UserRequestWrapper;
+
import static org.apache.syncope.client.enduser.resources.BaseResource.LOG;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.syncope.client.enduser.SyncopeEnduserSession;
import org.apache.syncope.client.enduser.annotations.Resource;
+import org.apache.syncope.common.lib.BaseBean;
import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.UserRequest;
import org.apache.syncope.common.rest.api.beans.UserRequestQuery;
@@ -47,7 +51,6 @@ public class UserRequestsResource extends BaseResource {
ResourceResponse response = new AbstractResource.ResourceResponse();
response.setContentType(MediaType.APPLICATION_JSON);
- StringValue username =
StringValue.valueOf(SyncopeEnduserSession.get().getSelfTO().getUsername());
try {
HttpServletRequest request = (HttpServletRequest)
attributes.getRequest().getContainerRequest();
if (!xsrfCheck(request)) {
@@ -81,21 +84,15 @@ public class UserRequestsResource extends BaseResource {
case HttpMethod.GET:
StringValue page =
requestParameters.getParameterValue("page");
StringValue size =
requestParameters.getParameterValue("size");
- LOG.debug("List available Flowable User Requests for user
[{}]", username);
- final PagedResult<UserRequest> userRequests =
SyncopeEnduserSession.get().
- getService(UserRequestService.class).list(
- new UserRequestQuery.Builder()
- .user(username.isEmpty()
- ?
SyncopeEnduserSession.get().getSelfTO().getUsername()
- : username.toString())
- .page(page.isEmpty()
- ? 1
- : Integer.parseInt(
- page.toString()))
- .size(size.isEmpty()
- ? 10
- : Integer.parseInt(
- size.toString())).build());
+ StringValue withForm =
requestParameters.getParameterValue("withForm");
+ LOG.debug("List available Flowable User Requests for user
[{}]",
+
SyncopeEnduserSession.get().getSelfTO().getUsername());
+
+ final PagedResult<? extends BaseBean> userRequests =
+ withForm.toBoolean(false)
+ ? fillWithForms(list(page, size))
+ : list(page, size);
+
response.setWriteCallback(new
AbstractResource.WriteCallback() {
@Override
@@ -117,7 +114,8 @@ public class UserRequestsResource extends BaseResource {
response.setTextEncoding(StandardCharsets.UTF_8.name());
response.setStatusCode(Response.Status.OK.getStatusCode());
} catch (Exception e) {
- LOG.error("Error retrieving user requests for [{}]", username, e);
+ LOG.error("Error retrieving user requests for [{}]",
SyncopeEnduserSession.get().getSelfTO().getUsername(),
+ e);
response.setError(Response.Status.BAD_REQUEST.getStatusCode(), new
StringBuilder()
.append("ErrorMessage{{ ")
.append(e.getMessage())
@@ -127,4 +125,34 @@ public class UserRequestsResource extends BaseResource {
return response;
}
+
+ private static PagedResult<UserRequest> list(final StringValue page, final
StringValue size)
+ throws NumberFormatException {
+ return SyncopeEnduserSession.get().getService(UserRequestService.class)
+ .list(new UserRequestQuery.Builder()
+
.user(SyncopeEnduserSession.get().getSelfTO().getUsername())
+ .page(page.isEmpty()
+ ? 1
+ : Integer.parseInt(
+ page.toString()))
+ .size(size.isEmpty()
+ ? 10
+ : Integer.parseInt(
+ size.toString())).build());
+ }
+
+ private PagedResult<UserRequestWrapper> fillWithForms(final
PagedResult<UserRequest> reqsResult) {
+ PagedResult<UserRequestWrapper> result = new PagedResult<>();
+ result.getResult().addAll(reqsResult.getResult().stream()
+ .map(ur -> new UserRequestWrapper(ur,
SyncopeEnduserSession.get().getService(UserRequestService.class)
+
.getForm(SyncopeEnduserSession.get().getSelfTO().getUsername(),
ur.getTaskId())))
+ .collect(Collectors.toList()));
+ result.setPage(reqsResult.getPage());
+ result.setSize(reqsResult.getSize());
+ result.setTotalCount(reqsResult.getTotalCount());
+ result.setPrev(reqsResult.getPrev());
+ result.setNext(reqsResult.getNext());
+
+ return result;
+ }
}
diff --git
a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequest.java
b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequest.java
index b0ce0a5..59f8129 100644
---
a/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequest.java
+++
b/ext/flowable/common-lib/src/main/java/org/apache/syncope/common/lib/to/UserRequest.java
@@ -38,6 +38,10 @@ public class UserRequest extends BaseBean {
private String executionId;
private String activityId;
+
+ private String taskId;
+
+ private boolean hasForm;
public String getBpmnProcess() {
return bpmnProcess;
@@ -78,4 +82,20 @@ public class UserRequest extends BaseBean {
public void setActivityId(final String activityId) {
this.activityId = activityId;
}
+
+ public String getTaskId() {
+ return taskId;
+ }
+
+ public void setTaskId(final String taskId) {
+ this.taskId = taskId;
+ }
+
+ public boolean getHasForm() {
+ return hasForm;
+ }
+
+ public void setHasForm(final boolean hasForm) {
+ this.hasForm = hasForm;
+ }
}
diff --git
a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java
b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java
index f7d7a35..73444f4 100644
---
a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java
+++
b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/api/UserRequestHandler.java
@@ -85,6 +85,15 @@ public interface UserRequestHandler {
void cancelByUser(AnyDeletedEvent event);
/**
+ * Get the form matching the provided task id.
+ *
+ * @param userKey user key
+ * @param taskId task id
+ * @return the form for the given task id
+ */
+ UserRequestForm getForm(String userKey, String taskId);
+
+ /**
* Get the forms matching the provided parameters.
*
* @param userKey user key (optional)
diff --git
a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java
b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java
index 86a6c03..06994a6 100644
---
a/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java
+++
b/ext/flowable/flowable-bpmn/src/main/java/org/apache/syncope/core/flowable/impl/FlowableUserRequestHandler.java
@@ -127,8 +127,11 @@ public class FlowableUserRequestHandler implements
UserRequestHandler {
userRequest.setStartTime(procInst.getStartTime());
userRequest.setUsername(userDAO.find(split.getRight()).getUsername());
userRequest.setExecutionId(procInst.getId());
- userRequest.setActivityId(engine.getTaskService().createTaskQuery().
-
processInstanceId(procInst.getProcessInstanceId()).singleResult().getTaskDefinitionKey());
+ final Task task = engine.getTaskService().createTaskQuery()
+
.processInstanceId(procInst.getProcessInstanceId()).singleResult();
+ userRequest.setActivityId(task.getTaskDefinitionKey());
+ userRequest.setTaskId(task.getId());
+ userRequest.setHasForm(StringUtils.isNotBlank(task.getFormKey()));
return userRequest;
}
@@ -300,7 +303,9 @@ public class FlowableUserRequestHandler implements
UserRequestHandler {
}
protected UserRequestForm getForm(final Task task) {
- return FlowableUserRequestHandler.this.getForm(task,
engine.getFormService().getTaskFormData(task.getId()));
+ return task == null
+ ? null
+ : FlowableUserRequestHandler.this.getForm(task,
engine.getFormService().getTaskFormData(task.getId()));
}
protected UserRequestForm getForm(final Task task, final TaskFormData fd) {
@@ -450,6 +455,20 @@ public class FlowableUserRequestHandler implements
UserRequestHandler {
return formTO;
}
+ @Override
+ public UserRequestForm getForm(final String userKey, final String taskId) {
+ TaskQuery query =
engine.getTaskService().createTaskQuery().taskId(taskId);
+ if (userKey != null) {
+
query.processInstanceBusinessKeyLike(FlowableRuntimeUtils.getProcBusinessKey("%",
userKey));
+ }
+
+ String authUser = AuthContextUtils.getUsername();
+
+ return adminUser.equals(authUser)
+ ? getForm(getTask(taskId))
+ :
getForm(query.taskCandidateOrAssigned(authUser).singleResult());
+ }
+
@Transactional(readOnly = true)
@Override
public Pair<Integer, List<UserRequestForm>> getForms(
@@ -522,15 +541,7 @@ public class FlowableUserRequestHandler implements
UserRequestHandler {
}
protected Pair<Task, TaskFormData> parseTask(final String taskId) {
- Task task;
- try {
- task =
engine.getTaskService().createTaskQuery().taskWithFormKey().taskId(taskId).singleResult();
- if (task == null) {
- throw new FlowableException("NULL result");
- }
- } catch (FlowableException e) {
- throw new NotFoundException("Flowable Task " + taskId, e);
- }
+ Task task = getTask(taskId);
TaskFormData formData;
try {
@@ -542,6 +553,19 @@ public class FlowableUserRequestHandler implements
UserRequestHandler {
return Pair.of(task, formData);
}
+ protected Task getTask(final String taskId) throws NotFoundException {
+ Task task;
+ try {
+ task =
engine.getTaskService().createTaskQuery().taskWithFormKey().taskId(taskId).singleResult();
+ if (task == null) {
+ throw new FlowableException("NULL result");
+ }
+ } catch (FlowableException e) {
+ throw new NotFoundException("Flowable Task " + taskId, e);
+ }
+ return task;
+ }
+
@Override
public UserRequestForm claimForm(final String taskId) {
Pair<Task, TaskFormData> parsed = parseTask(taskId);
diff --git
a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java
b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java
index cdef7bf..4b88eb8 100644
---
a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java
+++
b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java
@@ -153,27 +153,20 @@ public class UserRequestLogic extends
AbstractTransactionalLogic<EntityTO> {
}
@PreAuthorize("isAuthenticated()")
+ public UserRequestForm getForm(final String userKey, final String taskId) {
+ evaluateKey(userKey);
+
+ return userRequestHandler.getForm(userKey, taskId);
+ }
+
+ @PreAuthorize("isAuthenticated()")
@Transactional(readOnly = true)
public Pair<Integer, List<UserRequestForm>> getForms(
final String userKey,
final int page,
final int size,
final List<OrderByClause> orderByClauses) {
-
- if (userKey == null) {
- securityChecks(null,
- FlowableEntitlement.USER_REQUEST_FORM_LIST,
- "Listing forms not allowed");
- } else {
- User user = userDAO.find(userKey);
- if (user == null) {
- throw new NotFoundException("User " + userKey);
- }
-
- securityChecks(user.getUsername(),
- FlowableEntitlement.USER_REQUEST_FORM_LIST,
- "Listing forms for user" + user.getUsername() + " not
allowed");
- }
+ evaluateKey(userKey);
return userRequestHandler.getForms(userKey, page, size,
orderByClauses);
}
@@ -220,4 +213,21 @@ public class UserRequestLogic extends
AbstractTransactionalLogic<EntityTO> {
throw new UnresolvedReferenceException();
}
+
+ private void evaluateKey(final String userKey) {
+ if (userKey == null) {
+ securityChecks(null,
+ FlowableEntitlement.USER_REQUEST_FORM_LIST,
+ "Listing forms not allowed");
+ } else {
+ User user = userDAO.find(userKey);
+ if (user == null) {
+ throw new NotFoundException("User " + userKey);
+ }
+
+ securityChecks(user.getUsername(),
+ FlowableEntitlement.USER_REQUEST_FORM_LIST,
+ "Listing forms for user" + user.getUsername() + " not
allowed");
+ }
+ }
}
diff --git
a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java
b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java
index 7c2369b..dc55ad3 100644
---
a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java
+++
b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java
@@ -92,6 +92,20 @@ public interface UserRequestService extends JAXRSService {
@QueryParam("reason") String reason);
/**
+ * Returns a user request form matching the given task id.
+ *
+ * @param username username of the logged user
+ * @param taskId workflow task id
+ * @return the form for the given task id
+ */
+ @GET
+ @Path("forms/{username}/{taskId}")
+ @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML,
MediaType.APPLICATION_XML })
+ UserRequestForm getForm(
+ @NotNull @PathParam("username") String username,
+ @NotNull @PathParam("taskId") String taskId);
+
+ /**
* Returns a list of user request forms matching the given query.
*
* @param query query conditions
diff --git
a/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java
b/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java
index 580ca76..19c4f52 100644
---
a/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java
+++
b/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java
@@ -75,6 +75,11 @@ public class UserRequestServiceImpl extends
AbstractServiceImpl implements UserR
}
@Override
+ public UserRequestForm getForm(final String username, final String taskId)
{
+ return logic.getForm(getActualKey(userDAO, username), taskId);
+ }
+
+ @Override
public PagedResult<UserRequestForm> getForms(final UserRequestFormQuery
query) {
if (query.getUser() != null) {
query.setUser(getActualKey(userDAO, query.getUser()));