/*******************************************************************************
* Copyright 2013
* Ubiquitous Knowledge Processing (UKP) Lab
* Technische Universität Darmstadt
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package de.tudarmstadt.ukp.csniper.webapp.security.page;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.EmailTextField;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.ListChoice;
import org.apache.wicket.markup.html.form.ListMultipleChoice;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.validation.EqualPasswordInputValidator;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.ValidationError;
import org.springframework.security.core.context.SecurityContextHolder;
import de.tudarmstadt.ukp.csniper.webapp.page.ApplicationPageBase;
import de.tudarmstadt.ukp.csniper.webapp.page.welcome.WelcomePage;
import de.tudarmstadt.ukp.csniper.webapp.security.dao.UserDao;
import de.tudarmstadt.ukp.csniper.webapp.security.model.Role;
import de.tudarmstadt.ukp.csniper.webapp.security.model.User;
public class ManageUsersPage
extends ApplicationPageBase
{
private static final long serialVersionUID = -2102136855109258306L;
@SpringBean(name = "userRepository")
private UserDao userRepository;
private class SelectionForm
extends Form<SelectionModel>
{
private static final long serialVersionUID = -1L;
public SelectionForm(String id)
{
super(id, new CompoundPropertyModel<SelectionModel>(new SelectionModel()));
add(new Button("create", new ResourceModel("label"))
{
private static final long serialVersionUID = 1L;
@Override
public void onSubmit()
{
actionSelectionChanged(null);
actionCreate();
}
});
add(new Button("delete", new ResourceModel("label"))
{
private static final long serialVersionUID = 1L;
@Override
protected void onConfigure()
{
// disable delete button when active user is selected
setEnabled(selectionForm.getModelObject().user != null
&& !selectionForm.getModelObject().user.equals(getActiveUser()));
}
@Override
public void onSubmit()
{
actionDelete();
}
});
add(new ListChoice<User>("user")
{
private static final long serialVersionUID = 1L;
{
setChoices(new LoadableDetachableModel<List<User>>()
{
private static final long serialVersionUID = 1L;
@Override
protected List<User> load()
{
return userRepository.list();
}
});
setChoiceRenderer(new ChoiceRenderer<User>("username"));
setNullValid(false);
}
@Override
protected void onSelectionChanged(User aNewSelection)
{
actionSelectionChanged(aNewSelection);
}
@Override
protected boolean wantOnSelectionChangedNotifications()
{
return true;
}
@Override
protected CharSequence getDefaultChoice(String aSelectedValue)
{
return "";
}
});
}
}
static private class SelectionModel
implements Serializable
{
private static final long serialVersionUID = -1L;
private User user;
}
private class DetailForm
extends Form<User>
{
private static final long serialVersionUID = -1L;
public transient Model<String> passwordModel = new Model<String>();
public transient Model<String> repeatPasswordModel = new Model<String>();
public DetailForm(String id)
{
super(id, new CompoundPropertyModel<User>(new Model<User>(new User())));
add(new TextField<String>("username").setOutputMarkupId(true));
add(new PasswordTextField("password", passwordModel).setRequired(false));
add(new PasswordTextField("repeatPassword", repeatPasswordModel).setRequired(false));
add(new EmailTextField("email"));
WebMarkupContainer adminOnly = new WebMarkupContainer("adminOnly");
adminOnly.add(new ListMultipleChoice<Role>("roles",
new ArrayList<Role>(Role.getRoles())).add(new IValidator<Collection<Role>>()
{
private static final long serialVersionUID = 1L;
@Override
public void validate(IValidatable<Collection<Role>> aValidatable)
{
Collection<Role> newRoles = aValidatable.getValue();
// if (newRoles.isEmpty()) {
// aValidatable.error(new ValidationError()
// .setMessage("A user has to have at least one role."));
// }
// enforce users to have at least the ROLE_USER role
if (!newRoles.contains(Role.ROLE_USER)) {
aValidatable.error(new ValidationError()
.setMessage("Every user has to be a user."));
}
// don't let an admin user strip himself of admin rights
if (getActiveUser().equals(getModelObject())
&& !newRoles.contains(Role.ROLE_ADMIN)) {
aValidatable.error(new ValidationError()
.setMessage("You can't remove your own admin status."));
}
}
}));
adminOnly.add(new CheckBox("enabled").add(new IValidator<Boolean>()
{
private static final long serialVersionUID = 1L;
@Override
public void validate(IValidatable<Boolean> aValidatable)
{
if (!aValidatable.getValue() && getActiveUser().equals(getModelObject())) {
aValidatable.error(new ValidationError()
.setMessage("You can't disable your own account."));
}
}
}));
adminOnly.setVisible(isAdmin());
add(adminOnly);
add(new Button("save", new ResourceModel("label"))
{
private static final long serialVersionUID = 1L;
@Override
public void onSubmit()
{
actionSave();
}
});
add(new Button("cancel", new ResourceModel("label"))
{
private static final long serialVersionUID = 1L;
@Override
public void onSubmit()
{
actionCancel();
}
}.setDefaultFormProcessing(false));
add(new EqualPasswordInputValidator((FormComponent<?>) get("password"),
(FormComponent<?>) get("repeatPassword")));
}
public String getPassword()
{
return passwordModel.getObject();
}
}
private SelectionForm selectionForm;
private DetailForm detailForm;
public ManageUsersPage()
{
selectionForm = new SelectionForm("selectionForm");
detailForm = new DetailForm("detailForm");
// show only selectionForm when accessing this page as admin
if (isAdmin()) {
detailForm.setVisible(false);
}
// else show only the own options
else {
actionSelectionChanged(getActiveUser());
selectionForm.setVisible(false);
}
add(selectionForm);
add(detailForm);
}
public void actionSelectionChanged(User aNewSelection)
{
if (aNewSelection != null) {
detailForm.setModelObject(aNewSelection);
detailForm.setVisible(true);
detailForm.get("username").setEnabled(false);
}
else {
detailForm.setVisible(false);
}
}
public void actionCreate()
{
selectionForm.getModelObject().user = null;
detailForm.setModelObject(new User());
detailForm.setVisible(true);
detailForm.get("username").setEnabled(true);
}
public void actionDelete()
{
User user = selectionForm.getModelObject().user;
if (user != null) {
userRepository.delete(user);
}
selectionForm.getModelObject().user = null;
selectionForm.get("user").detachModels();
detailForm.setVisible(false);
info("User [" + user.getUsername() + "] has been removed.");
}
public void actionSave()
{
User user = detailForm.getModelObject();
if (detailForm.getPassword() != null) {
user.setPassword(detailForm.getPassword());
}
if (!userRepository.exists(user.getUsername())) {
userRepository.create(user);
}
else {
userRepository.update(user);
}
if (isAdmin()) {
detailForm.setModelObject(new User());
detailForm.setVisible(false);
}
selectionForm.getModelObject().user = null;
info("User details have been saved.");
}
public void actionCancel()
{
if (isAdmin()) {
detailForm.detach();
detailForm.setModelObject(new User());
detailForm.setVisible(false);
}
else {
setResponsePage(WelcomePage.class);
}
}
private boolean isAdmin()
{
return getActiveUser().getRoles().contains(Role.ROLE_ADMIN);
}
private User getActiveUser()
{
String authedUsername = SecurityContextHolder.getContext().getAuthentication().getName();
return userRepository.get(authedUsername);
}
}