package edu.ualberta.med.biobank.common.action.security;
import java.util.Set;
import edu.ualberta.med.biobank.common.action.Action;
import edu.ualberta.med.biobank.common.action.ActionContext;
import edu.ualberta.med.biobank.common.action.IdResult;
import edu.ualberta.med.biobank.common.action.exception.ActionException;
import edu.ualberta.med.biobank.common.permission.Permission;
import edu.ualberta.med.biobank.common.permission.security.UserManagerPermission;
import edu.ualberta.med.biobank.model.Domain;
import edu.ualberta.med.biobank.model.Group;
import edu.ualberta.med.biobank.model.Membership;
import edu.ualberta.med.biobank.model.User;
import edu.ualberta.med.biobank.util.SetDiff;
import edu.ualberta.med.biobank.util.SetDiff.Pair;
public class GroupSaveAction implements Action<IdResult> {
private static final long serialVersionUID = 1L;
private static final Permission PERMISSION = new UserManagerPermission();
private final GroupSaveInput input;
public GroupSaveAction(GroupSaveInput input) {
this.input = input;
}
@Override
public boolean isAllowed(ActionContext context) throws ActionException {
return PERMISSION.isAllowed(context);
}
@Override
public IdResult run(ActionContext context) throws ActionException {
User executingUser = context.getUser();
Group group = context.get(Group.class, input.getGroupId(), new Group());
checkFullyManageable(group, executingUser);
group.setName(input.getName());
group.setDescription(input.getDescription());
Set<User> users = context.load(User.class, input.getUserIds());
group.getUsers().clear();
group.getUsers().addAll(users);
setMemberships(context, group);
checkFullyManageable(group, executingUser);
context.getSession().saveOrUpdate(group);
return new IdResult(group.getId());
}
private void checkFullyManageable(Group group, User executingUser) {
if (!group.isFullyManageable(executingUser)) {
// TODO: better message
throw new ActionException("group is not manageable");
}
}
private void setMemberships(ActionContext context, Group group) {
SetDiff<Membership> diff = new SetDiff<Membership>(
group.getMemberships(), input.getMemberships());
for (Membership m : diff.getRemovals()) {
group.getMemberships().remove(m);
context.getSession().delete(m);
}
for (Membership m : diff.getAdditions()) {
group.getMemberships().add(m);
m.setPrincipal(group);
}
for (Pair<Membership> pair : diff.getIntersection()) {
Membership oldM = pair.getOld();
Membership newM = pair.getNew();
oldM.getPermissions().clear();
oldM.getPermissions().addAll(newM.getPermissions());
oldM.getRoles().clear();
oldM.getRoles().addAll(newM.getRoles());
oldM.setUserManager(newM.isUserManager());
oldM.setEveryPermission(newM.isEveryPermission());
// TODO: throw away old domain, copy into new? Shorter.
Domain newD = newM.getDomain();
Domain oldD = oldM.getDomain();
oldD.getCenters().clear();
oldD.getCenters().addAll(newD.getCenters());
oldD.setAllCenters(newD.isAllCenters());
oldD.getStudies().clear();
oldD.getStudies().addAll(newD.getStudies());
oldD.setAllStudies(newD.isAllStudies());
}
for (Membership m : group.getMemberships()) {
m.reducePermissions();
}
}
}