diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/ConfigurationRolesController.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/ConfigurationRolesController.java index 37b0e9da2..51a4e5bd5 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/ConfigurationRolesController.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/ConfigurationRolesController.java @@ -14,6 +14,7 @@ import org.libreccm.security.Permission; import org.libreccm.security.PermissionChecker; import org.libreccm.security.Role; import org.libreccm.security.RoleMembership; +import org.libreccm.security.RoleRepository; import java.util.Optional; @@ -27,15 +28,22 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionManager; import org.librecms.contentsection.ContentSectionRepository; import org.librecms.contentsection.Folder; import org.librecms.contentsection.privileges.AdminPrivileges; +import org.librecms.ui.CmsAdminMessages; +import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.stream.Collectors; +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; + /** * * @author Jens Pelzetter @@ -45,6 +53,12 @@ import java.util.stream.Collectors; @Path("/{sectionIdentifier}/configuration/roles") public class ConfigurationRolesController { + @Inject + private CmsAdminMessages messages; + + @Inject + private ContentSectionManager sectionManager; + @Inject private ContentSectionModel sectionModel; @@ -63,6 +77,9 @@ public class ConfigurationRolesController { @Inject private PermissionChecker permissionChecker; + @Inject + private RoleRepository roleRepo; + @Inject private SelectedRoleModel selectedRoleModel; @@ -112,12 +129,30 @@ public class ConfigurationRolesController { return "org/librecms/ui/contentsection/access-denied.xhtml"; } - final List roles = section - .getRoles() + final List sectionRoles = section.getRoles(); + + final Set otherRoles = roleRepo + .findAll() .stream() - .map(this::buildRoleListModel) - .collect(Collectors.toList()); - models.put("roles", roles); + .filter(role -> !sectionRoles.contains(role)) + .collect(Collectors.toSet()); + + models.put( + "roles", + sectionRoles + .stream() + .map(this::buildRoleListModel) + .collect(Collectors.toList()) + ); + models.put( + "otherRoles", + otherRoles + .stream() + .map(this::buildRoleListModel) + .sorted( + (role1, role2) -> role1.getName().compareTo(role2.getName()) + ).collect(Collectors.toList()) + ); return "org/librecms/ui/contentsection/configuration/roles.xhtml"; } @@ -231,6 +266,308 @@ public class ConfigurationRolesController { return "org/librecms/ui/contentsection/configuration/role.xhtml"; } + @POST + @Path("/@new") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String createRole( + @PathParam("sectionIdentifier") final String sectionIdentifierParam, + @FormParam("roleName") final String roleName + ) { + final Identifier sectionIdentifier = identifierParser.parseIdentifier( + sectionIdentifierParam + ); + + final Optional sectionResult; + switch (sectionIdentifier.getType()) { + case ID: + sectionResult = sectionRepo.findById( + Long.parseLong( + sectionIdentifier.getIdentifier() + ) + ); + break; + case UUID: + sectionResult = sectionRepo.findByUuid( + sectionIdentifier.getIdentifier() + ); + break; + default: + sectionResult = sectionRepo.findByLabel( + sectionIdentifier.getIdentifier() + ); + break; + } + + if (!sectionResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + return "org/librecms/ui/contentsection/contentsection-not-found.xhtml"; + } + final ContentSection section = sectionResult.get(); + sectionModel.setSection(section); + + if (!permissionChecker.isPermitted( + AdminPrivileges.ADMINISTER_ROLES, section + )) { + models.put("sectionIdentifier", sectionIdentifier); + return "org/librecms/ui/contentsection/access-denied.xhtml"; + } + + final List errors = new ArrayList<>(); + if (roleName == null || roleName.matches("\\s*")) { + errors.add( + messages.get( + "contentsection.configuration.roles.errors.name_not_empty" + ) + ); + } + if (roleName != null && !roleName.matches("[a-zA-Z0-9_-]*")) { + errors.add( + messages.get( + "contentsection.configuration.roles.errors.name_invalid" + ) + ); + } + if (!errors.isEmpty()) { + models.put("errors", errors); + models.put("roleName", roleName); + return listRoles(sectionIdentifierParam); + } + + sectionManager.addRoleToContentSection(section, roleName); + + return String.format( + "redirect:/%s/configuration/roles", sectionIdentifierParam + ); + } + + @POST + @Path("/@add") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String addRole( + @PathParam("sectionIdentifier") final String sectionIdentifierParam, + @FormParam("rolesToAdd") final List rolesToAdd + ) { + final Identifier sectionIdentifier = identifierParser.parseIdentifier( + sectionIdentifierParam + ); + + final Optional sectionResult; + switch (sectionIdentifier.getType()) { + case ID: + sectionResult = sectionRepo.findById( + Long.parseLong( + sectionIdentifier.getIdentifier() + ) + ); + break; + case UUID: + sectionResult = sectionRepo.findByUuid( + sectionIdentifier.getIdentifier() + ); + break; + default: + sectionResult = sectionRepo.findByLabel( + sectionIdentifier.getIdentifier() + ); + break; + } + + if (!sectionResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + return "org/librecms/ui/contentsection/contentsection-not-found.xhtml"; + } + final ContentSection section = sectionResult.get(); + sectionModel.setSection(section); + + if (!permissionChecker.isPermitted( + AdminPrivileges.ADMINISTER_ROLES, section + )) { + models.put("sectionIdentifier", sectionIdentifier); + return "org/librecms/ui/contentsection/access-denied.xhtml"; + } + + for (final String roleUuid : rolesToAdd) { + roleRepo + .findByUuid(roleUuid) + .ifPresent( + role -> sectionManager.addRoleToContentSection( + role, section + ) + ); + } + + return String.format( + "redirect:/%s/configuration/roles", sectionIdentifierParam + ); + } + + @POST + @Path("/{roleIdentifier}/@remove") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String removeRole( + @PathParam("sectionIdentifier") final String sectionIdentifierParam, + @PathParam("roleIdentifier") final String roleIdentifierParam + ) { + final Identifier sectionIdentifier = identifierParser.parseIdentifier( + sectionIdentifierParam + ); + + final Optional sectionResult; + switch (sectionIdentifier.getType()) { + case ID: + sectionResult = sectionRepo.findById( + Long.parseLong( + sectionIdentifier.getIdentifier() + ) + ); + break; + case UUID: + sectionResult = sectionRepo.findByUuid( + sectionIdentifier.getIdentifier() + ); + break; + default: + sectionResult = sectionRepo.findByLabel( + sectionIdentifier.getIdentifier() + ); + break; + } + + if (!sectionResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + return "org/librecms/ui/contentsection/contentsection-not-found.xhtml"; + } + final ContentSection section = sectionResult.get(); + sectionModel.setSection(section); + + if (!permissionChecker.isPermitted( + AdminPrivileges.ADMINISTER_ROLES, section + )) { + models.put("sectionIdentifier", sectionIdentifier); + return "org/librecms/ui/contentsection/access-denied.xhtml"; + } + + final Identifier roleIdentifier = identifierParser.parseIdentifier( + roleIdentifierParam + ); + + final Optional roleResult; + switch (roleIdentifier.getType()) { + case ID: + roleResult = roleRepo.findById( + Long.parseLong(roleIdentifier.getIdentifier()) + ); + break; + case UUID: + roleResult = roleRepo.findByUuid( + roleIdentifier.getIdentifier() + ); + break; + default: + roleResult = roleRepo.findByName( + roleIdentifier.getIdentifier() + ); + break; + } + + if (!roleResult.isPresent()) { + models.put("roleIdentifier", roleIdentifierParam); + return "org/librecms/ui/contentsection/configuration/role-not-found.xhtml"; + } + final Role role = roleResult.get(); + sectionManager.removeRoleFromContentSection(section, role); + + return String.format( + "redirect:/%s/configuration/roles", sectionIdentifierParam + ); + } + + @POST + @Path("/{roleIdentifier}/@delete") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String deleteRole( + @PathParam("sectionIdentifier") final String sectionIdentifierParam, + @PathParam("roleIdentifier") final String roleIdentifierParam + ) { + final Identifier sectionIdentifier = identifierParser.parseIdentifier( + sectionIdentifierParam + ); + + final Optional sectionResult; + switch (sectionIdentifier.getType()) { + case ID: + sectionResult = sectionRepo.findById( + Long.parseLong( + sectionIdentifier.getIdentifier() + ) + ); + break; + case UUID: + sectionResult = sectionRepo.findByUuid( + sectionIdentifier.getIdentifier() + ); + break; + default: + sectionResult = sectionRepo.findByLabel( + sectionIdentifier.getIdentifier() + ); + break; + } + + if (!sectionResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + return "org/librecms/ui/contentsection/contentsection-not-found.xhtml"; + } + final ContentSection section = sectionResult.get(); + sectionModel.setSection(section); + + if (!permissionChecker.isPermitted( + AdminPrivileges.ADMINISTER_ROLES, section + )) { + models.put("sectionIdentifier", sectionIdentifier); + return "org/librecms/ui/contentsection/access-denied.xhtml"; + } + + final Identifier roleIdentifier = identifierParser.parseIdentifier( + roleIdentifierParam + ); + + final Optional roleResult; + switch (roleIdentifier.getType()) { + case ID: + roleResult = roleRepo.findById( + Long.parseLong(roleIdentifier.getIdentifier()) + ); + break; + case UUID: + roleResult = roleRepo.findByUuid( + roleIdentifier.getIdentifier() + ); + break; + default: + roleResult = roleRepo.findByName( + roleIdentifier.getIdentifier() + ); + break; + } + + if (!roleResult.isPresent()) { + models.put("roleIdentifier", roleIdentifierParam); + return "org/librecms/ui/contentsection/configuration/role-not-found.xhtml"; + } + final Role role = roleResult.get(); + sectionManager.removeRoleFromContentSection(section, role); + roleRepo.delete(role); + + return String.format( + "redirect:/%s/configuration/roles", sectionIdentifierParam + ); + } + private RoleListItemModel buildRoleListModel(final Role role) { final RoleListItemModel model = new RoleListItemModel(); model.setRoleId(role.getRoleId()); diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/configuration/role-not-found.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/configuration/role-not-found.xhtml new file mode 100644 index 000000000..c839a4c26 --- /dev/null +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/configuration/role-not-found.xhtml @@ -0,0 +1,26 @@ +]> + + + + + + + + + + +
+ +
+
+
+ + diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/configuration/roles.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/configuration/roles.xhtml index c0b0f2480..1b647057e 100644 --- a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/configuration/roles.xhtml +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/configuration/roles.xhtml @@ -29,6 +29,14 @@

#{CmsAdminMessages['contentsection.configuration.roles.title']}

+ + + + + +
+ + + - +
@@ -79,22 +193,39 @@ diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/contentsection-not-found.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/contentsection-not-found.xhtml index 411536a8d..87b7527ed 100644 --- a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/contentsection-not-found.xhtml +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/contentsection-not-found.xhtml @@ -10,7 +10,12 @@ + diff --git a/ccm-cms/src/main/resources/org/librecms/CmsAdminMessages.properties b/ccm-cms/src/main/resources/org/librecms/CmsAdminMessages.properties index f30238232..47ae1332b 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsAdminMessages.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsAdminMessages.properties @@ -308,3 +308,22 @@ contentsection.configuration.role_details.members.cols.name=Member Name contentsection.configuration.role_details.members.cols.actions=Actions contentsection.configuration.roles.table.actions.remove=Remove contentsection.configuration.roles.role_details.name.edit=Edit +contentsection.configuration.roles.create.dialog.cancel=Cancel +contentsection.configuration.roles.create.dialog.submit=Create new role +contentsection.configuration.roles.create.dialog.title=Create role for content section {0} +contentsection.configuration.roles.create.dialog.rolename.help=Unique name of the role +contentsection.configuration.roles.create.dialog.rolename.label=Name +contentsection.configuration.roles.errors.name_not_empty=The name of a role can't be empty. +contentsection.configuration.roles.errors.name_invalid=The name of a role may only contain the letters a to z, A to Z, numbers, the underscore and the dash. +contentsection.configuration.roles.add.dialog.title=Add roles to content section {0} +contentsection.configuration.roles.add.dialog.cancel=Cancel +contentsection.configuration.roles.add.dialog.submit=Add selected roles +contentsection.role.not_found=Role {0} not found +contentsection.configuration.roles.table.actions.remove.cancel=Cancel +contentsection.configuration.roles.table.actions.remove.submit=Remove role from content section +contentsection.configuration.roles.table.actions.remove.title=Remove role from content section? +contentsection.configuration.roles.table.actions.remove.message=Are you sure to remove the role {0} from content section {1}? +contentsection.configuration.roles.table.actions.delete.cancel=Cancel +contentsection.configuration.roles.table.actions.delete.submit=Delete role +contentsection.configuration.roles.table.actions.delete.title=Confirm role deletion +contentsection.configuration.roles.table.actions.delete.message=Are you sure to remove role {0} from content section {1} and delete it? diff --git a/ccm-cms/src/main/resources/org/librecms/CmsAdminMessages_de.properties b/ccm-cms/src/main/resources/org/librecms/CmsAdminMessages_de.properties index c601845a4..e265690d9 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsAdminMessages_de.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsAdminMessages_de.properties @@ -309,3 +309,22 @@ contentsection.configuration.role_details.members.cols.name=Name des Mitglieds contentsection.configuration.role_details.members.cols.actions=Aktionen contentsection.configuration.roles.table.actions.remove=Entfernen contentsection.configuration.roles.role_details.name.edit=Bearbeiten +contentsection.configuration.roles.create.dialog.cancel=Abbrechen +contentsection.configuration.roles.create.dialog.submit=Neue Rolle anlegen +contentsection.configuration.roles.create.dialog.title=Neue Rolle f\u00fcr Content Section {0} anlegen +contentsection.configuration.roles.create.dialog.rolename.help=Eindeutiger Name der Rolle +contentsection.configuration.roles.create.dialog.rolename.label=Name +contentsection.configuration.roles.errors.name_not_empty=Der Name einer Rolle darf nicht leer sein. +contentsection.configuration.roles.errors.name_invalid=Der Name einer Rolle darf nur die Buchstaben a bis z, A bis Z, Ziffern, den Unterstrich und den Bindestrich enthalten. +contentsection.configuration.roles.add.dialog.title=Rollen der Content Section {0} hinzuf\u00fcgen +contentsection.configuration.roles.add.dialog.cancel=Abbrechen +contentsection.configuration.roles.add.dialog.submit=Ausgew\u00e4hlte Rollen hinzuf\u00fcgen +contentsection.role.not_found=Rolle {0} nicht gefunden +contentsection.configuration.roles.table.actions.remove.cancel=Abbrechen +contentsection.configuration.roles.table.actions.remove.submit=Remove role from content section +contentsection.configuration.roles.table.actions.remove.title=Remove role from content section? +contentsection.configuration.roles.table.actions.remove.message=Sind Sie sicher, dass Sie die Rolle {0} aus der Content Section {1} entfernen wollen? +contentsection.configuration.roles.table.actions.delete.cancel=Abbrechen +contentsection.configuration.roles.table.actions.delete.submit=Rolle l\u00f6schen +contentsection.configuration.roles.table.actions.delete.title=Confirm role deletion +contentsection.configuration.roles.table.actions.delete.message=Sind Sie sicher, dass die die Rolle {0} aus der Content Section {1} entfernen und l\u00f6schen wollen? diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RoleFormController.java b/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RoleFormController.java index 6f9abd5fe..08e7fa86b 100644 --- a/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RoleFormController.java +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RoleFormController.java @@ -97,7 +97,7 @@ public class RoleFormController { ) ); } - if (!roleName.matches("[a-zA-Z0-9_-]")) { + if (!roleName.matches("[a-zA-Z0-9_-]*")) { errors.add( adminMessages.get( "usersgroupsroles.roles.form.errors.name_invalid" diff --git a/ccm-core/src/main/resources/META-INF/resources/components/libreccm/deleteDialog.xhtml b/ccm-core/src/main/resources/META-INF/resources/components/libreccm/deleteDialog.xhtml index b70493b87..3f8450844 100644 --- a/ccm-core/src/main/resources/META-INF/resources/components/libreccm/deleteDialog.xhtml +++ b/ccm-core/src/main/resources/META-INF/resources/components/libreccm/deleteDialog.xhtml @@ -7,9 +7,14 @@ +
-
- -