package service.filestore; import static org.fest.assertions.Assertions.assertThat; import static org.junit.Assert.fail; import static play.test.Helpers.running; import static test.AorraTestUtils.fakeAorraApp; import static test.AorraTestUtils.fileStore; import static test.AorraTestUtils.jcrom; import static test.AorraTestUtils.sessionFactory; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import javax.jcr.AccessDeniedException; import javax.jcr.ItemExistsException; import javax.jcr.RepositoryException; import javax.jcr.Session; import models.GroupManager; import models.User; import models.UserDAO; import org.junit.Test; import com.google.common.io.ByteStreams; import play.Logger; import play.libs.F.Function; import service.JcrSessionFactory; import service.filestore.FileStore.Folder; import service.filestore.roles.Admin; public class FileStoreTest { @Test public void canGetRootFolder() { running(fakeAorraApp(), new Runnable() { @Override public void run() { sessionFactory().inSession(new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { FileStore.Manager fm = fileStore().getManager(session); Set<FileStore.Folder> folders = fileStore().getManager(session).getFolders(); assertThat(folders).hasSize(1); FileStore.Folder folder = folders.iterator().next(); assertThat(folder.getPath()).isEqualTo("/"); assertThat(folder.getParent()).isNull(); assertThat(folder.getDepth()).isEqualTo(0); assertThat(fm.getRoot().getIdentifier()) .isEqualTo(folder.getIdentifier()); // Following the removal of identifier-based equality, this is no // longer the case. //assertThat(fm.getByIdentifier(folder.getIdentifier())) // .isEqualTo(folder); return folder.getIdentifier(); } }); } }); } @Test public void equality() { running(fakeAorraApp(), new Runnable() { @Override public void run() { sessionFactory().inSession(new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { FileStore.Manager fm = fileStore().getManager(session); final FileStore.Folder folder = fm.getRoot().createFolder("test"); final FileStore.File file = folder.createFile("test", "text/plain", new ByteArrayInputStream("Hello World!".getBytes())); // Check folder equality assertThat(folder).isEqualTo(folder); assertThat(folder).isNotEqualTo(null); assertThat(folder).isNotEqualTo(file); assertThat(fm.getRoot()).isNotEqualTo(folder); assertThat(fm.getRoot()).isEqualTo(fm.getRoot()); // Check file equality assertThat(file).isEqualTo(file); assertThat(file).isNotEqualTo(null); assertThat(file).isNotEqualTo(folder); assertThat(file).isEqualTo(folder.getFileOrFolder("test")); // Versions are different to files assertThat(file).isNotEqualTo(file.getVersions().last()); return folder.getIdentifier(); } }); } }); } @Test public void parentKnowsOfChildren() { running(fakeAorraApp(), new Runnable() { @Override public void run() { sessionFactory().inSession(new Function<Session,Session>() { @Override public Session apply(Session session) throws RepositoryException { FileStore.Manager fm = fileStore().getManager(session); final FileStore.Folder folder = fm.getRoot().createFolder("test"); assertThat(folder.getFiles()).isEmpty(); { final FileStore.File file = folder.createFile("test1", "text/plain", new ByteArrayInputStream("Hello World!".getBytes())); assertThat(file.getParent()).isEqualTo(folder); assertThat(folder.getFiles()).isNotEmpty(); assertThat(folder.getFiles()).containsOnly(file); } { final FileStore.File file = folder.createFile("test2", "text/plain", new ByteArrayInputStream("Hello World!".getBytes())); assertThat(file.getParent()).isEqualTo(folder); assertThat(folder.getFiles()).hasSize(2); assertThat(folder.getFiles()).contains(file); } return session; } }); } }); } @Test public void noImplicitOverwriting() { running(fakeAorraApp(), new Runnable() { @Override public void run() { sessionFactory().inSession(new Function<Session,Session>() { @Override public Session apply(Session session) throws RepositoryException { final FileStore.Manager fm = fileStore().getManager(session); final FileStore.Folder rootFolder = fm.getRoot(); // Test overwritting folder { final FileStore.Folder folder = rootFolder.createFolder("test"); try { rootFolder.createFolder("test"); fail("Should have thrown ItemExistsException."); } catch (ItemExistsException e) { // All good } try { rootFolder.createFile("test", "text/plain", new ByteArrayInputStream("Hello World!".getBytes())); fail("Should have thrown ItemExistsException."); } catch (ItemExistsException e) { // All good } folder.delete(); } // Test overwritting file { final FileStore.File file = rootFolder.createFile("test", "text/plain", new ByteArrayInputStream("Hello World!".getBytes())); try { rootFolder.createFolder("test"); fail("Should have thrown ItemExistsException."); } catch (ItemExistsException e) { // All good } try { rootFolder.createFile("test", "text/plain", new ByteArrayInputStream("Hello World!".getBytes())); fail("Should have thrown ItemExistsException."); } catch (ItemExistsException e) { // All good } file.delete(); } // Test overwritting file by rename { final FileStore.File file1 = rootFolder.createFile("test", "text/plain", new ByteArrayInputStream("Hello World!".getBytes())); final FileStore.File file2 = rootFolder.createFile("rename.me", "text/plain", new ByteArrayInputStream("Hello World!".getBytes())); assertThat(rootFolder.getFiles()).hasSize(2); assertThat(file1.getParent()).isEqualTo(rootFolder); assertThat(file2.getParent()).isEqualTo(rootFolder); try { file2.rename("test"); fail("Should have thrown ItemExistsException."); } catch (ItemExistsException e) { // All good } assertThat(fm.getByIdentifier(file2.getIdentifier()).getName()) .isEqualTo("rename.me"); } return session; } }); } }); } @Test public void permissionOrder() { assertThat(FileStore.Permission.RW.isAtLeast(FileStore.Permission.RW)) .isTrue(); assertThat(FileStore.Permission.RW.isAtLeast(FileStore.Permission.RO)) .isTrue(); assertThat(FileStore.Permission.RO.isAtLeast(FileStore.Permission.RO)) .isTrue(); assertThat(FileStore.Permission.RO.isAtLeast(FileStore.Permission.RW)) .isFalse(); assertThat(FileStore.Permission.NONE.isAtLeast(FileStore.Permission.RW)) .isFalse(); assertThat(FileStore.Permission.NONE.isAtLeast(FileStore.Permission.RO)) .isFalse(); } @Test public void adminGroupPermissions() { running(fakeAorraApp(true), new Runnable() { @Override public void run() { final JcrSessionFactory sessionFactory = sessionFactory(); final FileStore fileStoreImpl = fileStore(); final String userId = sessionFactory.inSession( new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { // Create new user final String userId; UserDAO dao = new UserDAO(session, jcrom()); User user = new User(); user.setEmail("user@example.com"); user.setName("Test User"); user = dao.create(user); String token = user.createVerificationToken(); user.checkVerificationToken(token); dao.setPassword(user, "password"); userId = user.getJackrabbitUserId(); return userId; } }); sessionFactory.inSession(userId, new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { // Unprivileged users should see no folders Set<FileStore.Folder> folders = fileStoreImpl.getManager(session).getFolders(); assertThat(folders).hasSize(0); return null; } }); sessionFactory.inSession(new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { final GroupManager gm = new GroupManager(session); final String gAdmin = "testAdmin"; final String gNone = "testNone"; Admin.getInstance(session).getGroup().addMember(gm.create(gAdmin)); gm.create(gNone); session.save(); final FileStoreImpl.Folder rootFolder = (FileStoreImpl.Folder) fileStoreImpl.getManager(session).getRoot(); assertThat(rootFolder.getGroupPermissions().containsKey(gAdmin)) .as("created admin group has a listed permission") .isTrue(); assertThat(rootFolder.getGroupPermissions().containsKey(gNone)) .as("created unprivileged group has a listed permission") .isTrue(); assertThat(rootFolder.getGroupPermissions().get(gAdmin)) .as("created admin group has RW permissions") .isEqualTo(FileStore.Permission.RW); assertThat(rootFolder.getGroupPermissions().get(gNone)) .as("created unprivileged group has no permissions") .isEqualTo(FileStore.Permission.NONE); // Assign new user to admin group gm.addMember("testAdmin", userId); return userId; } }); sessionFactory.inSession(userId, new Function<Session,FileStore.Folder>() { @Override public FileStore.Folder apply(Session session) throws RepositoryException, IOException { { // Check user with admin sees only one root folder Set<FileStore.Folder> folders = fileStoreImpl.getManager(session).getFolders(); assertThat(folders).hasSize(1); } final FileStore.Folder rootFolder = fileStoreImpl.getManager(session).getRoot(); final String filename = "README.txt"; final String mimeType = "text/plain"; final String content = "Test content."; try { final FileStore.Manager fm = fileStoreImpl.getManager(session); final FileStore.File f = rootFolder.createFile(filename, mimeType, new ByteArrayInputStream(content.getBytes())); // Check the parent is correct right after save assertThat(f.getParent().getIdentifier()) .isEqualTo(rootFolder.getIdentifier()); final FileStore.FileOrFolder fof = fm.getFileOrFolder("/"+filename); assertThat(fof).isInstanceOf(FileStore.File.class); assertThat(fof).isEqualTo(f); final FileStore.File file = (FileStore.File) fof; assertThat(file.getIdentifier()).isNotNull(); assertThat(file.getName()).isEqualTo(filename); assertThat(file.getPath()).isEqualTo("/"+filename); assertThat(file.getDepth()).isEqualTo(1); assertThat(file.getMimeType()).isEqualTo(mimeType); // Check the parent is correct on retrieval assertThat(file.getParent().getIdentifier()) .isEqualTo(rootFolder.getIdentifier()); // Check the author info assertThat(file.getAuthor()).isNotNull(); assertThat(file.getAuthor().getJackrabbitUserId()) .isEqualTo(userId); assertThat(ByteStreams.toByteArray(file.getData())) .isEqualTo(content.getBytes()); assertThat(fm.getByIdentifier(file.getIdentifier())) .isEqualTo(file); } catch (AccessDeniedException ade) { Logger.debug("Access unexpectedly denied.", ade); fail("An admin user should be able to create a file."); } return rootFolder; } }); } }); } @Test public void groupPermissions() { running(fakeAorraApp(true), new Runnable() { @Override public void run() { final JcrSessionFactory sessionFactory = sessionFactory(); final FileStore fileStoreImpl = fileStore(); final String userId = sessionFactory.inSession( new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { // Create new user final String userId; UserDAO dao = new UserDAO(session, jcrom()); User user = new User(); user.setEmail("user@example.com"); user.setName("Test User"); user = dao.create(user); String token = user.createVerificationToken(); user.checkVerificationToken(token); dao.setPassword(user, "password"); userId = user.getJackrabbitUserId(); return userId; } }); sessionFactory.inSession(userId, new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { // Unprivileged users should see no folders Set<FileStore.Folder> folders = fileStoreImpl.getManager(session).getFolders(); assertThat(folders).hasSize(0); return null; } }); // Grant access to testGroup sessionFactory.inSession(new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { final GroupManager gm = new GroupManager(session); final String g = "testGroup"; gm.create(g); session.save(); final Folder rootFolder = fileStoreImpl.getManager(session).getRoot(); // Assign new user to admin group gm.addMember(g, userId); final FileStore.Folder testFolder = rootFolder.createFolder("test"); testFolder.grantAccess(g, FileStore.Permission.RW); return userId; } }); // Check granted access sessionFactory.inSession(userId, new Function<Session,FileStore.Folder>() { @Override public FileStore.Folder apply(Session session) throws RepositoryException, IOException { final Set<FileStore.Folder> folders = fileStoreImpl.getManager(session).getFolders(); assertThat(folders).hasSize(1); final FileStore.Folder folder = folders.iterator().next(); assertThat(folder.getPath()).isEqualTo("/test"); return folder; } }); // Revoke access to test group sessionFactory.inSession(new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { final FileStore.Folder testFolder = (FileStore.Folder) fileStoreImpl.getManager(session).getFileOrFolder("/test"); testFolder.revokeAccess("testGroup"); return userId; } }); // Check revoked access sessionFactory.inSession(userId, new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { // Unprivileged users should see no folders Set<FileStore.Folder> folders = fileStoreImpl.getManager(session).getFolders(); assertThat(folders).hasSize(0); return null; } }); } }); } @Test public void fileVersioning() { running(fakeAorraApp(), new Runnable() { @Override public void run() { final FileStore fileStoreImpl = fileStore(); final String userId = getAdminUser(sessionFactory()); sessionFactory().inSession(userId, new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException, IOException { FileStore.Folder folder = fileStoreImpl.getManager(session).getRoot(); final String filename = "README.txt"; final String mimeType = "text/plain"; int i; FileStore.File f = null; for (i = 1; i <= 10; i++) { final InputStream data = new ByteArrayInputStream(getSomeContent(i).getBytes()); if (f == null) { folder.createFile(filename, mimeType, data); } else { f.update(mimeType, data); } f = (FileStore.File) fileStoreImpl .getManager(session) .getFileOrFolder("/"+filename); assertThat(ByteStreams.toByteArray(f.getData())) .isEqualTo(getSomeContent(i).getBytes()); assertThat(f.getVersions().size()).isEqualTo(i); } f = (FileStore.File) fileStoreImpl .getManager(session) .getFileOrFolder("/"+filename); final SortedSet<FileStore.File> versions = f.getVersions(); i = 1; for (final FileStore.File v : versions) { assertThat(v.getName()).isEqualTo(String.format("1.%d", i-1)); assertThat(ByteStreams.toByteArray(v.getData())) .isEqualTo(getSomeContent(i).getBytes()); i++; } return folder.getIdentifier(); } }); } protected String getSomeContent(int seed) { return String.format("Test content, version #%d.", seed); } }); } public String getAdminUser(JcrSessionFactory sessionFactory) { return sessionFactory.inSession(new Function<Session,String>() { @Override public String apply(Session session) throws RepositoryException { // Create new user final String userId; UserDAO dao = new UserDAO(session, jcrom()); User user = new User(); user.setEmail("user@example.com"); user.setName("Test User"); user = dao.create(user); String token = user.createVerificationToken(); user.checkVerificationToken(token); dao.setPassword(user, "password"); userId = user.getJackrabbitUserId(); final GroupManager gm = new GroupManager(session); Admin.getInstance(session).getGroup().addMember(gm.create("testAdmin")); gm.addMember("testAdmin", userId); return userId; } }); } }