diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserDetails.java b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserDetails.java index 6abe01407..953912017 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserDetails.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserDetails.java @@ -20,7 +20,6 @@ package org.libreccm.admin.ui.usersgroupsroles; import com.arsdigita.ui.admin.AdminUiConstants; -import com.vaadin.cdi.CDIUI; import com.vaadin.icons.VaadinIcons; import com.vaadin.ui.Button; import com.vaadin.ui.FormLayout; @@ -36,6 +35,8 @@ import com.vaadin.ui.components.grid.HeaderRow; import com.vaadin.ui.renderers.ButtonRenderer; import com.vaadin.ui.themes.ValoTheme; import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.security.Group; +import org.libreccm.security.GroupRepository; import org.libreccm.security.Role; import org.libreccm.security.RoleRepository; import org.libreccm.security.User; @@ -141,16 +142,69 @@ public class UserDetails extends Window { final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final UserGroupsController groupsController = cdiUtil + .findBean(UserGroupsController.class); + final Grid groupsGrid = new Grid<>(); + groupsGrid + .addColumn(Group::getName) + .setId(COL_GROUP_NAME) + .setCaption("Group"); + groupsGrid + .addColumn(group -> bundle + .getString("ui.user.groups.remove"), + new ButtonRenderer<>(event -> { + groupsController + .removeUserFromGroup(user, event.getItem()); + groupsGrid.getDataProvider().refreshAll(); + })) + .setId(COL_GROUP_REMOVE); + + groupsGrid.setWidth("100%"); + + final GroupRepository groupRepo = cdiUtil + .findBean(GroupRepository.class); + + final HeaderRow groupsGridHeader = groupsGrid.prependHeaderRow(); + final Button addGroupButton = new Button("Add group"); + addGroupButton.setIcon(VaadinIcons.PLUS); + addGroupButton.setStyleName(ValoTheme.BUTTON_TINY); + addGroupButton.addClickListener(event -> { + final GroupSelector groupSelector = new GroupSelector( + "Select group(s) to which the user is added.", + "Add user to selected groups", + usersGroupsRoles, + groupRepo.findByMember(user), + (selectedGroups -> { + selectedGroups.forEach(group -> { + groupsController.addUserToGroup(user, group); + }); + groupsGrid.getDataProvider().refreshAll(); + })); + groupSelector.center(); + groupSelector.setWidth("80%"); + UI.getCurrent().addWindow(groupSelector); + }); + final HeaderCell groupsGridHeaderCell = groupsGridHeader + .join(COL_GROUP_NAME, + COL_GROUP_REMOVE); + groupsGridHeaderCell + .setComponent(new HorizontalLayout(addGroupButton)); + + final UserGroupsTableDataProvider groupsDataProvider = cdiUtil + .findBean(UserGroupsTableDataProvider.class); + groupsDataProvider.setUser(user); + groupsGrid.setDataProvider(groupsDataProvider); + final UserRolesController rolesController = cdiUtil .findBean(UserRolesController.class); final Grid rolesGrid = new Grid<>(); rolesGrid .addColumn(Role::getName) .setId(COL_ROLE_NAME) - .setCaption("Role name"); + .setCaption("Role"); rolesGrid .addColumn(role -> bundle - .getString("ui.groups.roles.remove"), + .getString("ui.user.roles.remove"), new ButtonRenderer<>(event -> { rolesController .removeRoleFromUser(event.getItem(), user); @@ -175,8 +229,8 @@ public class UserDetails extends Window { (selectedRoles -> { selectedRoles.forEach(role -> { rolesController.assignRoleToUser(role, user); - rolesGrid.getDataProvider().refreshAll(); }); + rolesGrid.getDataProvider().refreshAll(); })); roleSelector.center(); roleSelector.setWidth("80%"); @@ -192,10 +246,10 @@ public class UserDetails extends Window { .findBean(UserRolesTableDataProvider.class); rolesDataProvider.setUser(user); rolesGrid.setDataProvider(rolesDataProvider); - + final TabSheet tabs = new TabSheet(); tabs.addTab(layout, "Details"); - tabs.addTab(layout, "Groups"); + tabs.addTab(groupsGrid, "Groups"); tabs.addTab(rolesGrid, "Roles"); setContent(tabs); diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserEditor.java b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserEditor.java index 55d46a36d..67660c1be 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserEditor.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserEditor.java @@ -28,11 +28,9 @@ import com.vaadin.ui.Button; import com.vaadin.ui.CheckBox; import com.vaadin.ui.FormLayout; import com.vaadin.ui.HorizontalLayout; -import com.vaadin.ui.Label; import com.vaadin.ui.Panel; import com.vaadin.ui.PasswordField; import com.vaadin.ui.RadioButtonGroup; -import com.vaadin.ui.TabSheet; import com.vaadin.ui.TextField; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserGroupsDataProvider.java b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserGroupsTableDataProvider.java similarity index 97% rename from ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserGroupsDataProvider.java rename to ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserGroupsTableDataProvider.java index eb1b3ce21..b040db87e 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserGroupsDataProvider.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserGroupsTableDataProvider.java @@ -25,7 +25,6 @@ import org.libreccm.security.Group; import org.libreccm.security.GroupMembership; import org.libreccm.security.User; -import java.net.URI; import java.util.Objects; import java.util.stream.Stream; @@ -42,7 +41,7 @@ import javax.transaction.Transactional; * @author Jens Pelzetter */ @ViewScoped -class UserGroupsDataProvider extends AbstractDataProvider { +class UserGroupsTableDataProvider extends AbstractDataProvider { private static final long serialVersionUID = 3321330114174366998L; diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserRolesController.java b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserRolesController.java index 8548914b2..fbedde178 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserRolesController.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserRolesController.java @@ -67,7 +67,7 @@ class UserRolesController { .format("No user with ID %d in the database. ", user.getPartyId()))); - roleManager.assignRoleToParty(role, theUser); + roleManager.assignRoleToParty(theRole, theUser); } @Transactional(Transactional.TxType.REQUIRED) diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserSelector.java b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserSelector.java index 7c1def8e0..acebe5b60 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserSelector.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserSelector.java @@ -49,9 +49,6 @@ public class UserSelector extends Window { private static final String COL_FAMILY_NAME = "family_name"; private static final String COL_EMAIL = "email"; - private final UserRepository userRepo; - - private final UserSelectionAction groupSelectionAction; public UserSelector(final String caption, final String actionLabel, @@ -59,10 +56,6 @@ public class UserSelector extends Window { final List excludedUsers, final UserSelectionAction action) { - final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); - userRepo = cdiUtil.findBean(UserRepository.class); - this.groupSelectionAction = action; - addWidgets(caption, actionLabel, excludedUsers, action); } @@ -80,13 +73,16 @@ public class UserSelector extends Window { final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final Grid usersGrid = new Grid<>(); - usersGrid.addColumn(User::getName) + usersGrid + .addColumn(User::getName) .setId(COL_USER_NAME) .setCaption("User Name"); - usersGrid.addColumn(User::getGivenName) + usersGrid + .addColumn(User::getGivenName) .setId(COL_GIVEN_NAME) .setCaption("Given name"); - usersGrid.addColumn(User::getFamilyName) + usersGrid + .addColumn(User::getFamilyName) .setId(COL_FAMILY_NAME) .setCaption("Family name"); usersGrid diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserSelectorDataProvider.java b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserSelectorDataProvider.java index 14d69c4ba..ae847d489 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserSelectorDataProvider.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/usersgroupsroles/UserSelectorDataProvider.java @@ -57,10 +57,10 @@ public class UserSelectorDataProvider extends AbstractDataProvider @Transactional(Transactional.TxType.REQUIRED) @Override public int size(final Query query) { + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery criteriaQuery = builder.createQuery(Long.class); final Root from = criteriaQuery.from(User.class); - criteriaQuery = criteriaQuery.select(builder.count(from)); criteriaQuery = criteriaQuery.distinct(true); @@ -83,6 +83,7 @@ public class UserSelectorDataProvider extends AbstractDataProvider @Transactional @Override public Stream fetch(final Query query) { + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery criteriaQuery = builder .createQuery(User.class); diff --git a/ccm-core/src/main/java/org/libreccm/security/Group.java b/ccm-core/src/main/java/org/libreccm/security/Group.java index a22055d15..cf2fa2611 100644 --- a/ccm-core/src/main/java/org/libreccm/security/Group.java +++ b/ccm-core/src/main/java/org/libreccm/security/Group.java @@ -59,21 +59,31 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA; @NamedQuery( name = "Group.findByName", query = "SELECT g FROM Group g WHERE g.name = :name " - + "ORDER BY g.name"), + + "ORDER BY g.name") + , @NamedQuery( name = "Group.searchByName", query = "SELECT g FROM Group g " + "WHERE LOWER(g.name) LIKE CONCAT(LOWER(:name), '%') " - + "ORDER BY g.name"), + + "ORDER BY g.name") + , @NamedQuery( name = "Group.findAllOrderedByGroupName", query = "SELECT g FROM Group g ORDER BY g.name") + , + @NamedQuery( + name = "Group.findByMember", + query = "SELECT g FROM Group g " + + "JOIN g.memberships m " + + "WHERE m.member = :member" + ) }) @NamedEntityGraphs({ @NamedEntityGraph( name = "Group.withMembersAndRoleMemberships", attributeNodes = { - @NamedAttributeNode(value = "memberships"), + @NamedAttributeNode(value = "memberships") + , @NamedAttributeNode(value = "roleMemberships", subgraph = "role")}, subgraphs = { @@ -82,7 +92,8 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA; attributeNodes = { @NamedAttributeNode(value = "role", subgraph = "permissions") - }), + }) + , @NamedSubgraph( name = "permissions", attributeNodes = { diff --git a/ccm-core/src/main/java/org/libreccm/security/GroupRepository.java b/ccm-core/src/main/java/org/libreccm/security/GroupRepository.java index 7427cef5b..6141327a0 100644 --- a/ccm-core/src/main/java/org/libreccm/security/GroupRepository.java +++ b/ccm-core/src/main/java/org/libreccm/security/GroupRepository.java @@ -74,6 +74,15 @@ public class GroupRepository extends AbstractEntityRepository { } } + public List findByMember(final Party member) { + + final TypedQuery query = getEntityManager() + .createNamedQuery("Group.findByMember", Group.class); + query.setParameter("member", member); + + return query.getResultList(); + } + /** * Tries to find a group which name contains a provided token. * diff --git a/ccm-core/src/main/java/org/libreccm/security/Role.java b/ccm-core/src/main/java/org/libreccm/security/Role.java index ee2a07088..51a7ae24c 100644 --- a/ccm-core/src/main/java/org/libreccm/security/Role.java +++ b/ccm-core/src/main/java/org/libreccm/security/Role.java @@ -43,12 +43,12 @@ import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.Table; -import javax.validation.constraints.Pattern; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; + import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties index 4f8392c94..2e91bb7ed 100644 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties @@ -611,3 +611,4 @@ ui.admin.importexport.import.status.locked=This should not happen. ui.admin.importexport.import.current_status=Import current status ui.admin.importexport.import.report=Report from last import process ui.groups.roles.remove=Remove +ui.user.groups.remove=Remove diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties index 7bf2ec58e..c811afb1c 100644 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties @@ -615,3 +615,4 @@ ui.admin.importexport.import.status.locked=This should not happen. ui.admin.importexport.import.current_status=Aktueller Status des Import-Prozesses ui.admin.importexport.import.report=Bericht des letzten Import-Prozesses ui.groups.roles.remove=Entfernen +ui.user.groups.remove=Entfernen diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties index a8745d5a0..62922b182 100755 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties @@ -608,3 +608,4 @@ ui.admin.importexport.import.status.locked=This should not happen. ui.admin.importexport.import.current_status=Import current status ui.admin.importexport.import.report=Report from last import process ui.groups.roles.remove=Remove +ui.user.groups.remove=Remove diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties index 4ae40ab05..ca855f930 100755 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties @@ -599,3 +599,4 @@ ui.admin.importexport.import.status.locked=This should not happen. ui.admin.importexport.import.current_status=Import current status ui.admin.importexport.import.report=Report from last import process ui.groups.roles.remove=Remove +ui.user.groups.remove=Remove