Bugfixes users administration

Former-commit-id: 3fc63650cc
pull/7/head
Jens Pelzetter 2020-09-30 21:06:47 +02:00
parent be2e61de81
commit 06bba15fef
10 changed files with 243 additions and 49 deletions

View File

@ -22,7 +22,9 @@ import org.libreccm.core.EmailAddress;
import org.libreccm.security.Group; import org.libreccm.security.Group;
import org.libreccm.security.GroupMembership; import org.libreccm.security.GroupMembership;
import org.libreccm.security.GroupRepository; import org.libreccm.security.GroupRepository;
import org.libreccm.security.Role;
import org.libreccm.security.RoleMembership; import org.libreccm.security.RoleMembership;
import org.libreccm.security.RoleRepository;
import org.libreccm.security.User; import org.libreccm.security.User;
import org.libreccm.ui.Message; import org.libreccm.ui.Message;
@ -48,6 +50,9 @@ public class UserDetailsModel {
@Inject @Inject
private GroupRepository groupRepository; private GroupRepository groupRepository;
@Inject
private RoleRepository roleRepository;
private long userId; private long userId;
private String uuid; private String uuid;
@ -167,6 +172,14 @@ public class UserDetailsModel {
return Collections.unmodifiableList(roles); return Collections.unmodifiableList(roles);
} }
public List<UserRolesFormEntry> getUserRolesFormEntries() {
return roleRepository
.findAll()
.stream()
.map(this::buildUserRolesFormEntry)
.collect(Collectors.toList());
}
public boolean isNewUser() { public boolean isNewUser() {
return userId == 0; return userId == 0;
} }
@ -185,4 +198,19 @@ public class UserDetailsModel {
); );
return entry; return entry;
} }
private UserRolesFormEntry buildUserRolesFormEntry(final Role role) {
final UserRolesFormEntry entry = new UserRolesFormEntry();
entry.setRoleId(role.getRoleId());
entry.setRoleName(role.getName());
entry.setRoleUuid(role.getUuid());
entry.setMember(
roles
.stream()
.anyMatch(
membership -> membership.getRoleUuid().equals(role.getUuid())
)
);
return entry;
}
} }

View File

@ -229,4 +229,26 @@ public class UserFormController {
); );
} }
@POST
@Path("{userIdentifier}/roles")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String updateRoleMemberships(
@PathParam("userIdentifier") final String userIdentifierParam,
@FormParam("userRoles") final String[] userRoles
) {
// ToDo
return String.format(
"redirect:%s",
mvc.uri(
String.format(
"UsersController#getUserDetails",
"{userIdentifier: %s}",
userIdentifierParam
)
)
);
}
} }

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2020 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.ui.admin.usersgroupsroles;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class UserRolesFormEntry {
private long roleId;
private String roleUuid;
private String roleName;
private boolean member;
public long getRoleId() {
return roleId;
}
public void setRoleId(final long roleId) {
this.roleId = roleId;
}
public String getRoleUuid() {
return roleUuid;
}
public void setRoleUuid(final String roleUuid) {
this.roleUuid = roleUuid;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(final String roleName) {
this.roleName = roleName;
}
public boolean isMember() {
return member;
}
public void setMember(final boolean member) {
this.member = member;
}
}

View File

@ -142,6 +142,7 @@ public class UsersController {
@Path("/{userIdentifier}/edit") @Path("/{userIdentifier}/edit")
@AuthorizationRequired @AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String editUser( public String editUser(
@PathParam("userIdentifier") final String userIdentifierParam @PathParam("userIdentifier") final String userIdentifierParam
) { ) {

View File

@ -40,6 +40,7 @@ public class UsersGroupsRolesPage implements AdminPage {
classes.add(GroupsController.class); classes.add(GroupsController.class);
classes.add(RolesController.class); classes.add(RolesController.class);
classes.add(UsersController.class); classes.add(UsersController.class);
classes.add(UserFormController.class);
return classes; return classes;
} }

View File

@ -45,7 +45,7 @@
<dd>#{UserDetailsModel.givenName}</dd> <dd>#{UserDetailsModel.givenName}</dd>
</div> </div>
<div> <div>
<dt>#{AdminMessages['usergroupsroles.users.user_details.family name']}</dt> <dt>#{AdminMessages['usergroupsroles.users.user_details.family_name']}</dt>
<dd>#{UserDetailsModel.familyName}</dd> <dd>#{UserDetailsModel.familyName}</dd>
</div> </div>
<div> <div>
@ -118,7 +118,8 @@
</dd> </dd>
</div> </div>
</dl> </dl>
<a class="btn btn-primary" href="#"> <a class="btn btn-primary"
href="#{mvc.uri('UsersController#editUser', {'userIdentifier': UserDetailsModel.name })}">
<svg class="bi" <svg class="bi"
width="1em" width="1em"
height="1em" height="1em"
@ -222,7 +223,7 @@
id="confirm-remove-#{status.index}" id="confirm-remove-#{status.index}"
tabindex="-1"> tabindex="-1">
<div class="modal-dialog"> <div class="modal-dialog">
<form action="#{mvc.uri('UsersController#removeEmailAddress', { 'userIdentifier': user.name, 'emailId': status.index })}" <form action="#{mvc.uri('UsersController#removeEmailAddress', { 'userIdentifier': UserDetailsModel.name, 'emailId': status.index })}"
class="modal-content" class="modal-content"
method="post"> method="post">
<div class="modal-header"> <div class="modal-header">
@ -293,7 +294,7 @@
id="user-groups-dialog" id="user-groups-dialog"
tabindex="-1"> tabindex="-1">
<div class="modal-dialog"> <div class="modal-dialog">
<form action="" <form action="#{mvc.uri('UserFormController#updateGroupMemberships', {'userIdentifier': UserDetailsModel.name})}"
class="modal-content" class="modal-content"
method="post"> method="post">
<div class="modal-header"> <div class="modal-header">
@ -311,11 +312,18 @@
<div class="modal-body"> <div class="modal-body">
<c:forEach items="#{UserDetailsModel.userGroupsFormEntries}" <c:forEach items="#{UserDetailsModel.userGroupsFormEntries}"
var="entry"> var="entry">
<input checked="#{entry.member ? 'checked' : 'false'}" <div class="form-check form-check-inline">
<input class="form-check-input"
checked="#{entry.member ? 'checked' : ''}"
id="group-#{entry.groupName}" id="group-#{entry.groupName}"
name="userGroups[]" name="userGroups[]"
value="#{entry.groupName}" value="#{entry.groupName}"
type="checkbox" /> type="checkbox" />
<label class="form-check-label"
for="group-#{entry.groupName}">
#{entry.groupName}
</label>
</div>
</c:forEach> </c:forEach>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -355,7 +363,10 @@
<h2 class="mr-2"> <h2 class="mr-2">
#{AdminMessages['usergroupsroles.users.user_details.roles.heading']} #{AdminMessages['usergroupsroles.users.user_details.roles.heading']}
</h2> </h2>
<button class="btn btn-primary" type="button"> <button class="btn btn-primary"
data-toggle="modal"
data-target="#user-roles-dialog"
type="button">
<svg class="bi" <svg class="bi"
width="1em" width="1em"
height="1em" height="1em"
@ -364,6 +375,57 @@
</svg> </svg>
<span>#{AdminMessages['usergroupsroles.users.user_details.roles.edit']}</span> <span>#{AdminMessages['usergroupsroles.users.user_details.roles.edit']}</span>
</button> </button>
<div aria-labelledby="user-roles-dialog-title"
aria-hidden="true"
class="modal fade"
data-backdrop="static"
id="user-roles-dialog"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('UserFormController#updateRoleMemberships', {'userIdentifier': UserDetailsModel.name })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="model-title"
id="user-roles-dialog-title">
#{AdminMessages['usersgroupsroles.users.user_details.roles.dialog.title']}
</h3>
<button aria-label="#{AdminMessages['usersgroupsroles.users.user_details.roles.dialog.close']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<c:forEach items="#{UserDetailsModel.userRolesFormEntries}"
var="entry">
<div class="form-check form-check-inline">
<input class="form-check-input"
checked="#{entry.member ? 'checked' : ''}"
id="role-#{entry.roleName}"
name="userRoles[]"
value="#{entry.roleName}"
type="checkbox" />
<label for="role#{entry.roleName}">
#{entry.roleName}
</label>
</div>
</c:forEach>
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{AdminMessages['usersgroupsroles.users.user_details.roles.dialog.close']}
</button>
<button type="submit" class="btn btn-primary">
#{AdminMessages['usersgroupsroles.users.user_details.groups.dialog.save']}
</button>
</div>
</form>
</div>
</div>
</div> </div>
<c:choose> <c:choose>

View File

@ -7,7 +7,7 @@
<ui:param name="activePage" value="usersgroupsroles" /> <ui:param name="activePage" value="usersgroupsroles" />
<ui:param name="activePanel" value="users" /> <ui:param name="activePanel" value="users" />
<ui:param name="title" <ui:param name="title"
value="#{UserDetailsModel.newUser ? AdminMessages.getMessage('usersgroupsroles.users.edit.title', [UserDetailsModel.name]) : AdminMessages['usersgroupsroles.users.create.title']}" /> value="#{UserDetailsModel.newUser ? AdminMessages['usersgroupsroles.users.create.title'] : AdminMessages.getMessage('usersgroupsroles.users.edit.title', [UserDetailsModel.name]) }" />
<ui:define name="breadcrumb"> <ui:define name="breadcrumb">
<li class="breadcrumb-item"> <li class="breadcrumb-item">
@ -37,7 +37,7 @@
#{error} #{error}
</div> </div>
</c:forEach> </c:forEach>
<form action="#{UserDetailsModel.newUser ? mvc.uri("UserFormController#createUser") : mvc.uri('UserFormController#updateUser')}" <form action="#{UserDetailsModel.newUser ? mvc.uri('UserFormController#createUser') : mvc.uri('UserFormController#updateUser', { 'userIdentifier': UserDetailsModel.name })}"
method="post"> method="post">
<div class="form-group"> <div class="form-group">
<label for="username"> <label for="username">
@ -100,22 +100,23 @@
</small> </small>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" <input checked="#{UserDetailsModel.primaryEmailAddress.bouncing ? 'checked' : ''}"
class="form-check-input"
id="primary-email-address-bouncing" id="primary-email-address-bouncing"
name="primaryEmailAddressBouncing" name="primaryEmailAddressBouncing"
type="checkbox" type="checkbox" />
value="#{UserDetailsModel.primaryEmailAddress.bouncing}" />
<label for="primary-email-address-bouncing"> <label for="primary-email-address-bouncing">
#{AdminMessages['usersgroupsroles.users.form.primaryemailaddress.boucing.label']} #{AdminMessages['usersgroupsroles.users.form.primaryemailaddress.boucing.label']}
</label> </label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" <input checked="#{UserDetailsModel.primaryEmailAddress.verified ? 'checked' : ''}"
class="form-check-input"
id="primary-email-address-verified" id="primary-email-address-verified"
name="primaryEmailAddressVerified" name="primaryEmailAddressVerified"
type="checkbox" type="checkbox"
value="#{UserDetailsModel.primaryEmailAddress.verified}" /> />
<label for="primary-email-address-bouncing"> <label for="primary-email-address-verified">
#{AdminMessages['usersgroupsroles.users.form.primaryemailaddress.verified.label']} #{AdminMessages['usersgroupsroles.users.form.primaryemailaddress.verified.label']}
</label> </label>
</div> </div>
@ -128,7 +129,7 @@
class="form-control" class="form-control"
id="password" id="password"
name="password" name="password"
type="text" /> type="password" />
<small class="form-text text-muted" <small class="form-text text-muted"
id="password-help"> id="password-help">
#{AdminMessages['usersgroupsroles.users.form.password.help']} #{AdminMessages['usersgroupsroles.users.form.password.help']}
@ -142,7 +143,7 @@
class="form-control" class="form-control"
id="password-confirmation" id="password-confirmation"
name="passwordConfirmation" name="passwordConfirmation"
type="text" /> type="password" />
<small class="form-text text-muted" <small class="form-text text-muted"
id="password-help"> id="password-help">
#{AdminMessages['usersgroupsroles.users.form.passwordconfirmation.help']} #{AdminMessages['usersgroupsroles.users.form.passwordconfirmation.help']}
@ -150,21 +151,21 @@
</div> </div>
</c:if> </c:if>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" <input checked="#{UserDetailsModel.banned ? 'checked' : ''}"
class="form-check-input"
id="banned" id="banned"
name="banned" name="banned"
type="checkbox" type="checkbox" />
value="#{UserDetailsModel.banned}" />
<label for="banned"> <label for="banned">
#{AdminMessages['usersgroupsroles.users.form.banned.label']} #{AdminMessages['usersgroupsroles.users.form.banned.label']}
</label> </label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" <input checked="#{UserDetailsModel.passwordResetRequired ? 'checked' : ''}"
class="form-check-input"
id="password-reset-required" id="password-reset-required"
name="passwordResetRequired" name="passwordResetRequired"
type="checkbox" type="checkbox" />
value="#{UserDetailsModel.passwordResetRequired}" />
<label for="password-reset-required"> <label for="password-reset-required">
#{AdminMessages['usersgroupsroles.users.form.passwordresetrequired.label']} #{AdminMessages['usersgroupsroles.users.form.passwordresetrequired.label']}
</label> </label>
@ -185,6 +186,7 @@
</button> </button>
</form> </form>
</ui:define> </ui:define>
</ui:composition>
</html> </html>

View File

@ -43,7 +43,8 @@
</form> </form>
</div> </div>
<div class="col-sm-3 text-right"> <div class="col-sm-3 text-right">
<a class="btn btn-secondary" href="#"> <a class="btn btn-secondary"
href="#{mvc.uri('UsersController#newUser')}">
<svg class="bi" <svg class="bi"
width="1em" width="1em"
height="1em" height="1em"

View File

@ -124,3 +124,7 @@ usergroupsroles.users.user_details.additional_email_addresses.add=Add email addr
usergroupsroles.users.user_details.groups.dialog.title=Edit group memberships usergroupsroles.users.user_details.groups.dialog.title=Edit group memberships
usergroupsroles.users.user_details.groups.dialog.close=Cancel usergroupsroles.users.user_details.groups.dialog.close=Cancel
usergroupsroles.users.user_details.groups.dialog.save=Save usergroupsroles.users.user_details.groups.dialog.save=Save
usersgroupsroles.users.user_details.roles.dialog.title=Edit role memberships
usersgroupsroles.users.user_details.roles.dialog.close=Cancel
usersgroupsroles.users.user_details.groups.dialog.save=Save
usergroupsroles.users.user_details.family_name=Family Name

View File

@ -52,8 +52,8 @@ usergroupsroles.users.user_details.disabled.no=Nein
usergroupsroles.users.user_details.password_reset_required=Neues Password erforderlich? usergroupsroles.users.user_details.password_reset_required=Neues Password erforderlich?
usergroupsroles.users.user_details.password_reset_required.yes=Ja usergroupsroles.users.user_details.password_reset_required.yes=Ja
usergroupsroles.users.user_details.password_reset_required.no=Nein usergroupsroles.users.user_details.password_reset_required.no=Nein
usergroupsroles.users.user_details.additional_email_addresses.heading=Weitere E-Mail-Addressen usergroupsroles.users.user_details.additional_email_addresses.heading=Weitere E-Mail-Adressen
'usergroupsroles.users.user_details.additional_email_addresses.cols.address=Addresse 'usergroupsroles.users.user_details.additional_email_addresses.cols.address=Adresse
usergroupsroles.users.user_details.additional_email_addresses.cols.boucing=Wird zur\u00fcckgewiesen? usergroupsroles.users.user_details.additional_email_addresses.cols.boucing=Wird zur\u00fcckgewiesen?
usergroupsroles.users.user_details.additional_email_addresses.cols.verified=Verifizizert usergroupsroles.users.user_details.additional_email_addresses.cols.verified=Verifizizert
usergroupsroles.users.user_details.additional_email_addresses.cols.actions=Aktionen usergroupsroles.users.user_details.additional_email_addresses.cols.actions=Aktionen
@ -79,10 +79,10 @@ usersgroupsroles.users.form.givenname.label=Vorname
usersgroupsroles.users.form.givenname.help=Vorname des/der Benutzer*in usersgroupsroles.users.form.givenname.help=Vorname des/der Benutzer*in
usersgroupsroles.users.form.familyname.label=Familienname usersgroupsroles.users.form.familyname.label=Familienname
usersgroupsroles.users.form.familyname.help=Familienname des/der Benutzer*in usersgroupsroles.users.form.familyname.help=Familienname des/der Benutzer*in
usersgroupsroles.users.form.primaryemailaddress.label=Prim\u00e4re E-Mail-Addresse usersgroupsroles.users.form.primaryemailaddress.label=Prim\u00e4re E-Mail-Adresse
usersgroupsroles.users.form.primaryemailaddress.help=Prim\u00e4re E-Mail Addresse des/der Benutzer*in usersgroupsroles.users.form.primaryemailaddress.help=Prim\u00e4re E-Mail Adresse des/der Benutzer*in
usersgroupsroles.users.form.primaryemailaddress.boucing.label=Werden Mails an die prim\u00e4re E-Mail-Addresse zur\u00fcckgewiesen? usersgroupsroles.users.form.primaryemailaddress.boucing.label=Werden Mails an die prim\u00e4re E-Mail-Adresse zur\u00fcckgewiesen?
usersgroupsroles.users.form.primaryemailaddress.verified.label=Ist die prim\u00e4re E-Mail-Addresse verifiziert? usersgroupsroles.users.form.primaryemailaddress.verified.label=Ist die prim\u00e4re E-Mail-Adresse verifiziert?
usersgroupsroles.users.form.password=Passwort usersgroupsroles.users.form.password=Passwort
usersgroupsroles.users.form.password.help=Passwort des neuen Benutzers usersgroupsroles.users.form.password.help=Passwort des neuen Benutzers
usersgroupsroles.users.form.passwordconfirmation=Passwort-Best\u00e4tigung usersgroupsroles.users.form.passwordconfirmation=Passwort-Best\u00e4tigung
@ -93,16 +93,16 @@ usersgroupsroles.users.form.buttons.cancel=Abbrechen
usersgroupsroles.users.form.buttons.create=Benutzer*in neu anlegen usersgroupsroles.users.form.buttons.create=Benutzer*in neu anlegen
usersgroupsroles.users.form.buttons.save=Speichern usersgroupsroles.users.form.buttons.save=Speichern
usersgroupsroles.users.create.title=Neue(n) Benutzer*in anlegen usersgroupsroles.users.create.title=Neue(n) Benutzer*in anlegen
usersgroupsroles.users.email.not_found.title=E-Mail Addresse nicht gefunden usersgroupsroles.users.email.not_found.title=E-Mail Adresse nicht gefunden
usersgroupsroles.users.email.not_found.message=Benutzer*in {0} hat keine E-Mail-Addresse mit der ID {1}. usersgroupsroles.users.email.not_found.message=Benutzer*in {0} hat keine E-Mail-Adresse mit der ID {1}.
usersgroupsroles.users.breadcrumb.new=Benutzer*in anlegen usersgroupsroles.users.breadcrumb.new=Benutzer*in anlegen
usersgroupsroles.users.breadcrumb.edit=Benutzer*in bearbeiten usersgroupsroles.users.breadcrumb.edit=Benutzer*in bearbeiten
usersgroupsroles.users.breadcrumbs.email.add=E-Mail-Addresse hinzuf\u00fcgen usersgroupsroles.users.breadcrumbs.email.add=E-Mail-Adresse hinzuf\u00fcgen
usersgroupsroles.users.breadcrumbs.email.edit=E-Mail-Addresse bearbeiten usersgroupsroles.users.breadcrumbs.email.edit=E-Mail-Adresse bearbeiten
usersgroupsroles.users.email.edit.title=E-Mail Addresse bearbeiten usersgroupsroles.users.email.edit.title=E-Mail Adresse bearbeiten
usersgroupsroles.users.email.add.title=E-Mail Addresse hinzuf\u00fcgen usersgroupsroles.users.email.add.title=E-Mail Adresse hinzuf\u00fcgen
usersgroupsroles.users.email.form.address.label=E-Mail-Addresse usersgroupsroles.users.email.form.address.label=E-Mail-Adresse
usersgroupsroles.users.email.form.address.help=Die E-Mail-Addresse usersgroupsroles.users.email.form.address.help=Die E-Mail-Adresse
usersgroupsroles.users.email.form.bouncing.label=Wird zur\u00fcckgewiesen? usersgroupsroles.users.email.form.bouncing.label=Wird zur\u00fcckgewiesen?
usersgroupsroles.users.email.form.verified.label=Verifiziert usersgroupsroles.users.email.form.verified.label=Verifiziert
usersgroupsroles.users.email.form.buttons.add=Hinzuf\u00fcgen usersgroupsroles.users.email.form.buttons.add=Hinzuf\u00fcgen
@ -111,16 +111,20 @@ usersgroupsroles.users.disable.confirm.title=Deaktivierung Benutzer*in best\u00e
usersgroupsroles.users.disable.confirm.cancel=Abbrechen usersgroupsroles.users.disable.confirm.cancel=Abbrechen
usersgroupsroles.users.disable.confirm.message=Sind Sie sicher das Sie den/die Benutzer*in {0} deaktivieren wollen? usersgroupsroles.users.disable.confirm.message=Sind Sie sicher das Sie den/die Benutzer*in {0} deaktivieren wollen?
usersgroupsroles.users.disable.confirm.yes=Benutzer*in deaktivieren usersgroupsroles.users.disable.confirm.yes=Benutzer*in deaktivieren
usergroupsroles.users.user_details.email_addresses.remove.confirm.title=Entfernen E-Mail-Addresse best\u00e4tigen usergroupsroles.users.user_details.email_addresses.remove.confirm.title=Entfernen E-Mail-Adresse best\u00e4tigen
usergroupsroles.users.user_details.email_addresses.remove.confirm.cancel=Abbrechen usergroupsroles.users.user_details.email_addresses.remove.confirm.cancel=Abbrechen
usergroupsroles.users.user_details.email_addresses.remove.confirm.message=Sind Sie sicher, dass Sie die E-Mail-Addresse {0} entfernen wollen? usergroupsroles.users.user_details.email_addresses.remove.confirm.message=Sind Sie sicher, dass Sie die E-Mail-Adresse {0} entfernen wollen?
usergroupsroles.users.user_details.email_addresses.remove.confirm.yes=E-Mail-Addresse entfernen usergroupsroles.users.user_details.email_addresses.remove.confirm.yes=E-Mail-Adresse entfernen
usergroupsroles.users.user_details.groups.none=Diese(r) Benutzer*in ist nicht Mitglied einer Gruppe usergroupsroles.users.user_details.groups.none=Diese(r) Benutzer*in ist nicht Mitglied einer Gruppe
usergroupsroles.users.user_details.groups.edit=Bearbeiten usergroupsroles.users.user_details.groups.edit=Bearbeiten
usergroupsroles.users.user_details.roles.edit=Bearbeiten usergroupsroles.users.user_details.roles.edit=Bearbeiten
usergroupsroles.users.user_details.roles.none=Dieser(m) Benutzer*in sind keine Rollen zugeordnet usergroupsroles.users.user_details.roles.none=Dieser(m) Benutzer*in sind keine Rollen zugeordnet
usergroupsroles.users.user_details.email_addresses.none=Diese(r) Benutzer*in hat keine weiteren E-Mail-Addressen usergroupsroles.users.user_details.email_addresses.none=Diese(r) Benutzer*in hat keine weiteren E-Mail-Adressen
usergroupsroles.users.user_details.additional_email_addresses.add=E-Mail-Addresse hinzuf\u00fcgen usergroupsroles.users.user_details.additional_email_addresses.add=E-Mail-Adresse hinzuf\u00fcgen
usergroupsroles.users.user_details.groups.dialog.title=Gruppenmitgliedschaften bearbeiten usergroupsroles.users.user_details.groups.dialog.title=Gruppenmitgliedschaften bearbeiten
usergroupsroles.users.user_details.groups.dialog.close=Abbrechen usergroupsroles.users.user_details.groups.dialog.close=Abbrechen
usergroupsroles.users.user_details.groups.dialog.save=Anwenden usergroupsroles.users.user_details.groups.dialog.save=Anwenden
usersgroupsroles.users.user_details.roles.dialog.title=Rollenmitgliedschaften bearbeiten
usersgroupsroles.users.user_details.roles.dialog.close=Abbrechen
usersgroupsroles.users.user_details.groups.dialog.save=Anwenden
usergroupsroles.users.user_details.family_name=Familienname