/*
*------------------------------------------------------------------------------
* Copyright (C) 2014-2015 University of Dundee. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package integration;
import static org.testng.AssertJUnit.assertNotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import omero.RString;
import omero.api.IAdminPrx;
import omero.api.IContainerPrx;
import omero.api.ServiceFactoryPrx;
import omero.cmd.Chgrp2;
import omero.cmd.CmdCallbackI;
import omero.cmd.DoAll;
import omero.cmd.DoAllRsp;
import omero.cmd.ERR;
import omero.cmd.HandlePrx;
import omero.cmd.OK;
import omero.cmd.Request;
import omero.cmd.Response;
import omero.gateway.util.Requests;
import omero.model.Experimenter;
import omero.model.ExperimenterGroup;
import omero.model.ExperimenterGroupI;
import omero.model.ExperimenterI;
import omero.model.FileAnnotation;
import omero.model.FileAnnotationI;
import omero.model.IObject;
import omero.model.Image;
import omero.model.ImageAnnotationLink;
import omero.model.ImageAnnotationLinkI;
import omero.model.ImageI;
import omero.model.OriginalFile;
import omero.model.Permissions;
import omero.model.PermissionsI;
import omero.model.TagAnnotation;
import omero.model.TagAnnotationI;
import omero.model.TermAnnotation;
import omero.model.TermAnnotationI;
import omero.sys.ParametersI;
import omero.sys.Roles;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import omero.gateway.model.GroupData;
import omero.gateway.model.PermissionData;
import com.google.common.collect.ImmutableMap;
/**
*
*
* @author Balaji Ramalingam
* <a href="mailto:b.ramalingam@dundee.ac.uk">b.ramalingam@dundee.ac.uk</a>
* @since 5.1
*/
public class PermissionsTestAll extends AbstractServerTest {
private final String uuid = UUID.randomUUID().toString();
private final String[] testGroupTypes = { "rwra--", "rw----", "rwr---",
"rwrw--" };
private final List<String> subsetOfTestGroups = Arrays.asList(
testGroupTypes[0], testGroupTypes[3]);
private final String[] testUserNames = { "notOwner-notAdmin-1" + uuid,
"notOwner-notAdmin2" + uuid, "owner" + uuid, "admin" + uuid,
"notOwner-notAdmin-ra" + uuid, "notOwner-notAdmin-p" + uuid,
"notOwner-notAdmin-ro" + uuid, "notOwner-notAdmin-rw" + uuid };
private final Map<String, String> testGroupTypeNameMap = ImmutableMap.of(
"rwra--", "Read-Annotate-" + uuid + "-",
"rw----", "Private-" + uuid + "-",
"rwr---", "Read-Only-" + uuid + "-",
"rwrw--", "Read-Write-" + uuid + "-"
);
/** The security roles for that server. **/
private Roles securityRoles;
/** The password used for user. **/
private final static String PASSWORD = "ome";
@Override
@BeforeClass
protected void setUp() throws Exception {
super.setUp();
setupGroups();
setupTestImages();
annotateAllImages();
}
/**
* Sets up the groups.
* @throws Exception Thrown if an error occurred.
*/
void setupGroups() throws Exception {
omero.client client = newRootOmeroClient();
client.enableKeepAlive(60);
factory = client.getSession();
IAdminPrx svc = factory.getAdminService();
securityRoles = svc.getSecurityRoles();
List<ExperimenterGroup> groups = new ArrayList<ExperimenterGroup>();
List<ExperimenterGroup> groupCopies = new ArrayList<ExperimenterGroup>();
// Create two copies of every group type mentioned above
for (int i = 1; i <= 2; i++) {
for (Entry<String, String> groupTypeName : testGroupTypeNameMap
.entrySet()) {
String groupName = groupTypeName.getValue()
+ Integer.toString(i);
ExperimenterGroup group = new ExperimenterGroupI();
group.setName(omero.rtypes.rstring(groupName));
group.setLdap(omero.rtypes.rbool(false));
final Permissions perms = new PermissionsI(
groupTypeName.getKey());
group.getDetails().setPermissions(perms);
group = new ExperimenterGroupI(svc.createGroup(group), false);
groups.add(group);
if (i == 1) {
groupCopies.add(group);
}
}
}
RString omeroPassword = omero.rtypes.rstring(PASSWORD);
String admin = testUserNames[3];
String owner = testUserNames[2];
Roles roles = factory.getAdminService().getSecurityRoles();
ExperimenterGroup userGroup = new ExperimenterGroupI(roles.userGroupId,
false);
ExperimenterGroup systemGroup = new ExperimenterGroupI(
roles.systemGroupId, false);
int cntr = 0;
ExperimenterGroup defaultGroup;
List<ExperimenterGroup> targetGroups;
for (int i = 0; i < testUserNames.length; i++) {
targetGroups = new ArrayList<ExperimenterGroup>();
targetGroups.add(userGroup);
String username = testUserNames[i];
Experimenter experimenter = createExperimenterI(username,
username, username);
// Add admin user to system group
if (username.equalsIgnoreCase(admin)) {
defaultGroup = systemGroup;
targetGroups.addAll(groups);
} else if (i <= 3) {
// Add the first 4 users to all groups
defaultGroup = groups.get(0);
targetGroups.addAll(groups);
} else {
// Add the last 4 users to one group alone
defaultGroup = groups.get(cntr);
targetGroups.add(groupCopies.get(cntr));
cntr++;
}
factory.getAdminService().createExperimenterWithPassword(
experimenter, omeroPassword, defaultGroup, targetGroups);
// Make user : owner + uuid , owner of all the groups
if (username.equalsIgnoreCase(owner)) {
Experimenter user = svc.lookupExperimenter(testUserNames[i]);
for (int l = 0; l < targetGroups.size(); l++) {
svc.setGroupOwner(new ExperimenterGroupI(targetGroups
.get(l).getId(), false),
new ExperimenterI(user.getId(), false));
}
}
}
client.closeSession();
}
/**
* Creates 11 images for each user.
*
* @throws Exception
* Thrown if an error occurred during creation.
*/
void setupTestImages() throws Exception {
// Iterate through all the users
for (int i = 0; i < testUserNames.length; i++) {
omero.client client = new omero.client();
ServiceFactoryPrx session = client
.createSession(testUserNames[i], PASSWORD);
client.enableKeepAlive(60);
IAdminPrx adminSvc = session.getAdminService();
Experimenter user = adminSvc.lookupExperimenter(testUserNames[i]);
List<Long> groupIds = adminSvc.getMemberOfGroupIds(user);
// Switch group context for the user (Iterate through all the
// groups, the user is part of)
for (int j = 0; j < groupIds.size(); j++) {
long groupId = groupIds.get(j);
if (!isSecuritySystemGroup(groupId)) {
ExperimenterGroupI group = new ExperimenterGroupI(groupId,
false);
session.setSecurityContext(group);
iUpdate = session.getUpdateService();
mmFactory = new ModelMockFactory(session.getPixelsService());
// Create new Image Objects(with pixels) and attach it to
// the session
for (int k = 0; k <= groupIds.size(); k++) {
Image img = (Image) iUpdate
.saveAndReturnObject(mmFactory.simpleImage());
assertNotNull(img);
}
}
}
client.closeSession();
}
}
/**
* Annotates all the images created.
* @throws Exception Thrown if an error occurred.
*/
void annotateAllImages() throws Exception {
for (int i = 0; i < testUserNames.length; i++) {
omero.client client = new omero.client();
ServiceFactoryPrx session = client
.createSession(testUserNames[i], PASSWORD);
String commentText = testUserNames[i] + "_comment";
String tagText = testUserNames[i] + "_tag";
IAdminPrx adminSvc = session.getAdminService();
Experimenter user = adminSvc.lookupExperimenter(testUserNames[i]);
List<Long> userGroups = adminSvc.getMemberOfGroupIds(user);
Long userId = user.getId().getValue();
for (int j = 0; j < userGroups.size(); j++) {
if (!isSecuritySystemGroup(userGroups.get(j))) {
ExperimenterGroup group = adminSvc.getGroup(userGroups.get(j));
String permsAsString = permissionsAsString(group);
session.setSecurityContext(new ExperimenterGroupI(group.getId()
.getValue(), false));
iUpdate = session.getUpdateService();
mmFactory = new ModelMockFactory(session.getPixelsService());
List<Long> annotationIds = new ArrayList<Long>();
// Create Tags
TagAnnotation tag = new TagAnnotationI();
tag.setTextValue(omero.rtypes.rstring(tagText));
tag = (TagAnnotation) iUpdate.saveAndReturnObject(tag);
annotationIds.add(tag.getId().getValue());
// Create Comments
TermAnnotation comment = new TermAnnotationI();
comment.setTermValue(omero.rtypes.rstring(commentText));
comment = (TermAnnotation) iUpdate.saveAndReturnObject(comment);
annotationIds.add(comment.getId().getValue());
// Create File for FileAnnotation
OriginalFile originalFile = (OriginalFile) iUpdate
.saveAndReturnObject(mmFactory.createOriginalFile());
assertNotNull(originalFile);
FileAnnotation file = new FileAnnotationI();
file.setFile(originalFile);
file = (FileAnnotation) iUpdate.saveAndReturnObject(file);
annotationIds.add(file.getId().getValue());
ParametersI params = new omero.sys.ParametersI();
params.exp(user.getId());
IContainerPrx proxy = session.getContainerService();
List<Image> imageList = proxy.getUserImages(params);
for (int k = 0; k < imageList.size(); k++) {
Image img = imageList.get(k);
Long imageId = img.getId().getValue();
Long ownerId = img.getDetails().getOwner().getId().getValue();
if (ownerId == userId || subsetOfTestGroups.contains(permsAsString)) {
List<IObject> links = new ArrayList<IObject>();
// Create Links for Tags
ImageAnnotationLink link = new ImageAnnotationLinkI();
link.setChild(new TagAnnotationI(tag.getId().getValue(),
false));
link.setParent(new ImageI(imageId, false));
links.add(link);
// Create Links for Comments
link = new ImageAnnotationLinkI();
link.setChild(new TermAnnotationI(comment.getId().getValue(),
false));
link.setParent(new ImageI(imageId, false));
links.add(link);
// Create Links for Files
link = new ImageAnnotationLinkI();
link.setChild(new FileAnnotationI(file.getId().getValue(),
false));
link.setParent(new ImageI(imageId, false));
links.add(link);
iUpdate.saveAndReturnArray(links);
}
}
}
}
client.closeSession();
}
}
@Override
@AfterClass
public void tearDown() throws Exception {
}
/**
* Generates data for each user.
* @return Object[][] data.
*/
@DataProvider(name = "createData")
public Object[][] createData() throws Exception {
List<TestParam> testParams = new ArrayList<TestParam>();
Object[][] data = null;
for (int i = 0; i < testUserNames.length; i++) {
omero.client client = new omero.client();
ServiceFactoryPrx session = client.createSession(testUserNames[i],
PASSWORD);
Experimenter experimenter = session.getAdminService()
.lookupExperimenter(testUserNames[i]);
List<Long> groupIds = session.getAdminService()
.getMemberOfGroupIds(experimenter);
int n = groupIds.size();
for (int j = 0; j < n; j++) {
Long userId = session.getAdminService()
.getEventContext().userId;
ParametersI params = new omero.sys.ParametersI();
params.exp(omero.rtypes.rlong(userId));
long sourceGroup = groupIds.get(j);
if (!isSecuritySystemGroup(sourceGroup)) {
ExperimenterGroupI group = new ExperimenterGroupI(
sourceGroup, false);
session.setSecurityContext(group);
IContainerPrx proxy = session.getContainerService();
List<Image> images = proxy.getUserImages(params);
Image img = null;
for (int k = 0; k < n; k++) {
Long targetGroup = groupIds.get(k);
if (!isSecuritySystemGroup(targetGroup)
&& targetGroup != sourceGroup) {
img = images.get(k);
long imageId = img.getId().getValue();
final Chgrp2 dc = Requests.chgrp("Image", imageId, targetGroup);
testParams.add(new TestParam(dc, testUserNames[i],
PASSWORD, sourceGroup));
}
}
}
}
int index = 0;
Iterator<TestParam> testParamsIter = testParams.iterator();
data = new Object[testParams.size()][1];
while (testParamsIter.hasNext()) {
data[index][0] = testParamsIter.next();
index++;
}
}
return data;
}
/**
* Tests the move of data.
* @param param Hold information about the data to move.
* @throws Exception Thrown if an error occurred.
*/
@Test(dataProvider = "createData")
public void test(TestParam param) throws Exception {
String username = param.getUser();
String passwd = param.getPass();
Long sourceGroup = param.getSrcID();
// create session and switch context to source group
omero.client client = new omero.client();
ServiceFactoryPrx session = client.createSession(username, passwd);
ExperimenterGroupI group = new ExperimenterGroupI(sourceGroup, false);
session.setSecurityContext(group);
DoAll all = new DoAll();
List<Request> requests = new ArrayList<Request>();
requests.add(param.getChgrp());
all.requests = requests;
HandlePrx handle = session.submit(all);
long timeoutMove = scalingFactor * 1 * 100;
CmdCallbackI cb = new CmdCallbackI(client, handle);
cb.loop(10 * all.requests.size(), timeoutMove);
Response response = cb.getResponse();
Long userId = session.getAdminService().getEventContext().userId;
long targetGroup = param.getChgrp().groupId;
List<Long> targets = param.getChgrp().targetObjects.get(
Image.class.getSimpleName());
long imageId = targets.get(0);
if (response == null) {
String sourceGroupPerms = permissionsAsString(session
.getAdminService().getGroup(sourceGroup));
String targetGroupPerms = permissionsAsString(session
.getAdminService().getGroup(targetGroup));
Assert.fail("Failure : User id: " + userId + " (" + username + ")"
+ " tried moving image " + imageId + " from " + sourceGroup
+ "(" + sourceGroupPerms + ")" + " to " + targetGroup + "("
+ targetGroupPerms + ") no response returned");
} else if (response instanceof DoAllRsp) {
List<Response> responses = ((DoAllRsp) response).responses;
if (responses.size() == 1) {
Response r = responses.get(0);
Assert.assertTrue(r instanceof OK, "move OK");
}
} else if (response instanceof ERR) {
String sourceGroupPerms = permissionsAsString(session
.getAdminService().getGroup(sourceGroup));
String targetGroupPerms = permissionsAsString(session
.getAdminService().getGroup(targetGroup));
ERR err = (ERR) response;
Map<String, String> responseParameters = err.parameters;
StringBuffer buf = new StringBuffer();
for (Entry<String, String> responseParameter : responseParameters
.entrySet()) {
buf.append(responseParameter.getKey() + " -> "
+ responseParameter.getValue());
}
Assert.fail("Failure : User id: " + userId + " (" + username + ")"
+ " tried moving image " + imageId + " from " + sourceGroup
+ "(" + sourceGroupPerms + ")" + " to " + targetGroup + "("
+ targetGroupPerms + ") "+buf.toString());
}
client.closeSession();
}
/**
* Implemented as specified by {@link AdminService}.
*/
private boolean isSecuritySystemGroup(long groupID) {
if (securityRoles == null) {
return false;
}
return (securityRoles.guestGroupId == groupID
|| securityRoles.systemGroupId == groupID
|| securityRoles.userGroupId == groupID);
}
/**
* Extracts the permission of a group and presents it in string form.
*
* @param experimenterGroup
* the target group.
* @return String the group permissions.
*/
private String permissionsAsString(ExperimenterGroup experimenterGroup) {
PermissionData perms = new PermissionData(experimenterGroup
.getDetails().getPermissions());
switch (perms.getPermissionsLevel()) {
case GroupData.PERMISSIONS_GROUP_READ:
return "rwr---";
case GroupData.PERMISSIONS_GROUP_READ_LINK:
return "rwra--";
case GroupData.PERMISSIONS_GROUP_READ_WRITE:
return "rwrw--";
case GroupData.PERMISSIONS_PUBLIC_READ:
return "rwrwr-";
default:
return "rw----";
}
}
/**
* Inner class hosting information about object to move.
*
*/
class TestParam {
/** Hold information about the object to move.*/
private Chgrp2 chgrp;
/** The user to log as.*/
private String user;
/** The user's password.*/
private String password;
/** The identifier of the group to move the data from.*/
private Long srcID;
/**
* Creates a new instance.
*
* @param chgrp Hold information about the object to move.
* @param user The user to log as.
* @param password The user's password.
* @param srcID The identifier of the group to move the data from.
*/
TestParam(Chgrp2 chgrp, String user, String password, Long srcID) {
this.chgrp = chgrp;
this.user = user;
this.password = password;
this.srcID = srcID;
}
/**
* Returns the information object to move.
*
* @return See above.
*/
Chgrp2 getChgrp() {
return chgrp;
}
/**
* Returns the user to log as.
*
* @return See above.
*/
String getUser() {
return user;
}
/**
* Returns the user's password.
*
* @return See above.
*/
String getPass() {
return password;
}
/**
* Returns the identifier of the group to move the data from.
*
* @return See above.
*/
Long getSrcID() {
return srcID;
}
}
}