/*
* Copyright 2006 University of Dundee. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.services.sec.test;
import static omero.rtypes.rstring;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import ome.conditions.SecurityViolation;
import ome.model.core.Pixels;
import omero.ServerError;
import omero.api.ServiceFactoryPrx;
import omero.model.DatasetI;
import omero.model.Details;
import omero.model.DetailsI;
import omero.model.Experimenter;
import omero.model.ExperimenterGroup;
import omero.model.IObject;
import omero.model.Image;
import omero.model.Permissions;
import omero.model.PermissionsI;
import omero.model.Project;
import omero.model.ProjectDatasetLinkI;
import omero.model.ProjectI;
import org.testng.annotations.Test;
@Test(enabled=false, groups = { "broken", "ticket:337", "security", "integration" })
public class UseSecurityTest extends AbstractPermissionsTest {
// unlike READ and WRITE tests, we don't need to repeat the tests for each
// user
// create and the the test is what the user is trying to change.
// what's allowed when locked. then it makes sense to also test root
// too see if it will fail. don't need to test the unlinkable
// configurations.
boolean will_lock;
// ~ single
// =========================================================================
// single plays little role in USE, but verify not locked
@Override
public void testSingleProject_U() throws Exception {
createProject(u, new PermissionsI(RW_Rx_Rx.toString()), user_other_group);
verifyDetails(prj, user, user_other_group, new PermissionsI(RW_Rx_Rx.toString()));
}
@Override
public void testSingleProject_W() throws Exception {
createProject(w, new PermissionsI(RW_Rx_Rx.toString()), common_group);
verifyDetails(prj, world, common_group, new PermissionsI(RW_Rx_Rx.toString()));
}
@Override
public void testSingleProject_R() throws Exception {
createProject(r, new PermissionsI(RW_Rx_Rx.toString()), system_group);
verifyDetails(prj, root, system_group, new PermissionsI(RW_Rx_Rx.toString()));
}
// ~ one-to-many
// =========================================================================
@Override
public void test_U_Pixels_And_U_Thumbnails() throws Exception {
ownsfA = u;
ownerA = user;
groupA = user_other_group;
ownsfB = u;
ownerB = user;
groupB = user_other_group;
will_lock = true;
// RW_RW_RW / RW_RW_RW
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_RW.toString());
oneToMany(ownsfA, false, RW_xx_xx, common_group);
oneToMany(r, true, other);
// RW_RW_RW / RW_RW_Rx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_Rx.toString());
oneToMany(ownsfA, false, RW_xx_xx, common_group);
oneToMany(r, true, other);
// RW_RW_RW / RW_RW_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_xx.toString());
oneToMany(ownsfA, false, RW_xx_xx, common_group);
oneToMany(r, true, other);
// RW_RW_RW / RW_Rx_Rx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_Rx_Rx.toString());
oneToMany(ownsfA, false, RW_xx_xx, common_group);
oneToMany(r, true, other);
// RW_RW_RW / RW_xx_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
oneToMany(ownsfA, false, RW_xx_xx, common_group);
oneToMany(r, true, other);
// RW_RW_Rx / RW_RW_Rx
permsA = new PermissionsI(RW_RW_Rx.toString());
permsB = new PermissionsI(RW_RW_Rx.toString());
oneToMany(ownsfA, false, RW_xx_xx, common_group);
oneToMany(r, true, other);
// RW_RW_xx / RW_RW_xx
permsA = new PermissionsI(RW_RW_xx.toString());
permsB = new PermissionsI(RW_RW_xx.toString());
oneToMany(ownsfA, false, RW_xx_xx, common_group);
oneToMany(r, false, other);
// RW_Rx_Rx / RW_Rx_Rx
permsA = new PermissionsI(RW_Rx_Rx.toString());
permsB = new PermissionsI(RW_Rx_Rx.toString());
oneToMany(ownsfA, false, RW_xx_xx, common_group);
oneToMany(r, true, other);
// RW_xx_xx / RW_xx_xx
permsA = new PermissionsI(RW_xx_xx.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
oneToMany(ownsfA, false, xx_xx_xx, common_group);
oneToMany(r, false, other);
// Rx_Rx_Rx / Rx_Rx_Rx
permsA = new PermissionsI(Rx_Rx_Rx.toString());
permsB = new PermissionsI(Rx_Rx_Rx.toString());
oneToMany(ownsfA, false, RW_xx_xx, common_group);
oneToMany(r, true, other);
// xx_xx_xx / xx_xx_xx No need. can't create.
}
private void oneToMany(ServiceFactoryPrx ownsfA, boolean b,
Permissions rwXxXx, omero.model.ExperimenterGroup commonGroup)
{
// TODO Auto-generated method stub
//
throw new RuntimeException("Not implemented yet.");
}
@Override
public void test_O_Pixels_And_U_Thumbnails() throws Exception {
ownsfA = o;
ownerA = other;
groupA = user_other_group;
ownsfB = u;
ownerB = user;
groupB = user_other_group;
will_lock = true;
// RW_RW_RW / RW_RW_RW
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_RW.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, user);
// RW_RW_RW / RW_RW_Rx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_Rx.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, user);
// RW_RW_RW / RW_RW_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_xx.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, user);
// RW_RW_RW / RW_xx_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, user);
// RW_RW_RW / xx_xx_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(xx_xx_xx.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, user);
// RW_RW_xx / RW_xx_xx
permsA = new PermissionsI(RW_RW_xx.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, false, user);
}
/** */
@Override
public void test_U_Pixels_And_O_Thumbnails() throws Exception {
ownsfA = u;
ownerA = user;
groupA = user_other_group;
ownsfB = o;
ownerB = other;
groupB = user_other_group;
will_lock = true;
// RW_RW_RW / RW_RW_RW
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_RW.toString());
oneToMany(ownsfB, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, other);
// RW_RW_RW / RW_RW_Rx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_Rx.toString());
oneToMany(ownsfB, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, other);
// RW_RW_RW / RW_RW_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_xx.toString());
oneToMany(ownsfB, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, other);
// RW_RW_RW / RW_xx_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
oneToMany(ownsfB, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, other);
// RW_RW_RW / xx_xx_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(xx_xx_xx.toString());
oneToMany(ownsfB, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, other);
// RW_RW_xx / RW_xx_xx
permsA = new PermissionsI(RW_RW_xx.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
oneToMany(ownsfB, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, false, other);
}
@Override
public void test_U_Pixels_And_R_Thumbnails() throws Exception {
ownsfA = u;
ownerA = user;
groupA = user_other_group;
ownsfB = r;
ownerB = root;
groupB = system_group;
will_lock = true;
// root can read everything and so can lock everything.
// RW_RW_RW / RW_RW_RW
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_RW.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, other);
// RW_RW_RW / RW_RW_Rx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_Rx.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, other);
// RW_RW_RW / RW_RW_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_xx.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, other);
// RW_RW_RW / RW_xx_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, other);
// RW_RW_RW / xx_xx_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(xx_xx_xx.toString());
oneToMany(ownsfA, false, common_group, RW_xx_xx, RW_RW_xx);
oneToMany(r, true, other);
// RW_xx_xx / RW_xx_xx
permsA = new PermissionsI(RW_xx_xx.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
oneToMany(ownsfA, false, common_group, xx_xx_xx, RW_RW_xx);
oneToMany(r, false, other);
// xx_xx_xx / xx_xx_xx
permsA = new PermissionsI(xx_xx_xx.toString());
permsB = new PermissionsI(xx_xx_xx.toString());
oneToMany(ownsfA, false, common_group);
oneToMany(r, false, other);
}
protected void oneToMany(ServiceFactoryPrx sf, boolean can_change,
Object... details_changed) throws Exception {
// whether or not this is valid is handled in the ReadSecurityTest.
// an exception here means something went wrong elsewhere; most likely,
// that one tried to creat objects with permissions xx_xx_xx
createPixels(ownsfA, groupA, permsA);
verifyDetails(pix, ownerA, groupA, permsA);
createThumbnail(ownsfB, groupB, permsB, pix);
verifyDetails(tb, ownerB, groupB, permsB);
}
// ~ unidirectional many-to-one
// =========================================================================
/** */
@Override
public void test_U_Instrument_And_U_Microscope() throws Exception {
ownsfA = ownsfB = u;
ownerA = ownerB = user;
groupA = groupB = user_other_group;
will_lock = true;
// root can read everything and so can lock everything.
// RW_RW_RW / RW_RW_RW
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_RW.toString());
uniManyToOne(ownsfA, false, common_group, new PermissionsI(RW_xx_xx.toString()), new PermissionsI(RW_RW_xx.toString()));
uniManyToOne(r, true, other);
}
protected void uniManyToOne(ServiceFactoryPrx sf, boolean can_change,
Object... details_changed) throws Exception {
// whether or not this is valid is handled in the ReadSecurityTest.
// an exception here means something went wrong elsewhere; most likely,
// that one tried to creat objects with permissions xx_xx_xx
createMicroscope(ownsfA, groupA, permsA);
verifyDetails(micro, ownerA, groupA, permsA);
createInstrument(ownsfB, groupB, permsB, micro);
verifyDetails(instr, ownerB, groupB, permsB);
// it is not at all easy to clear a Pixels locked status, but
// microscope should be easy enough
if (will_lock) {
r.getUpdateService().deleteObject(instr);
List<IObject> micros = new ArrayList<IObject>();
micros.add(micro);
// boolean[] unlocked = r.getAdminService().unlock(micros);
// assertTrue(unlocked[0]); ticket:2039 - TOO BE REMOVED
}
}
// ~ many-to-many
// =========================================================================
@Override
public void test_U_Projects_U_Datasets_U_Link() throws Exception {
ownsfA = ownsfB = ownsfC = u;
ownerA = ownerB = ownerC = user;
groupA = groupB = groupC = user_other_group;
// RW_RW_RW / RW_RW_RW / RW_RW_RW
permsA = permsB = permsC = new PermissionsI(RW_RW_RW.toString());
manyToMany();
// RW_RW_RW / RW_RW_xx / RW_RW_RW
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_xx.toString());
permsC = new PermissionsI(RW_RW_RW.toString());
manyToMany();
// RW_RW_RW / RW_xx_xx / RW_RW_RW
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
permsC = new PermissionsI(RW_RW_RW.toString());
manyToMany();
}
// TODO add to abstract class.
@Test(enabled=false, groups = "ticket:553")
public void test_U_Projects_O_Datasets_O_Link() throws Exception {
ownsfA = u;
ownerA = user;
groupA = user_other_group;
ownsfB = ownsfC = o;
ownerB = ownerC = other;
groupB = groupC = user_other_group;
will_lock = true;
// RW_RW_RW / RW_RW_RW / RW_RW_RW
permsA = permsB = permsC = new PermissionsI(RW_RW_RW.toString());
manyToMany();
// RW_RW_RW / RW_RW_xx / RW_RW_RW
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_xx.toString());
permsC = new PermissionsI(RW_RW_RW.toString());
manyToMany();
// RW_RW_RW / RW_xx_xx / RW_RW_RW
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
permsC = new PermissionsI(RW_RW_RW.toString());
manyToMany();
}
/**
* performs various write operations on linked projects and datasets.
*/
protected void manyToMany() throws Exception {
createProject(ownsfA, permsA, groupA);
verifyDetails(prj, ownerA, groupA, permsA);
createDataset(ownsfB, permsB, groupB);
verifyDetails(ds, ownerB, groupB, permsB);
createPDLink(ownsfC, permsC, groupC);
verifyDetails(link, ownerC, groupC, permsC);
r.getUpdateService().deleteObject(link);
// boolean[] unlocked = r.getAdminService().unlock(Arrays.asList(prj, ds));
// assertTrue(unlocked[0]);
// assertTrue(unlocked[1]);ticket:2039 - TOO BE REMOVED
}
// ~ Special: "tag" (e.g. Image/Pixels)
// =========================================================================
// Note: in 3.0-Beta3 the special tag was removed. This test is now
// disabled.
@Override
@Test(enabled = false)
public void test_U_Image_U_Pixels() throws Exception {
ownsfA = ownsfB = u;
ownerA = ownerB = user;
groupA = groupB = user_other_group;
will_lock = true;
// RW_RW_RW / RW_RW_RW
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_RW.toString());
imagePixels(u, false, false, common_group);
imagePixels(r, true, true, other);
// RW_RW_RW / RW_RW_Rx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_RW_xx.toString());
imagePixels(u, false, false, common_group);
imagePixels(r, true, false, other);
// RW_RW_RW / RW_xx_xx
permsA = new PermissionsI(RW_RW_RW.toString());
permsB = new PermissionsI(RW_xx_xx.toString());
imagePixels(u, false, false, common_group);
imagePixels(r, true, false, other);
}
protected void imagePixels(ServiceFactoryPrx sf, boolean can_change_img,
boolean can_change_pix, Object... details_changed) throws Exception {
// whether or not this is valid is handled in the ReadSecurityTest.
// an exception here means something went wrong elsewhere; most likely,
// that one tried to create objects with permissions xx_xx_xx
createPixels(ownsfB, groupB, permsB);
createImage(ownsfA, groupA, permsA, pix);
verifyDetails(img, ownerA, groupA, permsA);
verifyDetails(pix, ownerB, groupB, permsB);
}
// ~ Other
// ========================================================================
@Test(enabled=false)
public void testNoLoadOnNonReadableProxy() throws Exception {
Permissions USER_PRIVATE = new PermissionsI(ome.model.internal.Permissions.USER_PRIVATE.toString());
prj = new ProjectI();
prj.setName(rstring("noloadonnonreadable"));
prj.getDetails().setPermissions(USER_PRIVATE);
prj = (Project) u.getUpdateService().saveAndReturnObject(prj);
prj.unload();
ds = new DatasetI();
ds.setName(rstring("tryingtoattachtononloadablenonreadable"));
link = new ProjectDatasetLinkI();
link.link(prj, ds);
try {
w.getUpdateService().saveObject(link);
fail("secvio!: A user should not be able to pass in an unreadable, unloaded"
+ " proxy and have it linked. This would allow RW to suffice"
+ " for RW*U*");
} catch (SecurityViolation sv) {
// ok.
}
}
@Test(enabled=false, groups = "ticket:339")
public void test_HandlesExplicitPermissionReduction() throws Exception {
prj = new ProjectI();
prj.setName(rstring("ticket:339"));
ds = new DatasetI();
ds.setName(rstring("ticket:339"));
prj.linkDataset(ds);
Permissions perms = new PermissionsI(ome.model.internal.Permissions.READ_ONLY.toString()); // relatively common
// use-case
prj.getDetails().setPermissions(perms);
Project t = (Project) u.getUpdateService().saveAndReturnObject(prj);
}
// ~ Helpers
// =========================================================================
private void assertSucceeds(ServiceFactoryPrx sf) throws ServerError {
prj = (Project) sf.getUpdateService().saveAndReturnObject(prj);
}
private void assertFails(ServiceFactoryPrx sf) throws ServerError {
try {
assertSucceeds(sf);
fail("secvio!");
} catch (SecurityViolation sv) {
// ok
}
}
private void assertNoChange(ServiceFactoryPrx sf) throws Exception {
Permissions p1 = prj.getDetails().getPermissions();
prj = (Project) sf.getUpdateService().saveAndReturnObject(prj);
Permissions p2 = prj.getDetails().getPermissions();
assertSameRights(p1, p2);
}
protected Details d(IObject _i, Object _o) {
fail("IMPLEMENT: ticket:1478");
// Details retVal = _i.getDetails().copy();
Details retVal = new DetailsI();
// prevent error on different update event versions.
retVal.setCreationEvent(null);
retVal.setUpdateEvent(null);
if (_o instanceof Experimenter) {
Experimenter _e = (Experimenter) _o;
retVal.setOwner(_e);
} else if (_o instanceof ExperimenterGroup) {
ExperimenterGroup _g = (ExperimenterGroup) _o;
retVal.setGroup(_g);
} else if (_o instanceof Permissions) {
Permissions _p = (Permissions) _o;
retVal.setPermissions(_p);
} else {
throw new IllegalArgumentException("Not user/group/permissions:"
+ _o);
}
return retVal;
}
}