CCM NG:
- User registration and password recover now work - Improvements for ChallengeManager - Groups and roles assigned to a user are now shown in in the user details view - Groups assigned to a user can be edited git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3981 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
49357d190a
commit
81fd867e31
|
|
@ -20,12 +20,12 @@ package com.arsdigita.ui.admin.usersgroupsroles;
|
||||||
|
|
||||||
import com.arsdigita.bebop.ActionLink;
|
import com.arsdigita.bebop.ActionLink;
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
import com.arsdigita.bebop.BoxPanel;
|
||||||
|
import com.arsdigita.bebop.ColumnPanel;
|
||||||
import com.arsdigita.bebop.Component;
|
import com.arsdigita.bebop.Component;
|
||||||
import com.arsdigita.bebop.ControlLink;
|
import com.arsdigita.bebop.ControlLink;
|
||||||
import com.arsdigita.bebop.Form;
|
import com.arsdigita.bebop.Form;
|
||||||
import com.arsdigita.bebop.FormData;
|
import com.arsdigita.bebop.FormData;
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
import com.arsdigita.bebop.FormSection;
|
|
||||||
import com.arsdigita.bebop.Label;
|
import com.arsdigita.bebop.Label;
|
||||||
import com.arsdigita.bebop.Page;
|
import com.arsdigita.bebop.Page;
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
|
|
@ -49,16 +49,30 @@ import com.arsdigita.bebop.table.TableCellRenderer;
|
||||||
import com.arsdigita.bebop.table.TableColumn;
|
import com.arsdigita.bebop.table.TableColumn;
|
||||||
import com.arsdigita.bebop.table.TableColumnModel;
|
import com.arsdigita.bebop.table.TableColumnModel;
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
import com.arsdigita.globalization.GlobalizedMessage;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
import org.libreccm.cdi.utils.CdiUtil;
|
||||||
import org.libreccm.core.EmailAddress;
|
import org.libreccm.core.EmailAddress;
|
||||||
import org.libreccm.security.ChallengeManager;
|
import org.libreccm.security.ChallengeManager;
|
||||||
|
import org.libreccm.security.Group;
|
||||||
|
import org.libreccm.security.GroupManager;
|
||||||
|
import org.libreccm.security.GroupRepository;
|
||||||
import org.libreccm.security.User;
|
import org.libreccm.security.User;
|
||||||
import org.libreccm.security.UserManager;
|
import org.libreccm.security.UserManager;
|
||||||
import org.libreccm.security.UserRepository;
|
import org.libreccm.security.UserRepository;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.TooManyListenersException;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
|
|
||||||
import static com.arsdigita.ui.admin.AdminUiConstants.*;
|
import static com.arsdigita.ui.admin.AdminUiConstants.*;
|
||||||
|
|
@ -86,6 +100,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
// private final UserDetails userDetails;
|
// private final UserDetails userDetails;
|
||||||
private final BoxPanel userDetails;
|
private final BoxPanel userDetails;
|
||||||
private final Form emailForm;
|
private final Form emailForm;
|
||||||
|
private final Form editGroupMembershipsForm;
|
||||||
private final Form newUserForm;
|
private final Form newUserForm;
|
||||||
|
|
||||||
public UserAdmin() {
|
public UserAdmin() {
|
||||||
|
|
@ -132,17 +147,6 @@ public class UserAdmin extends BoxPanel {
|
||||||
|
|
||||||
add(usersTablePanel);
|
add(usersTablePanel);
|
||||||
|
|
||||||
// final Text text = new Text();
|
|
||||||
// text.setPrintListener((final PrintEvent e) -> {
|
|
||||||
// final Text target = (Text) e.getTarget();
|
|
||||||
// final PageState state = e.getPageState();
|
|
||||||
// if (selectedUserId.isSelected(state)) {
|
|
||||||
// target.setText(selectedUserId.getSelectedKey(state));
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// add(text);
|
|
||||||
// userDetails = new UserDetails(this, selectedUserId);
|
|
||||||
// add(new UserDetails(this, selectedUserId));
|
|
||||||
userDetails = new BoxPanel();
|
userDetails = new BoxPanel();
|
||||||
userDetails.setIdAttr("userDetails");
|
userDetails.setIdAttr("userDetails");
|
||||||
|
|
||||||
|
|
@ -533,6 +537,71 @@ public class UserAdmin extends BoxPanel {
|
||||||
|
|
||||||
userDetails.add(emailTable);
|
userDetails.add(emailTable);
|
||||||
|
|
||||||
|
final Table groupsRolesTable = new Table();
|
||||||
|
groupsRolesTable.setModelBuilder(new UserGroupsRolesTableModelBuilder(
|
||||||
|
selectedUserId));
|
||||||
|
final TableColumnModel groupsRolesColModel = groupsRolesTable
|
||||||
|
.getColumnModel();
|
||||||
|
groupsRolesColModel.add(new TableColumn(
|
||||||
|
UserGroupsRolesTableModel.COL_LABEL));
|
||||||
|
groupsRolesColModel
|
||||||
|
.add(new TableColumn(UserGroupsRolesTableModel.COL_VALUE));
|
||||||
|
groupsRolesColModel.add(
|
||||||
|
new TableColumn(UserGroupsRolesTableModel.COL_ACTION));
|
||||||
|
groupsRolesColModel.get(UserGroupsRolesTableModel.COL_ACTION)
|
||||||
|
.setCellRenderer(new TableCellRenderer() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getComponent(final Table table,
|
||||||
|
final PageState state,
|
||||||
|
final Object value,
|
||||||
|
final boolean isSelected,
|
||||||
|
final Object key,
|
||||||
|
final int row,
|
||||||
|
final int column) {
|
||||||
|
switch (row) {
|
||||||
|
case UserGroupsRolesTableModel.ROW_GROUPS: {
|
||||||
|
return new ControlLink((Component) value);
|
||||||
|
}
|
||||||
|
case UserGroupsRolesTableModel.ROW_ROLES: {
|
||||||
|
return new ControlLink((Component) value);
|
||||||
|
}
|
||||||
|
case UserGroupsRolesTableModel.ROW_ALL_ROLES:
|
||||||
|
return new Text("");
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
groupsRolesTable.addTableActionListener(new TableActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cellSelected(final TableActionEvent event) {
|
||||||
|
final int selectedRow = Integer.parseInt((String) event
|
||||||
|
.getRowKey());
|
||||||
|
final PageState state = event.getPageState();
|
||||||
|
|
||||||
|
switch (selectedRow) {
|
||||||
|
case UserGroupsRolesTableModel.ROW_GROUPS:
|
||||||
|
showEditGroupMembershipsForm(state);
|
||||||
|
break;
|
||||||
|
case UserGroupsRolesTableModel.ROW_ROLES:
|
||||||
|
//ToDo
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void headSelected(final TableActionEvent event) {
|
||||||
|
//Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
userDetails.add(groupsRolesTable);
|
||||||
|
|
||||||
final ActionLink addEmailLink = new ActionLink(new GlobalizedMessage(
|
final ActionLink addEmailLink = new ActionLink(new GlobalizedMessage(
|
||||||
"ui.admin.user.email_addresses.add", ADMIN_BUNDLE));
|
"ui.admin.user.email_addresses.add", ADMIN_BUNDLE));
|
||||||
addEmailLink.addActionListener(e -> {
|
addEmailLink.addActionListener(e -> {
|
||||||
|
|
@ -541,9 +610,6 @@ public class UserAdmin extends BoxPanel {
|
||||||
userDetails.add(addEmailLink);
|
userDetails.add(addEmailLink);
|
||||||
|
|
||||||
emailForm = new Form("email_form");
|
emailForm = new Form("email_form");
|
||||||
// emailForm.add(new Label(new GlobalizedMessage(
|
|
||||||
// "ui.admin.user.email_form.address",
|
|
||||||
// ADMIN_BUNDLE)));
|
|
||||||
final TextField emailFormAddress = new TextField("email_form_address");
|
final TextField emailFormAddress = new TextField("email_form_address");
|
||||||
emailFormAddress.setLabel(new GlobalizedMessage(
|
emailFormAddress.setLabel(new GlobalizedMessage(
|
||||||
"ui.admin.user.email_form.address", ADMIN_BUNDLE));
|
"ui.admin.user.email_form.address", ADMIN_BUNDLE));
|
||||||
|
|
@ -668,11 +734,15 @@ public class UserAdmin extends BoxPanel {
|
||||||
|
|
||||||
add(userDetails);
|
add(userDetails);
|
||||||
|
|
||||||
|
editGroupMembershipsForm = buildEditGroupMembershipsForm();
|
||||||
|
add(editGroupMembershipsForm);
|
||||||
|
|
||||||
newUserForm = buildNewUserForm();
|
newUserForm = buildNewUserForm();
|
||||||
|
add(newUserForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBasicProperties() {
|
private void setBasicProperties() {
|
||||||
setIdAttr("userAdmin");
|
setIdAttr("userAdmin");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Form buildNewUserForm() {
|
private Form buildNewUserForm() {
|
||||||
|
|
@ -722,11 +792,24 @@ public class UserAdmin extends BoxPanel {
|
||||||
.addValidationListener(new StringLengthValidationListener(256));
|
.addValidationListener(new StringLengthValidationListener(256));
|
||||||
form.add(emailField);
|
form.add(emailField);
|
||||||
|
|
||||||
final FormSection setPasswordSection = new FormSection(new BoxPanel(
|
final String passwordOptions = "passwordOptions";
|
||||||
BoxPanel.VERTICAL));
|
final String optionSetPassword = "setPassword";
|
||||||
setPasswordSection.setLabel(new GlobalizedMessage(
|
final String optionSendPassword = "sendPassword";
|
||||||
"ui.admin.new_user_form.password_options.set_password.label",
|
final RadioGroup passwordOptionsGroup = new RadioGroup(passwordOptions);
|
||||||
ADMIN_BUNDLE));
|
final Option sendPasswordOption = new Option(
|
||||||
|
optionSendPassword,
|
||||||
|
new Label(new GlobalizedMessage(
|
||||||
|
"ui.admin.new_user_form.password_options.send_password.label",
|
||||||
|
ADMIN_BUNDLE)));
|
||||||
|
passwordOptionsGroup.addOption(sendPasswordOption);
|
||||||
|
final Option setPasswordOption = new Option(
|
||||||
|
optionSetPassword,
|
||||||
|
new Label(new GlobalizedMessage(
|
||||||
|
"ui.admin.new_user_form.password_options.set_password",
|
||||||
|
ADMIN_BUNDLE)));
|
||||||
|
passwordOptionsGroup.addOption(setPasswordOption);
|
||||||
|
form.add(passwordOptionsGroup);
|
||||||
|
|
||||||
final String password = "password";
|
final String password = "password";
|
||||||
final String passwordConfirmation = "passwordConfirmation";
|
final String passwordConfirmation = "passwordConfirmation";
|
||||||
final Password passwordField = new Password(password);
|
final Password passwordField = new Password(password);
|
||||||
|
|
@ -738,7 +821,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
passwordField.addValidationListener(new NotEmptyValidationListener());
|
passwordField.addValidationListener(new NotEmptyValidationListener());
|
||||||
passwordField.addValidationListener(new StringLengthValidationListener(
|
passwordField.addValidationListener(new StringLengthValidationListener(
|
||||||
256));
|
256));
|
||||||
setPasswordSection.add(passwordField);
|
form.add(passwordField);
|
||||||
final Password passwordConfirmationField = new Password(
|
final Password passwordConfirmationField = new Password(
|
||||||
passwordConfirmation);
|
passwordConfirmation);
|
||||||
passwordConfirmationField.setLabel(new GlobalizedMessage(
|
passwordConfirmationField.setLabel(new GlobalizedMessage(
|
||||||
|
|
@ -750,27 +833,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
new NotEmptyValidationListener());
|
new NotEmptyValidationListener());
|
||||||
passwordConfirmationField.addValidationListener(
|
passwordConfirmationField.addValidationListener(
|
||||||
new StringLengthValidationListener(256));
|
new StringLengthValidationListener(256));
|
||||||
setPasswordSection.add(passwordConfirmationField);
|
form.add(passwordConfirmationField);
|
||||||
|
|
||||||
final String passwordOptions = "passwordOptions";
|
|
||||||
final String optionSetPassword = "setPassword";
|
|
||||||
final String optionSendPassword = "sendPassword";
|
|
||||||
final RadioGroup passwordOptionsGroup = new RadioGroup(passwordOptions);
|
|
||||||
// final Option setPasswordOption = new Option(
|
|
||||||
// optionSetPassword,
|
|
||||||
// new Label(new GlobalizedMessage(
|
|
||||||
// "ui.admin.new_user_form.password_options.set_password",
|
|
||||||
// ADMIN_BUNDLE)));
|
|
||||||
final Option setPasswordOption = new Option(
|
|
||||||
optionSetPassword, setPasswordSection);
|
|
||||||
passwordOptionsGroup.addOption(setPasswordOption);
|
|
||||||
final Option sendPasswordOption = new Option(
|
|
||||||
optionSendPassword,
|
|
||||||
new Label(new GlobalizedMessage(
|
|
||||||
"ui.admin.new_user_form.password_options.send_password.label",
|
|
||||||
ADMIN_BUNDLE)));
|
|
||||||
passwordOptionsGroup.addOption(sendPasswordOption);
|
|
||||||
form.add(passwordOptionsGroup);
|
|
||||||
|
|
||||||
final SaveCancelSection saveCancelSection = new SaveCancelSection();
|
final SaveCancelSection saveCancelSection = new SaveCancelSection();
|
||||||
form.add(saveCancelSection);
|
form.add(saveCancelSection);
|
||||||
|
|
@ -871,6 +934,156 @@ public class UserAdmin extends BoxPanel {
|
||||||
return form;
|
return form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Form buildEditGroupMembershipsForm() {
|
||||||
|
final Form form = new Form("edit-usergroupmemberships-form");
|
||||||
|
|
||||||
|
final BoxPanel links = new BoxPanel(BoxPanel.VERTICAL);
|
||||||
|
final Label header = new Label(e -> {
|
||||||
|
final PageState state = e.getPageState();
|
||||||
|
final Label target = (Label) e.getTarget();
|
||||||
|
|
||||||
|
final String userIdStr = selectedUserId.getSelectedKey(state);
|
||||||
|
final UserRepository userRepository = CdiUtil.createCdiUtil()
|
||||||
|
.findBean(UserRepository.class);
|
||||||
|
final User user = userRepository.findById(Long.parseLong(userIdStr));
|
||||||
|
|
||||||
|
target.setLabel(new GlobalizedMessage(
|
||||||
|
"ui.admin.user.edit_group_memberships", ADMIN_BUNDLE,
|
||||||
|
new String[]{user.getName()}));
|
||||||
|
});
|
||||||
|
links.add(header);
|
||||||
|
|
||||||
|
final ActionLink backLink = new ActionLink(new GlobalizedMessage(
|
||||||
|
"ui.admin.user.edit_group_memberships.back_to_user_details",
|
||||||
|
ADMIN_BUNDLE));
|
||||||
|
backLink.addActionListener(e -> {
|
||||||
|
closeEditGroupMembershipsForm(e.getPageState());
|
||||||
|
});
|
||||||
|
links.add(backLink);
|
||||||
|
|
||||||
|
form.add(links);
|
||||||
|
|
||||||
|
final String groupsSelector = "groupsselector";
|
||||||
|
final CheckboxGroup groups = new CheckboxGroup(groupsSelector);
|
||||||
|
try {
|
||||||
|
groups.addPrintListener(e -> {
|
||||||
|
// final PageState state = e.getPageState();
|
||||||
|
final CheckboxGroup target = (CheckboxGroup) e.getTarget();
|
||||||
|
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||||
|
// final UserRepository userRepository = cdiUtil.findBean(
|
||||||
|
// UserRepository.class);
|
||||||
|
final GroupRepository groupRepository = cdiUtil.findBean(
|
||||||
|
GroupRepository.class);
|
||||||
|
|
||||||
|
target.clearOptions();
|
||||||
|
|
||||||
|
final SortedSet<Group> allGroups = new TreeSet<>(
|
||||||
|
(g1, g2) -> {
|
||||||
|
return g1.getName().compareTo(g2.getName());
|
||||||
|
});
|
||||||
|
allGroups.addAll(groupRepository.findAll());
|
||||||
|
// final List<Group> assignedGroups = new ArrayList<>();
|
||||||
|
// final User user = userRepository.findById(Long.parseLong(
|
||||||
|
// selectedUserId.getSelectedKey(state)));
|
||||||
|
// user.getGroupMemberships().forEach(m -> {
|
||||||
|
// assignedGroups.add(m.getGroup());
|
||||||
|
// });
|
||||||
|
|
||||||
|
allGroups.forEach(g -> {
|
||||||
|
final Option option = new Option(
|
||||||
|
Long.toString(g.getPartyId()), new Text(g.getName()));
|
||||||
|
target.addOption(option);
|
||||||
|
// if (assignedGroups.contains(g)) {
|
||||||
|
// target.setOptionSelected(option);
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (TooManyListenersException ex) {
|
||||||
|
throw new UncheckedWrapperException(ex);
|
||||||
|
}
|
||||||
|
form.add(groups);
|
||||||
|
|
||||||
|
final SaveCancelSection saveCancelSection = new SaveCancelSection();
|
||||||
|
form.add(saveCancelSection);
|
||||||
|
|
||||||
|
form.addInitListener(e -> {
|
||||||
|
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||||
|
final UserRepository userRepository = cdiUtil.findBean(
|
||||||
|
UserRepository.class);
|
||||||
|
|
||||||
|
final PageState state = e.getPageState();
|
||||||
|
|
||||||
|
final User user = userRepository.findById(Long.parseLong(
|
||||||
|
selectedUserId.getSelectedKey(state)));
|
||||||
|
final List<Group> assignedGroups = new ArrayList<>();
|
||||||
|
user.getGroupMemberships().forEach(m -> {
|
||||||
|
assignedGroups.add(m.getGroup());
|
||||||
|
});
|
||||||
|
|
||||||
|
final String[] selectedGroups = new String[assignedGroups.size()];
|
||||||
|
IntStream.range(0, assignedGroups.size()).forEach(i -> {
|
||||||
|
selectedGroups[i] = Long.toString(assignedGroups.get(i)
|
||||||
|
.getPartyId());
|
||||||
|
});
|
||||||
|
|
||||||
|
groups.setValue(state, selectedGroups);
|
||||||
|
});
|
||||||
|
|
||||||
|
form.addProcessListener(e -> {
|
||||||
|
final PageState state = e.getPageState();
|
||||||
|
if (saveCancelSection.getSaveButton().isSelected(state)) {
|
||||||
|
final FormData data = e.getFormData();
|
||||||
|
|
||||||
|
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||||
|
final UserRepository userRepository = cdiUtil.findBean(
|
||||||
|
UserRepository.class);
|
||||||
|
final GroupRepository groupRepository = cdiUtil.findBean(
|
||||||
|
GroupRepository.class);
|
||||||
|
final GroupManager groupManager = cdiUtil.findBean(
|
||||||
|
GroupManager.class);
|
||||||
|
|
||||||
|
final String[] selectedGroupIds = (String[]) data.get(
|
||||||
|
groupsSelector);
|
||||||
|
|
||||||
|
final User user = userRepository.findById(Long.parseLong(
|
||||||
|
selectedUserId.getSelectedKey(state)));
|
||||||
|
final List<Group> selectedGroups = new ArrayList<>();
|
||||||
|
if (selectedGroupIds != null) {
|
||||||
|
for (String selectedGroupId : selectedGroupIds) {
|
||||||
|
final Group group = groupRepository.findById(Long
|
||||||
|
.parseLong(
|
||||||
|
selectedGroupId));
|
||||||
|
selectedGroups.add(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final List<Group> assignedGroups = new ArrayList<>();
|
||||||
|
user.getGroupMemberships().forEach(m -> {
|
||||||
|
assignedGroups.add(m.getGroup());
|
||||||
|
});
|
||||||
|
|
||||||
|
//First check for newly added groups
|
||||||
|
selectedGroups.forEach(g -> {
|
||||||
|
if (!assignedGroups.contains(g)) {
|
||||||
|
groupManager.addMemberToGroup(user, g);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Than check for removed groups
|
||||||
|
assignedGroups.forEach(g -> {
|
||||||
|
if (!selectedGroups.contains(g)) {
|
||||||
|
final Group group = groupRepository.findById(
|
||||||
|
g.getPartyId());
|
||||||
|
groupManager.removeMemberFromGroup(user, group);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
closeEditGroupMembershipsForm(state);
|
||||||
|
});
|
||||||
|
|
||||||
|
return form;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(final Page page) {
|
public void register(final Page page) {
|
||||||
super.register(page);
|
super.register(page);
|
||||||
|
|
@ -883,6 +1096,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
page.setVisibleDefault(userEditForm, false);
|
page.setVisibleDefault(userEditForm, false);
|
||||||
page.setVisibleDefault(passwordSetForm, false);
|
page.setVisibleDefault(passwordSetForm, false);
|
||||||
page.setVisibleDefault(emailForm, false);
|
page.setVisibleDefault(emailForm, false);
|
||||||
|
page.setVisibleDefault(editGroupMembershipsForm, false);
|
||||||
page.setVisibleDefault(newUserForm, false);
|
page.setVisibleDefault(newUserForm, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -892,6 +1106,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
userEditForm.setVisible(state, false);
|
userEditForm.setVisible(state, false);
|
||||||
passwordSetForm.setVisible(state, false);
|
passwordSetForm.setVisible(state, false);
|
||||||
emailForm.setVisible(state, false);
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
newUserForm.setVisible(state, false);
|
newUserForm.setVisible(state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -902,6 +1117,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
userEditForm.setVisible(state, false);
|
userEditForm.setVisible(state, false);
|
||||||
passwordSetForm.setVisible(state, false);
|
passwordSetForm.setVisible(state, false);
|
||||||
emailForm.setVisible(state, false);
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
newUserForm.setVisible(state, false);
|
newUserForm.setVisible(state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -911,6 +1127,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
userEditForm.setVisible(state, true);
|
userEditForm.setVisible(state, true);
|
||||||
passwordSetForm.setVisible(state, false);
|
passwordSetForm.setVisible(state, false);
|
||||||
emailForm.setVisible(state, false);
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
newUserForm.setVisible(state, false);
|
newUserForm.setVisible(state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -920,6 +1137,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
userEditForm.setVisible(state, false);
|
userEditForm.setVisible(state, false);
|
||||||
passwordSetForm.setVisible(state, false);
|
passwordSetForm.setVisible(state, false);
|
||||||
emailForm.setVisible(state, false);
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
newUserForm.setVisible(state, false);
|
newUserForm.setVisible(state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -929,6 +1147,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
userEditForm.setVisible(state, false);
|
userEditForm.setVisible(state, false);
|
||||||
passwordSetForm.setVisible(state, true);
|
passwordSetForm.setVisible(state, true);
|
||||||
emailForm.setVisible(state, false);
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
newUserForm.setVisible(state, false);
|
newUserForm.setVisible(state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -938,6 +1157,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
userEditForm.setVisible(state, false);
|
userEditForm.setVisible(state, false);
|
||||||
passwordSetForm.setVisible(state, false);
|
passwordSetForm.setVisible(state, false);
|
||||||
emailForm.setVisible(state, false);
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
newUserForm.setVisible(state, false);
|
newUserForm.setVisible(state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -947,6 +1167,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
userEditForm.setVisible(state, false);
|
userEditForm.setVisible(state, false);
|
||||||
passwordSetForm.setVisible(state, false);
|
passwordSetForm.setVisible(state, false);
|
||||||
emailForm.setVisible(state, true);
|
emailForm.setVisible(state, true);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
newUserForm.setVisible(state, false);
|
newUserForm.setVisible(state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -957,6 +1178,28 @@ public class UserAdmin extends BoxPanel {
|
||||||
userEditForm.setVisible(state, false);
|
userEditForm.setVisible(state, false);
|
||||||
passwordSetForm.setVisible(state, false);
|
passwordSetForm.setVisible(state, false);
|
||||||
emailForm.setVisible(state, false);
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
|
newUserForm.setVisible(state, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void showEditGroupMembershipsForm(final PageState state) {
|
||||||
|
usersTablePanel.setVisible(state, false);
|
||||||
|
userDetails.setVisible(state, false);
|
||||||
|
userEditForm.setVisible(state, false);
|
||||||
|
passwordSetForm.setVisible(state, false);
|
||||||
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, true);
|
||||||
|
newUserForm.setVisible(state, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void closeEditGroupMembershipsForm(final PageState state) {
|
||||||
|
selectedEmailAddress.clearSelection(state);
|
||||||
|
usersTablePanel.setVisible(state, false);
|
||||||
|
userDetails.setVisible(state, true);
|
||||||
|
userEditForm.setVisible(state, false);
|
||||||
|
passwordSetForm.setVisible(state, false);
|
||||||
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
newUserForm.setVisible(state, false);
|
newUserForm.setVisible(state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -967,6 +1210,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
userEditForm.setVisible(state, false);
|
userEditForm.setVisible(state, false);
|
||||||
passwordSetForm.setVisible(state, false);
|
passwordSetForm.setVisible(state, false);
|
||||||
emailForm.setVisible(state, false);
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
newUserForm.setVisible(state, true);
|
newUserForm.setVisible(state, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -977,6 +1221,7 @@ public class UserAdmin extends BoxPanel {
|
||||||
userEditForm.setVisible(state, false);
|
userEditForm.setVisible(state, false);
|
||||||
passwordSetForm.setVisible(state, false);
|
passwordSetForm.setVisible(state, false);
|
||||||
emailForm.setVisible(state, false);
|
emailForm.setVisible(state, false);
|
||||||
|
editGroupMembershipsForm.setVisible(state, false);
|
||||||
newUserForm.setVisible(state, false);
|
newUserForm.setVisible(state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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 com.arsdigita.ui.admin.usersgroupsroles;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Label;
|
||||||
|
import com.arsdigita.bebop.table.TableModel;
|
||||||
|
import com.arsdigita.globalization.GlobalizedMessage;
|
||||||
|
|
||||||
|
import org.libreccm.security.User;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static com.arsdigita.ui.admin.AdminUiConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class UserGroupsRolesTableModel implements TableModel {
|
||||||
|
|
||||||
|
protected static final int COL_LABEL = 0;
|
||||||
|
protected static final int COL_VALUE = 1;
|
||||||
|
protected static final int COL_ACTION = 2;
|
||||||
|
|
||||||
|
protected static final int ROW_GROUPS = 0;
|
||||||
|
protected static final int ROW_ROLES = 1;
|
||||||
|
protected static final int ROW_ALL_ROLES = 2;
|
||||||
|
|
||||||
|
private int row = -1;
|
||||||
|
|
||||||
|
private final User user;
|
||||||
|
|
||||||
|
public UserGroupsRolesTableModel(final User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumnCount() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean nextRow() {
|
||||||
|
row++;
|
||||||
|
return row < 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getElementAt(final int columnIndex) {
|
||||||
|
switch (row) {
|
||||||
|
case ROW_GROUPS:
|
||||||
|
return buildGroupRow(columnIndex);
|
||||||
|
case ROW_ROLES:
|
||||||
|
return buildRolesRow(columnIndex);
|
||||||
|
case ROW_ALL_ROLES:
|
||||||
|
return buildAllRolesRow(columnIndex);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getKeyAt(final int columnIndex) {
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object buildGroupRow(final int columnIndex) {
|
||||||
|
switch (columnIndex) {
|
||||||
|
case COL_LABEL:
|
||||||
|
return new Label(new GlobalizedMessage("ui.admin.user.groups",
|
||||||
|
ADMIN_BUNDLE));
|
||||||
|
case COL_VALUE:
|
||||||
|
final List<String> groupNames = new ArrayList<>();
|
||||||
|
user.getGroupMemberships().forEach(m -> {
|
||||||
|
groupNames.add(m.getGroup().getName());
|
||||||
|
});
|
||||||
|
|
||||||
|
groupNames.sort((name1, name2) -> {
|
||||||
|
return name1.compareTo(name2);
|
||||||
|
});
|
||||||
|
|
||||||
|
return String.join(
|
||||||
|
", ", groupNames.toArray(new String[groupNames.size()]));
|
||||||
|
|
||||||
|
case COL_ACTION:
|
||||||
|
return new Label(new GlobalizedMessage(
|
||||||
|
"ui.admin.user.groups.edit", ADMIN_BUNDLE));
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object buildRolesRow(final int columnIndex) {
|
||||||
|
switch (columnIndex) {
|
||||||
|
case COL_LABEL:
|
||||||
|
return new Label(new GlobalizedMessage("ui.admin.user.roles",
|
||||||
|
ADMIN_BUNDLE));
|
||||||
|
case COL_VALUE:
|
||||||
|
final List<String> roleNames = new ArrayList<>();
|
||||||
|
user.getRoleMemberships().forEach(m -> {
|
||||||
|
roleNames.add(m.getRole().getName());
|
||||||
|
});
|
||||||
|
|
||||||
|
roleNames.sort((name1, name2) -> {
|
||||||
|
return name1.compareTo(name2);
|
||||||
|
});
|
||||||
|
|
||||||
|
return String.join(
|
||||||
|
", ", roleNames.toArray(new String[roleNames.size()]));
|
||||||
|
|
||||||
|
case COL_ACTION:
|
||||||
|
return new Label(new GlobalizedMessage(
|
||||||
|
"ui.admin.user.roles.edit", ADMIN_BUNDLE));
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object buildAllRolesRow(final int columnIndex) {
|
||||||
|
switch (columnIndex) {
|
||||||
|
case COL_LABEL:
|
||||||
|
return new Label(new GlobalizedMessage(
|
||||||
|
"ui.admin.user.all_roles", ADMIN_BUNDLE));
|
||||||
|
case COL_VALUE:
|
||||||
|
final Set<String> roleNames = new HashSet<>();
|
||||||
|
user.getRoleMemberships().forEach(m -> {
|
||||||
|
roleNames.add(m.getRole().getName());
|
||||||
|
});
|
||||||
|
|
||||||
|
user.getGroupMemberships().forEach(m -> {
|
||||||
|
m.getGroup().getRoleMemberships().forEach(r -> {
|
||||||
|
roleNames.add(r.getRole().getName());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<String> allRoleNames = new ArrayList<>(roleNames);
|
||||||
|
allRoleNames.sort((name1, name2) -> {
|
||||||
|
return name1.compareTo(name2);
|
||||||
|
});
|
||||||
|
|
||||||
|
return String.join(", ", allRoleNames.toArray(
|
||||||
|
new String[allRoleNames.size()]));
|
||||||
|
|
||||||
|
case COL_ACTION:
|
||||||
|
return "";
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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 com.arsdigita.ui.admin.usersgroupsroles;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
||||||
|
import com.arsdigita.bebop.Table;
|
||||||
|
import com.arsdigita.bebop.table.TableModel;
|
||||||
|
import com.arsdigita.bebop.table.TableModelBuilder;
|
||||||
|
import com.arsdigita.util.LockableImpl;
|
||||||
|
|
||||||
|
import org.libreccm.cdi.utils.CdiUtil;
|
||||||
|
import org.libreccm.security.User;
|
||||||
|
import org.libreccm.security.UserRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class UserGroupsRolesTableModelBuilder extends LockableImpl
|
||||||
|
implements TableModelBuilder{
|
||||||
|
|
||||||
|
private final ParameterSingleSelectionModel<String> selectedUserId;
|
||||||
|
|
||||||
|
public UserGroupsRolesTableModelBuilder(
|
||||||
|
final ParameterSingleSelectionModel<String> selectedUserId) {
|
||||||
|
this.selectedUserId = selectedUserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableModel makeModel(final Table table, final PageState state) {
|
||||||
|
final String userIdStr = selectedUserId.getSelectedKey(state);
|
||||||
|
final User selectedUser ;
|
||||||
|
if (userIdStr == null || userIdStr.isEmpty()) {
|
||||||
|
selectedUser = null;
|
||||||
|
} else {
|
||||||
|
final UserRepository userRepository = CdiUtil.createCdiUtil()
|
||||||
|
.findBean(UserRepository.class);
|
||||||
|
final long userId = Long.parseLong(userIdStr);
|
||||||
|
selectedUser = userRepository.findById(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new UserGroupsRolesTableModel(selectedUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -20,8 +20,10 @@ package com.arsdigita.ui.admin.usersgroupsroles;
|
||||||
|
|
||||||
import com.arsdigita.bebop.PropertySheetModel;
|
import com.arsdigita.bebop.PropertySheetModel;
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
import com.arsdigita.globalization.GlobalizedMessage;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.libreccm.security.User;
|
import org.libreccm.security.User;
|
||||||
|
|
||||||
import static com.arsdigita.ui.admin.AdminUiConstants.*;
|
import static com.arsdigita.ui.admin.AdminUiConstants.*;
|
||||||
|
|
@ -38,7 +40,7 @@ public class UserPropertySheetModel implements PropertySheetModel {
|
||||||
GIVEN_NAME,
|
GIVEN_NAME,
|
||||||
PASSWORD_SET,
|
PASSWORD_SET,
|
||||||
BANNED,
|
BANNED,
|
||||||
PASSWORD_RESET_REQUIRED,
|
PASSWORD_RESET_REQUIRED
|
||||||
}
|
}
|
||||||
|
|
||||||
private final User selectedUser;
|
private final User selectedUser;
|
||||||
|
|
@ -102,5 +104,4 @@ public class UserPropertySheetModel implements PropertySheetModel {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ public class UsersTable extends Table {
|
||||||
final UserRepository userRepository = CdiUtil.createCdiUtil()
|
final UserRepository userRepository = CdiUtil.createCdiUtil()
|
||||||
.findBean(UserRepository.class);
|
.findBean(UserRepository.class);
|
||||||
if (filterTerm == null || filterTerm.isEmpty()) {
|
if (filterTerm == null || filterTerm.isEmpty()) {
|
||||||
users = userRepository.findAll();
|
users = userRepository.findAllOrderdByUsername();
|
||||||
LOGGER.debug("Found {} users in database.", users.size());
|
LOGGER.debug("Found {} users in database.", users.size());
|
||||||
} else {
|
} else {
|
||||||
users = userRepository.filtered(filterTerm);
|
users = userRepository.filtered(filterTerm);
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,8 @@ public interface LoginConstants {
|
||||||
// updating existing databases (table applications)!
|
// updating existing databases (table applications)!
|
||||||
public static final String LOGIN_PAGE_URL = "/register/";
|
public static final String LOGIN_PAGE_URL = "/register/";
|
||||||
|
|
||||||
|
public static final String LOGIN_PATH = "/register";
|
||||||
|
|
||||||
public static final String LOGIN_SERVLET_PATH = "/login/*";
|
public static final String LOGIN_SERVLET_PATH = "/login/*";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,16 +108,25 @@ public class LoginServlet extends BebopApplicationServlet {
|
||||||
/**
|
/**
|
||||||
* PathInfo into the Login application to access the <em>password reset</em>
|
* PathInfo into the Login application to access the <em>password reset</em>
|
||||||
* page which allows the user to replace a forgotten password with a new one
|
* page which allows the user to replace a forgotten password with a new one
|
||||||
* (using a previously requested one time auth token). Ends with "/" because
|
* (using a previously requested one time authentication token). Ends with
|
||||||
* it is a servlet/directory
|
* "/" because it is a servlet/directory
|
||||||
*/
|
*/
|
||||||
public static final String RESET_USER_PASSWORD_PATH_INFO = "/reset-password";
|
public static final String RESET_USER_PASSWORD_PATH_INFO = "/reset-password/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PathInfo into the Login application to access the <em>verify email</em>
|
* PathInfo into the Login application to access the <em>verify email</em>
|
||||||
* page. Ends with "/" because it is a servlet/directory
|
* page (not implemted yet!). Ends with "/" because it is a
|
||||||
|
* servlet/directory
|
||||||
*/
|
*/
|
||||||
public static final String VERIFY_EMAIL = "/verify-email/";
|
public static final String VERIFY_EMAIL_PATH_INFO = "/verify-email/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PathInfo into the Login application to access the <em>confirm email</em>
|
||||||
|
* page which allows the user to confirm his/her email address by submitting
|
||||||
|
* a previously requested one time authentication token (not implemented!).
|
||||||
|
* Ends with "/" because it is a servlet/directory
|
||||||
|
*/
|
||||||
|
public static final String CONFIRM_EMAIL_PATH_INFO = "/verify-email/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PathInfo into the Login application to access the (optional) <em>explain
|
* PathInfo into the Login application to access the (optional) <em>explain
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
||||||
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
import com.arsdigita.globalization.GlobalizedMessage;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
import org.libreccm.cdi.utils.CdiUtil;
|
||||||
import org.libreccm.security.ChallengeManager;
|
import org.libreccm.security.ChallengeManager;
|
||||||
import org.libreccm.security.User;
|
import org.libreccm.security.User;
|
||||||
|
|
@ -48,6 +50,9 @@ import static com.arsdigita.ui.login.LoginServlet.*;
|
||||||
*/
|
*/
|
||||||
public class RecoverPasswordForm extends Form {
|
public class RecoverPasswordForm extends Form {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(
|
||||||
|
RecoverPasswordForm.class);
|
||||||
|
|
||||||
private static final String EMAIL = "email";
|
private static final String EMAIL = "email";
|
||||||
|
|
||||||
private BoxPanel formPanel;
|
private BoxPanel formPanel;
|
||||||
|
|
@ -93,6 +98,7 @@ public class RecoverPasswordForm extends Form {
|
||||||
LOGIN_BUNDLE)),
|
LOGIN_BUNDLE)),
|
||||||
LOGIN_PAGE_URL + RESET_USER_PASSWORD_PATH_INFO);
|
LOGIN_PAGE_URL + RESET_USER_PASSWORD_PATH_INFO);
|
||||||
finishedMessagePanel.add(link);
|
finishedMessagePanel.add(link);
|
||||||
|
add(finishedMessagePanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addListeners() {
|
private void addListeners() {
|
||||||
|
|
@ -155,9 +161,14 @@ public class RecoverPasswordForm extends Form {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Password recover requested for not existing user {}.",
|
||||||
|
data.get(EMAIL));
|
||||||
|
}
|
||||||
|
|
||||||
formPanel.setVisible(state, false);
|
formPanel.setVisible(state, false);
|
||||||
finishedMessagePanel.setVisible(state, true);
|
finishedMessagePanel.setVisible(state, true);
|
||||||
data.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import com.arsdigita.bebop.Form;
|
||||||
import com.arsdigita.bebop.FormData;
|
import com.arsdigita.bebop.FormData;
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
import com.arsdigita.bebop.Label;
|
import com.arsdigita.bebop.Label;
|
||||||
|
import com.arsdigita.bebop.Link;
|
||||||
import com.arsdigita.bebop.Page;
|
import com.arsdigita.bebop.Page;
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.bebop.SaveCancelSection;
|
import com.arsdigita.bebop.SaveCancelSection;
|
||||||
|
|
@ -31,6 +32,7 @@ import com.arsdigita.bebop.form.TextField;
|
||||||
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
||||||
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
import com.arsdigita.globalization.GlobalizedMessage;
|
||||||
|
import com.arsdigita.web.URL;
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
import org.libreccm.cdi.utils.CdiUtil;
|
||||||
import org.libreccm.configuration.ConfigurationManager;
|
import org.libreccm.configuration.ConfigurationManager;
|
||||||
|
|
@ -45,6 +47,8 @@ import org.libreccm.security.UserRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginConstants.*;
|
import static com.arsdigita.ui.login.LoginConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -136,12 +140,32 @@ public class ResetPasswordForm extends Form {
|
||||||
successPanel = new BoxPanel(BoxPanel.VERTICAL);
|
successPanel = new BoxPanel(BoxPanel.VERTICAL);
|
||||||
successPanel.add(new Label(new GlobalizedMessage(
|
successPanel.add(new Label(new GlobalizedMessage(
|
||||||
"login.form.reset_password.scucess", LOGIN_BUNDLE)));
|
"login.form.reset_password.scucess", LOGIN_BUNDLE)));
|
||||||
|
successPanel.add(new Link(new Label(new GlobalizedMessage(
|
||||||
|
"login.form.reset_password.scucess.login",
|
||||||
|
LOGIN_BUNDLE)),
|
||||||
|
URL.there(LOGIN_PAGE_URL, null).getURL()));
|
||||||
|
|
||||||
add(successPanel);
|
add(successPanel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addListeners() {
|
private void addListeners() {
|
||||||
|
addInitListener(e -> {
|
||||||
|
final PageState state = e.getPageState();
|
||||||
|
final HttpServletRequest request = state.getRequest();
|
||||||
|
|
||||||
|
final String paramEmail = request.getParameter("email");
|
||||||
|
final String paramToken = request.getParameter("token");
|
||||||
|
|
||||||
|
if (paramEmail != null) {
|
||||||
|
email.setValue(state, paramEmail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paramToken != null) {
|
||||||
|
authToken.setValue(state, paramToken);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
addValidationListener(e -> {
|
addValidationListener(e -> {
|
||||||
final PageState state = e.getPageState();
|
final PageState state = e.getPageState();
|
||||||
|
|
||||||
|
|
@ -177,7 +201,7 @@ public class ResetPasswordForm extends Form {
|
||||||
|
|
||||||
final List<OneTimeAuthToken> tokens = oneTimeAuthManager
|
final List<OneTimeAuthToken> tokens = oneTimeAuthManager
|
||||||
.retrieveForUser(
|
.retrieveForUser(
|
||||||
user, OneTimeAuthTokenPurpose.ACCOUNT_ACTIVATION);
|
user, OneTimeAuthTokenPurpose.RECOVER_PASSWORD);
|
||||||
|
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
for (OneTimeAuthToken token : tokens) {
|
for (OneTimeAuthToken token : tokens) {
|
||||||
|
|
@ -234,13 +258,12 @@ public class ResetPasswordForm extends Form {
|
||||||
throw new FormProcessException(
|
throw new FormProcessException(
|
||||||
"Failed to finish password recovery.",
|
"Failed to finish password recovery.",
|
||||||
new GlobalizedMessage(
|
new GlobalizedMessage(
|
||||||
"login.form.account_activation.error.failed"),
|
"login.form.password_reset.error.failed"),
|
||||||
ex);
|
ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
formPanel.setVisible(state, false);
|
formPanel.setVisible(state, false);
|
||||||
successPanel.setVisible(state, true);
|
successPanel.setVisible(state, true);
|
||||||
data.clear();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import com.arsdigita.bebop.Form;
|
||||||
import com.arsdigita.bebop.FormData;
|
import com.arsdigita.bebop.FormData;
|
||||||
import com.arsdigita.bebop.FormProcessException;
|
import com.arsdigita.bebop.FormProcessException;
|
||||||
import com.arsdigita.bebop.Label;
|
import com.arsdigita.bebop.Label;
|
||||||
|
import com.arsdigita.bebop.Link;
|
||||||
import com.arsdigita.bebop.Page;
|
import com.arsdigita.bebop.Page;
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
import com.arsdigita.bebop.SaveCancelSection;
|
import com.arsdigita.bebop.SaveCancelSection;
|
||||||
|
|
@ -30,6 +31,7 @@ import com.arsdigita.bebop.form.TextField;
|
||||||
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
|
||||||
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
import com.arsdigita.bebop.parameters.StringLengthValidationListener;
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
import com.arsdigita.globalization.GlobalizedMessage;
|
||||||
|
import com.arsdigita.web.URL;
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
import org.libreccm.cdi.utils.CdiUtil;
|
||||||
import org.libreccm.configuration.ConfigurationManager;
|
import org.libreccm.configuration.ConfigurationManager;
|
||||||
|
|
@ -44,6 +46,8 @@ import org.libreccm.security.UserRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import static com.arsdigita.ui.login.LoginConstants.*;
|
import static com.arsdigita.ui.login.LoginConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -102,11 +106,30 @@ public class UserAccountActivationForm extends Form {
|
||||||
successPanel = new BoxPanel(BoxPanel.VERTICAL);
|
successPanel = new BoxPanel(BoxPanel.VERTICAL);
|
||||||
successPanel.add(new Label(new GlobalizedMessage(
|
successPanel.add(new Label(new GlobalizedMessage(
|
||||||
"login.form.account_activation.success", LOGIN_BUNDLE)));
|
"login.form.account_activation.success", LOGIN_BUNDLE)));
|
||||||
|
successPanel.add(new Link(new Label(
|
||||||
|
new GlobalizedMessage("login.form.account_activation.success.login",
|
||||||
|
LOGIN_BUNDLE)),
|
||||||
|
URL.there(LOGIN_PAGE_URL, null).getURL()));
|
||||||
add(successPanel);
|
add(successPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addListeners() {
|
private void addListeners() {
|
||||||
|
addInitListener(e -> {
|
||||||
|
final PageState state = e.getPageState();
|
||||||
|
final HttpServletRequest request = state.getRequest();
|
||||||
|
|
||||||
|
final String paramEmail = request.getParameter("email");
|
||||||
|
final String paramToken = request.getParameter("token");
|
||||||
|
|
||||||
|
if (paramEmail != null) {
|
||||||
|
email.setValue(state, paramEmail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paramToken != null) {
|
||||||
|
authToken.setValue(state, paramToken);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
addValidationListener(e -> {
|
addValidationListener(e -> {
|
||||||
final PageState state = e.getPageState();
|
final PageState state = e.getPageState();
|
||||||
|
|
||||||
|
|
@ -193,7 +216,6 @@ public class UserAccountActivationForm extends Form {
|
||||||
|
|
||||||
formPanel.setVisible(state, false);
|
formPanel.setVisible(state, false);
|
||||||
successPanel.setVisible(state, true);
|
successPanel.setVisible(state, true);
|
||||||
data.clear();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import javax.persistence.EntityManager;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.Order;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
import javax.transaction.Transactional;
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
|
|
@ -208,8 +209,7 @@ public abstract class AbstractEntityRepository<K, E> {
|
||||||
public List<E> findAll(final String entityGraphName) {
|
public List<E> findAll(final String entityGraphName) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final EntityGraph<E> entityGraph = (EntityGraph<E>) entityManager
|
final EntityGraph<E> entityGraph = (EntityGraph<E>) entityManager
|
||||||
.getEntityGraph(
|
.getEntityGraph(entityGraphName);
|
||||||
entityGraphName);
|
|
||||||
|
|
||||||
return findAll(entityGraph);
|
return findAll(entityGraph);
|
||||||
}
|
}
|
||||||
|
|
@ -237,8 +237,8 @@ public abstract class AbstractEntityRepository<K, E> {
|
||||||
if (hasDefaultEntityGraph()) {
|
if (hasDefaultEntityGraph()) {
|
||||||
return executeCriteriaQuery(criteriaQuery, getDefaultEntityGraph());
|
return executeCriteriaQuery(criteriaQuery, getDefaultEntityGraph());
|
||||||
} else {
|
} else {
|
||||||
final TypedQuery<E> query = entityManager.createQuery(criteriaQuery);
|
final TypedQuery<E> query = entityManager.createQuery(criteriaQuery);
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,9 +286,9 @@ public abstract class AbstractEntityRepository<K, E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overwrite this method to initialise new entities with default values.
|
* Overwrite this method to initialise new entities with default values. One
|
||||||
* One example is assigning a (random) UUID to new entity which implements
|
* example is assigning a (random) UUID to new entity which implements the
|
||||||
* the {@link Identifiable} interface.
|
* {@link Identifiable} interface.
|
||||||
*
|
*
|
||||||
* @param entity The entity to init.
|
* @param entity The entity to init.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,11 @@ import javax.servlet.http.HttpSession;
|
||||||
* </li>
|
* </li>
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* A historic note: This CDI bean replaces the old {@code GlobalizationHelper} class which used
|
* A historic note: This CDI bean replaces the old {@code GlobalizationHelper}
|
||||||
* static methods and relied on the old {@code DispatcherHelper} for getting the
|
* class which used static methods and relied on the old
|
||||||
* current request. In a CDI environment we can simply inject the current request
|
* {@code DispatcherHelper} for getting the current request. In a CDI
|
||||||
* and don't need to bother with static methods etc.
|
* environment we can simply inject the current request and don't need to bother
|
||||||
|
* with static methods etc.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
*/
|
*/
|
||||||
|
|
@ -73,13 +74,12 @@ public class GlobalizationHelper {
|
||||||
private ConfigurationManager confManager;
|
private ConfigurationManager confManager;
|
||||||
|
|
||||||
// private final KernelConfig kernelConfig;
|
// private final KernelConfig kernelConfig;
|
||||||
|
|
||||||
// public GlobalizationHelper() {
|
// public GlobalizationHelper() {
|
||||||
// kernelConfig = confManager.findConfiguration(KernelConfig.class);
|
// kernelConfig = confManager.findConfiguration(KernelConfig.class);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public Locale getNegotiatedLocale() {
|
public Locale getNegotiatedLocale() {
|
||||||
final KernelConfig kernelConfig = confManager.findConfiguration(KernelConfig.class);
|
final KernelConfig kernelConfig = confManager.findConfiguration(
|
||||||
|
KernelConfig.class);
|
||||||
|
|
||||||
Locale preferred = new Locale(kernelConfig.getDefaultLanguage());
|
Locale preferred = new Locale(kernelConfig.getDefaultLanguage());
|
||||||
|
|
||||||
|
|
@ -91,7 +91,7 @@ public class GlobalizationHelper {
|
||||||
while (acceptedLocales.hasMoreElements()) {
|
while (acceptedLocales.hasMoreElements()) {
|
||||||
final Locale current = acceptedLocales.nextElement();
|
final Locale current = acceptedLocales.nextElement();
|
||||||
if (kernelConfig.hasLanguage(current.getLanguage())) {
|
if (kernelConfig.hasLanguage(current.getLanguage())) {
|
||||||
preferred = current;
|
preferred = new Locale(current.getLanguage());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,13 @@ package org.libreccm.security;
|
||||||
|
|
||||||
import com.arsdigita.kernel.KernelConfig;
|
import com.arsdigita.kernel.KernelConfig;
|
||||||
import com.arsdigita.mail.Mail;
|
import com.arsdigita.mail.Mail;
|
||||||
|
import com.arsdigita.ui.login.LoginConstants;
|
||||||
|
import com.arsdigita.web.ParameterMap;
|
||||||
|
import com.arsdigita.web.URL;
|
||||||
|
|
||||||
import org.apache.commons.lang.text.StrSubstitutor;
|
import org.apache.commons.lang.text.StrSubstitutor;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.libreccm.configuration.ConfigurationManager;
|
import org.libreccm.configuration.ConfigurationManager;
|
||||||
import org.libreccm.configuration.LocalizedStringSetting;
|
import org.libreccm.configuration.LocalizedStringSetting;
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
import org.libreccm.l10n.GlobalizationHelper;
|
||||||
|
|
@ -37,6 +42,9 @@ import javax.enterprise.context.RequestScoped;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import static com.arsdigita.ui.login.LoginServlet.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service class for managing several so called challenges. These challenges
|
* A service class for managing several so called challenges. These challenges
|
||||||
|
|
@ -73,6 +81,9 @@ import javax.servlet.ServletContext;
|
||||||
@RequestScoped
|
@RequestScoped
|
||||||
public class ChallengeManager {
|
public class ChallengeManager {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(
|
||||||
|
ChallengeManager.class);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private GlobalizationHelper globalizationHelper;
|
private GlobalizationHelper globalizationHelper;
|
||||||
|
|
||||||
|
|
@ -89,7 +100,7 @@ public class ChallengeManager {
|
||||||
private UserManager userManager;
|
private UserManager userManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ServletContext servletContext;
|
private HttpServletRequest request;
|
||||||
|
|
||||||
public String createEmailVerification(final User user) {
|
public String createEmailVerification(final User user) {
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
|
|
@ -137,7 +148,7 @@ public class ChallengeManager {
|
||||||
|
|
||||||
public void sendAccountActivation(final User user)
|
public void sendAccountActivation(final User user)
|
||||||
throws MessagingException {
|
throws MessagingException {
|
||||||
final String text = createEmailVerification(user);
|
final String text = createAccountActivation(user);
|
||||||
sendMessage(
|
sendMessage(
|
||||||
user,
|
user,
|
||||||
retrieveEmailSubject(OneTimeAuthTokenPurpose.ACCOUNT_ACTIVATION),
|
retrieveEmailSubject(OneTimeAuthTokenPurpose.ACCOUNT_ACTIVATION),
|
||||||
|
|
@ -172,7 +183,7 @@ public class ChallengeManager {
|
||||||
|
|
||||||
public void sendPasswordRecover(final User user)
|
public void sendPasswordRecover(final User user)
|
||||||
throws MessagingException {
|
throws MessagingException {
|
||||||
final String text = createEmailVerification(user);
|
final String text = createPasswordRecover(user);
|
||||||
sendMessage(
|
sendMessage(
|
||||||
user,
|
user,
|
||||||
retrieveEmailSubject(OneTimeAuthTokenPurpose.RECOVER_PASSWORD),
|
retrieveEmailSubject(OneTimeAuthTokenPurpose.RECOVER_PASSWORD),
|
||||||
|
|
@ -211,13 +222,13 @@ public class ChallengeManager {
|
||||||
final String path;
|
final String path;
|
||||||
switch (purpose) {
|
switch (purpose) {
|
||||||
case ACCOUNT_ACTIVATION:
|
case ACCOUNT_ACTIVATION:
|
||||||
path = "activate-account";
|
path = ACTIVATE_ACCOUNT_PATH_INFO;
|
||||||
break;
|
break;
|
||||||
case EMAIL_VERIFICATION:
|
case EMAIL_VERIFICATION:
|
||||||
path = "verify-email";
|
path = VERIFY_EMAIL_PATH_INFO;
|
||||||
break;
|
break;
|
||||||
case RECOVER_PASSWORD:
|
case RECOVER_PASSWORD:
|
||||||
path = "recover-password";
|
path = RESET_USER_PASSWORD_PATH_INFO;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(String.format(
|
||||||
|
|
@ -225,17 +236,28 @@ public class ChallengeManager {
|
||||||
purpose.toString()));
|
purpose.toString()));
|
||||||
}
|
}
|
||||||
values.put("link",
|
values.put("link",
|
||||||
String.format("%s/%s/register/%s",
|
URL.there(request,
|
||||||
servletContext.getVirtualServerName(),
|
LoginConstants.LOGIN_PATH + path, null)
|
||||||
servletContext.getContextPath(),
|
.getURL());
|
||||||
path));
|
|
||||||
|
final ParameterMap params = new ParameterMap();
|
||||||
|
params.setParameter("email", user.getPrimaryEmailAddress().getAddress());
|
||||||
|
params.setParameter("token", token.getToken());
|
||||||
|
values.put("full_link",
|
||||||
|
URL.there(request,
|
||||||
|
LoginConstants.LOGIN_PATH + path, params)
|
||||||
|
.getURL());
|
||||||
|
|
||||||
|
values.put("token", token.getToken());
|
||||||
|
|
||||||
final StrSubstitutor substitutor = new StrSubstitutor(values);
|
final StrSubstitutor substitutor = new StrSubstitutor(values);
|
||||||
return substitutor.replace(template);
|
return substitutor.replace(template);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String retrieveEmailSubject(final OneTimeAuthTokenPurpose purpose) {
|
private String retrieveEmailSubject(final OneTimeAuthTokenPurpose purpose) {
|
||||||
|
LOGGER.debug("Retreving email subject...");
|
||||||
final Locale locale = globalizationHelper.getNegotiatedLocale();
|
final Locale locale = globalizationHelper.getNegotiatedLocale();
|
||||||
|
LOGGER.debug("Negoiated locale is {}.", locale.toString());
|
||||||
|
|
||||||
final EmailTemplates emailTemplates = configurationManager
|
final EmailTemplates emailTemplates = configurationManager
|
||||||
.findConfiguration(EmailTemplates.class);
|
.findConfiguration(EmailTemplates.class);
|
||||||
|
|
|
||||||
|
|
@ -67,17 +67,35 @@ public final class EmailTemplates {
|
||||||
"Please follow the following link to finish the email verfication "
|
"Please follow the following link to finish the email verfication "
|
||||||
+ "process:\n"
|
+ "process:\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "${link}"
|
+ "${full_link}\n"
|
||||||
+ "\n\n"
|
+ "\n"
|
||||||
+ "Please be aware that your verification token expires"
|
+ "or go to\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${link}\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "and enter your email address and the following verification "
|
||||||
|
+ "token:\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${token}\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "Please be aware that your verification token expires "
|
||||||
+ "at ${expires_date}.");
|
+ "at ${expires_date}.");
|
||||||
emailVerificationMail.getValue().addValue(
|
emailVerificationMail.getValue().addValue(
|
||||||
Locale.GERMAN,
|
Locale.GERMAN,
|
||||||
"Bitte folgen Sie dem folgenden Link, um die Überprüfung ihrer E-"
|
"Bitte folgen Sie dem folgenden Link, um die Überprüfung ihrer E-"
|
||||||
+ "Mail-Adresse abzuschließen:\n"
|
+ "Mail-Adresse abzuschließen:\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "${link}"
|
+ "${full_link}\n"
|
||||||
+ "\n\n"
|
+ "\n"
|
||||||
|
+ "oder rufen Sie\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${link}\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "auf und geben Sie Ihre E-Mail-Adresse und das folgende Token "
|
||||||
|
+ "ein:\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${token}\n"
|
||||||
|
+ "\n"
|
||||||
+ "Bitte beachten Sie, dass Sie den Prozess bis zu folgendem "
|
+ "Bitte beachten Sie, dass Sie den Prozess bis zu folgendem "
|
||||||
+ "Zeitpunkt abschließen müssen: ${expires_date}");
|
+ "Zeitpunkt abschließen müssen: ${expires_date}");
|
||||||
|
|
||||||
|
|
@ -95,17 +113,33 @@ public final class EmailTemplates {
|
||||||
"Please follow the following link to complete the password recover "
|
"Please follow the following link to complete the password recover "
|
||||||
+ "process:\n"
|
+ "process:\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "${link}"
|
+ "${full_link}\n"
|
||||||
+ "\n\n"
|
+ "\n"
|
||||||
|
+ "or go to\n"
|
||||||
|
+ "${link}\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "and enter your email address and the following token:\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${token}\n"
|
||||||
|
+ "\n"
|
||||||
+ "Please be aware that you must complete the process until "
|
+ "Please be aware that you must complete the process until "
|
||||||
+ "${expires_date}");
|
+ "${expires_date}.");
|
||||||
passwordRecoverMail.getValue().addValue(
|
passwordRecoverMail.getValue().addValue(
|
||||||
Locale.GERMAN,
|
Locale.GERMAN,
|
||||||
"Bitte folgen Sie dem folgenden Link um ein neues Passwort "
|
"Bitte folgen Sie dem folgenden Link um ein neues Passwort "
|
||||||
+ "einzugeben:\n"
|
+ "einzugeben:\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "${link}"
|
+ "${full_link}\n"
|
||||||
+ "\n\n"
|
+ "\n"
|
||||||
|
+ "oder rufen Sie\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${link}\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "auf und geben Sie Ihre E-Mail-adresse und der folgende Token"
|
||||||
|
+ "ein:\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${token}\n"
|
||||||
|
+ "\n"
|
||||||
+ "Bitte beachten Sie, dass den den Prozess bis zu folgenden "
|
+ "Bitte beachten Sie, dass den den Prozess bis zu folgenden "
|
||||||
+ "Zeitpunkt abschließen müsssen: ${expires_date}");
|
+ "Zeitpunkt abschließen müsssen: ${expires_date}");
|
||||||
|
|
||||||
|
|
@ -122,8 +156,16 @@ public final class EmailTemplates {
|
||||||
Locale.ENGLISH,
|
Locale.ENGLISH,
|
||||||
"Please follow the following link to enable your new account:\n"
|
"Please follow the following link to enable your new account:\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "${link}"
|
+ "${full_link}\n"
|
||||||
+ "\n\n"
|
+ "\n"
|
||||||
|
+ "or got to\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${link}\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "and enter your email address and the following token:\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${token}\n"
|
||||||
|
+ "\n"
|
||||||
+ "Please be aware that you must activate your account before "
|
+ "Please be aware that you must activate your account before "
|
||||||
+ "${expires_date}.");
|
+ "${expires_date}.");
|
||||||
accountActivationMail.getValue().addValue(
|
accountActivationMail.getValue().addValue(
|
||||||
|
|
@ -131,9 +173,18 @@ public final class EmailTemplates {
|
||||||
"Bitte folgen Sie den folgendem Link, um ihr Benutzerkonto zu "
|
"Bitte folgen Sie den folgendem Link, um ihr Benutzerkonto zu "
|
||||||
+ "aktivieren:\n"
|
+ "aktivieren:\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "${link}"
|
+ "${full_link}\n"
|
||||||
+ "\n\n"
|
+ "\n"
|
||||||
+ "Bitte beachten Sie, dass Sie ihr Benutzerkonto spätestens"
|
+ "oder rufen Sie\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${link}\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "auf und geben Sie Ihre E-Mail-Adresse und das folgende Token "
|
||||||
|
+ "ein:\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "${token}\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "Bitte beachten Sie, dass Sie ihr Benutzerkonto spätestens "
|
||||||
+ "bis zu folgendem Zeitpunkt aktivieren müssen: ${expires_date}");
|
+ "bis zu folgendem Zeitpunkt aktivieren müssen: ${expires_date}");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ package org.libreccm.security;
|
||||||
|
|
||||||
import static org.libreccm.core.CoreConstants.*;
|
import static org.libreccm.core.CoreConstants.*;
|
||||||
|
|
||||||
|
import org.libreccm.core.DefaultEntityGraph;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
@ -27,8 +29,12 @@ import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.NamedAttributeNode;
|
||||||
|
import javax.persistence.NamedEntityGraph;
|
||||||
|
import javax.persistence.NamedEntityGraphs;
|
||||||
import javax.persistence.NamedQueries;
|
import javax.persistence.NamedQueries;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.NamedSubgraph;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
|
@ -53,6 +59,29 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||||
query = "SELECT g FROM Group g "
|
query = "SELECT g FROM Group g "
|
||||||
+ "WHERE LOWER(g.name) LIKE '%:name%'")
|
+ "WHERE LOWER(g.name) LIKE '%:name%'")
|
||||||
})
|
})
|
||||||
|
@NamedEntityGraphs({
|
||||||
|
@NamedEntityGraph(
|
||||||
|
name = "Group.withMembersAndRoleMemberships",
|
||||||
|
attributeNodes = {
|
||||||
|
@NamedAttributeNode(
|
||||||
|
value = "memberships"),
|
||||||
|
@NamedAttributeNode(
|
||||||
|
value = "roleMemberships",
|
||||||
|
subgraph = "role")},
|
||||||
|
subgraphs = {
|
||||||
|
@NamedSubgraph(
|
||||||
|
name = "role",
|
||||||
|
attributeNodes = {
|
||||||
|
@NamedAttributeNode(value = "role",
|
||||||
|
subgraph = "permissions")
|
||||||
|
}),
|
||||||
|
@NamedSubgraph(
|
||||||
|
name = "permissions",
|
||||||
|
attributeNodes = {
|
||||||
|
@NamedAttributeNode(value = "permissions")})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
@DefaultEntityGraph("Group.withMembersAndRoleMemberships")
|
||||||
@XmlRootElement(name = "user-group", namespace = CORE_XML_NS)
|
@XmlRootElement(name = "user-group", namespace = CORE_XML_NS)
|
||||||
public class Group extends Party implements Serializable {
|
public class Group extends Party implements Serializable {
|
||||||
|
|
||||||
|
|
@ -119,8 +148,6 @@ public class Group extends Party implements Serializable {
|
||||||
return super.hashCode();
|
return super.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(final String data) {
|
public String toString(final String data) {
|
||||||
return super.toString(String.format(", members = { %s }%s",
|
return super.toString(String.format(", members = { %s }%s",
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ public class GroupManager {
|
||||||
* @param user The user to add to a group.
|
* @param user The user to add to a group.
|
||||||
* @param group The group to which the user is added.
|
* @param group The group to which the user is added.
|
||||||
*/
|
*/
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public void addMemberToGroup(final User user, final Group group) {
|
public void addMemberToGroup(final User user, final Group group) {
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,11 @@ public class OneTimeAuthManager {
|
||||||
throw new IllegalArgumentException("Can't invalidate a token null");
|
throw new IllegalArgumentException("Can't invalidate a token null");
|
||||||
}
|
}
|
||||||
|
|
||||||
entityManager.remove(token);
|
//Ensure that we have a none detached instance
|
||||||
|
final OneTimeAuthToken delete = entityManager.find(
|
||||||
|
OneTimeAuthToken.class, token.getTokenId());
|
||||||
|
|
||||||
|
entityManager.remove(delete);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,10 @@ public class OneTimeAuthTokenCleaner {
|
||||||
// final long interval = 60 * 60 * 1000;
|
// final long interval = 60 * 60 * 1000;
|
||||||
|
|
||||||
LOGGER.debug("Creating interval for {} s.", interval / 1000);
|
LOGGER.debug("Creating interval for {} s.", interval / 1000);
|
||||||
timerService.createIntervalTimer(interval, interval, new TimerConfig());
|
LOGGER.debug("First run cleaning process will be executed in 5 min.");
|
||||||
|
timerService.createIntervalTimer(5 * 60 * 1000,
|
||||||
|
interval,
|
||||||
|
new TimerConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Timeout
|
@Timeout
|
||||||
|
|
@ -88,7 +91,7 @@ public class OneTimeAuthTokenCleaner {
|
||||||
LOGGER.debug("Found {} one time auth tokens.", tokens.size());
|
LOGGER.debug("Found {} one time auth tokens.", tokens.size());
|
||||||
if (LOGGER.isDebugEnabled()) {
|
if (LOGGER.isDebugEnabled()) {
|
||||||
final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
|
final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
|
||||||
LOGGER.debug("Current time is: {}", now);
|
LOGGER.debug("Current time (UTC) is: {}", now);
|
||||||
tokens.forEach(t -> {
|
tokens.forEach(t -> {
|
||||||
if (oneTimeAuthManager.isValid(t)) {
|
if (oneTimeAuthManager.isValid(t)) {
|
||||||
LOGGER.debug("OneTimeAuthToken with id {} is still valid. "
|
LOGGER.debug("OneTimeAuthToken with id {} is still valid. "
|
||||||
|
|
@ -97,7 +100,7 @@ public class OneTimeAuthTokenCleaner {
|
||||||
t.getValidUntil());
|
t.getValidUntil());
|
||||||
} else {
|
} else {
|
||||||
LOGGER.debug("OneTimeAuthToken with id {} is invalid. "
|
LOGGER.debug("OneTimeAuthToken with id {} is invalid. "
|
||||||
+ "Expires at {}.",
|
+ "Expires at {} UTC.",
|
||||||
t.getTokenId(),
|
t.getTokenId(),
|
||||||
t.getValidUntil());
|
t.getValidUntil());
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +110,7 @@ public class OneTimeAuthTokenCleaner {
|
||||||
tokens.stream()
|
tokens.stream()
|
||||||
.filter((token) -> (!oneTimeAuthManager.isValid(token)))
|
.filter((token) -> (!oneTimeAuthManager.isValid(token)))
|
||||||
.forEach((token) -> {
|
.forEach((token) -> {
|
||||||
LOGGER.debug("Token with id {} expired at {}. "
|
LOGGER.debug("Token with id {} expired at {} UTC. "
|
||||||
+ "Invalidating token.",
|
+ "Invalidating token.",
|
||||||
token.getTokenId(), token.getValidUntil());
|
token.getTokenId(), token.getValidUntil());
|
||||||
oneTimeAuthManager.invalidate(token);
|
oneTimeAuthManager.invalidate(token);
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,13 @@ import javax.xml.bind.annotation.XmlTransient;
|
||||||
+ "LOWER(u.name) LIKE CONCAT(LOWER(:term), '%') "
|
+ "LOWER(u.name) LIKE CONCAT(LOWER(:term), '%') "
|
||||||
+ "OR LOWER(u.givenName) LIKE CONCAT(LOWER(:term), '%') "
|
+ "OR LOWER(u.givenName) LIKE CONCAT(LOWER(:term), '%') "
|
||||||
+ "OR LOWER(u.familyName) LIKE CONCAT(LOWER(:term), '%') "
|
+ "OR LOWER(u.familyName) LIKE CONCAT(LOWER(:term), '%') "
|
||||||
+ "OR LOWER(u.primaryEmailAddress.address) LIKE CONCAT('%', LOWER(:term), '%')")
|
+ "OR LOWER(u.primaryEmailAddress.address) LIKE CONCAT('%', LOWER(:term), '%')"),
|
||||||
|
@NamedQuery(
|
||||||
|
name = "User.findAllOrderedByUsername",
|
||||||
|
query = "SELECT u FROM User u ORDER BY u.name, "
|
||||||
|
+ " u.familyName, "
|
||||||
|
+ " u.givenName, "
|
||||||
|
+ " u.primaryEmailAddress.address")
|
||||||
})
|
})
|
||||||
@NamedEntityGraphs({
|
@NamedEntityGraphs({
|
||||||
@NamedEntityGraph(
|
@NamedEntityGraph(
|
||||||
|
|
@ -98,7 +104,6 @@ import javax.xml.bind.annotation.XmlTransient;
|
||||||
@NamedAttributeNode(value = "permissions")}
|
@NamedAttributeNode(value = "permissions")}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
@DefaultEntityGraph("User.withGroupAndRoleMemberships")
|
@DefaultEntityGraph("User.withGroupAndRoleMemberships")
|
||||||
@XmlRootElement(name = "user", namespace = CORE_XML_NS)
|
@XmlRootElement(name = "user", namespace = CORE_XML_NS)
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,13 @@ public class UserManager {
|
||||||
* Creates a new user and saves the user in the database. The method also
|
* Creates a new user and saves the user in the database. The method also
|
||||||
* creates the password hash.
|
* creates the password hash.
|
||||||
*
|
*
|
||||||
* @param givenName The given name of the new user.
|
* @param givenName The given name of the new user.
|
||||||
* @param familyName The family name of the new user.
|
* @param familyName The family name of the new user.
|
||||||
* @param name The name of the new user.
|
* @param name The name of the new user.
|
||||||
* @param emailAddress The email address of the new user.
|
* @param emailAddress The email address of the new user.
|
||||||
* @param password The password of the new user. The password is hashed
|
* @param password The password of the new user. The password is hashed
|
||||||
* using the algorithm configured in the {@link SecurityConfig}.
|
* using the algorithm configured in the
|
||||||
|
* {@link SecurityConfig}.
|
||||||
*
|
*
|
||||||
* @return The new user.
|
* @return The new user.
|
||||||
*/
|
*/
|
||||||
|
|
@ -77,7 +78,11 @@ public class UserManager {
|
||||||
email.setAddress(emailAddress);
|
email.setAddress(emailAddress);
|
||||||
user.setPrimaryEmailAddress(email);
|
user.setPrimaryEmailAddress(email);
|
||||||
email.setVerified(true);
|
email.setVerified(true);
|
||||||
user.setPassword(hashPassword(password));
|
if (password == null) {
|
||||||
|
user.setPassword(null);
|
||||||
|
} else {
|
||||||
|
user.setPassword(hashPassword(password));
|
||||||
|
}
|
||||||
|
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
|
|
||||||
|
|
@ -90,9 +95,9 @@ public class UserManager {
|
||||||
* the user can't login or that the authentication for this user is done by
|
* the user can't login or that the authentication for this user is done by
|
||||||
* an external system.
|
* an external system.
|
||||||
*
|
*
|
||||||
* @param user The user which password should be upgraded.
|
* @param user The user which password should be upgraded.
|
||||||
* @param newPassword The new password. The password is hashed using the
|
* @param newPassword The new password. The password is hashed using the
|
||||||
* algorithm configured in the {@link SecurityConfig}.
|
* algorithm configured in the {@link SecurityConfig}.
|
||||||
*/
|
*/
|
||||||
public void updatePassword(@NotNull final User user,
|
public void updatePassword(@NotNull final User user,
|
||||||
final String newPassword) {
|
final String newPassword) {
|
||||||
|
|
@ -105,11 +110,11 @@ public class UserManager {
|
||||||
* Verifies the password of a user. This can be useful if you want to verify
|
* Verifies the password of a user. This can be useful if you want to verify
|
||||||
* the password of a user already logged in again.
|
* the password of a user already logged in again.
|
||||||
*
|
*
|
||||||
* @param user The user against which the password is verified.
|
* @param user The user against which the password is verified.
|
||||||
* @param password The password to verify.
|
* @param password The password to verify.
|
||||||
*
|
*
|
||||||
* @return {@code true} if the provided passworda matches the password from
|
* @return {@code true} if the provided passworda matches the password from
|
||||||
* the database, {@code false} otherwise.
|
* the database, {@code false} otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean verifyPassword(final User user, final String password) {
|
public boolean verifyPassword(final User user, final String password) {
|
||||||
//Create a new Shiro PasswordMatcher instance
|
//Create a new Shiro PasswordMatcher instance
|
||||||
|
|
@ -142,9 +147,10 @@ public class UserManager {
|
||||||
//We want to use the Shiro1 format for storing the password. This
|
//We want to use the Shiro1 format for storing the password. This
|
||||||
//format includes the algorithm used, the salt and the number of
|
//format includes the algorithm used, the salt and the number of
|
||||||
//iterations used and the hashed password in special formatted string.
|
//iterations used and the hashed password in special formatted string.
|
||||||
final HashFormatFactory hashFormatFactory = new DefaultHashFormatFactory();
|
final HashFormatFactory hashFormatFactory
|
||||||
|
= new DefaultHashFormatFactory();
|
||||||
final HashFormat hashFormat = hashFormatFactory.getInstance(
|
final HashFormat hashFormat = hashFormatFactory.getInstance(
|
||||||
Shiro1CryptFormat.class.getName());
|
Shiro1CryptFormat.class.getName());
|
||||||
|
|
||||||
return hashFormat.format(hash);
|
return hashFormat.format(hash);
|
||||||
}
|
}
|
||||||
|
|
@ -160,11 +166,13 @@ public class UserManager {
|
||||||
|
|
||||||
if (generatedSaltSize % 8 != 0) {
|
if (generatedSaltSize % 8 != 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Salt length is not a multipe of 8");
|
"Salt length is not a multipe of 8");
|
||||||
}
|
}
|
||||||
|
|
||||||
final SecureRandomNumberGenerator generator = new SecureRandomNumberGenerator();
|
final SecureRandomNumberGenerator generator
|
||||||
|
= new SecureRandomNumberGenerator();
|
||||||
final int byteSize = generatedSaltSize / 8; //generatedSaltSize is in *bits* - convert to byte size:
|
final int byteSize = generatedSaltSize / 8; //generatedSaltSize is in *bits* - convert to byte size:
|
||||||
return generator.nextBytes(byteSize);
|
return generator.nextBytes(byteSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -153,4 +153,10 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<User> findAllOrderdByUsername() {
|
||||||
|
final TypedQuery<User> query = getEntityManager().createNamedQuery(
|
||||||
|
"User.findAllOrderedByUsername", User.class);
|
||||||
|
return query.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -228,3 +228,12 @@ ui.admin.new_user_form.error.username_already_in_use=The provided user name is a
|
||||||
ui.admin.new_user_form.error.email_already_in_use=The provided email address is already assigned with an user account.
|
ui.admin.new_user_form.error.email_already_in_use=The provided email address is already assigned with an user account.
|
||||||
ui.admin.new_user_form.error.password_do_not_match=Passwords do not match.
|
ui.admin.new_user_form.error.password_do_not_match=Passwords do not match.
|
||||||
ui.admin.new_user_form.error.failed_to_send_password=Failed to send password to new user.
|
ui.admin.new_user_form.error.failed_to_send_password=Failed to send password to new user.
|
||||||
|
ui.admin.new_user_form.password_options.set_password=Set password
|
||||||
|
ui.admin.user_details.groups=Groups
|
||||||
|
ui.admin.user.groups.edit=Edit
|
||||||
|
ui.admin.user.roles=Directly assigned Roles
|
||||||
|
ui.admin.user.roles.edit=Edit
|
||||||
|
ui.admin.user.all_roles=All roles
|
||||||
|
ui.admin.user.groups=Groups
|
||||||
|
ui.admin.user.edit_group_memberships=Edit group memberships for user {0}
|
||||||
|
ui.admin.user.edit_group_memberships.back_to_user_details=Back to user details
|
||||||
|
|
|
||||||
|
|
@ -228,3 +228,12 @@ ui.admin.new_user_form.error.username_already_in_use=Der angegebene Benutzername
|
||||||
ui.admin.new_user_form.error.email_already_in_use=Die angegebene E-Mail-Adresse ist bereits mit einem Benutzerkonto verbunden.
|
ui.admin.new_user_form.error.email_already_in_use=Die angegebene E-Mail-Adresse ist bereits mit einem Benutzerkonto verbunden.
|
||||||
ui.admin.new_user_form.error.password_do_not_match=Die eingegebenen Passw\u00f6rter stimmen nicht \u00fcberein.
|
ui.admin.new_user_form.error.password_do_not_match=Die eingegebenen Passw\u00f6rter stimmen nicht \u00fcberein.
|
||||||
ui.admin.new_user_form.error.failed_to_send_password=Fehler beim Senden des Passworts an den neuen Benutzer.
|
ui.admin.new_user_form.error.failed_to_send_password=Fehler beim Senden des Passworts an den neuen Benutzer.
|
||||||
|
ui.admin.new_user_form.password_options.set_password=Passwert setzen
|
||||||
|
ui.admin.user_details.groups=Gruppen
|
||||||
|
ui.admin.user.groups.edit=Bearbeiten
|
||||||
|
ui.admin.user.roles=Zugewiesene Rollen
|
||||||
|
ui.admin.user.roles.edit=Bearbeiten
|
||||||
|
ui.admin.user.all_roles=Alle Rollen
|
||||||
|
ui.admin.user.groups=Gruppen
|
||||||
|
ui.admin.user.edit_group_memberships=Gruppen f\u00fcr Benutzer {0} bearbeiten
|
||||||
|
ui.admin.user.edit_group_memberships.back_to_user_details=Zur\u00fcck zu den Eigenschaften des Benutzers
|
||||||
|
|
|
||||||
|
|
@ -201,3 +201,12 @@ ui.admin.new_user_form.error.username_already_in_use=The provided user name is a
|
||||||
ui.admin.new_user_form.error.email_already_in_use=The provided email address is already assigned with an user account.
|
ui.admin.new_user_form.error.email_already_in_use=The provided email address is already assigned with an user account.
|
||||||
ui.admin.new_user_form.error.password_do_not_match=Passwords do not match.
|
ui.admin.new_user_form.error.password_do_not_match=Passwords do not match.
|
||||||
ui.admin.new_user_form.error.failed_to_send_password=Failed to send password to new user.
|
ui.admin.new_user_form.error.failed_to_send_password=Failed to send password to new user.
|
||||||
|
ui.admin.new_user_form.password_options.set_password=Set password
|
||||||
|
ui.admin.user_details.groups=Groups
|
||||||
|
ui.admin.user.groups.edit=Edit
|
||||||
|
ui.admin.user.roles=Directly assigned Roles
|
||||||
|
ui.admin.user.roles.edit=Edit
|
||||||
|
ui.admin.user.all_roles=All roles
|
||||||
|
ui.admin.user.groups=Groups
|
||||||
|
ui.admin.user.edit_group_memberships=Edit group memberships for user {0}
|
||||||
|
ui.admin.user.edit_group_memberships.back_to_user_details=Back to user details
|
||||||
|
|
|
||||||
|
|
@ -192,3 +192,12 @@ ui.admin.new_user_form.error.username_already_in_use=The provided user name is a
|
||||||
ui.admin.new_user_form.error.email_already_in_use=The provided email address is already assigned with an user account.
|
ui.admin.new_user_form.error.email_already_in_use=The provided email address is already assigned with an user account.
|
||||||
ui.admin.new_user_form.error.password_do_not_match=Passwords do not match.
|
ui.admin.new_user_form.error.password_do_not_match=Passwords do not match.
|
||||||
ui.admin.new_user_form.error.failed_to_send_password=Failed to send password to new user.
|
ui.admin.new_user_form.error.failed_to_send_password=Failed to send password to new user.
|
||||||
|
ui.admin.new_user_form.password_options.set_password=Set password
|
||||||
|
ui.admin.user_details.groups=Groups
|
||||||
|
ui.admin.user.groups.edit=Edit
|
||||||
|
ui.admin.user.roles=Directly assigned Roles
|
||||||
|
ui.admin.user.roles.edit=Edit
|
||||||
|
ui.admin.user.all_roles=All roles
|
||||||
|
ui.admin.user.groups=Groups
|
||||||
|
ui.admin.user.edit_group_memberships=Edit group memberships for user {0}
|
||||||
|
ui.admin.user.edit_group_memberships.back_to_user_details=Back to user details
|
||||||
|
|
|
||||||
|
|
@ -101,3 +101,9 @@ login.form.reset_password.auth_token.hint=Please provide the one time authentica
|
||||||
login.form.account_activation.success=Your account has been activated.
|
login.form.account_activation.success=Your account has been activated.
|
||||||
login.form.new_user.error.passwords_do_not_match=Password and confirmation do not match.
|
login.form.new_user.error.passwords_do_not_match=Password and confirmation do not match.
|
||||||
login.form_new_user.error.creating_challenge_failed=Failed to send registration confirmation. Please contact the administrator.
|
login.form_new_user.error.creating_challenge_failed=Failed to send registration confirmation. Please contact the administrator.
|
||||||
|
login.form.account_activation.success.login=Click here to login.
|
||||||
|
login.form.reset_password.error=Error while resetting password.
|
||||||
|
login.form.reset_password.error.password_mismatch=Password and confirmation do not match.
|
||||||
|
login.form.new_user.error.username_already_in_use=The provided user name is already in use. Please choose another user name.
|
||||||
|
login.form.new_user.error.email_already_registered=There is an account already registered for the provided email address.
|
||||||
|
login.form.reset_password.scucess.login=Click here to login
|
||||||
|
|
|
||||||
|
|
@ -101,3 +101,9 @@ login.form.reset_password.auth_token.hint=Bitte geben Sie das Einmalpasswort, da
|
||||||
login.form.account_activation.success=Ihr Benutzerkonto wurde aktiviert.
|
login.form.account_activation.success=Ihr Benutzerkonto wurde aktiviert.
|
||||||
login.form.new_user.error.passwords_do_not_match=Passwort und Best\u00e4tigung sind nicht gleich
|
login.form.new_user.error.passwords_do_not_match=Passwort und Best\u00e4tigung sind nicht gleich
|
||||||
login.form_new_user.error.creating_challenge_failed=Fehler beim Senden der Anmeldebest\u00e4tigung. Bitte kontaktieren Sie den Systemadministrator.
|
login.form_new_user.error.creating_challenge_failed=Fehler beim Senden der Anmeldebest\u00e4tigung. Bitte kontaktieren Sie den Systemadministrator.
|
||||||
|
login.form.account_activation.success.login=Klicken Sie hier, um sich anzumelden.
|
||||||
|
login.form.reset_password.error=Beim \u00c4ndern des Passwortes ist ein Fehler aufgetreten.
|
||||||
|
login.form.reset_password.error.password_mismatch=Passwort und Best\u00e4tigung stimmen nicht \u00fcberein.
|
||||||
|
login.form.new_user.error.username_already_in_use=Der eingegeben Benutzername ist bereits vergeben. Bitte w\u00e4hlen Sie einen anderen Benutzernamen.
|
||||||
|
login.form.new_user.error.email_already_registered=Es gibt bereits ein Benutzerkonto f\u00fcr die eingebene E-Mail-Adresse
|
||||||
|
login.form.reset_password.scucess.login=Zur Anmeldung
|
||||||
|
|
|
||||||
|
|
@ -101,3 +101,9 @@ login.form.reset_password.auth_token.hint=Please provide the one time authentica
|
||||||
login.form.account_activation.success=Your account has been activated.
|
login.form.account_activation.success=Your account has been activated.
|
||||||
login.form.new_user.error.passwords_do_not_match=Password and confirmation do not match.
|
login.form.new_user.error.passwords_do_not_match=Password and confirmation do not match.
|
||||||
login.form_new_user.error.creating_challenge_failed=Failed to send registration confirmation. Please contact the administrator.
|
login.form_new_user.error.creating_challenge_failed=Failed to send registration confirmation. Please contact the administrator.
|
||||||
|
login.form.account_activation.success.login=Click here to login.
|
||||||
|
login.form.reset_password.error=Error while resetting password.
|
||||||
|
login.form.reset_password.error.password_mismatch=Password and confirmation do not match.
|
||||||
|
login.form.new_user.error.username_already_in_use=The provided user name is already in use. Please choose another user name.
|
||||||
|
login.form.new_user.error.email_already_registered=There is an account already registered for the provided email address.
|
||||||
|
login.form.reset_password.scucess.login=Click here to login
|
||||||
|
|
|
||||||
|
|
@ -101,3 +101,9 @@ login.form.reset_password.auth_token.hint=Please provide the one time authentica
|
||||||
login.form.account_activation.success=Your account has been activated.
|
login.form.account_activation.success=Your account has been activated.
|
||||||
login.form.new_user.error.passwords_do_not_match=Password and confirmation do not match.
|
login.form.new_user.error.passwords_do_not_match=Password and confirmation do not match.
|
||||||
login.form_new_user.error.creating_challenge_failed=Failed to send registration confirmation. Please contact the administrator.
|
login.form_new_user.error.creating_challenge_failed=Failed to send registration confirmation. Please contact the administrator.
|
||||||
|
login.form.account_activation.success.login=Click here to login.
|
||||||
|
login.form.reset_password.error=Error while resetting password.
|
||||||
|
login.form.reset_password.error.password_mismatch=Password and confirmation do not match.
|
||||||
|
login.form.new_user.error.username_already_in_use=The provided user name is already in use. Please choose another user name.
|
||||||
|
login.form.new_user.error.email_already_registered=There is an account already registered for the provided email address.
|
||||||
|
login.form.reset_password.scucess.login=Click here to login
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue