package com.sismics.docs.rest; import java.io.File; import com.google.common.io.Resources; import com.icegreen.greenmail.util.GreenMail; import com.icegreen.greenmail.util.GreenMailUtil; import com.icegreen.greenmail.util.ServerSetup; import com.sismics.docs.core.model.context.AppContext; import com.sismics.util.filter.TokenBasedSecurityFilter; import jakarta.json.JsonArray; import jakarta.json.JsonObject; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.core.Form; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response.Status; import org.apache.directory.api.ldap.model.name.Dn; import org.apache.directory.server.core.api.DirectoryService; import org.apache.directory.server.core.api.partition.Partition; import org.apache.directory.server.core.factory.DefaultDirectoryServiceFactory; import org.apache.directory.server.core.factory.DirectoryServiceFactory; import org.apache.directory.server.core.partition.impl.avl.AvlPartition; import org.apache.directory.server.ldap.LdapServer; import org.apache.directory.server.protocol.shared.store.LdifFileLoader; import org.apache.directory.server.protocol.shared.transport.TcpTransport; import org.junit.Assert; import org.junit.Test; /** * Test the app resource. * * @author jtremeaux */ public class TestAppResource extends BaseJerseyTest { /** * Test the API resource. */ @Test public void testAppResource() { // Login admin String adminToken = adminToken(); // Check the application info JsonObject json = target().path("/app").request() .get(JsonObject.class); Assert.assertNotNull(json.getString("current_version")); Assert.assertNotNull(json.getString("min_version")); Long freeMemory = json.getJsonNumber("free_memory").longValue(); Assert.assertTrue(freeMemory > 0); Long totalMemory = json.getJsonNumber("total_memory").longValue(); Assert.assertTrue(totalMemory > 0 && totalMemory > freeMemory); Assert.assertEquals(0, json.getJsonNumber("queued_tasks").intValue()); Assert.assertFalse(json.getBoolean("guest_login")); Assert.assertEquals("eng", json.getString("default_language")); Assert.assertTrue(json.containsKey("global_storage_current")); Assert.assertTrue(json.getJsonNumber("active_user_count").longValue() > 0); // Rebuild Lucene index Response response = target().path("/app/batch/reindex").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); // Clean storage response = target().path("/app/batch/clean_storage").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); // Change the default language response = target().path("/app/config").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form().param("default_language", "fra"))); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); // Check the application info json = target().path("/app").request() .get(JsonObject.class); Assert.assertEquals("fra", json.getString("default_language")); // Change the default language response = target().path("/app/config").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form().param("default_language", "eng"))); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); // Check the application info json = target().path("/app").request() .get(JsonObject.class); Assert.assertEquals("eng", json.getString("default_language")); } /** * Test the log resource. */ @Test public void testLogResource() { // Login admin String adminToken = adminToken(); // Check the logs (page 1) JsonObject json = target().path("/app/log") .queryParam("level", "DEBUG") .request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); JsonArray logs = json.getJsonArray("logs"); Assert.assertTrue(logs.size() > 0); Long date1 = logs.getJsonObject(0).getJsonNumber("date").longValue(); Long date2 = logs.getJsonObject(9).getJsonNumber("date").longValue(); Assert.assertTrue(date1 >= date2); // Check the logs (page 2) json = target().path("/app/log") .queryParam("offset", "10") .queryParam("level", "DEBUG") .request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); logs = json.getJsonArray("logs"); Assert.assertTrue(logs.size() > 0); Long date3 = logs.getJsonObject(0).getJsonNumber("date").longValue(); Long date4 = logs.getJsonObject(9).getJsonNumber("date").longValue(); Assert.assertTrue(date3 >= date4); } /** * Test the guest login. */ @Test public void testGuestLogin() { // Login admin String adminToken = adminToken(); // Try to login as guest Response response = target().path("/user/login").request() .post(Entity.form(new Form() .param("username", "guest"))); Assert.assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus()); // Enable guest login target().path("/app/guest_login").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form() .param("enabled", "true")), JsonObject.class); // Login as guest String guestToken = clientUtil.login("guest", "", false); // Guest cannot delete himself response = target().path("/user").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, guestToken) .delete(); Assert.assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus()); // Guest cannot see opened sessions JsonObject json = target().path("/user/session").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, guestToken) .get(JsonObject.class); Assert.assertEquals(0, json.getJsonArray("sessions").size()); // Guest cannot delete opened sessions response = target().path("/user/session").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, guestToken) .delete(); Assert.assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus()); // Guest cannot enable TOTP response = target().path("/user/enable_totp").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, guestToken) .post(Entity.form(new Form())); Assert.assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus()); // Guest cannot disable TOTP response = target().path("/user/disable_totp").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, guestToken) .post(Entity.form(new Form())); Assert.assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus()); // Guest cannot update itself response = target().path("/user").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, guestToken) .post(Entity.form(new Form())); Assert.assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus()); // Guest can see its documents target().path("/document/list").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, guestToken) .get(JsonObject.class); } /** * Test SMTP configuration changes. */ @Test public void testSmtpConfiguration() { // Login admin String adminToken = adminToken(); // Get SMTP configuration JsonObject json = target().path("/app/config_smtp").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); Assert.assertTrue(json.isNull("hostname")); Assert.assertTrue(json.isNull("port")); Assert.assertTrue(json.isNull("username")); Assert.assertTrue(json.isNull("password")); Assert.assertTrue(json.isNull("from")); // Change SMTP configuration target().path("/app/config_smtp").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form() .param("hostname", "smtp.sismics.com") .param("port", "1234") .param("username", "sismics") .param("from", "contact@sismics.com") ), JsonObject.class); // Get SMTP configuration json = target().path("/app/config_smtp").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); Assert.assertEquals("smtp.sismics.com", json.getString("hostname")); Assert.assertEquals(1234, json.getInt("port")); Assert.assertEquals("sismics", json.getString("username")); Assert.assertTrue(json.isNull("password")); Assert.assertEquals("contact@sismics.com", json.getString("from")); } /** * Test inbox scanning. */ @Test public void testInbox() { // Login admin String adminToken = adminToken(); // Create a tag JsonObject json = target().path("/tag").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .put(Entity.form(new Form() .param("name", "Inbox") .param("color", "#ff0000")), JsonObject.class); String tagInboxId = json.getString("id"); // Get inbox configuration json = target().path("/app/config_inbox").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); Assert.assertFalse(json.getBoolean("enabled")); Assert.assertEquals("", json.getString("hostname")); Assert.assertEquals(993, json.getJsonNumber("port").intValue()); Assert.assertEquals("", json.getString("username")); Assert.assertEquals("", json.getString("password")); Assert.assertEquals("INBOX", json.getString("folder")); Assert.assertEquals("", json.getString("tag")); JsonObject lastSync = json.getJsonObject("last_sync"); Assert.assertTrue(lastSync.isNull("date")); Assert.assertTrue(lastSync.isNull("error")); Assert.assertEquals(0, lastSync.getJsonNumber("count").intValue()); // Change inbox configuration target().path("/app/config_inbox").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form() .param("enabled", "true") .param("starttls", "false") .param("autoTagsEnabled", "false") .param("deleteImported", "false") .param("hostname", "localhost") .param("port", "9755") .param("username", "test@sismics.com") .param("password", "12345678") .param("folder", "INBOX") .param("tag", tagInboxId) ), JsonObject.class); // Get inbox configuration json = target().path("/app/config_inbox").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); Assert.assertTrue(json.getBoolean("enabled")); Assert.assertEquals("localhost", json.getString("hostname")); Assert.assertEquals(9755, json.getInt("port")); Assert.assertEquals("test@sismics.com", json.getString("username")); Assert.assertEquals("12345678", json.getString("password")); Assert.assertEquals("INBOX", json.getString("folder")); Assert.assertEquals(tagInboxId, json.getString("tag")); ServerSetup serverSetupSmtp = new ServerSetup(9754, null, ServerSetup.PROTOCOL_SMTP); ServerSetup serverSetupImap = new ServerSetup(9755, null, ServerSetup.PROTOCOL_IMAP); GreenMail greenMail = new GreenMail(new ServerSetup[] { serverSetupSmtp, serverSetupImap }); greenMail.setUser("test@sismics.com", "12345678"); greenMail.start(); // Test the inbox json = target().path("/app/test_inbox").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form()), JsonObject.class); Assert.assertEquals(0, json.getJsonNumber("count").intValue()); // Send an email GreenMailUtil.sendTextEmail("test@sismics.com", "test@sismicsdocs.com", "Test email 1", "Test content 1", serverSetupSmtp); // Trigger an inbox sync AppContext.getInstance().getInboxService().syncInbox(); // Search for added documents json = target().path("/document/list") .queryParam("search", "tag:Inbox full:content") .request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); Assert.assertEquals(1, json.getJsonArray("documents").size()); // Get inbox configuration json = target().path("/app/config_inbox").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); lastSync = json.getJsonObject("last_sync"); Assert.assertFalse(lastSync.isNull("date")); Assert.assertTrue(lastSync.isNull("error")); Assert.assertEquals(1, lastSync.getJsonNumber("count").intValue()); // Trigger an inbox sync AppContext.getInstance().getInboxService().syncInbox(); // Search for added documents json = target().path("/document/list") .queryParam("search", "tag:Inbox full:content") .request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); Assert.assertEquals(1, json.getJsonArray("documents").size()); // Get inbox configuration json = target().path("/app/config_inbox").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); lastSync = json.getJsonObject("last_sync"); Assert.assertFalse(lastSync.isNull("date")); Assert.assertTrue(lastSync.isNull("error")); Assert.assertEquals(0, lastSync.getJsonNumber("count").intValue()); greenMail.stop(); } /** * Test the LDAP authentication. */ @Test public void testLdapAuthentication() throws Exception { // Start LDAP server final DirectoryServiceFactory factory = new DefaultDirectoryServiceFactory(); factory.init("Test"); final DirectoryService directoryService = factory.getDirectoryService(); directoryService.getChangeLog().setEnabled(false); directoryService.setShutdownHookEnabled(true); final Partition partition = new AvlPartition(directoryService.getSchemaManager()); partition.setId("Test"); partition.setSuffixDn(new Dn(directoryService.getSchemaManager(), "o=TEST")); partition.initialize(); directoryService.addPartition(partition); final LdapServer ldapServer = new LdapServer(); ldapServer.setTransports(new TcpTransport("localhost", 11389)); ldapServer.setDirectoryService(directoryService); directoryService.startup(); ldapServer.start(); // Load test data in LDAP new LdifFileLoader(directoryService.getAdminSession(), new File(Resources.getResource("test.ldif").getFile()), null).execute(); // Login admin String adminToken = adminToken(); // Get the LDAP configuration JsonObject json = target().path("/app/config_ldap").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); Assert.assertFalse(json.getBoolean("enabled")); // Change LDAP configuration target().path("/app/config_ldap").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form() .param("enabled", "true") .param("host", "localhost") .param("port", "11389") .param("usessl", "false") .param("admin_dn", "uid=admin,ou=system") .param("admin_password", "secret") .param("base_dn", "o=TEST") .param("filter", "(&(objectclass=inetOrgPerson)(uid=USERNAME))") .param("default_email", "devnull@teedy.io") .param("default_storage", "100000000") ), JsonObject.class); // Get the LDAP configuration json = target().path("/app/config_ldap").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .get(JsonObject.class); Assert.assertTrue(json.getBoolean("enabled")); Assert.assertEquals("localhost", json.getString("host")); Assert.assertEquals(11389, json.getJsonNumber("port").intValue()); Assert.assertEquals("uid=admin,ou=system", json.getString("admin_dn")); Assert.assertEquals("secret", json.getString("admin_password")); Assert.assertEquals("o=TEST", json.getString("base_dn")); Assert.assertEquals("(&(objectclass=inetOrgPerson)(uid=USERNAME))", json.getString("filter")); Assert.assertEquals("devnull@teedy.io", json.getString("default_email")); Assert.assertEquals(100000000L, json.getJsonNumber("default_storage").longValue()); // Login with a LDAP user String ldapTopen = clientUtil.login("ldap1", "secret", false); // Check user informations json = target().path("/user").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, ldapTopen) .get(JsonObject.class); Assert.assertEquals("ldap1@teedy.io", json.getString("email")); // List all documents json = target().path("/document/list") .queryParam("sort_column", 3) .queryParam("asc", true) .request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, ldapTopen) .get(JsonObject.class); JsonArray documents = json.getJsonArray("documents"); Assert.assertEquals(0, documents.size()); // Stop LDAP server ldapServer.stop(); directoryService.shutdown(); } }