Forms for managing users (not tested yet!)

ccm-docs
Jens Pelzetter 2020-09-25 20:03:33 +02:00
parent 29a567f448
commit d2c296a84a
12 changed files with 1224 additions and 53 deletions

View File

@ -0,0 +1,281 @@
/*
* 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;
import org.libreccm.api.Identifier;
import org.libreccm.api.IdentifierParser;
import org.libreccm.core.CoreConstants;
import org.libreccm.core.EmailAddress;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege;
import org.libreccm.security.User;
import org.libreccm.security.UserRepository;
import org.libreccm.ui.Message;
import org.libreccm.ui.MessageType;
import org.libreccm.ui.admin.AdminMessages;
import java.util.Arrays;
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.MvcBinding;
import javax.transaction.Transactional;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Controller
@Path("/users-groups-roles/users/{userIdentifier}/email-addresses")
public class EmailFormController {
@Inject
private AdminMessages adminMessages;
@Inject
private EmailFormModel emailFormModel;
@Inject
private IdentifierParser identifierParser;
@Inject
private Models models;
@Inject
private UserDetailsModel userDetailsModel;
@Inject
private UserRepository userRepository;
@MvcBinding
@FormParam("address")
@NotBlank
@Email
private String address;
@FormParam("bouncing")
private boolean bouncing;
@FormParam("verified")
private boolean verified;
@GET
@Path("/new")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String getNewEmailAddressForm(
@PathParam("userIdentifier") final String userIdentifierParam
) {
return "org/libreccm/ui/admin/users-groups-roles/email-form.xhtml";
}
@POST
@Path("/new")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String addNewEmailAddress(
@PathParam("userIdentifier") final String userIdentifierParam
) {
final Identifier identifier = identifierParser.parseIdentifier(
userIdentifierParam
);
final Optional<User> result;
switch (identifier.getType()) {
case ID:
result = userRepository.findById(
Long.parseLong(identifier.getIdentifier())
);
break;
case UUID:
result = userRepository.findByUuid(
identifier.getIdentifier()
);
break;
default:
result = userRepository.findByName(identifier.getIdentifier());
break;
}
if (result.isPresent()) {
final User user = result.get();
final EmailAddress emailAddress = new EmailAddress();
emailAddress.setAddress(address);
emailAddress.setBouncing(bouncing);
emailAddress.setVerified(verified);
user.addEmailAddress(emailAddress);
userRepository.save(user);
return String.format(
"redirect:/users-groups-roles/users/%s/details",
user.getName()
);
} else {
userDetailsModel.addMessage(
new Message(
adminMessages.getMessage(
"usersgroupsroles.users.not_found.message",
Arrays.asList(userIdentifierParam)
),
MessageType.WARNING
)
);
return "org/libreccm/ui/admin/users-groups-roles/user-not-found.xhtml";
}
}
@GET
@Path("/{emailId}")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String getEditEmailAddressForm(
@PathParam("userIdentifier") final String userIdentifierParam,
@PathParam("emailId") final int emailId
) {
final Identifier identifier = identifierParser.parseIdentifier(
userIdentifierParam
);
final Optional<User> result;
switch (identifier.getType()) {
case ID:
result = userRepository.findById(
Long.parseLong(identifier.getIdentifier())
);
break;
case UUID:
result = userRepository.findByUuid(
identifier.getIdentifier()
);
break;
default:
result = userRepository.findByName(identifier.getIdentifier());
break;
}
if (result.isPresent()) {
final User user = result.get();
if (user.getEmailAddresses().size() <= emailId) {
models.put("error.userIdentifier", userIdentifierParam);
models.put("error.emailId", emailId);
return "org/libreccm/ui/admin/users-groups-roles/email-not-found.xhtml";
} else {
final EmailAddress emailAddress = user
.getEmailAddresses()
.get(emailId);
emailFormModel.setAddress(emailAddress.getAddress());
emailFormModel.setBouncing(emailAddress.isBouncing());
emailFormModel.setVerified(emailAddress.isVerified());
return "org/libreccm/ui/admin/users-groups-roles/email-form.xhtml";
}
} else {
userDetailsModel.addMessage(
new Message(
adminMessages.getMessage(
"usersgroupsroles.users.not_found.message",
Arrays.asList(userIdentifierParam)
),
MessageType.WARNING
)
);
return "org/libreccm/ui/admin/users-groups-roles/user-not-found.xhtml";
}
}
@POST
@Path("/{emailId}")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String updateEmailAddress(
@PathParam("userIdentifier") final String userIdentifierParam,
@PathParam("emailId") final int emailId
) {
final Identifier identifier = identifierParser.parseIdentifier(
userIdentifierParam
);
final Optional<User> result;
switch (identifier.getType()) {
case ID:
result = userRepository.findById(
Long.parseLong(identifier.getIdentifier())
);
break;
case UUID:
result = userRepository.findByUuid(
identifier.getIdentifier()
);
break;
default:
result = userRepository.findByName(identifier.getIdentifier());
break;
}
if (result.isPresent()) {
final User user = result.get();
if (user.getEmailAddresses().size() <= emailId) {
models.put("error.userIdentifier", userIdentifierParam);
models.put("error.emailId", emailId);
return "org/libreccm/ui/admin/users-groups-roles/email-not-found.xhtml";
} else {
final EmailAddress emailAddress = user
.getEmailAddresses()
.get(emailId);
emailAddress.setAddress(address);
emailAddress.setBouncing(bouncing);
emailAddress.setVerified(verified);
userRepository.save(user);
return "org/libreccm/ui/admin/users-groups-roles/email-form.xhtml";
}
} else {
userDetailsModel.addMessage(
new Message(
adminMessages.getMessage(
"usersgroupsroles.users.not_found.message",
Arrays.asList(userIdentifierParam)
),
MessageType.WARNING
)
);
return "org/libreccm/ui/admin/users-groups-roles/user-not-found.xhtml";
}
}
}

View File

@ -0,0 +1,76 @@
/*
* 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;
import org.libreccm.core.EmailAddress;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named("EmailFormModel")
public class EmailFormModel {
private String address;
private boolean bouncing;
private boolean verified;
public void setEmailAddress(final EmailAddress emailAddress) {
address = emailAddress.getAddress();
bouncing = emailAddress.isBouncing();
verified = emailAddress.isVerified();
}
public boolean isNew() {
return address == null;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public boolean isBouncing() {
return bouncing;
}
public void setBouncing(boolean bouncing) {
this.bouncing = bouncing;
}
public boolean isVerified() {
return verified;
}
public void setVerified(boolean verified) {
this.verified = verified;
}
}

View File

@ -58,7 +58,7 @@ public class UserDetailsModel {
private boolean banned; private boolean banned;
private boolean passwordResetRequired; private boolean passwordResetRequired = true;
private List<UserGroupMembership> groupMemberships; private List<UserGroupMembership> groupMemberships;
@ -153,4 +153,7 @@ public class UserDetailsModel {
return Collections.unmodifiableList(roles); return Collections.unmodifiableList(roles);
} }
public boolean isNewUser() {
return userId == 0;
}
} }

View File

@ -0,0 +1,207 @@
/*
* 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;
import org.libreccm.api.Identifier;
import org.libreccm.api.IdentifierParser;
import org.libreccm.core.CoreConstants;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege;
import org.libreccm.security.User;
import org.libreccm.security.UserManager;
import org.libreccm.security.UserRepository;
import org.libreccm.ui.admin.AdminMessages;
import java.util.Arrays;
import java.util.Objects;
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.Email;
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;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Controller
@Path("/users-groups-roles/users/")
@RequestScoped
public class UserFormController {
@Inject
private AdminMessages adminMessages;
@Inject
private BindingResult bindingResult;
@Inject
private IdentifierParser identifierParser;
@Inject
private Models models;
@Inject
private UserManager userManager;
@Inject
private UserRepository userRepository;
@MvcBinding
@FormParam("userName")
@NotBlank
private String userName;
@FormParam("givenName")
private String givenName;
@FormParam("familyName")
private String familyName;
@MvcBinding
@FormParam("primaryEmailAddress")
@NotBlank
@Email
private String primaryEmailAddress;
@FormParam("primaryEmailAddressBouncing")
private boolean primaryEmailAddressBouncing;
@FormParam("primaryEmailAddressVerified")
private boolean primaryEmailAddressVerified;
@FormParam("banned")
private boolean banned;
@FormParam("passwordResetRequired")
private boolean passwordResetRequired;
@FormParam("password")
private String password;
@FormParam("passwordConfirmation")
private String passwordConfirmation;
@POST
@Path("/new")
@AuthorizationRequired
@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";
}
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";
}
if (!Objects.equals(password, passwordConfirmation)) {
models.put("errors", Arrays.asList(
adminMessages.get(
"usersgroupsroles.users.new.errors.password.no_match")
));
return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
}
userManager.createUser(
givenName, familyName, userName, primaryEmailAddress, password
);
return "redirect:users-groups-roles/users";
}
@POST
@Path("{userIdentifier}/edit")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
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
);
final Optional<User> result;
switch (identifier.getType()) {
case ID:
result = userRepository.findById(
Long.parseLong(identifier.getIdentifier())
);
break;
case UUID:
result = userRepository.findByUuid(
identifier.getIdentifier()
);
break;
default:
result = userRepository.findByName(identifier.getIdentifier());
break;
}
if (result.isPresent()) {
final User user = result.get();
user.setUuid(userName);
user.setGivenName(givenName);
user.setFamilyName(familyName);
user.getPrimaryEmailAddress().setAddress(primaryEmailAddress);
user
.getPrimaryEmailAddress()
.setBouncing(primaryEmailAddressBouncing);
user
.getPrimaryEmailAddress()
.setBouncing(primaryEmailAddressVerified);
user.setBanned(banned);
user.setPasswordResetRequired(passwordResetRequired);
userRepository.save(user);
return "redirect:users-groups-roles/users";
} else {
models.put("errors", Arrays.asList(
adminMessages.getMessage(
"usersgroupsroles.users.not_found.message",
Arrays.asList(userIdentifierParam)
)
));
return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
}
}
}

View File

@ -35,8 +35,10 @@ import java.util.Optional;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.mvc.Controller; import javax.mvc.Controller;
import javax.mvc.MvcContext;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import javax.ws.rs.DefaultValue; import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
@ -58,6 +60,9 @@ public class UsersController {
@Inject @Inject
private IdentifierParser identifierParser; private IdentifierParser identifierParser;
@Inject
private MvcContext mvc;
@Inject @Inject
private UserDetailsModel userDetailsModel; private UserDetailsModel userDetailsModel;
@ -123,81 +128,189 @@ public class UsersController {
} }
} }
@POST @GET
@Path("/{userIdentifier}/create") @Path("/new")
@AuthorizationRequired @AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public String createUser( public String newUser(
@PathParam("userIdentifier") final String userIdentifier @PathParam("userIdentifier") final String userIdentifier
) { ) {
return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
throw new UnsupportedOperationException();
} }
@GET @GET
@Path("/users/{userIdentifier}/edit") @Path("/{userIdentifier}/edit")
@AuthorizationRequired @AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public String editUser( public String editUser(
@PathParam("userIdentifier") final String userIdentifier @PathParam("userIdentifier") final String userIdentifierParam
) { ) {
final Identifier identifier = identifierParser.parseIdentifier(
userIdentifierParam
);
final Optional<User> result;
switch (identifier.getType()) {
case ID:
result = userRepository.findById(
Long.parseLong(identifier.getIdentifier())
);
break;
case UUID:
result = userRepository.findByUuid(
identifier.getIdentifier()
);
break;
default:
result = userRepository.findByName(identifier.getIdentifier());
break;
}
throw new UnsupportedOperationException(); if (result.isPresent()) {
userDetailsModel.setUser(result.get());
return "org/libreccm/ui/admin/users-groups-roles/user-form.xhtml";
} else {
userDetailsModel.addMessage(
new Message(
adminMessages.getMessage(
"usersgroupsroles.users.not_found.message",
Arrays.asList(userIdentifierParam)
),
MessageType.WARNING
)
);
return "org/libreccm/ui/admin/users-groups-roles/user-not-found.xhtml";
}
} }
@POST @POST
@Path("/users/{userIdentifier}/edit") @Path("/{userIdentifier}/disable")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public String updateUser(
@PathParam("userIdentifier") final String userIdentifier
) {
throw new UnsupportedOperationException();
}
@POST
@Path("/users/{userIdentifier}/disable")
@AuthorizationRequired @AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public String disableUser( public String disableUser(
@PathParam("userIdentifier") final String userIdentifier @PathParam("userIdentifier") final String userIdentifierParam,
@FormParam("confirmed") final boolean confirmed
) { ) {
final Identifier identifier = identifierParser.parseIdentifier(
throw new UnsupportedOperationException(); userIdentifierParam
);
final Optional<User> result;
switch (identifier.getType()) {
case ID:
result = userRepository.findById(
Long.parseLong(identifier.getIdentifier())
);
break;
case UUID:
result = userRepository.findByUuid(
identifier.getIdentifier()
);
break;
default:
result = userRepository.findByName(identifier.getIdentifier());
break;
} }
@GET if (result.isPresent()) {
@Path("/{userIdentifier}/emailaddresses") final User user = result.get();
@AuthorizationRequired user.setBanned(true);
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) userRepository.save(user);
public String getEmailAddressesOfUser( return String.format(
@PathParam("userIdentifier") final String userIdentifier "redirect:%s", mvc.uri("UsersController#getUsers")
) { );
} else {
throw new UnsupportedOperationException(); userDetailsModel.addMessage(
new Message(
adminMessages.getMessage(
"usersgroupsroles.users.not_found.message",
Arrays.asList(userIdentifierParam)
),
MessageType.WARNING
)
);
return "org/libreccm/ui/admin/users-groups-roles/user-not-found.xhtml";
}
} }
@POST @POST
@Path("/{userIdentifier}/emailaddresses/{address}/add") @Path("/{userIdentifier}/email-addresses/{emailId}/remove")
@AuthorizationRequired @AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public String addEmailAddresses( public String removeEmailAddress(
@PathParam("userIdentifier") final String userIdentifier, @PathParam("userIdentifier") final String userIdentifierParam,
@PathParam("address") final String addressToAdd @PathParam("emailId") final int emailId,
@FormParam("confirmed") final boolean confirmed
) { ) {
throw new UnsupportedOperationException(); if (!confirmed) {
return String.format(
"redirect:%s",
mvc.uri(
String.format(
"UsersController#getUserDetails",
"{ userIdentifier: %s}",
userIdentifierParam
)
)
);
} }
@POST final Identifier identifier = identifierParser.parseIdentifier(
@Path("/{userIdentifier}/emailaddresses/{address}/remove") userIdentifierParam
@AuthorizationRequired );
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) final Optional<User> result;
public String removeEmailAddresses( switch (identifier.getType()) {
@PathParam("userIdentifier") final String userIdentifier, case ID:
@PathParam("address") final String addressToRemove result = userRepository.findById(
) { Long.parseLong(identifier.getIdentifier())
throw new UnsupportedOperationException(); );
break;
case UUID:
result = userRepository.findByUuid(
identifier.getIdentifier()
);
break;
default:
result = userRepository.findByName(identifier.getIdentifier());
break;
}
if (result.isPresent()) {
final User user = result.get();
if (user.getEmailAddresses().size() <= emailId) {
return String.format(
"redirect:%s",
mvc.uri(
String.format(
"UsersController#getUserDetails",
"{ userIdentifier: %s}",
userIdentifierParam
)
)
);
}
user.getEmailAddresses().remove(emailId);
userRepository.save(user);
return String.format(
"redirect:%s",
mvc.uri(
String.format(
"UsersController#getUserDetails",
"{ userIdentifier: %s}",
userIdentifierParam
)
)
);
} else {
userDetailsModel.addMessage(
new Message(
adminMessages.getMessage(
"usersgroupsroles.users.not_found.message",
Arrays.asList(userIdentifierParam)
),
MessageType.WARNING
)
);
return "org/libreccm/ui/admin/users-groups-roles/user-not-found.xhtml";
}
} }
} }

View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/users-groups-roles.xhtml">
<ui:param name="activePage" value="usersgroupsroles" />
<ui:param name="activePanel" value="users" />
<ui:param name="title"
value="#{EmailFormModel.new ? AdminMessages.getMessage('usersgroupsroles.users.email.edit.title', [UserDetailsModel.name]) : AdminMessages['usersgroupsroles.users.email.add.title']}" />
<ui:define name="breadcrumb">
<li class="breadcrumb-item">
<a href="#{mvc.uri('UsersGroupsRolesController#getOverview')}">
#{AdminMessages['usersgroupsroles.label']}
</a>
</li>
<li class="breadcrumb-item">
<a href="#{mvc.uri('UsersController#getUsers')}">
#{AdminMessages['usersgroupsroles.users.label']}
</a>
</li>
<li class="breadcrumb-item">
<a href="#{mvn.uri('UsersController#getUserDetails', { 'userIdentfier': user.name })}">
#{UserDetailsModel.name}
</a>
</li>
<li class=breadcrumb-item active">
#{EmailFormModel.new ? AdminMessages['usersgroupsroles.users.breadcrumbs.email.add'] : AdminMessages['usersgroupsroles.users.breadcrumbs.email.edit']}
</li>
</ui:define>
<ui:define name="panel">
<c:forEach items="#{errors}" var="error">
<div class="alert alert-danger" role="alert">
#{error}
</div>
</c:forEach>
<form action="#{EmailFormModel.new ? mvc.uri('EmailFormController#addNewEmailAddress') : mvc.uri('EmailFormController#updateEmailAddress')}"
method="post">
<div class="form-group">
<label for="address">
#{AdminMessages['usersgroupsroles.users.email.form.address.label']}
</label>
<input aria-described-by="address-help"
class="form-control"
id="address"
name="address"
value="#{EmailFormModel.address}"
type="email" />
<small class="form-text text-muted"
id="address-help">
#{AdminMessages['usersgroupsroles.users.email.form.address.help']}
</small>
</div>
<div class="form-check">
<input class="form-check-input"
id="bouncing"
name="bouncing"
type="checkbox"
value="#{EmailFormModel.bouncing}" />
<label for="bouncing">
#{AdminMessages['usersgroupsroles.users.email.form.bouncing.label']}
</label>
</div>
<div class="form-check">
<input class="form-check-input"
id="verified"
name="verified"
type="checkbox"
value="#{EmailFormModel.verified}" />
<label for="verified">
#{AdminMessages['usersgroupsroles.users.email.form.verified.label']}
</label>
</div>
<button class="btn btn-success" type="submit">
<c:choose>
<c:when test="#{EmailFormModel.new}">
#{AdminMessages['usersgroupsroles.users.email.form.buttons.add']}
</c:when>
<c:otherwise>
#{AdminMessages['usersgroupsroles.users.email.form.buttons.save']}
</c:otherwise>
</c:choose>
</button>
</form>
</ui:define>
</ui:composition>
</html>

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/users-groups-roles.xhtml">
<ui:param name="activePage" value="usersgroupsroles" />
<ui:param name="activePanel" value="users" />
<ui:param name="title"
value="#{AdminMessages('usersgroupsroles.users.email.not_found.title')}" />
<ui:define name="breadcrumb">
<li class="breadcrumb-item">
<a href="#{mvc.uri('UsersGroupsRolesController#getOverview')}">
#{AdminMessages['usersgroupsroles.label']}
</a>
</li>
<li class="breadcrumb-item">
<a href="#{mvc.uri('UsersController#getUsers')}">
#{AdminMessages['usersgroupsroles.users.label']}
</a>
</li>
<li class="breadcrumb-item">
#{AdminMessages['usersgroupsroles.users.email.not_found.title']}
</li>
</ui:define>
<ui:define name="panel">
<div class="alert alert-danger" role="alert">
#{AdminMessages.getMessage('usersgroupsroles.users.email.not_found.message', [models['errors.userIdentifier'], models['errors.emailId']])}
</div>
</ui:define>
</ui:composition>
</html>

View File

@ -161,7 +161,8 @@
</th> </th>
</tr> </tr>
<c:forEach items="#{UserDetailsModel.emailAddresses}" <c:forEach items="#{UserDetailsModel.emailAddresses}"
var="address"> var="address"
varStatus="status">
<tr> <tr>
<td> <td>
#{address.address} #{address.address}
@ -200,7 +201,9 @@
</a> </a>
</td> </td>
<td> <td>
<a class="btn btn-danger" href="#"> <button class="btn btn-danger"
data-toggle="modal"
data-target="#confirm-remove-#{status.index}">
<svg class="bi" <svg class="bi"
width="1em" width="1em"
height="1em" height="1em"
@ -210,7 +213,46 @@
<span> <span>
#{AdminMessages['usergroupsroles.users.user_details.email_addresses.remove']} #{AdminMessages['usergroupsroles.users.user_details.email_addresses.remove']}
</span> </span>
</a> </button>
<div class="modal"
id="confirm-remove-#{status.index}"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('UsersController#removeEmailAddress', { 'userIdentifier': user.name, 'emailId': status.index })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-title">
#{AdminMessages['usergroupsroles.users.user_details.email_addresses.remove.confirm.title']}
</h3>
<button aria-label="#{AdminMessages['usergroupsroles.users.user_details.email_addresses.remove.confirm.cancel']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
#{AdminMessages.getMessage('usergroupsroles.users.user_details.email_addresses.remove.confirm.message', [address.address])}
<input name="confirmed"
type="hidden"
value="true" />
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button">
#{'usergroupsroles.users.user_details.email_addresses.remove.confirm.cancel'}
</button>
<button class="btn btn-danger"
data-dismiss="modal"
type="submit">
#{'usergroupsroles.users.user_details.email_addresses.remove.confirm.yes'}
</button>
</div>
</form>
</div>
</div>
</td> </td>
</tr> </tr>
</c:forEach> </c:forEach>

View File

@ -0,0 +1,190 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/users-groups-roles.xhtml">
<ui:param name="activePage" value="usersgroupsroles" />
<ui:param name="activePanel" value="users" />
<ui:param name="title"
value="#{UserDetailsModel.newUser ? AdminMessages.getMessage('usersgroupsroles.users.edit.title', [UserDetailsModel.name]) : AdminMessages['usersgroupsroles.users.create.title']}" />
<ui:define name="breadcrumb">
<li class="breadcrumb-item">
<a href="#{mvc.uri('UsersGroupsRolesController#getOverview')}">
#{AdminMessages['usersgroupsroles.label']}
</a>
</li>
<li class="breadcrumb-item">
<a href="#{mvc.uri('UsersController#getUsers')}">
#{AdminMessages['usersgroupsroles.users.label']}
</a>
</li>
<li class="breadcrumb-item">
<a href="#{mvn.uri('UsersController#getUserDetails', { 'userIdentfier': user.name })}">
#{UserDetailsModel.name}
</a>
</li>
<li>
#{UserDetailsModel.newUser ? AdminMessages['usersgroupsroles.users.breadcrumb.new'] : AdminMessages['usersgroupsroles.users.breadcrumb.edit']}
</li>
</ui:define>
<ui:define name="panel">
<c:forEach items="#{errors}" var="error">
<div class="alert alert-danger" role="alert">
#{error}
</div>
</c:forEach>
<form action="#{UserDetailsModel.newUser ? mvc.uri("UserFormController#createUser") : mvc.uri('UserFormController#updateUser')}"
method="post">
<div class="form-group">
<label for="username">
#{AdminMessages['usersgroupsroles.users.form.username.label']}
</label>
<input aria-described-by="username-help"
class="form-control"
id="username"
name="userName"
value="#{UserDetailsModel.name}"
type="text" />
<small class="form-text text-muted"
id="username-help">
#{AdminMessages['usersgroupsroles.users.form.username.help']}
</small>
</div>
<div class="form-group">
<label for="givenname">
#{AdminMessages['usersgroupsroles.users.form.givenname.label']}
</label>
<input aria-described-by="givenname-help"
class="form-control"
id="givenname"
name="givenName"
value="#{UserDetailsModel.givenName}"
type="text" />
<small class="form-text text-muted"
id="givenname-help">
#{AdminMessages['usersgroupsroles.users.form.givenname.help']}
</small>
</div>
<div class="form-group">
<label for="familyname">
#{AdminMessages['usersgroupsroles.users.form.familyname.label']}
</label>
<input aria-described-by="familyname-help"
class="form-control"
id="familyname"
name="familyName"
value="#{UserDetailsModel.familyName}"
type="text" />
<small class="form-text text-muted"
id="familyname-help">
#{AdminMessages['usersgroupsroles.users.form.familyname.help']}
</small>
</div>
<div class="form-group">
<label for="primary-email-address">
#{AdminMessages['usersgroupsroles.users.form.primaryemailaddress.label']}
</label>
<input aria-described-by="primary-email-address-help"
class="form-control"
id="primary-email-address"
name="primaryEmailAddress"
value="#{UserDetailsModel.primaryEmailAddress.address}"
type="email" />
<small class="form-text text-muted"
id="primary-email-address-help">
#{AdminMessages['usersgroupsroles.users.form.primaryemailaddress.help']}
</small>
</div>
<div class="form-check">
<input class="form-check-input"
id="primary-email-address-bouncing"
name="primaryEmailAddressBouncing"
type="checkbox"
value="#{UserDetailsModel.primaryEmailAddress.bouncing}" />
<label for="primary-email-address-bouncing">
#{AdminMessages['usersgroupsroles.users.form.primaryemailaddress.boucing.label']}
</label>
</div>
<div class="form-check">
<input class="form-check-input"
id="primary-email-address-verified"
name="primaryEmailAddressVerified"
type="checkbox"
value="#{UserDetailsModel.primaryEmailAddress.verified}" />
<label for="primary-email-address-bouncing">
#{AdminMessages['usersgroupsroles.users.form.primaryemailaddress.verified.label']}
</label>
</div>
<c:if test="#{UserDetailsModel.newUser}">
<div class="form-group">
<label for="password">
#{AdminMessages['usersgroupsroles.users.form.password']}
</label>
<input aria-described-by="password-help"
class="form-control"
id="password"
name="password"
type="text" />
<small class="form-text text-muted"
id="password-help">
#{AdminMessages['usersgroupsroles.users.form.password.help']}
</small>
</div>
<div class="form-group">
<label for="password-confirmation">
#{AdminMessages['usersgroupsroles.users.form.passwordconfirmation']}
</label>
<input aria-described-by="password-confirmation-help"
class="form-control"
id="password-confirmation"
name="passwordConfirmation"
type="text" />
<small class="form-text text-muted"
id="password-help">
#{AdminMessages['usersgroupsroles.users.form.passwordconfirmation.help']}
</small>
</div>
</c:if>
<div class="form-check">
<input class="form-check-input"
id="banned"
name="banned"
type="checkbox"
value="#{UserDetailsModel.banned}" />
<label for="banned">
#{AdminMessages['usersgroupsroles.users.form.banned.label']}
</label>
</div>
<div class="form-check">
<input class="form-check-input"
id="password-reset-required"
name="passwordResetRequired"
type="checkbox"
value="#{UserDetailsModel.passwordResetRequired}" />
<label for="password-reset-required">
#{AdminMessages['usersgroupsroles.users.form.passwordresetrequired.label']}
</label>
</div>
<a class="btn btn-warning"
href="#{mvc.uri('UsersController#getUsers')}">
#{AdminMessages['usersgroupsroles.users.form.buttons.cancel']}
</a>
<button class="btn btn-success" type="submit">
<c:choose>
<c:when test="#{UserDetailsModel.newUser}">
#{AdminMessages['usersgroupsroles.users.form.buttons.create']}
</c:when>
<c:otherwise>
#{AdminMessages['usersgroupsroles.users.form.buttons.save']}
</c:otherwise>
</c:choose>
</button>
</form>
</ui:define>
</html>

View File

@ -92,7 +92,9 @@
</a> </a>
</td> </td>
<td class="text-center action-col"> <td class="text-center action-col">
<button class="btn btn-danger"> <button class="btn btn-danger"
data-toggle="modal"
data-target="#confirm-disable-#{user.name}">
<svg class="bi" <svg class="bi"
width="1em" width="1em"
height="1em" height="1em"
@ -103,6 +105,45 @@
#{AdminMessages['usersgroupsroles.users.disablebutton.label']} #{AdminMessages['usersgroupsroles.users.disablebutton.label']}
</span> </span>
</button> </button>
<div class="modal"
id="confirm-disable-#{user.name}"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('UsersController#disableUser', { 'userIdentifier': user.name })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-title">
#{AdminMessages['usersgroupsroles.users.disable.confirm.title']}
</h3>
<button aria-label="#{AdminMessages['usersgroupsroles.users.disable.confirm.cancel']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
#{AdminMessages.getMessage('usersgroupsroles.users.disable.confirm.message', [user.name])}
<input name="confirmed"
type="hidden"
value="true" />
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button">
#{'usersgroupsroles.users.disable.confirm.cancel'}
</button>
<button class="btn btn-danger"
data-dismiss="modal"
type="submit">
#{'usersgroupsroles.users.disable.confirm.yes'}
</button>
</div>
</form>
</div>
</div>
</td> </td>
</tr> </tr>
</c:forEach> </c:forEach>

View File

@ -70,3 +70,48 @@ usergroupsroles.users.user_details.roles.heading=Roles
usergroupsroles.users.user_details.roles.add=Add usergroupsroles.users.user_details.roles.add=Add
usergroupsroles.users.user_details.roles.remove=Remove usergroupsroles.users.user_details.roles.remove=Remove
usergroupsroles.users.user_details.edit_user=Edit usergroupsroles.users.user_details.edit_user=Edit
usersgroupsroles.users.new.errors.password.empty=Password of a new user can't be empty
usersgroupsroles.users.new.errors.password.no_match=Password and confirmation do not match
usersgroupsroles.users.edit.title=Edit user {0}
usersgroupsroles.users.form.username.label=User name
usersgroupsroles.users.form.username.help=Unique name of the user which can be used to login
usersgroupsroles.users.form.givenname.label=Given Name
usersgroupsroles.users.form.givenname.help=Given name of the user
usersgroupsroles.users.form.familyname.label=Family Name
usersgroupsroles.users.form.familyname.help=Family name of the user
usersgroupsroles.users.form.primaryemailaddress.label=Primary Email address
usersgroupsroles.users.form.primaryemailaddress.help=Primary email address of the user
usersgroupsroles.users.form.primaryemailaddress.boucing.label=Primary email address bouncing?
usersgroupsroles.users.form.primaryemailaddress.verified.label=Primary email address verified?
usersgroupsroles.users.form.password=Password
usersgroupsroles.users.form.password.help=Password of the new user
usersgroupsroles.users.form.passwordconfirmation=Password Confirmation
usersgroupsroles.users.form.passwordconfirmation.help=Confirm the password by repeating it
usersgroupsroles.users.form.banned.label=Disabled?
usersgroupsroles.users.form.passwordresetrequired.label=Password reset required
usersgroupsroles.users.form.buttons.cancel=Cancel
usersgroupsroles.users.form.buttons.create=Create new user
usersgroupsroles.users.form.buttons.save=Save
usersgroupsroles.users.create.title=Create new user
usersgroupsroles.users.email.not_found.title=Email address not found
usersgroupsroles.users.email.not_found.message=User {0} has no email address with ID {1}.
usersgroupsroles.users.breadcrumb.new=New User
usersgroupsroles.users.breadcrumb.edit=Edit user
usersgroupsroles.users.breadcrumbs.email.add=Add Email Address
usersgroupsroles.users.breadcrumbs.email.edit=Edit Email Address
usersgroupsroles.users.email.edit.title=Edit Email Address
usersgroupsroles.users.email.add.title=Add Email Address
usersgroupsroles.users.email.form.address.label=Email Address
usersgroupsroles.users.email.form.address.help=The Email Address
usersgroupsroles.users.email.form.bouncing.label=Bouncing?
usersgroupsroles.users.email.form.verified.label=Verified
usersgroupsroles.users.email.form.buttons.add=Add
usersgroupsroles.users.email.form.buttons.save=Save
usersgroupsroles.users.disable.confirm.title=Confirm to disable user
usersgroupsroles.users.disable.confirm.cancel=Cancel
usersgroupsroles.users.disable.confirm.message=Are you sure to disable user {0}
usersgroupsroles.users.disable.confirm.yes=Disable User
usergroupsroles.users.user_details.email_addresses.remove.confirm.title=Confirm Removal Of Email Address
usergroupsroles.users.user_details.email_addresses.remove.confirm.cancel=Cancel
usergroupsroles.users.user_details.email_addresses.remove.confirm.message=Are you sure to remove email address {0}?
usergroupsroles.users.user_details.email_addresses.remove.confirm.yes=Remove Email Address

View File

@ -70,3 +70,48 @@ usergroupsroles.users.user_details.roles.heading=Rollen
usergroupsroles.users.user_details.roles.add=Hinzuf\u00fcgen usergroupsroles.users.user_details.roles.add=Hinzuf\u00fcgen
usergroupsroles.users.user_details.roles.remove=Entfernen usergroupsroles.users.user_details.roles.remove=Entfernen
usergroupsroles.users.user_details.edit_user=Bearbeiten usergroupsroles.users.user_details.edit_user=Bearbeiten
usersgroupsroles.users.new.errors.password.empty=Das Passwort eines neuen Benutzers darf nicht leer sein.
usersgroupsroles.users.new.errors.password.no_match=Password und Best\u00e4tigung stimmen nicht \u00fcberein.
usersgroupsroles.users.edit.title=Benutzer*in {0} bearbeiten
usersgroupsroles.users.form.username.label=Login-Name
usersgroupsroles.users.form.username.help=Eindeutiger Name f\u00fcr den/die Benutzer*in
usersgroupsroles.users.form.givenname.label=Vorname
usersgroupsroles.users.form.givenname.help=Vorname des/der Benutzer*in
usersgroupsroles.users.form.familyname.label=Familienname
usersgroupsroles.users.form.familyname.help=Familienname des/der Benutzer*in
usersgroupsroles.users.form.primaryemailaddress.label=Prim\u00e4re E-Mail-Addresse
usersgroupsroles.users.form.primaryemailaddress.help=Prim\u00e4re E-Mail Addresse 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.verified.label=Ist die prim\u00e4re E-Mail-Addresse verifiziert?
usersgroupsroles.users.form.password=Passwort
usersgroupsroles.users.form.password.help=Passwort des neuen Benutzers
usersgroupsroles.users.form.passwordconfirmation=Passwort-Best\u00e4tigung
usersgroupsroles.users.form.passwordconfirmation.help=Wiederholen Sie das Passwort zur Best\u00e4tigung
usersgroupsroles.users.form.banned.label=Inaktiv?
usersgroupsroles.users.form.passwordresetrequired.label=Neues Passwort erforderlich?
usersgroupsroles.users.form.buttons.cancel=Abbrechen
usersgroupsroles.users.form.buttons.create=Benutzer*in neu anlegen
usersgroupsroles.users.form.buttons.save=Speichern
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.message=Benutzer*in {0} hat keine E-Mail-Addresse mit der ID {1}.
usersgroupsroles.users.breadcrumb.new=Benutzer*in anlegen
usersgroupsroles.users.breadcrumb.edit=Benutzer*in bearbeiten
usersgroupsroles.users.breadcrumbs.email.add=E-Mail-Addresse hinzuf\u00fcgen
usersgroupsroles.users.breadcrumbs.email.edit=E-Mail-Addresse bearbeiten
usersgroupsroles.users.email.edit.title=E-Mail Addresse bearbeiten
usersgroupsroles.users.email.add.title=E-Mail Addresse hinzuf\u00fcgen
usersgroupsroles.users.email.form.address.label=E-Mail-Addresse
usersgroupsroles.users.email.form.address.help=Die E-Mail-Addresse
usersgroupsroles.users.email.form.bouncing.label=Wird zur\u00fcckgewiesen?
usersgroupsroles.users.email.form.verified.label=Verifiziert
usersgroupsroles.users.email.form.buttons.add=Hinzuf\u00fcgen
usersgroupsroles.users.email.form.buttons.save=Speichern
usersgroupsroles.users.disable.confirm.title=Deaktivierung Benutzer*in best\u00e4tigen
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.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.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.yes=E-Mail-Addresse entfernen