diff --git a/src/edu/ucsb/nceas/metacat/dataone/MNodeService.java b/src/edu/ucsb/nceas/metacat/dataone/MNodeService.java index fe1a4adc1..cdc30f26d 100644 --- a/src/edu/ucsb/nceas/metacat/dataone/MNodeService.java +++ b/src/edu/ucsb/nceas/metacat/dataone/MNodeService.java @@ -483,6 +483,17 @@ public Identifier update(Session session, Identifier pid, InputStream object, D1AuthHelper authDel = new D1AuthHelper(request,pid,"1200","1310"); authDel.doUpdateAuth(session, existingSysMeta, Permission.WRITE, this.getCurrentNodeId()); allowed = true; + //only the users who have the the change_permission can change access rules + try { + authDel.doUpdateAuth(session, existingSysMeta, Permission.CHANGE_PERMISSION, this.getCurrentNodeId()); + } catch(ServiceFailure e) { + throw new ServiceFailure("1310", "Can't determine if the client has the permission to update the object with id " + pid.getValue() + " since "+e.getDescription()); + } catch(NotAuthorized e) { + //now the user doesn't have the change the permission. If the access rules in the new and old system metadata are the same, it is fine; otherwise, Metacat throws an exception + if (!D1NodeService.equals(sysmeta.getAccessPolicy(), existingSysMeta.getAccessPolicy())) { + throw new NotAuthorized("1200", "Can't update the object with id " + pid.getValue() + " since the user try to change the access rules without the change permission: " + e.getDescription()); + } + } } catch(ServiceFailure e) { throw new ServiceFailure("1310", "Can't determine if the client has the permission to update the object with id "+pid.getValue()+" since "+e.getDescription()); } catch(NotAuthorized e) { diff --git a/test/edu/ucsb/nceas/metacat/dataone/MNodeServiceTest.java b/test/edu/ucsb/nceas/metacat/dataone/MNodeServiceTest.java index 83b0ec40d..a6c4d0eec 100644 --- a/test/edu/ucsb/nceas/metacat/dataone/MNodeServiceTest.java +++ b/test/edu/ucsb/nceas/metacat/dataone/MNodeServiceTest.java @@ -746,6 +746,57 @@ public void testUpdate() { } catch (InvalidRequest ee) { //assertTrue(ee.getMessage().contains(newPid.getValue())); } + + //test update an object with new access rules + Subject write = new Subject(); + write.setValue("Write"); + Session writeSession = new Session(); + writeSession.setSubject(write); + Subject change = new Subject(); + change.setValue("Change"); + Session changeSession = new Session(); + changeSession.setSubject(change); + + Identifier guid20 = new Identifier(); + guid20.setValue("testUpdatewithAccessChange." + System.currentTimeMillis()); + object = new ByteArrayInputStream("test".getBytes("UTF-8")); + sysmeta = createSystemMetadata(guid20, session.getSubject(), object); + AccessRule writeRule = new AccessRule(); + writeRule.addSubject(write); + writeRule.addPermission(Permission.WRITE); + sysmeta.getAccessPolicy().addAllow(writeRule); + AccessRule changeRule = new AccessRule(); + changeRule.addSubject(change); + changeRule.addPermission(Permission.CHANGE_PERMISSION); + sysmeta.getAccessPolicy().addAllow(changeRule); + MNodeService.getInstance(request).create(session, guid20, object, sysmeta); + + //the write user fails to update the object since it modified the access rules of the original one + Identifier guid21 = new Identifier(); + guid21.setValue("testUpdatewithAccessChange2." + System.currentTimeMillis()); + object = new ByteArrayInputStream("test".getBytes("UTF-8")); + updatedSysMeta = createSystemMetadata(guid21, session.getSubject(), object); + try { + MNodeService.getInstance(request).update(writeSession, guid20, object, guid21, updatedSysMeta); + fail("The write-permission-only user can't change the access rules"); + } catch (Exception ee) { + assertTrue( ee instanceof NotAuthorized); + } + + //the write user can update the object without modifying access rules + object = new ByteArrayInputStream("test".getBytes("UTF-8")); + updatedSysMeta = createSystemMetadata(guid21, session.getSubject(), object); + updatedSysMeta.getAccessPolicy().addAllow(writeRule); + updatedSysMeta.getAccessPolicy().addAllow(changeRule); + MNodeService.getInstance(request).update(writeSession, guid20, object, guid21, updatedSysMeta); + + //the change user can update the object even with the modified access rules + Identifier guid22 = new Identifier(); + guid22.setValue("testUpdatewithAccessChange3." + System.currentTimeMillis()); + object = new ByteArrayInputStream("test".getBytes("UTF-8")); + updatedSysMeta = createSystemMetadata(guid22, session.getSubject(), object); + MNodeService.getInstance(request).update(changeSession, guid21, object, guid22, updatedSysMeta); + } catch (UnsupportedEncodingException e) { e.printStackTrace(); fail("Unexpected error: " + e.getMessage());