keycloak-memoizeit
Changes
forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js 73(+67 -6)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html 54(+28 -26)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html 7(+6 -1)
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java 1(+1 -0)
Details
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
index 5e01598..1ad2411 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
@@ -1080,6 +1080,24 @@ module.config([ '$routeProvider', function($routeProvider) {
},
flows : function(AuthenticationFlowsLoader) {
return AuthenticationFlowsLoader();
+ },
+ selectedFlow : function() {
+ return null;
+ }
+ },
+ controller : 'AuthenticationFlowsCtrl'
+ })
+ .when('/realms/:realm/authentication/flows/:flow', {
+ templateUrl : resourceUrl + '/partials/authentication-flows.html',
+ resolve : {
+ realm : function(RealmLoader) {
+ return RealmLoader();
+ },
+ flows : function(AuthenticationFlowsLoader) {
+ return AuthenticationFlowsLoader();
+ },
+ selectedFlow : function($route) {
+ return $route.current.params.flow;
}
},
controller : 'AuthenticationFlowsCtrl'
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index 15a8fa9..d4db267 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -1616,41 +1616,102 @@ module.controller('IdentityProviderMapperCreateCtrl', function($scope, realm, id
});
-module.controller('AuthenticationFlowsCtrl', function($scope, realm, flows, AuthenticationExecutions, Notifications, Dialog, $location) {
+module.controller('AuthenticationFlowsCtrl', function($scope, realm, flows, selectedFlow,
+ AuthenticationFlowsCopy, AuthenticationFlowExecutions,
+ AuthenticationExecution, AuthenticationExecutionRaisePriority, AuthenticationExecutionLowerPriority,
+ $modal, Notifications, CopyDialog, $location) {
$scope.realm = realm;
$scope.flows = flows;
if (flows.length > 0) {
$scope.flow = flows[0];
+ if (selectedFlow) {
+ for (var i = 0; i < flows.length; i++) {
+ if (flows[i].alias == selectedFlow) {
+ $scope.flow = flows[i];
+ break;
+ }
+ }
+ }
}
+
var setupForm = function() {
- AuthenticationExecutions.query({realm: realm.realm, alias: $scope.flow.alias}, function(data) {
+ AuthenticationFlowExecutions.query({realm: realm.realm, alias: $scope.flow.alias}, function(data) {
$scope.executions = data;
$scope.flowmax = 0;
+ $scope.levelmax = 0;
for (var i = 0; i < $scope.executions.length; i++ ) {
- execution = $scope.executions[i];
+ var execution = $scope.executions[i];
if (execution.requirementChoices.length > $scope.flowmax) {
$scope.flowmax = execution.requirementChoices.length;
}
+ if (execution.level > $scope.levelmax) {
+ $scope.levelmax = execution.level;
+ }
+ }
+ console.log("levelmax: " + $scope.levelmax);
+ $scope.levelmaxempties = [];
+ for (j = 0; j < $scope.levelmax; j++) {
+ $scope.levelmaxempties.push(j);
+
}
for (var i = 0; i < $scope.executions.length; i++ ) {
- execution = $scope.executions[i];
+ var execution = $scope.executions[i];
execution.empties = [];
for (j = 0; j < $scope.flowmax - execution.requirementChoices.length; j++) {
execution.empties.push(j);
}
+ execution.levels = [];
+ for (j = 0; j < execution.level; j++) {
+ execution.levels.push(j);
+ }
}
})
};
+ $scope.copyFlow = function() {
+ CopyDialog.open('Copy AuthenticationFlow', $scope.flow.alias, function(name) {
+ AuthenticationFlowsCopy.save({realm: realm.realm, alias: $scope.flow.alias}, {
+ newName: name
+ }, function() {
+ $location.url("/realms/" + realm.realm + '/authentication/flows/' + name);
+ Notifications.success("Flow copied.");
+ })
+ })
+ };
+
$scope.updateExecution = function(execution) {
var copy = angular.copy(execution);
delete copy.empties;
- AuthenticationExecutions.update({realm: realm.realm, alias: $scope.flow.alias}, copy, function() {
+ delete copy.levels;
+ AuthenticationFlowExecutions.update({realm: realm.realm, alias: $scope.flow.alias}, copy, function() {
Notifications.success("Auth requirement updated");
setupForm();
});
};
+
+ $scope.removeExecution = function(execution) {
+ console.log('removeExecution: ' + execution.id);
+ AuthenticationExecution.remove({realm: realm.realm, execution: execution.id}, function() {
+ Notifications.success("Execution removed");
+ setupForm();
+ })
+ }
+
+ $scope.raisePriority = function(execution) {
+ AuthenticationExecutionRaisePriority.save({realm: realm.realm, execution: execution.id}, function() {
+ Notifications.success("Priority raised");
+ setupForm();
+ })
+ }
+
+ $scope.lowerPriority = function(execution) {
+ AuthenticationExecutionLowerPriority.save({realm: realm.realm, execution: execution.id}, function() {
+ Notifications.success("Priority lowered");
+ setupForm();
+ })
+ }
+
$scope.setupForm = setupForm;
setupForm();
@@ -1658,7 +1719,7 @@ module.controller('AuthenticationFlowsCtrl', function($scope, realm, flows, Auth
});
-module.controller('RequiredActionsCtrl', function($scope, realm, RequiredActions, Notifications, Dialog, $location) {
+module.controller('RequiredActionsCtrl', function($scope, realm, RequiredActions, Notifications) {
console.log('RequiredActionsCtrl');
$scope.realm = realm;
$scope.requiredActions = [];
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
index 04929ef..479702e 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -94,6 +94,34 @@ module.service('Dialog', function($modal) {
return dialog
});
+module.service('CopyDialog', function($modal) {
+ var dialog = {};
+ dialog.open = function (title, suggested, success) {
+ var controller = function($scope, $modalInstance, title) {
+ $scope.title = title;
+ $scope.name = { value: 'Copy of ' + suggested };
+ $scope.ok = function () {
+ console.log('ok with name: ' + $scope.name);
+ $modalInstance.close();
+ success($scope.name.value);
+ };
+ $scope.cancel = function () {
+ $modalInstance.dismiss('cancel');
+ };
+ }
+ $modal.open({
+ templateUrl: resourceUrl + '/templates/kc-copy.html',
+ controller: controller,
+ resolve: {
+ title: function() {
+ return title;
+ }
+ }
+ });
+ };
+ return dialog;
+});
+
module.factory('Notifications', function($rootScope, $timeout) {
// time (in ms) the notifications are shown
var delay = 5000;
@@ -1133,7 +1161,7 @@ module.factory('IdentityProviderMapper', function($resource) {
});
});
-module.factory('AuthenticationExecutions', function($resource) {
+module.factory('AuthenticationFlowExecutions', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/authentication/flows/:alias/executions', {
realm : '@realm',
alias : '@alias'
@@ -1149,6 +1177,12 @@ module.factory('AuthenticationFlows', function($resource) {
realm : '@realm'
});
});
+module.factory('AuthenticationFlowsCopy', function($resource) {
+ return $resource(authUrl + '/admin/realms/:realm/authentication/flows/:alias/copy', {
+ realm : '@realm',
+ alias : '@alias'
+ });
+});
module.factory('AuthenticationConfigDescription', function($resource) {
return $resource(authUrl + '/admin/realms/:realm/authentication/config-description/:provider', {
realm : '@realm',
@@ -1173,6 +1207,33 @@ module.factory('AuthenticationExecutionConfig', function($resource) {
});
});
+module.factory('AuthenticationExecution', function($resource) {
+ return $resource(authUrl + '/admin/realms/:realm/authentication/executions/:execution', {
+ realm : '@realm',
+ execution : '@execution'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+});
+
+module.factory('AuthenticationExecutionRaisePriority', function($resource) {
+ return $resource(authUrl + '/admin/realms/:realm/authentication/executions/:execution/raise-priority', {
+ realm : '@realm',
+ execution : '@execution'
+ });
+});
+
+module.factory('AuthenticationExecutionLowerPriority', function($resource) {
+ return $resource(authUrl + '/admin/realms/:realm/authentication/executions/:execution/lower-priority', {
+ realm : '@realm',
+ execution : '@execution'
+ });
+});
+
+
+
module.service('SelectRoleDialog', function($modal) {
var dialog = {};
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
index 50f01b9..7f98234 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
@@ -6,43 +6,34 @@
<table class="table table-striped table-bordered">
<thead>
<tr>
- <th colspan="6" class="kc-table-actions">
+ <th colspan="{{levelmax + 1 + flowmax + 4}}" class="kc-table-actions">
<div class="dropdown pull-left">
<select class="form-control" ng-model="flow"
ng-options="(flow.alias|capitalize) for flow in flows"
data-ng-change="setupForm()">
</select>
</div>
+ <div class="pull-right" data-ng-show="access.manageRealm">
+ <button class="btn btn-default" data-ng-click="newFlow()">New</button>
+ <button class="btn btn-default" data-ng-click="copyFlow()">Copy</button>
+ <button class="btn btn-default" data-ng-hide="flow.builtIn" data-ng-click="removeFlow()">Delete</button>
+ <button class="btn btn-default" data-ng-hide="flow.builtIn" data-ng-click="addExecution()">Add Execution</button>
+ <button class="btn btn-default" data-ng-hide="flow.builtIn" data-ng-click="addFlow()">Add Flow</button>
+ </div>
</th>
- </tr>
+ </tr>
<tr data-ng-hide="executions.length == 0">
- <th colspan="2">Auth Type</th>
+ <th colspan="{{levelmax + 1}}">Auth Type</th>
<th colspan="{{flowmax}}">Requirement</th>
- <th></th>
+ <th colspan="3">Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="execution in executions" data-ng-show="executions.length > 0">
- <td ng-show="execution.subFlow"></td>
- <td>{{execution.referenceType|capitalize}}</td>
- <td ng-hide="execution.subFlow"></td>
+ <td ng-repeat="lev in execution.levels"></td>
+ <td><button data-ng-hide="flow.builtIn || $first" class="btn btn-default" data-ng-click="raisePriority(execution)"><i class="fa fa-angle-up"></i></button><button data-ng-hide="flow.builtIn || $last" class="btn btn-default" data-ng-click="lowerPriority(execution)"><i class="fa fa-angle-down"></i></button> {{execution.displayName|capitalize}}</td>
+ <td data-ng-show="execution.level == 0" ng-repeat="levmax in levelmaxempties"></td>
<td ng-repeat="choice in execution.requirementChoices">
- <!--
- <div class="dropdown pull-left">
- <select class="form-control"
- ng-model="execution.requirement"
- ng-options="choice for choice in execution.requirementChoices">
- </select>
- </div>
- -->
- <!--
- <div ng-repeat="choice in execution.requirementChoices">
- <label >
- <input type="radio" ng-model="execution.requirement" ng-value="choice">
- {{choice}}
- </label>
- </div>
- -->
<label >
<input type="radio" ng-model="execution.requirement" ng-value="choice" ng-change="updateExecution(execution)">
{{choice}}
@@ -50,9 +41,20 @@
</td>
<td ng-repeat="emptee in execution.empties"></td>
- <td>
- <a data-ng-show="execution.configurable && execution.authenticationConfig == null" class="btn btn-default" href="#/create/authentication/{{realm.realm}}/execution/{{execution.id}}/provider/{{execution.providerId}}">Configure</a>
- <a data-ng-show="execution.configurable && execution.authenticationConfig != null" class="btn btn-default" href="#/realms/{{realm.realm}}/authentication/config/{{execution.providerId}}/{{execution.authenticationConfig}}">Configure</a>
+ <td data-ng-hide="flow.builtIn" class="kc-action-cell">
+ <button class="btn btn-default btn-block btn-sm" data-ng-click="removeExecution(execution)">Delete</button>
+ </td>
+ <td data-ng-hide="flow.builtIn || !execution.authenticationFlow" class="kc-action-cell">
+ <button class="btn btn-default btn-block btn-sm" data-ng-click="addSubFlowExecution(execution)">Add Execution</button>
+ </td>
+ <td data-ng-hide="flow.builtIn || !execution.authenticationFlow" class="kc-action-cell">
+ <button class="btn btn-default btn-block btn-sm" data-ng-click="addSubFlowExecution(execution)">Add Flow</button>
+ </td>
+ <td data-ng-show="execution.configurable && execution.authenticationConfig == null" class="kc-action-cell">
+ <button data-ng-show="execution.configurable && execution.authenticationConfig == null" class="btn btn-default btn-block btn-sm" kc-open="/create/authentication/{{realm.realm}}/execution/{{execution.id}}/provider/{{execution.providerId}}">Config</button>
+ </td>
+ <td data-ng-show="execution.configurable && execution.authenticationConfig != null" class="kc-action-cell">
+ <button data-ng-show="execution.configurable && execution.authenticationConfig != null" class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/authentication/config/{{execution.providerId}}/{{execution.authenticationConfig}}">Config</button>
</td>
</tr>
<tr data-ng-show="executions.length == 0">
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html
index 55c5430..866ecf0 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/modal/role-selector.html
@@ -1,5 +1,10 @@
+<div class="modal-header">
+ <button type="button" class="close" ng-click="cancel()">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Role Selector</h4>
+</div>
<div style="padding: 15px 60px 75px 60px">
- <h2>Role Selector</h2>
<form>
<div data-ng-show="realmRoles.length > 0">
<label class="control-label" for="available">Realm Roles</label>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-copy.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-copy.html
new file mode 100755
index 0000000..e074432
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-copy.html
@@ -0,0 +1,18 @@
+<div class="modal-header">
+ <button type="button" class="close" ng-click="cancel()">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">{{title}}</h4>
+</div>
+<div class="modal-body">
+ <form>
+ <div>
+ <label class="control-label" for="name">New name</label>
+ <input class="form-control" type="text" id="name" data-ng-model="name.value">
+ </div>
+ </form>
+</div>
+<div class="modal-footer">
+ <button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
+ <button type="button" class="btn btn-primary" ng-click="ok()">Ok</button>
+</div>
\ No newline at end of file
diff --git a/model/api/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java b/model/api/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java
index f390d1f..c4f1b6b 100755
--- a/model/api/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java
+++ b/model/api/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java
@@ -23,7 +23,7 @@ public class AuthenticationExecutionModel implements Serializable {
private String authenticatorConfig;
private String authenticator;
private String flowId;
- private boolean autheticatorFlow;
+ private boolean authenticatorFlow;
private Requirement requirement;
private boolean userSetupAllowed;
private int priority;
@@ -103,12 +103,12 @@ public class AuthenticationExecutionModel implements Serializable {
*
* @return
*/
- public boolean isAutheticatorFlow() {
- return autheticatorFlow;
+ public boolean isAuthenticatorFlow() {
+ return authenticatorFlow;
}
- public void setAutheticatorFlow(boolean autheticatorFlow) {
- this.autheticatorFlow = autheticatorFlow;
+ public void setAuthenticatorFlow(boolean authenticatorFlow) {
+ this.authenticatorFlow = authenticatorFlow;
}
public enum Requirement {
diff --git a/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java b/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
index 1733c06..a2c6422 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
@@ -2,13 +2,9 @@ package org.keycloak.models.utils;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
-import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
-import java.util.HashMap;
-import java.util.Map;
-
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@@ -60,7 +56,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("registration-page-form");
execution.setPriority(10);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(true);
+ execution.setAuthenticatorFlow(true);
execution.setFlowId(registrationFormFlow.getId());
realm.addAuthenticatorExecution(execution);
@@ -70,7 +66,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("registration-user-creation");
execution.setPriority(20);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
execution = new AuthenticationExecutionModel();
@@ -79,7 +75,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("registration-profile-action");
execution.setPriority(40);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
execution = new AuthenticationExecutionModel();
@@ -88,7 +84,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("registration-password-action");
execution.setPriority(50);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
//AuthenticatorConfigModel captchaConfig = new AuthenticatorConfigModel();
@@ -104,7 +100,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("registration-recaptcha-action");
execution.setPriority(60);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
//execution.setAuthenticatorConfig(captchaConfig.getId());
realm.addAuthenticatorExecution(execution);
@@ -142,7 +138,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("direct-grant-validate-username");
execution.setPriority(10);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
// password
@@ -155,7 +151,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("direct-grant-validate-password");
execution.setPriority(20);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
// otp
@@ -168,7 +164,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("direct-grant-validate-otp");
execution.setPriority(30);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
@@ -189,7 +185,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("auth-cookie");
execution.setPriority(10);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
execution = new AuthenticationExecutionModel();
execution.setParentFlow(browser.getId());
@@ -201,7 +197,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("auth-spnego");
execution.setPriority(20);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
@@ -218,7 +214,7 @@ public class DefaultAuthenticationFlows {
execution.setFlowId(forms.getId());
execution.setPriority(30);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(true);
+ execution.setAuthenticatorFlow(true);
realm.addAuthenticatorExecution(execution);
// forms
@@ -229,7 +225,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("auth-username-password-form");
execution.setPriority(10);
execution.setUserSetupAllowed(false);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
// otp processing
@@ -244,7 +240,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticator("auth-otp-form");
execution.setPriority(20);
execution.setUserSetupAllowed(true);
- execution.setAutheticatorFlow(false);
+ execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
}
}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index c2b14cd..9e1b44e 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -462,7 +462,7 @@ public class ModelToRepresentation {
rep.setAuthenticatorConfig(config.getAlias());
}
rep.setAuthenticator(model.getAuthenticator());
- rep.setAutheticatorFlow(model.isAutheticatorFlow());
+ rep.setAutheticatorFlow(model.isAuthenticatorFlow());
if (model.getFlowId() != null) {
AuthenticationFlowModel flow = realm.getAuthenticationFlowById(model.getFlowId());
rep.setFlowAlias(flow.getAlias());
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 83c8273..fe08937 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -1077,7 +1077,7 @@ public class RepresentationToModel {
model.setAuthenticatorConfig(config.getId());
}
model.setAuthenticator(rep.getAuthenticator());
- model.setAutheticatorFlow(rep.isAutheticatorFlow());
+ model.setAuthenticatorFlow(rep.isAutheticatorFlow());
if (rep.getFlowAlias() != null) {
AuthenticationFlowModel flow = realm.getFlowByAlias(rep.getFlowAlias());
model.setFlowId(flow.getId());
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
index 09d4304..3d67e93 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
@@ -1314,7 +1314,7 @@ public class RealmAdapter implements RealmModel {
model.setAuthenticator(entity.getAuthenticator());
model.setParentFlow(entity.getParentFlow());
model.setFlowId(entity.getFlowId());
- model.setAutheticatorFlow(entity.isAuthenticatorFlow());
+ model.setAuthenticatorFlow(entity.isAuthenticatorFlow());
model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
return model;
}
@@ -1346,7 +1346,7 @@ public class RealmAdapter implements RealmModel {
entity.setPriority(model.getPriority());
entity.setRequirement(model.getRequirement());
entity.setUserSetupAllowed(model.isUserSetupAllowed());
- entity.setAuthenticatorFlow(model.isAutheticatorFlow());
+ entity.setAuthenticatorFlow(model.isAuthenticatorFlow());
entity.setFlowId(model.getFlowId());
entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
AuthenticationFlowEntity flow = getFlowEntity(model.getId());
@@ -1366,7 +1366,7 @@ public class RealmAdapter implements RealmModel {
}
}
if (entity == null) return;
- entity.setAuthenticatorFlow(model.isAutheticatorFlow());
+ entity.setAuthenticatorFlow(model.isAuthenticatorFlow());
entity.setAuthenticator(model.getAuthenticator());
entity.setPriority(model.getPriority());
entity.setRequirement(model.getRequirement());
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
index dd6e2e7..f4b1e35 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
@@ -197,6 +197,7 @@ public class CachedRealm implements Serializable {
defaultLocale = model.getDefaultLocale();
for (AuthenticationFlowModel flow : model.getAuthenticationFlows()) {
authenticationFlows.put(flow.getId(), flow);
+ authenticationExecutions.put(flow.getId(), new LinkedList<AuthenticationExecutionModel>());
for (AuthenticationExecutionModel execution : model.getAuthenticationExecutions(flow.getId())) {
authenticationExecutions.add(flow.getId(), execution);
executionsById.put(execution.getId(), execution);
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
index fe2ded8..84938bf 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
@@ -1075,7 +1075,6 @@ public class RealmAdapter implements RealmModel {
@Override
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
if (updated != null) return updated.getAuthenticationExecutions(flowId);
- List<AuthenticationExecutionModel> models = new ArrayList<>();
return cached.getAuthenticationExecutions().get(flowId);
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 51148f0..f3d44b1 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -1628,7 +1628,7 @@ public class RealmAdapter implements RealmModel {
model.setAuthenticator(entity.getAuthenticator());
model.setFlowId(entity.getFlowId());
model.setParentFlow(entity.getParentFlow().getId());
- model.setAutheticatorFlow(entity.isAutheticatorFlow());
+ model.setAuthenticatorFlow(entity.isAutheticatorFlow());
model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
return model;
}
@@ -1655,7 +1655,7 @@ public class RealmAdapter implements RealmModel {
flow.getExecutions().add(entity);
entity.setRealm(realm);
entity.setUserSetupAllowed(model.isUserSetupAllowed());
- entity.setAutheticatorFlow(model.isAutheticatorFlow());
+ entity.setAutheticatorFlow(model.isAuthenticatorFlow());
em.persist(entity);
em.flush();
model.setId(entity.getId());
@@ -1667,7 +1667,7 @@ public class RealmAdapter implements RealmModel {
public void updateAuthenticatorExecution(AuthenticationExecutionModel model) {
AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId());
if (entity == null) return;
- entity.setAutheticatorFlow(model.isAutheticatorFlow());
+ entity.setAutheticatorFlow(model.isAuthenticatorFlow());
entity.setAuthenticator(model.getAuthenticator());
entity.setPriority(model.getPriority());
entity.setRequirement(model.getRequirement());
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 823a51b..28b1c4d 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -1390,7 +1390,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
model.setAuthenticator(entity.getAuthenticator());
model.setFlowId(entity.getFlowId());
model.setParentFlow(entity.getParentFlow());
- model.setAutheticatorFlow(entity.isAuthenticatorFlow());
+ model.setAuthenticatorFlow(entity.isAuthenticatorFlow());
model.setAuthenticatorConfig(entity.getAuthenticatorConfig());
return model;
}
@@ -1422,7 +1422,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
entity.setPriority(model.getPriority());
entity.setRequirement(model.getRequirement());
entity.setUserSetupAllowed(model.isUserSetupAllowed());
- entity.setAuthenticatorFlow(model.isAutheticatorFlow());
+ entity.setAuthenticatorFlow(model.isAuthenticatorFlow());
entity.setFlowId(model.getFlowId());
entity.setParentFlow(model.getParentFlow());
entity.setAuthenticatorConfig(model.getAuthenticatorConfig());
@@ -1444,7 +1444,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
}
}
if (entity == null) return;
- entity.setAuthenticatorFlow(model.isAutheticatorFlow());
+ entity.setAuthenticatorFlow(model.isAuthenticatorFlow());
entity.setAuthenticator(model.getAuthenticator());
entity.setPriority(model.getPriority());
entity.setRequirement(model.getRequirement());
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java b/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java
index 45e8c3a..aa8a3a8 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticatorUtil.java
@@ -1,7 +1,6 @@
package org.keycloak.authentication;
import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.RealmModel;
import java.util.LinkedList;
@@ -21,9 +20,11 @@ public class AuthenticatorUtil {
}
public static void recurseExecutions(RealmModel realm, String flowId, List<AuthenticationExecutionModel> executions) {
- for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
+ List<AuthenticationExecutionModel> authenticationExecutions = realm.getAuthenticationExecutions(flowId);
+ if (authenticationExecutions == null) return;
+ for (AuthenticationExecutionModel model : authenticationExecutions) {
executions.add(model);
- if (model.isAutheticatorFlow() && model.isEnabled()) {
+ if (model.isAuthenticatorFlow() && model.isEnabled()) {
recurseExecutions(realm, model.getFlowId(), executions);
}
}
@@ -31,7 +32,7 @@ public class AuthenticatorUtil {
public static AuthenticationExecutionModel findExecutionByAuthenticator(RealmModel realm, String flowId, String authProviderId) {
for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
- if (model.isAutheticatorFlow()) {
+ if (model.isAuthenticatorFlow()) {
AuthenticationExecutionModel recurse = findExecutionByAuthenticator(realm, model.getFlowId(), authProviderId);
if (recurse != null) return recurse;
diff --git a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
index 524d7a9..be92d6e 100755
--- a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
+++ b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
@@ -49,7 +49,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
alternativeSuccessful = true;
continue;
}
- if (model.isAutheticatorFlow()) {
+ if (model.isAuthenticatorFlow()) {
AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
return authenticationFlow.processAction(actionExecution);
} else if (model.getId().equals(actionExecution)) {
@@ -79,7 +79,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
continue;
}
- if (model.isAutheticatorFlow()) {
+ if (model.isAuthenticatorFlow()) {
AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
Response flowChallenge = authenticationFlow.processFlow();
if (flowChallenge == null) {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
index c4618ea..3ce1e19 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
@@ -35,7 +35,7 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
property.setName(ROLE_CONFIG);
property.setLabel("Role");
property.setHelpText("Role name you want changed. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
- property.setType(ProviderConfigProperty.STRING_TYPE);
+ property.setType(ProviderConfigProperty.ROLE_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(NEW_ROLE_NAME);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
index 5f55c76..41380ab 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
@@ -2,6 +2,7 @@ package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.spi.BadRequestException;
import org.jboss.resteasy.spi.NotFoundException;
import org.keycloak.authentication.AuthenticationFlow;
import org.keycloak.authentication.AuthenticatorUtil;
@@ -28,6 +29,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
+import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -59,13 +61,15 @@ public class AuthenticationManagementResource {
public static class AuthenticationExecutionRepresentation {
protected String id;
- protected String referenceType;
protected String requirement;
+ protected String displayName;
protected List<String> requirementChoices;
protected Boolean configurable;
- protected Boolean subFlow;
+ protected Boolean authenticationFlow;
protected String providerId;
protected String authenticationConfig;
+ protected int level;
+ protected int index;
public String getId() {
return id;
@@ -75,12 +79,12 @@ public class AuthenticationManagementResource {
this.id = execution;
}
- public String getReferenceType() {
- return referenceType;
+ public String getDisplayName() {
+ return displayName;
}
- public void setReferenceType(String referenceType) {
- this.referenceType = referenceType;
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
}
public String getRequirement() {
@@ -107,14 +111,6 @@ public class AuthenticationManagementResource {
this.configurable = configurable;
}
- public Boolean getSubFlow() {
- return subFlow;
- }
-
- public void setSubFlow(Boolean subFlow) {
- this.subFlow = subFlow;
- }
-
public String getProviderId() {
return providerId;
}
@@ -130,6 +126,30 @@ public class AuthenticationManagementResource {
public void setAuthenticationConfig(String authenticationConfig) {
this.authenticationConfig = authenticationConfig;
}
+
+ public Boolean getAuthenticationFlow() {
+ return authenticationFlow;
+ }
+
+ public void setAuthenticationFlow(Boolean authenticationFlow) {
+ this.authenticationFlow = authenticationFlow;
+ }
+
+ public int getLevel() {
+ return level;
+ }
+
+ public void setLevel(int level) {
+ this.level = level;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
}
@Path("/flows")
@@ -147,6 +167,72 @@ public class AuthenticationManagementResource {
return flows;
}
+ @Path("/flows")
+ @POST
+ @NoCache
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response createFlow(AuthenticationFlowModel model) {
+ this.auth.requireManage();
+
+ if (realm.getFlowByAlias(model.getAlias()) != null) {
+ return Response.status(Response.Status.CONFLICT).build();
+ }
+
+ realm.addAuthenticationFlow(model);
+ return Response.status(201).build();
+
+ }
+
+ @Path("/flows/{flowAlias}/copy")
+ @POST
+ @NoCache
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response copy(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
+ this.auth.requireManage();
+
+ String newName = data.get("newName");
+ if (realm.getFlowByAlias(newName) != null) {
+ return Response.status(Response.Status.CONFLICT).build();
+ }
+
+ AuthenticationFlowModel flow = realm.getFlowByAlias(flowAlias);
+ if (flow == null) {
+ logger.debug("flow not found: " + flowAlias);
+ return Response.status(NOT_FOUND).build();
+ }
+ AuthenticationFlowModel copy = new AuthenticationFlowModel();
+ copy.setAlias(newName);
+ copy.setDescription(flow.getDescription());
+ copy.setProviderId(flow.getProviderId());
+ copy.setBuiltIn(false);
+ copy.setTopLevel(flow.isTopLevel());
+ copy = realm.addAuthenticationFlow(copy);
+ copy(newName, flow, copy);
+
+ return Response.status(201).build();
+
+ }
+
+ protected void copy(String newName, AuthenticationFlowModel from, AuthenticationFlowModel to) {
+ for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(from.getId())) {
+ if (execution.isAuthenticatorFlow()) {
+ AuthenticationFlowModel subFlow = realm.getAuthenticationFlowById(execution.getFlowId());
+ AuthenticationFlowModel copy = new AuthenticationFlowModel();
+ copy.setAlias(newName + " " + subFlow.getAlias());
+ copy.setDescription(subFlow.getDescription());
+ copy.setProviderId(subFlow.getProviderId());
+ copy.setBuiltIn(false);
+ copy.setTopLevel(false);
+ copy = realm.addAuthenticationFlow(copy);
+ execution.setFlowId(copy.getId());
+ copy(newName, subFlow, copy);
+ }
+ execution.setId(null);
+ execution.setParentFlow(to.getId());
+ realm.addAuthenticatorExecution(execution);
+ }
+ }
+
@Path("/flows/{flowAlias}/executions")
@GET
@NoCache
@@ -160,12 +246,22 @@ public class AuthenticationManagementResource {
return Response.status(NOT_FOUND).build();
}
List<AuthenticationExecutionRepresentation> result = new LinkedList<>();
- List<AuthenticationExecutionModel> executions = AuthenticatorUtil.getEnabledExecutionsRecursively(realm, flow.getId());
+
+ int level = 0;
+
+ recurseExecutions(flow, result, level);
+ return Response.ok(result).build();
+ }
+
+ public void recurseExecutions(AuthenticationFlowModel flow, List<AuthenticationExecutionRepresentation> result, int level) {
+ int index = 0;
+ List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(flow.getId());
for (AuthenticationExecutionModel execution : executions) {
AuthenticationExecutionRepresentation rep = new AuthenticationExecutionRepresentation();
- rep.setSubFlow(false);
+ rep.setLevel(level);
+ rep.setIndex(index++);
rep.setRequirementChoices(new LinkedList<String>());
- if (execution.isAutheticatorFlow()) {
+ if (execution.isAuthenticatorFlow()) {
AuthenticationFlowModel flowRef = realm.getAuthenticationFlowById(execution.getFlowId());
if (AuthenticationFlow.BASIC_FLOW.equals(flowRef.getProviderId())) {
rep.getRequirementChoices().add(AuthenticationExecutionModel.Requirement.ALTERNATIVE.name());
@@ -176,20 +272,19 @@ public class AuthenticationManagementResource {
rep.getRequirementChoices().add(AuthenticationExecutionModel.Requirement.DISABLED.name());
rep.setProviderId(execution.getAuthenticator());
rep.setAuthenticationConfig(execution.getAuthenticatorConfig());
-
}
- rep.setReferenceType(flowRef.getAlias());
+ rep.setDisplayName(flowRef.getAlias());
rep.setConfigurable(false);
rep.setId(execution.getId());
+ rep.setAuthenticationFlow(execution.isAuthenticatorFlow());
rep.setRequirement(execution.getRequirement().name());
result.add(rep);
+ AuthenticationFlowModel subFlow = realm.getAuthenticationFlowById(execution.getFlowId());
+ recurseExecutions(subFlow, result, level + 1);
} else {
- if (!flow.getId().equals(execution.getParentFlow())) {
- rep.setSubFlow(true);
- }
String providerId = execution.getAuthenticator();
ConfigurableAuthenticatorFactory factory = CredentialHelper.getConfigurableAuthenticatorFactory(session, providerId);
- rep.setReferenceType(factory.getDisplayType());
+ rep.setDisplayName(factory.getDisplayType());
rep.setConfigurable(factory.isConfigurable());
for (AuthenticationExecutionModel.Requirement choice : factory.getRequirementChoices()) {
rep.getRequirementChoices().add(choice.name());
@@ -199,11 +294,8 @@ public class AuthenticationManagementResource {
rep.setProviderId(execution.getAuthenticator());
rep.setAuthenticationConfig(execution.getAuthenticatorConfig());
result.add(rep);
-
}
-
}
- return Response.ok(result).build();
}
@Path("/flows/{flowAlias}/executions")
@@ -231,6 +323,134 @@ public class AuthenticationManagementResource {
}
}
+ @Path("/executions")
+ @POST
+ @NoCache
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response addExecution(AuthenticationExecutionModel model) {
+ this.auth.requireManage();
+ AuthenticationFlowModel parentFlow = getParentFlow(model);
+ if (parentFlow.isBuiltIn()) {
+ throw new BadRequestException("It is illegal to add execution to a built in flow");
+ }
+ int priority = 0;
+ List<AuthenticationExecutionModel> executions = getSortedExecutions(parentFlow);
+ for (AuthenticationExecutionModel execution : executions) {
+ priority = execution.getPriority();
+ }
+ if (priority > 0) priority += 10;
+ model.setPriority(priority);
+ model = realm.addAuthenticatorExecution(model);
+ return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
+ }
+
+ public AuthenticationFlowModel getParentFlow(AuthenticationExecutionModel model) {
+ if (model.getParentFlow() == null) {
+ throw new BadRequestException("parent flow not set on new execution");
+ }
+ AuthenticationFlowModel parentFlow = realm.getAuthenticationFlowById(model.getParentFlow());
+ if (parentFlow == null) {
+ throw new BadRequestException("execution parent flow does not exist");
+
+ }
+ return parentFlow;
+ }
+
+ @Path("/executions/{executionId}/raise-priority")
+ @POST
+ @NoCache
+ public void raisePriority(@PathParam("executionId") String execution) {
+ this.auth.requireManage();
+
+ AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
+ if (model == null) {
+ session.getTransaction().setRollbackOnly();
+ throw new NotFoundException("Illegal execution");
+
+ }
+ AuthenticationFlowModel parentFlow = getParentFlow(model);
+ if (parentFlow.isBuiltIn()) {
+ throw new BadRequestException("It is illegal to modify execution in a built in flow");
+ }
+ List<AuthenticationExecutionModel> executions = getSortedExecutions(parentFlow);
+ AuthenticationExecutionModel previous = null;
+ for (AuthenticationExecutionModel exe : executions) {
+ if (exe.getId().equals(model.getId())) {
+ break;
+ }
+ previous = exe;
+
+ }
+ if (previous == null) return;
+ int tmp = previous.getPriority();
+ previous.setPriority(model.getPriority());
+ realm.updateAuthenticatorExecution(previous);
+ model.setPriority(tmp);
+ realm.updateAuthenticatorExecution(model);
+ }
+
+ public List<AuthenticationExecutionModel> getSortedExecutions(AuthenticationFlowModel parentFlow) {
+ List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(parentFlow.getId());
+ Collections.sort(executions, AuthenticationExecutionModel.ExecutionComparator.SINGLETON);
+ return executions;
+ }
+
+ @Path("/executions/{executionId}/lower-priority")
+ @POST
+ @NoCache
+ public void lowerPriority(@PathParam("executionId") String execution) {
+ this.auth.requireManage();
+
+ AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
+ if (model == null) {
+ session.getTransaction().setRollbackOnly();
+ throw new NotFoundException("Illegal execution");
+
+ }
+ AuthenticationFlowModel parentFlow = getParentFlow(model);
+ if (parentFlow.isBuiltIn()) {
+ throw new BadRequestException("It is illegal to modify execution in a built in flow");
+ }
+ List<AuthenticationExecutionModel> executions = getSortedExecutions(parentFlow);
+ int i = 0;
+ for (i = 0; i < executions.size(); i++) {
+ if (executions.get(i).getId().equals(model.getId())) {
+ break;
+ }
+ }
+ if (i + 1 >= executions.size()) return;
+ AuthenticationExecutionModel next = executions.get(i + 1);
+ int tmp = model.getPriority();
+ model.setPriority(next.getPriority());
+ realm.updateAuthenticatorExecution(model);
+ next.setPriority(tmp);
+ realm.updateAuthenticatorExecution(next);
+ }
+
+
+ @Path("/executions/{executionId}")
+ @DELETE
+ @NoCache
+ public void removeExecution(@PathParam("executionId") String execution) {
+ this.auth.requireManage();
+
+ AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
+ if (model == null) {
+ session.getTransaction().setRollbackOnly();
+ throw new NotFoundException("Illegal execution");
+
+ }
+ AuthenticationFlowModel parentFlow = getParentFlow(model);
+ if (parentFlow.isBuiltIn()) {
+ throw new BadRequestException("It is illegal to remove execution from a built in flow");
+ }
+ realm.removeAuthenticatorExecution(model);
+ }
+
+
+
+
+
@Path("/executions/{executionId}/config")
@POST
@NoCache