Details
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/users.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/users.js
index 0d5f4cd..6b3ac2f 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/users.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/users.js
@@ -136,6 +136,39 @@ module.controller('UserDetailCtrl', function($scope, realm, user, User, $locatio
$scope.changed = false; // $scope.create;
+ // ID - Name map for required actions. IDs are enum names.
+ var userReqActionList = [
+ {id: "VERIFY_EMAIL", text: "Verify Email"},
+ {id: "UPDATE_PROFILE", text: "Update Profile"},
+ {id: "CONFIGURE_TOTP", text: "Configure Totp"},
+ {id: "UPDATE_PASSWORD", text: "Update Password"}
+ ];
+
+ // Options for the req actions tag selector
+ $scope.userReqActionsOptions = {
+ 'multiple' : true,
+ 'tags' : userReqActionList
+ };
+
+ // Model for the req actions tag selector
+ $scope.userActions = [];
+ for (var i = 0; i < userReqActionList.length; i++){
+ var action = userReqActionList[i];
+
+ if ($scope.user.requiredActions.indexOf(action.id) > -1){
+ $scope.userActions.push({id: action.id, text: action.text});
+ }
+ }
+
+ // Watching ui-select2 model to properly format the req actions for user
+ $scope.$watch("userActions", function(newValue, oldValue) {
+ $scope.user.requiredActions = [];
+ for (var i=0; i < newValue.length; i++){
+ var action = newValue[i];
+ $scope.user.requiredActions.push(action.id);
+ }
+ });
+
$scope.$watch('user', function() {
if (!angular.equals($scope.user, user)) {
$scope.changed = true;
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/user-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/user-detail.html
index fec6872..5505366 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/user-detail.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/user-detail.html
@@ -78,7 +78,13 @@
<label for="emailVerified" class="control-label">Email verified</label>
<input ng-model="user.emailVerified" name="emailVerified" id="emailVerified" onoffswitch />
</div>
+ <div class="form-group clearfix">
+ <label for="reqActions" class="control-label two-lines">Required User Actions</label>
+ <div class="controls">
+ <input type="text" ui-select2="userReqActionsOptions" ng-model="userActions" id="reqActions"/>
+ </div>
+ </div>
</fieldset>
<div class="form-actions" data-ng-show="create">
<button type="submit" data-ng-click="save()" class="primary" data-ng-show="changed">Save
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 7c49e9d..347aca8 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -390,6 +390,14 @@ public class RealmManager {
rep.setEnabled(user.isEnabled());
rep.setEmailVerified(user.isEmailVerified());
rep.setTotp(user.isTotp());
+
+ List<String> reqActions = new ArrayList<String>();
+ for (RequiredAction ra : user.getRequiredActions()){
+ reqActions.add(ra.name());
+ }
+
+ rep.setRequiredActions(reqActions);
+
if (user.getAttributes() != null && !user.getAttributes().isEmpty()) {
Map<String, String> attrs = new HashMap<String, String>();
attrs.putAll(user.getAttributes());
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index b81480d..2901c9c 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -64,19 +64,7 @@ public class UsersResource {
if (user == null) {
throw new NotFoundException();
}
- user.setEmail(rep.getEmail());
- user.setFirstName(rep.getFirstName());
- user.setLastName(rep.getLastName());
-
- user.setEnabled(rep.isEnabled());
- user.setTotp(rep.isTotp());
- user.setEmailVerified(rep.isEmailVerified());
-
- if (rep.getAttributes() != null) {
- for (Map.Entry<String, String> attr : rep.getAttributes().entrySet()) {
- user.setAttribute(attr.getKey(), attr.getValue());
- }
- }
+ updateUserFromRep(user, rep);
}
@POST
@@ -89,6 +77,13 @@ public class UsersResource {
if (user == null) {
throw new NotFoundException();
}
+
+ updateUserFromRep(user, rep);
+
+ return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getLoginName()).build()).build();
+ }
+
+ private void updateUserFromRep(UserModel user, UserRepresentation rep){
user.setEmail(rep.getEmail());
user.setFirstName(rep.getFirstName());
user.setLastName(rep.getLastName());
@@ -97,12 +92,21 @@ public class UsersResource {
user.setTotp(rep.isTotp());
user.setEmailVerified(rep.isEmailVerified());
+ List<String> reqActions = rep.getRequiredActions();
+
+ for(UserModel.RequiredAction ra : UserModel.RequiredAction.values()){
+ if (reqActions.contains(ra.name())) {
+ user.addRequiredAction(ra);
+ } else {
+ user.removeRequiredAction(ra);
+ }
+ }
+
if (rep.getAttributes() != null) {
for (Map.Entry<String, String> attr : rep.getAttributes().entrySet()) {
user.setAttribute(attr.getKey(), attr.getValue());
}
}
- return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getLoginName()).build()).build();
}
@Path("{username}")