syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From giacom...@apache.org
Subject syncope git commit: [SYNCOPE-719] Base group management added
Date Fri, 15 Jan 2016 15:33:16 GMT
Repository: syncope
Updated Branches:
  refs/heads/master fa23a95d2 -> a1c3ed3ac


[SYNCOPE-719] Base group management added


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/a1c3ed3a
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/a1c3ed3a
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/a1c3ed3a

Branch: refs/heads/master
Commit: a1c3ed3acfaf44603eb8d6311099ee5c9161b859
Parents: fa23a95
Author: giacomolm <giacomolm@hotmail.it>
Authored: Fri Jan 15 16:27:23 2016 +0100
Committer: giacomolm <giacomolm@hotmail.it>
Committed: Fri Jan 15 16:27:36 2016 +0100

----------------------------------------------------------------------
 .../enduser/SyncopeEnduserApplication.java      |  11 ++
 .../client/enduser/adapters/GroupTOAdapter.java |  41 ++++++
 .../client/enduser/adapters/UserTOAdapter.java  |   4 +
 .../client/enduser/model/GroupResponse.java     |  45 +++++++
 .../client/enduser/model/UserTORequest.java     |  13 ++
 .../enduser/resources/SyncopeGroupResource.java |  91 +++++++++++++
 .../resources/UserSelfCreateResource.java       |  12 +-
 .../META-INF/resources/app/css/editUser.css     |   4 +-
 .../resources/META-INF/resources/app/index.html |   2 +
 .../app/js/controllers/UserController.js        | 129 +++++++++++--------
 .../resources/app/js/directives/groups.js       |  58 +++++++++
 .../resources/app/js/filters/propsFilter.js     |  37 +++---
 .../resources/app/js/services/groupService.js   |  42 ++++++
 .../META-INF/resources/app/views/groups.html    |  11 ++
 .../META-INF/resources/app/views/resources.html |   7 +-
 .../app/views/user-derived-schemas.html         |   4 +-
 .../resources/app/views/user-groups.html        |   5 +-
 .../resources/app/views/user-resources.html     |   2 +-
 .../app/views/user-virtual-schemas.html         |   4 +-
 pom.xml                                         |   2 +-
 20 files changed, 433 insertions(+), 91 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
index 9fe4cf7..17a92ed 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
@@ -34,6 +34,7 @@ import org.apache.syncope.client.enduser.resources.LoginResource;
 import org.apache.syncope.client.enduser.resources.LogoutResource;
 import org.apache.syncope.client.enduser.resources.SchemaResource;
 import org.apache.syncope.client.enduser.resources.SecurityQuestionResource;
+import org.apache.syncope.client.enduser.resources.SyncopeGroupResource;
 import org.apache.syncope.client.enduser.resources.SyncopeResourceResource;
 import org.apache.syncope.client.enduser.resources.UserSelfCreateResource;
 import org.apache.syncope.client.enduser.resources.UserSelfPasswordReset;
@@ -256,6 +257,16 @@ public class SyncopeEnduserApplication extends WebApplication implements
Seriali
             }
         });
 
+        mountResource("/api/groups", new ResourceReference("groups") {
+
+            private static final long serialVersionUID = -128426276529456602L;
+
+            @Override
+            public IResource getResource() {
+                return new SyncopeGroupResource();
+            }
+        });
+
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/GroupTOAdapter.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/GroupTOAdapter.java
b/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/GroupTOAdapter.java
new file mode 100644
index 0000000..280c4ea
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/GroupTOAdapter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.adapters;
+
+import java.util.List;
+import org.apache.syncope.client.enduser.model.GroupResponse;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GroupTOAdapter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(GroupTOAdapter.class);
+
+    public GroupResponse fromGroupTO(final List<GroupTO> groupTOs) {
+
+        GroupResponse groupTOResponse = new GroupResponse();
+
+        for (GroupTO groupTO : groupTOs) {
+            groupTOResponse.getGroups().put(groupTO.getKey(), groupTO.getName());
+        }
+
+        return groupTOResponse;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/UserTOAdapter.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/UserTOAdapter.java
b/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/UserTOAdapter.java
index 2dc32dd..22aa139 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/UserTOAdapter.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/adapters/UserTOAdapter.java
@@ -56,6 +56,8 @@ public class UserTOAdapter {
         userTO.getVirAttrs().addAll(userTORequest.getVirAttrs().values());
         // add resources
         userTO.getResources().addAll(userTORequest.getResources());
+        // add memberships
+        userTO.getMemberships().addAll(userTORequest.getMemberships());
 
         return userTO;
     }
@@ -74,6 +76,8 @@ public class UserTOAdapter {
         userTORequest.getVirAttrs().putAll(userTO.getVirAttrMap());
         
         userTORequest.getResources().addAll(userTO.getResources());
+               
+        userTORequest.getMemberships().addAll(userTO.getMemberships());
 
         return userTORequest;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/GroupResponse.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/GroupResponse.java
b/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/GroupResponse.java
new file mode 100644
index 0000000..49c2992
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/GroupResponse.java
@@ -0,0 +1,45 @@
+/*
+ * 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 java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+public class GroupResponse implements Serializable {
+
+    private static final long serialVersionUID = -7499232727784886980L;
+
+    private Map<Long, String> groups = new HashMap<>();
+
+    public Map<Long, String> getGroups() {
+        return groups;
+    }
+
+    public void setGroups(final Map<Long, String> groups) {
+        this.groups = groups;
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/UserTORequest.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/UserTORequest.java
b/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/UserTORequest.java
index 7196f39..be841a4 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/UserTORequest.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/model/UserTORequest.java
@@ -19,12 +19,15 @@
 package org.apache.syncope.client.enduser.model;
 
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
 
 public class UserTORequest implements Serializable {
 
@@ -49,6 +52,8 @@ public class UserTORequest implements Serializable {
     private Map<String, AttrTO> virAttrs = new HashMap<>();
 
     private Set<String> resources = new HashSet<>();
+    
+    private List<MembershipTO> memberships = new ArrayList<>();
 
     public UserTORequest() {
     }
@@ -132,6 +137,14 @@ public class UserTORequest implements Serializable {
     public void setResources(final Set<String> resources) {
         this.resources = resources;
     }
+    
+    public List<MembershipTO> getMemberships() {
+        return memberships;
+    }
+
+    public void setMemberships(final List<MembershipTO> memberships) {
+        this.memberships = memberships;
+    }
 
     public UserTORequest key(final Long value) {
         this.key = value;

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SyncopeGroupResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SyncopeGroupResource.java
b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SyncopeGroupResource.java
new file mode 100644
index 0000000..21d050a
--- /dev/null
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SyncopeGroupResource.java
@@ -0,0 +1,91 @@
+/*
+ * 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.resources;
+
+import java.io.IOException;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.adapters.GroupTOAdapter;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.rest.api.beans.AnyListQuery;
+import org.apache.syncope.common.rest.api.service.GroupService;
+import org.apache.syncope.core.misc.serialization.POJOHelper;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SyncopeGroupResource extends AbstractBaseResource {
+
+    private static final long serialVersionUID = 7475706378304995200L;
+
+    private static final Logger LOG = LoggerFactory.getLogger(SyncopeGroupResource.class);
+
+    private final GroupService groupService;
+
+    private final GroupTOAdapter groupTOAdapter;
+
+    public SyncopeGroupResource() {
+        groupTOAdapter = new GroupTOAdapter();
+        groupService = SyncopeEnduserSession.get().getService(GroupService.class);
+    }
+
+    @Override
+    protected ResourceResponse newResourceResponse(final Attributes attributes) {
+
+        LOG.debug("Search all available groups");
+
+        ResourceResponse response = new ResourceResponse();
+
+        try {
+
+            HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+            if (!xsrfCheck(request)) {
+                LOG.error("XSRF TOKEN does not match");
+                response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN
does not match");
+                return response;
+            }
+
+            String realm = java.net.URLDecoder.decode(attributes.getParameters().get("realm").toString(
+                    SyncopeConstants.ROOT_REALM), "UTF-8");
+            final List<GroupTO> groupTOs = groupService.list(new AnyListQuery.Builder().realm(realm).build()).
+                    getResult();
+
+            response.setWriteCallback(new AbstractResource.WriteCallback() {
+
+                @Override
+                public void writeData(final Attributes attributes) throws IOException {
+                    attributes.getResponse().write(POJOHelper.serialize(groupTOAdapter.fromGroupTO(groupTOs)));
+                }
+            });
+            response.setStatusCode(Response.Status.OK.getStatusCode());
+        } catch (Exception e) {
+            LOG.error("Error retrieving available grupss", e);
+            response.setError(Response.Status.BAD_REQUEST.getStatusCode(), new StringBuilder()
+                    .append("ErrorMessage{{ ")
+                    .append(e.getMessage())
+                    .append(" }}")
+                    .toString());
+        }
+        return response;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
index 42b45fc..5328666 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
@@ -26,7 +26,6 @@ import org.apache.syncope.client.enduser.adapters.UserTOAdapter;
 import org.apache.syncope.client.enduser.model.UserTORequest;
 import org.apache.syncope.common.rest.api.service.UserSelfService;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
-import org.apache.wicket.util.io.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -59,9 +58,10 @@ public class UserSelfCreateResource extends AbstractBaseResource {
                 response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN
is not matching");
                 return response;
             }
+
+            String jsonString = request.getReader().readLine();
             
-            final UserTORequest userTORequest = POJOHelper.deserialize(IOUtils.toString(request.getInputStream()),
-                    UserTORequest.class);
+            final UserTORequest userTORequest = POJOHelper.deserialize(jsonString, UserTORequest.class);
 
             if (isSelfRegistrationAllowed() && userTORequest != null) {
                 LOG.debug("Received user self registration request for user: [{}]", userTORequest.getUsername());
@@ -76,7 +76,7 @@ public class UserSelfCreateResource extends AbstractBaseResource {
                         attributes.getResponse().write(res.getStatusInfo().getFamily().equals(
                                 Response.Status.Family.SUCCESSFUL)
                                         ? responseMessage.append("User: ").append(userTORequest.getUsername()).append(
-                                        " successfully created")
+                                                " successfully created")
                                         : new StringBuilder().append("ErrorMessage{{ ").
                                         append(res.getStatusInfo().getReasonPhrase()).append("
}}"));
                     }
@@ -85,8 +85,8 @@ public class UserSelfCreateResource extends AbstractBaseResource {
             } else {
                 response.setError(Response.Status.FORBIDDEN.getStatusCode(), new StringBuilder().
                         append("ErrorMessage{{").append(userTORequest == null
-                        ? "Request received is not valid }}"
-                        : "Self registration not allowed }}").toString());
+                                        ? "Request received is not valid }}"
+                                        : "Self registration not allowed }}").toString());
             }
 
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css
----------------------------------------------------------------------
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 f87981b..6383d03 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
@@ -84,8 +84,8 @@ under the License.
 }
 
 .attribute-ui-select {
-  width: 60%;
-  margin-left: 20%;
+  width: 100%;
+  /*margin-left: 20%;*/
   list-style: none;
 }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/index.html
----------------------------------------------------------------------
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 f83defa..b888051 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
@@ -85,6 +85,7 @@ under the License.
     <script src="js/services/securityQuestionService.js"></script>
     <script src="js/services/infoService.js"></script>
     <script src="js/services/resourceService.js"></script>
+    <script src="js/services/groupService.js"></script>
     <script src="js/services/captchaService.js"></script>
     <!--controllers-->
     <script src="js/controllers/HomeController.js"></script>
@@ -103,6 +104,7 @@ under the License.
     <script src="js/directives/equals.js"></script>
     <script src="js/directives/captcha.js"></script>
     <script src="js/directives/resources.js"></script>
+    <script src="js/directives/groups.js"></script>
     <!--filters-->
     <script src="js/filters/propsFilter.js"></script>
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js
b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js
index 7521553..1d35bc6 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js
@@ -21,8 +21,9 @@
 
 angular.module("self").controller("UserController", ['$scope', '$rootScope', '$location',
'$compile', 'AuthService',
   'UserSelfService', 'SchemaService', 'RealmService', 'ResourceService', 'SecurityQuestionService',
'CaptchaService',
+  'GroupService',
   function ($scope, $rootScope, $location, $compile, AuthService, UserSelfService, SchemaService,
RealmService,
-          ResourceService, SecurityQuestionService, CaptchaService) {
+          ResourceService, SecurityQuestionService, CaptchaService, GroupService) {
 
     $scope.user = {};
     $scope.confirmPassword = {
@@ -46,10 +47,12 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope',
'$l
         derSchemas: [],
         virSchemas: [],
         resources: [],
+        groups: [],
         errorMessage: '',
         attributeTable: {},
         virtualAttributeTable: {},
-        selectedResources: []
+        selectedResources: [],
+        selectedGroups: []
       };
 
       var initSchemas = function () {
@@ -173,6 +176,18 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope',
'$l
         });
       };
 
+      var initGroups = function () {
+        var realm = $scope.user.realm || "/";
+        GroupService.getGroups(realm).then(function (response) {
+          $scope.dynamicForm.groups = new Array();
+          for (var key in response.groups) {
+            $scope.dynamicForm.groups.push({"rightKey": key, "groupName": response.groups[key]});
+          }
+        }, function (e) {
+          $scope.showError("An error occur during retrieving groups " + e, $scope.notification)
+        });
+      };
+
       var readUser = function () {
         UserSelfService.read().then(function (response) {
           $scope.user = response;
@@ -180,6 +195,14 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope',
'$l
           $scope.initialSecurityQuestion = $scope.user.securityQuestion;
           // initialize already assigned resources
           $scope.dynamicForm.selectedResources = $scope.user.resources;
+          // initialize already assigned groups -- keeping the same structure of groups 
     
+          for (var index in $scope.user.memberships) {
+            $scope.dynamicForm.selectedGroups.push(
+                    {
+                      "rightKey": $scope.user.memberships[index]["rightKey"].toString(),
+                      "groupName": $scope.user.memberships[index]["groupName"]
+                    });
+          }
         }, function () {
           console.log("Error");
         });
@@ -212,6 +235,8 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope',
'$l
       initSchemas();
       // initialize available resources
       initResources();
+      //initialize available groups
+      initGroups();
     };
 
     $scope.saveUser = function (user) {
@@ -274,62 +299,62 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope',
'$l
         return;
       });
     },
-    $scope.retrieveSecurityQuestion = function (user) {
-      if ($rootScope.pwdResetRequiringSecurityQuestions){
-        if(user && user.username && user.username.length) {
-        return SecurityQuestionService.
-                getSecurityQuestionByUser(user.username).then(function (data) {
-                  $scope.userSecurityQuestion = data.content;          
+            $scope.retrieveSecurityQuestion = function (user) {
+              if ($rootScope.pwdResetRequiringSecurityQuestions) {
+                if (user && user.username && user.username.length) {
+                  return SecurityQuestionService.
+                          getSecurityQuestionByUser(user.username).then(function (data) {
+                    $scope.userSecurityQuestion = data.content;
+                  }, function (response) {
+                    var errorMessage;
+                    // parse error response 
+                    if (response !== undefined) {
+                      errorMessage = response.split("ErrorMessage{{")[1];
+                      errorMessage = errorMessage.split("}}")[0];
+                      $scope.userSecurityQuestion = "";
+                    }
+                    $scope.showError("Error retrieving user security question: " + errorMessage,
$scope.notification);
+                  });
+                }
+                else {
+                  $scope.userSecurityQuestion = "";
+                }
+              }
+            },
+            $scope.resetPassword = function (user) {
+              if (user && user.username) {
+                $scope.retrieveSecurityQuestion(user);
+                CaptchaService.validate($scope.captchaInput).then(function (response) {
+                  if (!(response === 'true')) {
+                    $scope.showError("Captcha inserted is not valid, please digit the correct
captcha", $scope.notification);
+                    return;
+                  }
+                  UserSelfService.passwordReset(user).then(function (data) {
+                    $scope.showSuccess(data, $scope.notification);
+                    $location.path('/self');
+                  }, function (response) {
+                    var errorMessage;
+                    // parse error response 
+                    if (response !== undefined) {
+                      errorMessage = response.split("ErrorMessage{{")[1];
+                      errorMessage = errorMessage.split("}}")[0];
+                      $scope.showError("An error occured during password reset: " + errorMessage,
$scope.notification);
+                      //we need to refresh captcha after a valid request
+                      $scope.$broadcast("refreshCaptcha");
+                    }
+                  });
                 }, function (response) {
                   var errorMessage;
                   // parse error response 
                   if (response !== undefined) {
                     errorMessage = response.split("ErrorMessage{{")[1];
                     errorMessage = errorMessage.split("}}")[0];
-                    $scope.userSecurityQuestion = "";
                   }
-                  $scope.showError("Error retrieving user security question: " + errorMessage,
$scope.notification);
+                  $scope.showError("Error: " + (errorMessage || response), $scope.notification);
+                  return;
                 });
-        }
-        else{
-           $scope.userSecurityQuestion = "";
-        }    
-      }
-    },
-    $scope.resetPassword = function (user) {
-      if (user && user.username) {
-        $scope.retrieveSecurityQuestion(user);
-        CaptchaService.validate($scope.captchaInput).then(function (response) {
-          if (!(response === 'true')) {
-            $scope.showError("Captcha inserted is not valid, please digit the correct captcha",
$scope.notification);
-            return;
-          }
-          UserSelfService.passwordReset(user).then(function (data) {
-            $scope.showSuccess(data, $scope.notification);
-            $location.path('/self');
-          }, function (response) {
-            var errorMessage;
-            // parse error response 
-            if (response !== undefined) {
-              errorMessage = response.split("ErrorMessage{{")[1];
-              errorMessage = errorMessage.split("}}")[0];
-              $scope.showError("An error occured during password reset: " + errorMessage,
$scope.notification);
-              //we need to refresh captcha after a valid request
-              $scope.$broadcast("refreshCaptcha");
-            }
-          });
-        }, function (response) {          
-          var errorMessage;
-          // parse error response 
-          if (response !== undefined) {
-            errorMessage = response.split("ErrorMessage{{")[1];
-            errorMessage = errorMessage.split("}}")[0];
-          }
-          $scope.showError("Error: " + (errorMessage || response), $scope.notification);
-          return;
-        });
-      } else {
-        $scope.showError("You should use a valid and non-empty username", $scope.notification);
-      }
-    };
+              } else {
+                $scope.showError("You should use a valid and non-empty username", $scope.notification);
+              }
+            };
   }]);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/groups.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/groups.js
b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/groups.js
new file mode 100644
index 0000000..1f4fa4b
--- /dev/null
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/groups.js
@@ -0,0 +1,58 @@
+/* 
+ * 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('groups', function () {
+          return {
+            restrict: 'E',
+            templateUrl: 'views/groups.html',
+            scope: {
+              dynamicForm: "=form",
+              user: "="
+            },
+            controller: function ($scope, $filter) {
+
+              $scope.init = function () {
+                if (!$scope.user.memberships) {
+                  $scope.user.memberships = new Array();
+                }
+                $scope.groupDisabled = false
+              };
+
+              $scope.addGroup = function (item, model) {
+                var group = item;
+                $scope.user.memberships.push({"rightKey": group.rightKey});             
  
+              };
+
+              $scope.removeGroup = function (item, model) {
+                var groupIndex = $scope.getIndex(item);
+                $scope.user.memberships.splice(groupIndex, 1);                
+              };
+
+              $scope.getIndex = function (selectedGroup) {
+                var groupIndex = $scope.user.memberships.map(function (groupName) {
+                  return groupName;
+                }).indexOf(selectedGroup);
+                return groupIndex;
+              };
+
+            }
+          };
+        });

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/js/filters/propsFilter.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/filters/propsFilter.js
b/client/enduser/src/main/resources/META-INF/resources/app/js/filters/propsFilter.js
index a092d0c..fe23dce 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/filters/propsFilter.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/filters/propsFilter.js
@@ -17,36 +17,37 @@
  * under the License.
  */
 
+/**
+ * This filter has been defined in order to have a workaround for this bug: 
+ * https://github.com/angular-ui/ui-select/issues/665
+ * 
+ * When the bug is fixed, we can remove it.
+ */
+
 'use strict'
 
 angular.module("self")
         .filter('propsFilter', function () {
           return function (items, props) {
-            var out = [];
-
-            if (angular.isArray(items)) {
-              items.forEach(function (item) {
-                var itemMatches = false;
-
-                var keys = Object.keys(props);
-                for (var i = 0; i < keys.length; i++) {
-                  var prop = keys[i];
-                  var text = props[prop].toLowerCase();
-                  if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
-                    itemMatches = true;
+            var out = [];            
+            if (items && items.length && props.selected && props.selected.length)
{
+              var selected = props.selected;              
+              for (var i = 0; i < items.length; i++) {
+                var item = items[i], itemMisses = true;
+                for (var j = 0; j < selected.length; j++) {
+                  if (item.rightKey == selected[j].rightKey) {
+                    itemMisses = false;
                     break;
                   }
                 }
-
-                if (itemMatches) {
+                if(itemMisses){
                   out.push(item);
                 }
-              });
-            } else {
-              // Let the output be the input untouched
+              }
+            }
+            else{
               out = items;
             }
-
             return out;
           };
         });

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/js/services/groupService.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/groupService.js
b/client/enduser/src/main/resources/META-INF/resources/app/js/services/groupService.js
new file mode 100644
index 0000000..17e2add
--- /dev/null
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/groupService.js
@@ -0,0 +1,42 @@
+/* 
+ * 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')
+        .factory('GroupService', ['$resource', '$q', '$http',
+          function ($group, $q, $http) {
+
+            var groupService = {};
+
+            groupService.getGroups = function (realm) {
+              console.log(realm)
+              return  $http.get("/syncope-enduser/api/groups?realm="+encodeURI(realm))
+                      .then(function (response) {
+                        console.log("groupAPI response: ", response);
+                        return response.data;
+                      }, function (response) {
+                        console.log("Something went wrong during groups retrieval, exit with
status: ", response);
+                        return $q.reject(response.data || response.statusText);
+                      });
+            };
+            return groupService;
+          }]);
+
+

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/views/groups.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/groups.html b/client/enduser/src/main/resources/META-INF/resources/app/views/groups.html
new file mode 100644
index 0000000..79cd5a5
--- /dev/null
+++ b/client/enduser/src/main/resources/META-INF/resources/app/views/groups.html
@@ -0,0 +1,11 @@
+<div ng-init='init()'>
+  <ui-select on-select="addGroup($item, $model)" on-remove="removeGroup($item, $model)"
multiple
+             ng-model="dynamicForm.selectedGroups" theme="select2" class="attribute-ui-select"

+             ng-disabled="{{groupDisabled}}">
+    <ui-select-match placeholder="Click to select groups...">{{$item.groupName}}</ui-select-match>
+    <ui-select-choices repeat="group in dynamicForm.groups | propsFilter: {selected: dynamicForm.selectedGroups}

+                       track by group.rightKey">
+      <div ng-bind-html="group.groupName | highlight: $select.search"></div>
+    </ui-select-choices>
+  </ui-select>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/views/resources.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/resources.html
b/client/enduser/src/main/resources/META-INF/resources/app/views/resources.html
index f2c1a10..7882e15 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/views/resources.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/views/resources.html
@@ -4,9 +4,4 @@
   <ui-select-choices repeat="resource in dynamicForm.resources">
     <div ng-bind-html="resource | highlight: $select.search"></div>
   </ui-select-choices>
-</ui-select>
-<ul class="attribute-ui-select">
-  <li class="attribute-virtual-value-field" ng-if="dynamicForm.selectedResources.length
== 0">
-    <strong>No resources selected...</strong>
-  </li>
-</ul>
\ No newline at end of file
+</ui-select>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/views/user-derived-schemas.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/user-derived-schemas.html
b/client/enduser/src/main/resources/META-INF/resources/app/views/user-derived-schemas.html
index 7a3a3ec..fbb2dbd 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/views/user-derived-schemas.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/views/user-derived-schemas.html
@@ -26,10 +26,10 @@ under the License.
     </div>-->
 <!--</div>-->
 
-<div class="form-group row">
+<div id="attribute" class="form-group row">
   <navigation-buttons ng-show="createMode" next="create.virtualSchemas" previous="create.plainSchemas"></navigation-buttons>
   <navigation-buttons ng-show="!createMode" next="update.virtualSchemas" previous="update.plainSchemas"></navigation-buttons>
-  <div class="col-xs-6 col-xs-offset-3">
+  <div class="pull-left">
     <a id="cancel" href="#/self" class="btn btn-danger">Cancel</a>
   </div>
 </div>

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/views/user-groups.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/user-groups.html
b/client/enduser/src/main/resources/META-INF/resources/app/views/user-groups.html
index efca039..26ca1ce 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/views/user-groups.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/views/user-groups.html
@@ -27,7 +27,10 @@ under the License.
     <option ng-repeat="realm in availableRealms" value="{{realm}}">{{realm}}</option>
   </select>
 </div>
-
+<div id="attribute" class="form-group row upper-select">
+  <label>Groups</label><br/>
+  <groups form="dynamicForm" user="user"></groups>
+</div>
 <div id="attribute" class="form-group row">
   <navigation-buttons ng-show="createMode" next="create.plainSchemas" previous="create.credentials"></navigation-buttons>
   <navigation-buttons ng-show="!createMode" next="update.plainSchemas" previous="update.credentials"></navigation-buttons>

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/views/user-resources.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/user-resources.html
b/client/enduser/src/main/resources/META-INF/resources/app/views/user-resources.html
index d2498c0..205cc1f 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/views/user-resources.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/views/user-resources.html
@@ -17,7 +17,7 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 -->
-<div>
+<div id="attribute" class="form-group row upper-select ng-scope">
   <resources form="dynamicForm" user="user"></resources>
 </div>
 <div id="attribute" class="form-group row">

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/client/enduser/src/main/resources/META-INF/resources/app/views/user-virtual-schemas.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/user-virtual-schemas.html
b/client/enduser/src/main/resources/META-INF/resources/app/views/user-virtual-schemas.html
index 7a3fe66..3a99ffa 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/views/user-virtual-schemas.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/views/user-virtual-schemas.html
@@ -25,10 +25,10 @@ under the License.
       <div class="col-md-7">{{attribute.validationMessage| translate }}</div>
     </div>-->
 <!--</div>-->
-<div class="form-group row">
+<div id="attribute" class="form-group row">
   <navigation-buttons ng-show="createMode" next="create.groups" previous="create.derivedSchemas"></navigation-buttons>
   <navigation-buttons ng-show="!createMode" next="update.groups" previous="update.derivedSchemas"></navigation-buttons>
-  <div class="col-xs-6 col-xs-offset-3">
+  <div class="pull-left">
     <a id="cancel" href="#/self" class="btn btn-danger">Cancel</a>
   </div>
 </div>

http://git-wip-us.apache.org/repos/asf/syncope/blob/a1c3ed3a/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index da4517e..9846744 100644
--- a/pom.xml
+++ b/pom.xml
@@ -401,7 +401,7 @@ under the License.
     <angular-cookies.version>1.4.8</angular-cookies.version>
     <angular-animate.version>1.4.8</angular-animate.version>
     <angular-ui-router.version>0.2.15</angular-ui-router.version>
-    <angular-ui-bootstrap.version>0.14.0</angular-ui-bootstrap.version>
+    <angular-ui-bootstrap.version>1.0.3</angular-ui-bootstrap.version>
     <angular-ui-select.version>0.13.1</angular-ui-select.version>
     <angular-sanitize.version>1.4.8</angular-sanitize.version>
     <kendo-ui-core.version>2014.2.716</kendo-ui-core.version>


Mime
View raw message