From f4e6b1da9617ed7b81931f176cc301fc5cc58a11 Mon Sep 17 00:00:00 2001 From: jensp Date: Tue, 12 Apr 2016 17:16:52 +0000 Subject: [PATCH] CCM NG: Form for editing roles for a user git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3984 8810af33-2d31-482b-a856-94f89814c4df --- .../ui/admin/usersgroupsroles/UserAdmin.java | 228 +++++++++++++++--- .../java/org/libreccm/security/Group.java | 8 +- .../security/OneTimeAuthTokenCleaner.java | 3 +- .../main/java/org/libreccm/security/Role.java | 34 ++- .../ui/admin/AdminResources.properties | 2 + .../ui/admin/AdminResources_de.properties | 2 + .../ui/admin/AdminResources_en.properties | 2 + .../ui/admin/AdminResources_fr.properties | 2 + 8 files changed, 237 insertions(+), 44 deletions(-) diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserAdmin.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserAdmin.java index c59326c3b..2365c65d0 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserAdmin.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserAdmin.java @@ -20,7 +20,6 @@ package com.arsdigita.ui.admin.usersgroupsroles; import com.arsdigita.bebop.ActionLink; import com.arsdigita.bebop.BoxPanel; -import com.arsdigita.bebop.ColumnPanel; import com.arsdigita.bebop.Component; import com.arsdigita.bebop.ControlLink; import com.arsdigita.bebop.Form; @@ -59,19 +58,20 @@ import org.libreccm.security.ChallengeManager; import org.libreccm.security.Group; import org.libreccm.security.GroupManager; import org.libreccm.security.GroupRepository; +import org.libreccm.security.Role; +import org.libreccm.security.RoleManager; +import org.libreccm.security.RoleRepository; import org.libreccm.security.User; import org.libreccm.security.UserManager; import org.libreccm.security.UserRepository; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import java.util.Set; import java.util.SortedSet; import java.util.TooManyListenersException; import java.util.TreeSet; -import java.util.logging.Level; import java.util.stream.IntStream; -import java.util.stream.StreamSupport; import javax.mail.MessagingException; @@ -101,6 +101,7 @@ public class UserAdmin extends BoxPanel { private final BoxPanel userDetails; private final Form emailForm; private final Form editGroupMembershipsForm; + private final Form editRoleMembershipsForm; private final Form newUserForm; public UserAdmin() { @@ -587,7 +588,7 @@ public class UserAdmin extends BoxPanel { showEditGroupMembershipsForm(state); break; case UserGroupsRolesTableModel.ROW_ROLES: - //ToDo + showEditRoleMembershipsForm(state); break; } } @@ -737,6 +738,9 @@ public class UserAdmin extends BoxPanel { editGroupMembershipsForm = buildEditGroupMembershipsForm(); add(editGroupMembershipsForm); + editRoleMembershipsForm = buildEditRoleMembershipsForm(); + add(editRoleMembershipsForm); + newUserForm = buildNewUserForm(); add(newUserForm); } @@ -948,7 +952,8 @@ public class UserAdmin extends BoxPanel { final User user = userRepository.findById(Long.parseLong(userIdStr)); target.setLabel(new GlobalizedMessage( - "ui.admin.user.edit_group_memberships", ADMIN_BUNDLE, + "ui.admin.user.edit_group_memberships", + ADMIN_BUNDLE, new String[]{user.getName()})); }); links.add(header); @@ -967,11 +972,8 @@ public class UserAdmin extends BoxPanel { final CheckboxGroup groups = new CheckboxGroup(groupsSelector); try { groups.addPrintListener(e -> { -// final PageState state = e.getPageState(); final CheckboxGroup target = (CheckboxGroup) e.getTarget(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); -// final UserRepository userRepository = cdiUtil.findBean( -// UserRepository.class); final GroupRepository groupRepository = cdiUtil.findBean( GroupRepository.class); @@ -982,23 +984,16 @@ public class UserAdmin extends BoxPanel { return g1.getName().compareTo(g2.getName()); }); allGroups.addAll(groupRepository.findAll()); -// final List assignedGroups = new ArrayList<>(); -// final User user = userRepository.findById(Long.parseLong( -// selectedUserId.getSelectedKey(state))); -// user.getGroupMemberships().forEach(m -> { -// assignedGroups.add(m.getGroup()); -// }); allGroups.forEach(g -> { final Option option = new Option( Long.toString(g.getPartyId()), new Text(g.getName())); target.addOption(option); -// if (assignedGroups.contains(g)) { -// target.setOptionSelected(option); -// } }); }); } catch (TooManyListenersException ex) { + //This should never happen, and if its happens something is + //seriously wrong... throw new UncheckedWrapperException(ex); } form.add(groups); @@ -1049,12 +1044,16 @@ public class UserAdmin extends BoxPanel { selectedUserId.getSelectedKey(state))); final List selectedGroups = new ArrayList<>(); if (selectedGroupIds != null) { - for (String selectedGroupId : selectedGroupIds) { - final Group group = groupRepository.findById(Long - .parseLong( - selectedGroupId)); + Arrays.stream(selectedGroupIds).forEach(id -> { + final Group group = groupRepository.findById( + Long.parseLong(id)); selectedGroups.add(group); - } + }); +// for (String selectedGroupId : selectedGroupIds) { +// final Group group = groupRepository.findById(Long +// .parseLong(selectedGroupId)); +// selectedGroups.add(group); +// } } final List assignedGroups = new ArrayList<>(); user.getGroupMemberships().forEach(m -> { @@ -1071,6 +1070,8 @@ public class UserAdmin extends BoxPanel { //Than check for removed groups assignedGroups.forEach(g -> { if (!selectedGroups.contains(g)) { + //The group is maybe detached or not fully loaded, + //therefore we load the group from the database. final Group group = groupRepository.findById( g.getPartyId()); groupManager.removeMemberFromGroup(user, group); @@ -1084,6 +1085,148 @@ public class UserAdmin extends BoxPanel { return form; } + public Form buildEditRoleMembershipsForm() { + final Form form = new Form("edit-userrolesmemberships-form"); + + final BoxPanel links = new BoxPanel(BoxPanel.VERTICAL); + final Label header = new Label(e -> { + final PageState state = e.getPageState(); + final Label target = (Label) e.getTarget(); + + final String userIdStr = selectedUserId.getSelectedKey(state); + final UserRepository userRepository = CdiUtil.createCdiUtil() + .findBean(UserRepository.class); + final User user = userRepository.findById(Long.parseLong(userIdStr)); + + target.setLabel(new GlobalizedMessage( + "ui.admin.user_edit_role_memberships", + ADMIN_BUNDLE, + new String[]{user.getName()})); + }); + links.add(header); + + final ActionLink backLink = new ActionLink(new GlobalizedMessage( + "ui.admin.user.edit_role_memberships.back_to_user_details", + ADMIN_BUNDLE)); + backLink.addActionListener(e -> { + closeEditRoleMembershipsForm(e.getPageState()); + }); + links.add(backLink); + + form.add(links); + + final String rolesSelector = "rolesselector"; + final CheckboxGroup roles = new CheckboxGroup(rolesSelector); + try { + roles.addPrintListener(e -> { + final CheckboxGroup target = (CheckboxGroup) e.getTarget(); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + + final RoleRepository roleRepository = cdiUtil.findBean( + RoleRepository.class); + + target.clearOptions(); + + final SortedSet allRoles = new TreeSet<>( + (r1, r2) -> { + return r1.getName().compareTo(r2.getName()); + }); + allRoles.addAll(roleRepository.findAll()); + + allRoles.forEach(r -> { + final Option option = new Option(Long.toString( + r.getRoleId()), new Text(r.getName())); + target.addOption(option); + }); + }); + } catch (TooManyListenersException ex) { + //This should never happen, and if its happens something is + //seriously wrong... + throw new UncheckedWrapperException(ex); + } + form.add(roles); + + final SaveCancelSection saveCancelSection = new SaveCancelSection(); + form.add(saveCancelSection); + + form.addInitListener(e -> { + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final UserRepository userRepository = cdiUtil.findBean( + UserRepository.class); + + final PageState state = e.getPageState(); + + final User user = userRepository.findById(Long.parseLong( + selectedUserId.getSelectedKey(state))); + final List assignedRoles = new ArrayList<>(); + user.getRoleMemberships().forEach(m -> { + assignedRoles.add(m.getRole()); + }); + + final String[] selectedRoles = new String[assignedRoles.size()]; + IntStream.range(0, assignedRoles.size()).forEach(i -> { + selectedRoles[i] = Long.toString(assignedRoles.get(i) + .getRoleId()); + }); + + roles.setValue(state, selectedRoles); + }); + + form.addProcessListener(e -> { + final PageState state = e.getPageState(); + if (saveCancelSection.getSaveButton().isSelected(state)) { + final FormData data = e.getFormData(); + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final UserRepository userRepository = cdiUtil.findBean( + UserRepository.class); + final RoleRepository roleRepository = cdiUtil.findBean( + RoleRepository.class); + final RoleManager roleManager = cdiUtil.findBean( + RoleManager.class); + + final String[] selectedRolesIds = (String[]) data.get( + rolesSelector); + + final User user = userRepository.findById(Long.parseLong( + selectedUserId.getSelectedKey(state))); + final List selectedRoles = new ArrayList<>(); + if (selectedRolesIds != null) { + Arrays.stream(selectedRolesIds).forEach(id -> { + final Role role = roleRepository.findById( + Long.parseLong(id)); + selectedRoles.add(role); + }); + } + final List assignedRoles = new ArrayList<>(); + user.getRoleMemberships().forEach(m -> { + assignedRoles.add(m.getRole()); + }); + + //First check for newly added roles + selectedRoles.forEach(r -> { + if (!assignedRoles.contains(r)) { + roleManager.assignRoleToParty(r, user); + } + }); + + //Than check for removed roles + assignedRoles.forEach(r -> { + if (!selectedRoles.contains(r)) { + //Role is maybe detached or not fully loaded, + //therefore we load the role from the database. + final Role role = roleRepository.findById(r.getRoleId()); + roleManager.removeRoleFromParty(role, user); + } + }); + } + + closeEditRoleMembershipsForm(state); + }); + + return form; + } + @Override public void register(final Page page) { super.register(page); @@ -1097,6 +1240,7 @@ public class UserAdmin extends BoxPanel { page.setVisibleDefault(passwordSetForm, false); page.setVisibleDefault(emailForm, false); page.setVisibleDefault(editGroupMembershipsForm, false); + page.setVisibleDefault(editRoleMembershipsForm, false); page.setVisibleDefault(newUserForm, false); } @@ -1107,6 +1251,7 @@ public class UserAdmin extends BoxPanel { passwordSetForm.setVisible(state, false); emailForm.setVisible(state, false); editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, false); } @@ -1118,6 +1263,7 @@ public class UserAdmin extends BoxPanel { passwordSetForm.setVisible(state, false); emailForm.setVisible(state, false); editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, false); } @@ -1128,6 +1274,7 @@ public class UserAdmin extends BoxPanel { passwordSetForm.setVisible(state, false); emailForm.setVisible(state, false); editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, false); } @@ -1138,6 +1285,7 @@ public class UserAdmin extends BoxPanel { passwordSetForm.setVisible(state, false); emailForm.setVisible(state, false); editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, false); } @@ -1148,6 +1296,7 @@ public class UserAdmin extends BoxPanel { passwordSetForm.setVisible(state, true); emailForm.setVisible(state, false); editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, false); } @@ -1158,6 +1307,7 @@ public class UserAdmin extends BoxPanel { passwordSetForm.setVisible(state, false); emailForm.setVisible(state, false); editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, false); } @@ -1168,6 +1318,7 @@ public class UserAdmin extends BoxPanel { passwordSetForm.setVisible(state, false); emailForm.setVisible(state, true); editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, false); } @@ -1189,39 +1340,62 @@ public class UserAdmin extends BoxPanel { passwordSetForm.setVisible(state, false); emailForm.setVisible(state, false); editGroupMembershipsForm.setVisible(state, true); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, false); } protected void closeEditGroupMembershipsForm(final PageState state) { - selectedEmailAddress.clearSelection(state); usersTablePanel.setVisible(state, false); userDetails.setVisible(state, true); userEditForm.setVisible(state, false); passwordSetForm.setVisible(state, false); emailForm.setVisible(state, false); editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, false); } - protected void showNewUserForm(final PageState state) { - selectedEmailAddress.clearSelection(state); + protected void showEditRoleMembershipsForm(final PageState state) { usersTablePanel.setVisible(state, false); userDetails.setVisible(state, false); userEditForm.setVisible(state, false); passwordSetForm.setVisible(state, false); emailForm.setVisible(state, false); editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, true); + newUserForm.setVisible(state, false); + } + + protected void closeEditRoleMembershipsForm(final PageState state) { + usersTablePanel.setVisible(state, false); + userDetails.setVisible(state, true); + userEditForm.setVisible(state, false); + passwordSetForm.setVisible(state, false); + emailForm.setVisible(state, false); + editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); + newUserForm.setVisible(state, false); + } + + protected void showNewUserForm(final PageState state) { + usersTablePanel.setVisible(state, false); + userDetails.setVisible(state, false); + userEditForm.setVisible(state, false); + passwordSetForm.setVisible(state, false); + emailForm.setVisible(state, false); + editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, true); } protected void closeNewUserForm(final PageState state) { - selectedEmailAddress.clearSelection(state); usersTablePanel.setVisible(state, true); userDetails.setVisible(state, false); userEditForm.setVisible(state, false); passwordSetForm.setVisible(state, false); emailForm.setVisible(state, false); editGroupMembershipsForm.setVisible(state, false); + editRoleMembershipsForm.setVisible(state, false); newUserForm.setVisible(state, false); } 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 b181911e0..e307be138 100644 --- a/ccm-core/src/main/java/org/libreccm/security/Group.java +++ b/ccm-core/src/main/java/org/libreccm/security/Group.java @@ -63,11 +63,9 @@ import javax.xml.bind.annotation.XmlRootElement; @NamedEntityGraph( name = "Group.withMembersAndRoleMemberships", attributeNodes = { - @NamedAttributeNode( - value = "memberships"), - @NamedAttributeNode( - value = "roleMemberships", - subgraph = "role")}, + @NamedAttributeNode(value = "memberships"), + @NamedAttributeNode(value = "roleMemberships", + subgraph = "role")}, subgraphs = { @NamedSubgraph( name = "role", diff --git a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthTokenCleaner.java b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthTokenCleaner.java index 7a901863a..047aaf510 100644 --- a/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthTokenCleaner.java +++ b/ccm-core/src/main/java/org/libreccm/security/OneTimeAuthTokenCleaner.java @@ -77,7 +77,8 @@ public class OneTimeAuthTokenCleaner { // final long interval = 60 * 60 * 1000; LOGGER.debug("Creating interval for {} s.", interval / 1000); - LOGGER.debug("First run cleaning process will be executed in 5 min."); +// LOGGER.debug("First run cleaning process will be executed in {} s.", +// interval / 1000); timerService.createIntervalTimer(interval, interval, new TimerConfig()); 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 de0e36616..29fc17e0e 100644 --- a/ccm-core/src/main/java/org/libreccm/security/Role.java +++ b/ccm-core/src/main/java/org/libreccm/security/Role.java @@ -21,6 +21,7 @@ package org.libreccm.security; import static org.libreccm.core.CoreConstants.*; import org.hibernate.validator.constraints.NotBlank; +import org.libreccm.core.DefaultEntityGraph; import org.libreccm.workflow.TaskAssignment; import java.io.Serializable; @@ -36,6 +37,9 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.NamedAttributeNode; +import javax.persistence.NamedEntityGraph; +import javax.persistence.NamedEntityGraphs; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; @@ -47,7 +51,7 @@ import javax.xml.bind.annotation.XmlRootElement; /** * A role is basically a collection a {@link Permission}s and {@code Task}s. - * + * * @author Jens Pelzetter */ @Entity @@ -57,6 +61,14 @@ import javax.xml.bind.annotation.XmlRootElement; query = "SELECT r FROM Role r " + "WHERE r.name = :name") }) +@NamedEntityGraphs({ + @NamedEntityGraph( + name = "Role.withMembers", + attributeNodes = { + @NamedAttributeNode(value = "memberships") + }) +}) +@DefaultEntityGraph("Role.withMembers") @XmlRootElement(name = "role", namespace = CORE_XML_NS) @SuppressWarnings({"PMD.ShortClassName", "PMD.TooManyMethods"}) public class Role implements Serializable { @@ -86,7 +98,7 @@ public class Role implements Serializable { @XmlElementWrapper(name = "role-memberships", namespace = CORE_XML_NS) @XmlElement(name = "role-membership", namespace = CORE_XML_NS) private Set memberships = new HashSet<>(); - + /** * Permissions granted to the role. */ @@ -97,7 +109,7 @@ public class Role implements Serializable { @OneToMany(mappedBy = "role") private List assignedTasks; - + protected Role() { super(); } @@ -125,19 +137,19 @@ public class Role implements Serializable { return Collections.unmodifiableSet(memberships); } } - + protected void setMemberships(final Set memberships) { this.memberships = memberships; } - + protected void addMembership(final RoleMembership membership) { memberships.add(membership); } - + protected void removeMembership(final RoleMembership membership) { memberships.remove(membership); } - + public List getPermissions() { if (permissions == null) { return null; @@ -157,7 +169,7 @@ public class Role implements Serializable { protected void removePermission(final Permission permission) { permissions.remove(permission); } - + public List getAssignedTasks() { if (assignedTasks == null) { return null; @@ -165,15 +177,15 @@ public class Role implements Serializable { return Collections.unmodifiableList(assignedTasks); } } - + protected void setAssignedTasks(final List assignedTasks) { this.assignedTasks = assignedTasks; } - + protected void addAssignedTask(final TaskAssignment taskAssignment) { assignedTasks.add(taskAssignment); } - + protected void removeAssignedTask(final TaskAssignment taskAssignment) { assignedTasks.remove(taskAssignment); } 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 3e8b3b022..5749714c7 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 @@ -237,3 +237,5 @@ ui.admin.user.all_roles=All roles ui.admin.user.groups=Groups ui.admin.user.edit_group_memberships=Edit group memberships for user {0} ui.admin.user.edit_group_memberships.back_to_user_details=Back to user details +ui.admin.user_edit_role_memberships=Edit role memberships for user {0} +ui.admin.user.edit_role_memberships.back_to_user_details=Back to user details 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 7f30f14be..497c18a87 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 @@ -237,3 +237,5 @@ ui.admin.user.all_roles=Alle Rollen ui.admin.user.groups=Gruppen ui.admin.user.edit_group_memberships=Gruppen f\u00fcr Benutzer {0} bearbeiten ui.admin.user.edit_group_memberships.back_to_user_details=Zur\u00fcck zu den Eigenschaften des Benutzers +ui.admin.user_edit_role_memberships=Rollen f\u00fcr Benutzer {0} bearbeiten +ui.admin.user.edit_role_memberships.back_to_user_details=Zur\u00fcck zu den Eigenschaften des Benutzers 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 1c12ae11f..220c06b37 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 @@ -210,3 +210,5 @@ ui.admin.user.all_roles=All roles ui.admin.user.groups=Groups ui.admin.user.edit_group_memberships=Edit group memberships for user {0} ui.admin.user.edit_group_memberships.back_to_user_details=Back to user details +ui.admin.user_edit_role_memberships=Edit role memberships for user {0} +ui.admin.user.edit_role_memberships.back_to_user_details=Back to user details 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 5350281e0..d7c0ede60 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 @@ -201,3 +201,5 @@ ui.admin.user.all_roles=All roles ui.admin.user.groups=Groups ui.admin.user.edit_group_memberships=Edit group memberships for user {0} ui.admin.user.edit_group_memberships.back_to_user_details=Back to user details +ui.admin.user_edit_role_memberships=Edit role memberships for user {0} +ui.admin.user.edit_role_memberships.back_to_user_details=Back to user details