Some bugfixes for the users/groups/roles adminstration, JavaDoc

Former-commit-id: 1b0962bbfb
pull/7/head
Jens Pelzetter 2020-10-23 09:45:23 +02:00
parent acb7b25058
commit 54858c3ce4
23 changed files with 346 additions and 80 deletions

View File

@ -44,7 +44,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
* Controller managing the post request from the email edit form.
* Controller managing the post requests from the email edit form.
*
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
@ -59,8 +59,6 @@ public class EmailFormController {
@Inject
private AdminMessages adminMessages;
// @Inject
// private BindingResult bindingResult;
@Inject
private EmailFormModel emailFormModel;
@ -76,7 +74,7 @@ public class EmailFormController {
@Inject
private UserRepository userRepository;
// MVC does not work with Krazo 1.1.0-M1
// MvcBinding does not work with Krazo 1.1.0-M1
// @MvcBinding
@FormParam("address")
// @NotBlank
@ -121,7 +119,7 @@ public class EmailFormController {
if (result.isPresent()) {
final User user = result.get();
// MVC Binding does not work with Krazo 1.1.0-M1
// MvcBinding does not work with Krazo 1.1.0-M1
// if (bindingResult.isFailed()) {
// models.put("errors", bindingResult.getAllMessages());
// emailFormModel.setUserIdentifier(userIdentifierParam);

View File

@ -89,6 +89,10 @@ public class GroupDetailsModel {
return groupName;
}
public void setGroupName(final String groupName) {
this.groupName = groupName;
}
public List<GroupUserMembership> getMembers() {
return Collections.unmodifiableList(members);
}

View File

@ -27,23 +27,25 @@ import org.libreccm.security.GroupRepository;
import org.libreccm.security.RequiresPrivilege;
import org.libreccm.ui.admin.AdminMessages;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.mvc.Controller;
import javax.mvc.Models;
import javax.mvc.binding.BindingResult;
import javax.mvc.binding.MvcBinding;
import javax.transaction.Transactional;
import javax.validation.constraints.NotBlank;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
* Controller for processing the POST requests from the group form. Depending
* on the value returned by {@link GroupDetailsModel#isNewGroup()} a new group
* is created or an existing group is updated.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ -56,8 +58,11 @@ public class GroupFormController {
private AdminMessages adminMessages;
@Inject
private BindingResult bindingResult;
private GroupDetailsModel groupDetailsModel;
// MvcBinding does not work with Krazo 1.1.0-M1
// @Inject
// private BindingResult bindingResult;
@Inject
private IdentifierParser identifierParser;
@ -67,9 +72,10 @@ public class GroupFormController {
@Inject
private GroupRepository groupRepository;
@MvcBinding
// MvcBinding does not work with Krazo 1.1.0-M1
// @MvcBinding
@FormParam("groupName")
@NotBlank
// @NotBlank
private String groupName;
@POST
@ -78,8 +84,29 @@ public class GroupFormController {
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String createGroup() {
if (bindingResult.isFailed()) {
models.put("errors", bindingResult.getAllMessages());
// MvcBinding does not work with Krazo 1.1.0-M1
// if (bindingResult.isFailed()) {
// models.put("errors", bindingResult.getAllMessages());
// return "org/libreccm/ui/admin/users-groups-roles/group-form.xhtml";
// }
final List<String> errors = new ArrayList<>();
if (groupName == null || groupName.matches("\\s*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.groups.form.errors.name_not_empty"
)
);
}
if (!groupName.matches("[a-zA-Z0-9_-]*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.groups.form.errors.name_invalid"
)
);
}
if (!errors.isEmpty()) {
models.put("errors", errors);
groupDetailsModel.setGroupName(groupName);
return "org/libreccm/ui/admin/users-groups-roles/group-form.xhtml";
}
@ -98,10 +125,6 @@ public class GroupFormController {
public String updateGroup(
@PathParam("groupIdentifier") final String groupIdentifierParam
) {
if (bindingResult.isFailed()) {
models.put("errors", bindingResult.getAllMessages());
return "org/libreccm/ui/admin/users-groups-roles/group-form.xhtml";
}
final Identifier identifier = identifierParser.parseIdentifier(
groupIdentifierParam
@ -123,6 +146,33 @@ public class GroupFormController {
if (result.isPresent()) {
final Group group = result.get();
// MvcBinding does not work with Krazo 1.1.0-M1
// if (bindingResult.isFailed()) {
// models.put("errors", bindingResult.getAllMessages());
// return "org/libreccm/ui/admin/users-groups-roles/group-form.xhtml";
// }
final List<String> errors = new ArrayList<>();
if (groupName == null || groupName.matches("\\s*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.groups.form.errors.name_not_empty"
)
);
}
if (!groupName.matches("[a-zA-Z_-]*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.groups.form.errors.name_invalid"
)
);
}
if (!errors.isEmpty()) {
models.put("errors", errors);
groupDetailsModel.setGroup(group);
return "org/libreccm/ui/admin/users-groups-roles/group-form.xhtml";
}
group.setName(groupName);
groupRepository.save(group);

View File

@ -49,6 +49,8 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
* Controller for adding members to a group or removing members from a group
* based on the selections in the member form (dialog in group-details).
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -19,6 +19,7 @@
package org.libreccm.ui.admin.usersgroupsroles;
/**
* Model of an entry in the form for managing the members of group.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -49,6 +49,9 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
* Primary controller for managing groups. Retrieves data for the views and
* shows them. Processing of POST requests from the forms is done in other
* controllers.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -36,6 +36,7 @@ import javax.inject.Named;
import javax.transaction.Transactional;
/**
* Provides the data for the details view of a role and the role edit form.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ -82,6 +83,10 @@ public class RoleDetailsModel {
return roleName;
}
public void setRoleName(final String roleName) {
this.roleName = roleName;
}
public List<RolePartyMembership> getMembers() {
return Collections.unmodifiableList(members);
}

View File

@ -27,23 +27,25 @@ import org.libreccm.security.Role;
import org.libreccm.security.RoleRepository;
import org.libreccm.ui.admin.AdminMessages;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.mvc.Controller;
import javax.mvc.Models;
import javax.mvc.binding.BindingResult;
import javax.mvc.binding.MvcBinding;
import javax.transaction.Transactional;
import javax.validation.constraints.NotBlank;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
* Processes the POST requests from the role edit form. Depending on the value
* returned by {@link RoleDetailsModel#isNewRole()} a new role is created or
* an existing role updated.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ -55,21 +57,25 @@ public class RoleFormController {
@Inject
private AdminMessages adminMessages;
@Inject
private BindingResult bindingResult;
// MvcBinding does not work with Krazo 1.1.0-M1
// @Inject
// private BindingResult bindingResult;
@Inject
private IdentifierParser identifierParser;
@Inject
private Models models;
@Inject
private RoleDetailsModel roleDetailsModel;
@Inject
private RoleRepository roleRepository;
@MvcBinding
// MvcBinding does not work with Krazo 1.1.0-M1
// @MvcBinding
@FormParam("roleName")
@NotBlank
// @NotBlank
private String roleName;
@POST
@ -78,8 +84,29 @@ public class RoleFormController {
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String createRole() {
if (bindingResult.isFailed()) {
models.put("errors", bindingResult.getAllMessages());
// MvcBinding does not work with Krazo 1.1.0-M1
// if (bindingResult.isFailed()) {
// models.put("errors", bindingResult.getAllMessages());
// return "org/libreccm/ui/admin/users-groups-roles/role-form.xhtml";
// }
final List<String> errors = new ArrayList<>();
if (roleName == null || roleName.matches("\\s*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.roles.form.errors.name_not_empty"
)
);
}
if (!roleName.matches("[a-zA-Z0-9_-]")) {
errors.add(
adminMessages.get(
"usersgroupsroles.roles.form.errors.name_invalid"
)
);
}
if (!errors.isEmpty()) {
models.put("errors", errors);
roleDetailsModel.setRoleName(roleName);
return "org/libreccm/ui/admin/users-groups-roles/role-form.xhtml";
}
@ -98,11 +125,6 @@ public class RoleFormController {
public String updateRole(
@PathParam("roleIdentifier") final String roleIdentifierParam
) {
if (bindingResult.isFailed()) {
models.put("errors", bindingResult.getAllMessages());
return "org/libreccm/ui/admin/users-groups-roles/role-form.xhtml";
}
final Identifier identifier = identifierParser.parseIdentifier(
roleIdentifierParam
);
@ -123,8 +145,34 @@ public class RoleFormController {
if (result.isPresent()) {
final Role role = result.get();
role.setName(roleName);
// MvcBinding does not work with Krazo 1.1.0-M1
// if (bindingResult.isFailed()) {
// models.put("errors", bindingResult.getAllMessages());
// return "org/libreccm/ui/admin/users-groups-roles/role-form.xhtml";
// }
final List<String> errors = new ArrayList<>();
if (roleName == null || roleName.matches("\\s*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.roles.form.errors.name_not_empty"
)
);
}
if (!roleName.matches("[a-zA-Z0-9_-]")) {
errors.add(
adminMessages.get(
"usersgroupsroles.roles.form.errors.name_invalid"
)
);
}
if (!errors.isEmpty()) {
models.put("errors", errors);
roleDetailsModel.setRole(role);
return "org/libreccm/ui/admin/users-groups-roles/role-form.xhtml";
}
role.setName(roleName);
return "redirect:users-groups-roles/roles";
} else {
models.put(

View File

@ -46,6 +46,9 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
* Controller for adding members to a role and removing members from a role
* depending on the selections in the role members management form (dialog in
* role details).
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -19,6 +19,7 @@
package org.libreccm.ui.admin.usersgroupsroles;
/**
* Model for an entry in the role members form.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -23,6 +23,7 @@ import org.libreccm.security.Party;
import java.util.Objects;
/**
* Model friendly representation of a member of a role.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -23,6 +23,7 @@ import org.libreccm.security.Permission;
import java.util.Objects;
/**
* Model friendly representation of a permission granted to a role.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -45,6 +45,9 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
* Primary controller for managing roles. Retrieves the data for the views for
* manageing roles. POST requests from the forms a processed by other
* controllers.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -135,14 +135,26 @@ public class UserDetailsModel {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getGivenName() {
return givenName;
}
public void setGivenName(final String givenName) {
this.givenName = givenName;
}
public String getFamilyName() {
return familyName;
}
public void setFamilyName(final String familyName) {
this.familyName = familyName;
}
public EmailAddress getPrimaryEmailAddress() {
return primaryEmailAddress;
}
@ -155,10 +167,20 @@ public class UserDetailsModel {
return banned;
}
public void setBanned(final boolean banned) {
this.banned = banned;
}
public boolean isPasswordResetRequired() {
return passwordResetRequired;
}
public void setPasswordResetRequired(
final boolean passwordResetRequired
) {
this.passwordResetRequired = passwordResetRequired;
}
public List<UserGroupMembership> getGroupMemberships() {
return Collections.unmodifiableList(groupMemberships);
}

View File

@ -28,8 +28,9 @@ import org.libreccm.security.UserManager;
import org.libreccm.security.UserRepository;
import org.libreccm.ui.admin.AdminMessages;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@ -37,12 +38,7 @@ import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.mvc.Controller;
import javax.mvc.Models;
import javax.mvc.MvcContext;
import javax.mvc.binding.BindingResult;
import javax.mvc.binding.MvcBinding;
import javax.transaction.Transactional;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@ -61,9 +57,9 @@ public class UserFormController {
@Inject
private AdminMessages adminMessages;
@Inject
private BindingResult bindingResult;
// MvcBinding does not work with Krazo 1.1.0-M1
// @Inject
// private BindingResult bindingResult;
@Inject
private IdentifierParser identifierParser;
@ -71,7 +67,7 @@ public class UserFormController {
private Models models;
@Inject
private MvcContext mvc;
private UserDetailsModel userDetailsModel;
@Inject
private UserManager userManager;
@ -79,9 +75,10 @@ public class UserFormController {
@Inject
private UserRepository userRepository;
@MvcBinding
// MvcBinding does not work with Krazo 1.1.0-M1
// @MvcBinding
@FormParam("userName")
@NotBlank
// @NotBlank
private String userName;
@FormParam("givenName")
@ -90,10 +87,11 @@ public class UserFormController {
@FormParam("familyName")
private String familyName;
@MvcBinding
// MvcBinding does not work with Krazo 1.1.0-M1
// @MvcBinding
@FormParam("primaryEmailAddress")
@NotBlank
@Email
// @NotBlank
// @Email
private String primaryEmailAddress;
@FormParam("primaryEmailAddressBouncing")
@ -120,24 +118,75 @@ public class UserFormController {
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String createUser() {
if (bindingResult.isFailed()) {
models.put("errors", bindingResult.getAllMessages());
return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
// MvcBinding does not work with Krazo 1.1.0-M1
// if (bindingResult.isFailed()) {
// models.put("errors", bindingResult.getAllMessages());
// return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
// }
final List<String> errors = new ArrayList<>();
if (userName == null || userName.matches("\\s*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.users.form.errors.username.empty"
)
);
}
if (!userName.matches("[a-zA-Z0-9_-]*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.users.form.errors.username.invalid"
)
);
}
if (primaryEmailAddress == null || primaryEmailAddress.matches("\\s*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.users.form.errors.primary_email.empty"
)
);
}
if (!primaryEmailAddress.matches(
"^[a-zA-Z0-9\\._-]*@[a-zA-Z0-9\\._-]*$"
)) {
errors.add(
adminMessages.get(
"usersgroupsroles.users.form.errors.primary_email.invalid"
)
);
}
if (password == null || password.isEmpty()) {
models.put("errors", Arrays.asList(
adminMessages.get(
"usersgroupsroles.users.new.errors.password.empty")
));
return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
errors.add(
adminMessages.get(
"usersgroupsroles.users.new.errors.password.empty"
)
);
}
if (!Objects.equals(password, passwordConfirmation)) {
models.put("errors", Arrays.asList(
adminMessages.get(
"usersgroupsroles.users.new.errors.password.no_match")
));
errors.add(
adminMessages.get(
"usersgroupsroles.users.new.errors.password.no_match"
)
);
}
if (!errors.isEmpty()) {
models.put("errors", errors);
userDetailsModel.setName(userName);
userDetailsModel.setGivenName(givenName);
userDetailsModel.setFamilyName(familyName);
userDetailsModel
.getPrimaryEmailAddress()
.setAddress(primaryEmailAddress);
userDetailsModel
.getPrimaryEmailAddress()
.setBouncing(primaryEmailAddressBouncing);
userDetailsModel
.getPrimaryEmailAddress()
.setVerified(primaryEmailAddressVerified);
userDetailsModel.setBanned(banned);
userDetailsModel.setPasswordResetRequired(passwordResetRequired);
return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
}
@ -156,11 +205,6 @@ public class UserFormController {
public String updateUser(
@PathParam("userIdentifier") final String userIdentifierParam
) {
if (bindingResult.isFailed()) {
models.put("errors", bindingResult.getAllMessages());
return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
}
final Identifier identifier = identifierParser.parseIdentifier(
userIdentifierParam
);
@ -183,6 +227,60 @@ public class UserFormController {
if (result.isPresent()) {
final User user = result.get();
// MvcBinding does not work with Krazo 1.1.0-M1
// if (bindingResult.isFailed()) {
// models.put("errors", bindingResult.getAllMessages());
// return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
// }
final List<String> errors = new ArrayList<>();
if (userName == null || userName.matches("\\s*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.users.form.errors.username.empty"
)
);
}
if (!userName.matches("[a-zA-Z0-9_-]*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.users.form.errors.username.invalid"
)
);
}
if (primaryEmailAddress == null || primaryEmailAddress.matches(
"\\s*")) {
errors.add(
adminMessages.get(
"usersgroupsroles.users.form.errors.primary_email.empty"
)
);
}
if (!primaryEmailAddress.matches(
"^[a-zA-Z0-9\\._-]*@[a-zA-Z0-9\\._-]*$"
)) {
errors.add(
adminMessages.get(
"usersgroupsroles.users.form.errors.primary_email.invalid"
)
);
}
if (password != null) {
if (!Objects.equals(password, passwordConfirmation)) {
errors.add(
adminMessages.get(
"usersgroupsroles.users.new.errors.password.no_match"
)
);
}
}
if (!errors.isEmpty()) {
userDetailsModel.setUser(user);
return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
}
user.setUuid(userName);
user.setGivenName(givenName);
user.setFamilyName(familyName);

View File

@ -35,7 +35,6 @@ import org.libreccm.ui.admin.AdminMessages;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
@ -50,6 +49,8 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
* Adds and removes a user from groups and roles depending on the selections
* in the corresponding dialogs in the user details view.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -28,7 +28,7 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path;
/**
*
* Controller for the overview page of the users/groups/roles admin section.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -27,6 +27,8 @@ import java.util.Set;
import javax.enterprise.context.ApplicationScoped;
/**
* {@link AdminPage} implementation for the users/groups/roles section of the
* AdminUI.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/

View File

@ -47,6 +47,8 @@
class="form-control"
id="groupname"
name="groupName"
pattern="[a-zA-Z0-9_-]*"
required="required"
value="#{GroupDetailsModel.groupName}"
type="text" />
<small class="form-text text-muted"

View File

@ -47,6 +47,8 @@
class="form-control"
id="rolename"
name="roleName"
pattern="[a-zA-Z0-9_-]*"
required="required"
value="#{RoleDetailsModel.roleName}"
type="text" />
<small class="form-text text-muted"

View File

@ -47,6 +47,8 @@
class="form-control"
id="username"
name="userName"
pattern="[a-zA-Z0-9_-]*"
required="required"
value="#{UserDetailsModel.name}"
type="text" />
<small class="form-text text-muted"
@ -92,6 +94,7 @@
class="form-control"
id="primary-email-address"
name="primaryEmailAddress"
required="required"
value="#{UserDetailsModel.primaryEmailAddress.address}"
type="email" />
<small class="form-text text-muted"
@ -129,6 +132,7 @@
class="form-control"
id="password"
name="password"
required="required"
type="password" />
<small class="form-text text-muted"
id="password-help">
@ -143,6 +147,7 @@
class="form-control"
id="password-confirmation"
name="passwordConfirmation"
required="required"
type="password" />
<small class="form-text text-muted"
id="password-help">

View File

@ -199,3 +199,10 @@ usersgroupsroles.roles.delete.confirm.message=Are you sure to delete role {0}?
usersgroupsroles.roles.delete.confirm.cancel=Cancel
usersgroupsroles.roles.delete.confirm.yes=Delete role
usersgroupsroles.roles.role_details.uuid=UUID
usersgroupsroles.groups.form.errors.name_not_empty=The name of a group can't be empty
usersgroupsroles.groups.form.errors.name_invalid=The name of a group may only contain the characters a to z, A to Z, 0 to 9, the dash (-), and the underscore (_).
usersgroupsroles.roles.form.errors.name_not_empty=The name of a role can't be empty
usersgroupsroles.users.form.errors.username.empty=The username of a user can't be empty
usersgroupsroles.users.form.errors.username.invalid=The username may only contain the characters a to z, A to Z, 0 to 9, the dash (-) and the underscore (_)
usersgroupsroles.users.form.errors.primary_email.empty=The primary email address of a user can't b be empty
usersgroupsroles.users.form.errors.primary_email.invalid=The primary email address of a user must be a valid email address

View File

@ -199,3 +199,10 @@ usersgroupsroles.roles.delete.confirm.message=Sind Sie sicher, dass Sie die Roll
usersgroupsroles.roles.delete.confirm.cancel=Abbrechen
usersgroupsroles.roles.delete.confirm.yes=Rolle l\u00f6schen
usersgroupsroles.roles.role_details.uuid=UUID
usersgroupsroles.groups.form.errors.name_not_empty=Der Name einer Gruppe darf nicht leer sein
usersgroupsroles.groups.form.errors.name_invalid=Der Name einer Gruppe darf nur die Zeichen a bis z, A bis Z, 0 bis 9, den Bindestrich (-) und den Unterstrich (_) enthalten
usersgroupsroles.roles.form.errors.name_not_empty=Der Name einer Rolle darf nicht leer sein
usersgroupsroles.users.form.errors.username.empty=Der Benutzername eines Benutzers darf nicht leer sein
usersgroupsroles.users.form.errors.username.invalid=Der Benutzername eines Benutzers darf nur die Zeichen a bis z, A bis Z, 0 bis 9, den Bindestrich (-) und den Unterstrich (_) enthalten
usersgroupsroles.users.form.errors.primary_email.empty=Die prim\u00e4re E-Mail-Addresse eines Benutzers darf nicht leer sein.
usersgroupsroles.users.form.errors.primary_email.invalid=Die prim\u00e4re E-Mail-Addresse eines Benutzers muss eine valide E-Mail-Addresse sein