diff options
Diffstat (limited to 'src/test/java/com')
4 files changed, 352 insertions, 144 deletions
diff --git a/src/test/java/com/juick/MessageTest.java b/src/test/java/com/juick/MessageTest.java index 1d59a8db..eabeeb0f 100644 --- a/src/test/java/com/juick/MessageTest.java +++ b/src/test/java/com/juick/MessageTest.java @@ -20,6 +20,8 @@ package com.juick; import com.juick.model.Entity; import com.juick.test.util.MockUtils; import com.juick.util.MessageUtils; +import com.overzealous.remark.Options; +import com.overzealous.remark.Remark; import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.StringUtils; import org.junit.Test; @@ -191,5 +193,39 @@ public class MessageTest { assertThat(entities.stream().filter(e -> e.getType().equals("q")).count(), is(1L)); assertThat(entities.stream().filter(e -> e.getType().equals("u")).count(), is(1L)); assertThat(entities.stream().filter(e -> e.getType().equals("a")).count(), is(4L)); + Entity yo = entities.stream().filter(e -> e.getType().equals("q")).findFirst().orElseThrow(IllegalStateException::new); + assertThat(yo.getText(), is("how ?")); + assertThat(yo.getStart(), is(0)); + assertThat(yo.getEnd(), is(7)); + } + @Test + public void ActivityStreamsHTMLtoMarkdownTest() { + String text = "<p><span class=\"h-card\"><a href=\"https://juick.com/stanislavv/\" class=\"u-url mention\">@<span>stanislavv</span></a></span> я в <span class=\"h-card\"><a href=\"https://mastodonsocial.ru/@rf\" class=\"u-url mention\">@<span>rf</span></a></span> выкладывал =)</p>"; + Options options = new Options(); + options.inlineLinks = true; + Remark remark = new Remark(options); + String parsed = remark.convertFragment(text); + } + @Test + public void messageFormatTest() { + String msg = "> quote\nmessage"; + assertThat(MessageUtils.formatMessage(msg), is("<q>quote</q>message")); + String brokenComment = "<!-- read next"; + assertThat(MessageUtils.formatMessage(brokenComment), is("<!-- read next")); + String url = "[ya](http://ya.ru)"; + assertThat(MessageUtils.formatMessage(url), is("<a href=\"http://ya.ru\" rel=\"nofollow\">ya</a>")); + String complexMessage = "У футболистов нет мозгов. Что в России, что в Беларуси:\n" + + "\n" + + ">Отец футболиста Лухвича, объехавшего пробку по тротуару: «Сына задержали, Infiniti арестовали» https://auto.onliner.by/2019/01/23/probka-9\n" + + "\n" + + "Вкратце: малолетний долбоёб ездил по встрече, по тротуарам, парковался где хотел и всё это выкладывал в сеть, мол, хули вы мне сделоете. Сделали. Ибо нехуй."; + String formattedMessage = "У футболистов нет мозгов. Что в России, что в Беларуси:<br/>\n<br/>\n" + + "<q>Отец футболиста Лухвича, объехавшего пробку по тротуару: «Сына задержали, Infiniti арестовали» <a href=\"https://auto.onliner.by/2019/01/23/probka-9\" rel=\"nofollow\">auto.onliner.by</a></q>" + + "<br/>\n" + + "Вкратце: малолетний долбоёб ездил по встрече, по тротуарам, парковался где хотел и всё это выкладывал в сеть, мол, хули вы мне сделоете. Сделали. Ибо нехуй."; + + assertThat(MessageUtils.formatMessage(complexMessage), is(formattedMessage)); + String multiQuote = "> quote line 1\n> quote line 2\nmessage"; + assertThat(MessageUtils.formatMessage(multiQuote), is("<q>quote line 1<br/>\nquote line 2</q>message")); } } diff --git a/src/test/java/com/juick/server/configuration/TestActivityConfiguration.java b/src/test/java/com/juick/server/configuration/TestActivityConfiguration.java new file mode 100644 index 00000000..5daf4900 --- /dev/null +++ b/src/test/java/com/juick/server/configuration/TestActivityConfiguration.java @@ -0,0 +1,19 @@ +package com.juick.server.configuration; + +import com.juick.server.KeystoreManager; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; + +import java.io.IOException; + +@Configuration +public class TestActivityConfiguration { + @Value("classpath:test.p12") + Resource keystoreFile; + @Bean + public KeystoreManager testKeystoreManager() throws IOException { + return new KeystoreManager(keystoreFile.getFile().getAbsolutePath(), "secret"); + } +} diff --git a/src/test/java/com/juick/server/tests/ServerTests.java b/src/test/java/com/juick/server/tests/ServerTests.java index deef6f30..7f46968f 100644 --- a/src/test/java/com/juick/server/tests/ServerTests.java +++ b/src/test/java/com/juick/server/tests/ServerTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2017, Juick + * Copyright (C) 2008-2019, Juick * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -19,6 +19,7 @@ package com.juick.server.tests; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.gargoylesoftware.htmlunit.CookieManager; import com.gargoylesoftware.htmlunit.WebClient; @@ -33,27 +34,22 @@ import com.juick.model.PrivateChats; import com.juick.model.TagStats; import com.juick.server.*; import com.juick.server.api.activity.model.Context; -import com.juick.server.api.activity.model.activities.Create; -import com.juick.server.api.activity.model.activities.Delete; -import com.juick.server.api.activity.model.activities.Follow; -import com.juick.server.api.activity.model.activities.Like; -import com.juick.server.api.activity.model.activities.Undo; +import com.juick.server.api.activity.model.activities.*; import com.juick.server.api.activity.model.objects.Note; import com.juick.server.api.activity.model.objects.Person; import com.juick.server.api.webfinger.model.Account; import com.juick.server.api.xnodeinfo2.model.NodeInfo; import com.juick.server.util.HttpUtils; import com.juick.server.util.ImageUtils; -import com.juick.server.xmpp.helpers.XMPPStatus; -import com.juick.server.xmpp.s2s.ConnectionIn; +import com.juick.server.www.WebApp; import com.juick.service.*; import com.juick.service.component.MessageEvent; +import com.juick.test.util.MockUtils; import com.juick.util.DateFormattersHolder; import com.juick.util.MessageUtils; import com.mitchellbosecke.pebble.PebbleEngine; import com.mitchellbosecke.pebble.error.PebbleException; import com.mitchellbosecke.pebble.template.PebbleTemplate; -import org.apache.commons.codec.CharEncoding; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.IteratorUtils; import org.apache.commons.io.IOUtils; @@ -70,16 +66,22 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import org.springframework.http.*; +import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.util.DigestUtils; import org.springframework.util.FileSystemUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; import org.w3c.dom.Document; @@ -91,9 +93,6 @@ import rocks.xmpp.addr.Jid; import rocks.xmpp.core.session.Extension; import rocks.xmpp.core.session.XmppSession; import rocks.xmpp.core.session.XmppSessionConfiguration; -import rocks.xmpp.core.stanza.model.StanzaError; -import rocks.xmpp.core.stanza.model.client.ClientMessage; -import rocks.xmpp.core.stanza.model.errors.Condition; import javax.inject.Inject; import javax.servlet.http.Cookie; @@ -105,7 +104,6 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.*; -import java.net.Socket; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; @@ -117,17 +115,20 @@ import java.sql.Timestamp; import java.time.Instant; import java.util.*; import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.StreamSupport; +import static com.juick.server.api.activity.model.Context.ACTIVITY_MEDIA_TYPE; import static junit.framework.TestCase.assertTrue; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; +import static org.springframework.test.web.client.ExpectedCount.times; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -140,9 +141,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @TestPropertySource(properties = { "broken_ssl_hosts=localhost,serverstorageisfull.tld", "ios_app_id=12345678.com.juick.ExampleApp", - "xmppbot_jid=juick@localhost/Juick", - "hostname=localhost", - "componentname=localhost", "spring.jackson.default-property-inclusion=non_default" }) @AutoConfigureMockMvc @@ -163,12 +161,8 @@ public class ServerTests { @Inject private ObjectMapper jsonMapper; @Inject - private XMPPServer server; - @Inject private CommandsManager commandsManager; @Inject - private XMPPConnection router; - @Inject private SubscriptionService subscriptionService; @Inject private PrivacyQueriesService privacyQueriesService; @@ -188,10 +182,6 @@ public class ServerTests { private ServerManager serverManager; @Inject private KeystoreManager keystoreManager; - @Value("${hostname:localhost}") - private Jid jid; - @Value("${xmppbot_jid:juick@localhost}") - private Jid botJid; @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") private String tmpDir; @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}") @@ -204,6 +194,32 @@ public class ServerTests { private SignatureManager signatureManager; @Inject private ActivityPubManager activityPubManager; + @Inject + private WebApp webApp; + @Inject + private RestTemplate apClient; + + @Value("classpath:mocks/activity/testuser.json") + private Resource testuserResponse; + @Value("classpath:mocks/activity/testfollow.json") + private Resource testfollowRequest; + @Value("classpath:static/av-96.png") + private Resource defaultAvatar; + @Value("classpath:cmyk.jpg") + private Resource cmykJpeg; + @Value("classpath:nojfif.jpg") + private Resource nojfif; + @Value("classpath:hubzilla_activity.json") + private Resource hubzillaActivity; + @Value("classpath:hubzilla_follow.json") + private Resource hubzillaFollow; + @Value("classpath:announce.json") + private Resource noteWithDocument; + @Value("classpath:2936611-57.jpg") + private Resource jpegNoJfifTiff; + + @Inject + private KeystoreManager testKeystoreManager; private static User ugnich, freefd, juick; static String ugnichName, ugnichPassword, freefdName, freefdPassword, juickName, juickPassword; @@ -217,10 +233,16 @@ public class ServerTests { FileSystemUtils.deleteRecursively(Paths.get(imgDir, "photos-1024")); FileSystemUtils.deleteRecursively(Paths.get(imgDir, "photos-512")); FileSystemUtils.deleteRecursively(Paths.get(imgDir, "ps")); + FileSystemUtils.deleteRecursively(Paths.get(imgDir, "a")); + FileSystemUtils.deleteRecursively(Paths.get(imgDir, "ao")); + FileSystemUtils.deleteRecursively(Paths.get(imgDir, "as")); Files.createDirectory(Paths.get(imgDir, "p")); Files.createDirectory(Paths.get(imgDir, "photos-1024")); Files.createDirectory(Paths.get(imgDir, "photos-512")); Files.createDirectory(Paths.get(imgDir, "ps")); + Files.createDirectory(Paths.get(imgDir, "a")); + Files.createDirectory(Paths.get(imgDir, "ao")); + Files.createDirectory(Paths.get(imgDir, "as")); if (!isSetUp) { ugnichName = "ugnich"; ugnichPassword = "secret"; @@ -339,7 +361,7 @@ public class ServerTests { Message msg3 = messagesService.getMessage(mid2).get(); assertEquals(2, msg3.getReplies()); - assertEquals("weather", msg3.getTags().get(0).getName()); + assertEquals("weather", msg3.getTags().stream().findFirst().get().getName()); assertEquals(ugnich.getUid(), userService.checkPassword(ugnich.getName(), "x")); assertEquals(-1, userService.checkPassword(ugnich.getName(), "xy")); @@ -411,7 +433,7 @@ public class ServerTests { Timestamp.class, mid).toInstant(); assertThat(rts, greaterThan(ts)); Message msg = messagesService.getReply(mid, rid); - assertThat(rts, equalTo(msg.getTimestamp())); + assertThat(rts, equalTo(msg.getCreated())); messagesService.deleteMessage(ugnich_id, mid); } @@ -436,11 +458,10 @@ public class ServerTests { @Test public void homeTestWithMessages() throws Exception { String msgText = "Привет, я - Угнич"; - CommandResult result = commandsManager.processCommand(ugnich, msgText, URI.create("http://static.juick.com/settings/facebook.png")); + CommandResult result = commandsManager.processCommand(ugnich, msgText, URI.create("https://static.juick.com/settings/facebook.png")); int mid = result.getNewMessage().get().getMid(); Message msg = messagesService.getMessage(mid).get(); tagService.createTag("тест"); - ClassPathResource defaultAvatar = new ClassPathResource("static/av-96.png"); String hash = DigestUtils.md5DigestAsHex(IOUtils.toByteArray(defaultAvatar.getInputStream())); mockMvc.perform( get("/api/home") @@ -449,7 +470,7 @@ public class ServerTests { .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(jsonPath("$[0].mid", is(msg.getMid()))) .andExpect(jsonPath("$[0].timestamp", - is(DateFormattersHolder.getMessageFormatterInstance().format(msg.getTimestamp())))) + is(DateFormattersHolder.getMessageFormatterInstance().format(msg.getCreated())))) .andExpect(jsonPath("$[0].body", is(msg.getText()))) .andExpect(jsonPath("$[0].attachment.url", is(String.format("https://i.juick.com/p/%d.png", msg.getMid())))) @@ -481,6 +502,11 @@ public class ServerTests { .header("Origin", "http://api.example.net")) .andExpect(status().isOk()) .andExpect(header().string("Access-Control-Allow-Origin", "*")); + mockMvc.perform( + get("/u/ugnich") + .header("Origin", "http://api.example.net")) + .andExpect(status().isOk()) + .andExpect(header().string("Access-Control-Allow-Origin", "*")); } @Test @@ -675,63 +701,6 @@ public class ServerTests { .andExpect(xpath("/rss/channel/description").string("The latest messages at Juick")); } @Test - public void statusPageIsUp() throws Exception { - mockMvc.perform(get("/api/status").with(httpBasic(ugnichName, ugnichPassword))).andExpect(status().isOk()); - assertThat(server.getJid(), equalTo(jid)); - } - @Test - public void botIsUpAndProcessingResourceConstraints() throws Exception { - jdbcTemplate.execute("DELETE FROM users WHERE nick='renha'"); - int renhaId = userService.createUser("renha", "umnnbt"); - Jid from = Jid.of("renha@serverstorageisfull.tld"); - jdbcTemplate.update("INSERT INTO jids(user_id,jid,active) VALUES(?,?,?)", - renhaId, from.toEscapedString(), 1); - rocks.xmpp.core.stanza.model.Message xmppMessage = new rocks.xmpp.core.stanza.model.Message(); - xmppMessage.setType(rocks.xmpp.core.stanza.model.Message.Type.ERROR); - xmppMessage.setFrom(from); - xmppMessage.setTo(botJid); - StanzaError err = new StanzaError(StanzaError.Type.CANCEL, Condition.RESOURCE_CONSTRAINT); - xmppMessage.setError(err); - Function<Integer, Boolean> isActive = f -> jdbcTemplate.queryForObject("SELECT active FROM jids WHERE user_id=?", Integer.class, f) == 1; - assertThat(isActive.apply(renhaId), equalTo(true)); - ClientMessage result = router.incomingMessage(xmppMessage); - assertNull(result); - assertThat(isActive.apply(renhaId), equalTo(false)); - xmppMessage.setError(null); - xmppMessage.setType(rocks.xmpp.core.stanza.model.Message.Type.CHAT); - xmppMessage.setBody("On"); - result = router.incomingMessage(xmppMessage); - assertThat(result.getBody(), equalTo("XMPP notifications are activated")); - assertTrue(isActive.apply(renhaId)); - xmppMessage.setBody("*test test"); - result = router.incomingMessage(xmppMessage); - assertThat(result.getBody(), startsWith("New message posted")); - xmppMessage.setFrom(from); - xmppMessage.setBody("PING"); - result = router.incomingMessage(xmppMessage); - assertThat(result.getBody(), equalTo("PONG")); - int secretlySadId = userService.createUser("secretlysad", "bbk"); - xmppMessage.setTo(botJid.withLocal("secretlysad")); - xmppMessage.setBody("What's up?"); - result = router.incomingMessage(xmppMessage); - assertThat(result, is(nullValue())); - xmppMessage.setTo(botJid); - xmppMessage.setBody("@secretlysad Hey!"); - result = router.incomingMessage(xmppMessage); - assertThat(result.getBody(), is("Private message sent")); - assertThat(pmQueriesService.getPMMessages(renhaId, secretlySadId).size(), is(2)); - String xml = "<message xmlns=\"jabber:server\" from=\"" + botJid + "\" to=\"renha@serverstorageisfull.tld\" type=\"chat\"><body>@yo:\n" + - "343432434\n" + - "\n" + - "#2 http://juick.com/2</body><thread>juick-2</thread><juick xmlns=\"http://juick.com/message\" mid=\"2\" privacy=\"1\" quote=\"\" replyto=\"0\" rid=\"0\" ts=\"2018-04-10 06:58:23\"><body>343432434</body><updated></updated><user xmlns=\"http://juick.com/user\" uname=\"yo\" uid=\"2\"></user></juick><nick xmlns=\"http://jabber.org/protocol/nick\">@yo</nick></message>"; - result = router.incomingMessage((rocks.xmpp.core.stanza.model.Message)server.parse(xml)); - String active = "<message xmlns=\"jabber:server\" from=\"renha@serverstorageisfull.tld/work\" to=\"" - + botJid.asBareJid().toEscapedString() + "\" type=\"chat\" id=\"purple553384c6\"><active xmlns=\"http://jabber.org/protocol/chatstates\"></active></message>"; - result = router.incomingMessage((rocks.xmpp.core.stanza.model.Message)server.parse(active)); - xmppMessage.setFrom(botJid); - // TODO: assert events - } - @Test public void botCommandsTests() throws Exception { assertThat(commandsManager.processCommand(AnonymousUser.INSTANCE, "PING", emptyUri).getText(), is("PONG")); // subscription commands have two lines, others have 1 @@ -743,21 +712,21 @@ public class ServerTests { int uid = userService.createUser("me", "secret"); User user = userService.getUserByUID(uid).orElse(AnonymousUser.INSTANCE); Tag yo = tagService.getTag("yo", true); - Message msg = commandsManager.processCommand(user, "*yo yoyo", URI.create("http://static.juick.com/settings/facebook.png")).getNewMessage().get(); + Message msg = commandsManager.processCommand(user, "*yo yoyo", URI.create("https://static.juick.com/settings/facebook.png")).getNewMessage().get(); assertThat(msg.getAttachmentType(), is("png")); - Message msgreply = commandsManager.processCommand(user, "#" + msg.getMid() + " yyy", HttpUtils.downloadImage(URI.create("http://static.juick.com/settings/xmpp.png").toURL(), tmpDir)).getNewMessage().get(); + Message msgreply = commandsManager.processCommand(user, "#" + msg.getMid() + " yyy", HttpUtils.downloadImage(URI.create("https://static.juick.com/settings/xmpp.png").toURL(), tmpDir)).getNewMessage().get(); assertThat(msgreply.getAttachmentType(), equalTo("png")); assertEquals("text should match", "yoyo", messagesService.getMessage(msg.getMid()).get().getText()); assertEquals("tag should match", "yo", tagService.getMessageTags(msg.getMid()).get(0).getTag().getName()); - CommandResult yoyoMsg = commandsManager.processCommand(user, "*yo", URI.create("http://static.juick.com/settings/facebook.png")); + CommandResult yoyoMsg = commandsManager.processCommand(user, "*yo", URI.create("https://static.juick.com/settings/facebook.png")); assertTrue(yoyoMsg.getNewMessage().isPresent()); - assertThat(yoyoMsg.getNewMessage().get().getTags().get(0), is(yo)); + assertThat(yoyoMsg.getNewMessage().get().getTags().stream().findFirst().get(), is(yo)); Message msg2 = yoyoMsg.getNewMessage().get(); int mid = msg2.getMid(); Timestamp last = jdbcTemplate.queryForObject("SELECT lastmessage FROM users WHERE id=?", Timestamp.class, user.getUid()); - assertThat(last.toInstant(), equalTo(yoyoMsg.getNewMessage().get().getTimestamp())); + assertThat(last.toInstant(), equalTo(yoyoMsg.getNewMessage().get().getCreated())); assertEquals("should be message", true, commandsManager.processCommand(user, String.format("#%d", mid), emptyUri).getText().startsWith("@me")); int readerUid = userService.createUser("dummyReader", "dummySecret"); @@ -795,14 +764,14 @@ public class ServerTests { String expectedThirdReply = "Reply posted.\n#" + mid + "/3 " + "https://juick.com/m/" + mid + "#3"; assertEquals("should be second reply", expectedSecondReply, - commandsManager.processCommand(user, "#" + mid + " yoyo", URI.create("http://static.juick.com/settings/facebook.png")).getText()); + commandsManager.processCommand(user, "#" + mid + " yoyo", URI.create("https://static.juick.com/settings/facebook.png")).getText()); assertEquals("should be third reply", expectedThirdReply, commandsManager.processCommand(user, " \t\n #" + mid + "/2 ", - URI.create("http://static.juick.com/settings/facebook.png")).getText()); + URI.create("https://static.juick.com/settings/facebook.png")).getText()); Message reply = messagesService.getReplies(user, mid).stream().filter(m -> m.getRid() == 3).findFirst() .orElse(new Message()); Timestamp lastreply = jdbcTemplate.queryForObject("SELECT lastmessage FROM users WHERE id=?", Timestamp.class, user.getUid()); - assertThat(lastreply.toInstant(), equalTo(reply.getTimestamp())); + assertThat(lastreply.toInstant(), equalTo(reply.getCreated())); assertEquals("should be reply to second comment", 2, reply.getReplyto()); assertThat(commandsManager.processCommand(readerUser, "#" + mid + " *yo *there", emptyUri) .getText(), startsWith("Reply posted")); @@ -857,11 +826,11 @@ public class ServerTests { "> }"; String codeAndTags = "*code\n" + expectedCodeMessage; Message codeAndTagsMessage = commandsManager.processCommand(user, codeAndTags, emptyUri).getNewMessage().get(); - List<Tag> codeAndTagsTags = codeAndTagsMessage.getTags(); + Set<Tag> codeAndTagsTags = codeAndTagsMessage.getTags(); assertEquals("expected single tag", 1, codeAndTagsTags.size()); assertEquals("the single tag should be the 'code'", "code", - codeAndTagsTags.get(0).getName()); + codeAndTagsTags.stream().findFirst().get().getName()); assertEquals("and the message should be with a C-code and without tags", expectedCodeMessage, codeAndTagsMessage.getText()); CommandResult result = commandsManager.processCommand(user, "*one *two *three *four *five *six test", emptyUri); @@ -885,7 +854,7 @@ public class ServerTests { data = "* \u043c\u0443\u0441\u043e\u0440\\n\u0423 \u043c\u0435\u043d\u044f \u043a\u0430\u0436\u0434\u0443\u044e \u043d\u0435\u0434\u0435\u043b\u044e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043f\u043e 4-5 \u0431\u0443\u0442\u044b\u043b\u043e\u043a 1,5\u043b \u041f\u0415\u0422. \u041c\u043d\u0435 \u0433\u0435\u043c\u043e\u0440\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043f\u043e \u043a\u0438\u043b\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0438\u043b\u0438 \u043f\u043e 5\u043a\u0433 \u044d\u0442\u043e\u0433\u043e \u043c\u0443\u0441\u043e\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u0432\u0435\u0437\u0442\u0438 \u0435\u0433\u043e \u0435\u0449\u0435 \u043a\u0443\u0434\u0430-\u0442\u043e.\\n\u041d\u0435, \u043d\u0443 \u0435\u0441\u0442\u044c \u043b\u044e\u0434\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442 \u0432\u0442\u043e\u0440\u0441\u044b\u0440\u044c\u0435 \u043f\u043e \u043c\u0443\u0441\u043e\u0440\u043a\u0430\u043c, \u0441\u0432\u0430\u043b\u043a\u0430\u043c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0434\u0435\u043d\u044c\u0433\u0438 \u043d\u0443\u0436\u043d\u044b. \u0418 \u0431\u044b\u0432\u0430\u044e\u0442 \u0441\u0442\u043e\u044f\u0442 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b-\u043a\u043b\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u043f\u043b\u0430\u0441\u0442\u0438\u043a\u0430, \u043d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u0443\u0441\u043e\u0440 \u0432\u044b\u0432\u043e\u0437\u044f\u0442 \u043d\u0435 \u0447\u0430\u0441\u0442\u043e \u0438\u043b\u0438 \u043b\u044e\u0434\u0438 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0432\u044b\u043a\u0438\u0434\u044b\u0432\u0430\u044e\u0442 \u043c\u043d\u043e\u0433\u043e \u043c\u0443\u0441\u043e\u0440\u0430, \u0442\u043e \u0432 \u0442\u043e\u0439 \u043a\u043b\u0435\u0442\u043a\u0435 \u0442\u043e\u0442 \u043c\u0443\u0441\u043e\u0440, \u0447\u0442\u043e \u043d\u0435 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043b\u0441\u044f \u0432 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u0445."; result = commandsManager.processCommand(user, String.format("%s %s", tags, data), emptyUri); assertThat(result.getNewMessage().get().getTags().size(), equalTo(2)); - assertThat(result.getNewMessage().get().getTags().get(0).getName(), equalTo("Киев")); + assertThat(result.getNewMessage().get().getTags().stream().findFirst().get().getName(), equalTo("Киев")); assertThat(result.getNewMessage().get().getText(), equalTo(data)); result = commandsManager.processCommand(user, "S @unknown-user", emptyUri); assertThat(result.getNewMessage(), is(Optional.empty())); @@ -933,7 +902,7 @@ public class ServerTests { mockMvc.perform(get("/api/thread?mid=" + mid + "&hash=" + freefdHash)) .andExpect(status().isOk()) .andExpect(jsonPath("$[0].recommendations.length()", is(1))) - .andExpect(jsonPath("$[0].recommendations[0]", is(freefdName))); + .andExpect(jsonPath("$[0].recommendations[0].uname", is(freefdName))); mockMvc.perform(post("/api/like?mid=" + freefdMid + "&hash=" + freefdHash)) .andExpect(status().isForbidden()); } @@ -1029,8 +998,8 @@ public class ServerTests { tagService.updateTags(newMid, Collections.singletonList(banned)); assertThat(messagesService.getMessage(newMid).get().getTags().size(), is(0)); privacyQueriesService.blacklistUser(freefd, userService.getUserByUID(newUid).orElse(AnonymousUser.INSTANCE)); - assertTrue(messagesService.getMessages(AnonymousUser.INSTANCE, messagesService.getMyFeed(freefd.getUid(), 0, true)) - .stream().noneMatch(m -> m.getMid() == newMid)); + assertTrue(messagesService.getMyFeed(freefd.getUid(), 0, true) + .stream().noneMatch(m -> m == newMid)); } @Test public void tagsShouldBeDeserializedFromXml() throws JAXBException { @@ -1055,18 +1024,21 @@ public class ServerTests { Tag xmlTag = (Tag) unmarshaller.unmarshal(new StringReader(tag)); assertThat(xmlTag.getName(), equalTo("yo")); Message juickMessage = xmppMessage.getExtension(Message.class); - assertThat(juickMessage.getTags().get(0).getName(), equalTo("yo")); + List<Tag> tags = new ArrayList<>(juickMessage.getTags()); + assertThat(tags.get(0).getName(), equalTo("yo")); } @Test public void messageParserSerializer() throws ParserConfigurationException, IOException, SAXException, JAXBException { + Set<Tag> tags = MessageUtils.parseTags("test test" + (char) 0xA0 + "2 test3"); + List<Tag> tagList = new ArrayList<>(tags); + assertEquals("First tag must be", "test", tagList.get(0).getName()); + assertEquals("Third tag must be", "test3", tagList.get(2).getName()); + assertEquals("Count of tags must be", 3, tagList.size()); Message msg = new Message(); - msg.setTags(MessageUtils.parseTags("test test" + (char) 0xA0 + "2 test3")); - assertEquals("First tag must be", "test", msg.getTags().get(0).getName()); - assertEquals("Third tag must be", "test3", msg.getTags().get(2).getName()); - assertEquals("Count of tags must be", 3, msg.getTags().size()); + msg.setTags(tags); Instant currentDate = Instant.now(); - msg.setTimestamp(currentDate); + msg.setCreated(currentDate); String jsonMessage = jsonMapper.writeValueAsString(msg); assertEquals("date should be in timestamp field", DateFormattersHolder.getMessageFormatterInstance().format(currentDate), JsonPath.read(jsonMessage, "$.timestamp")); @@ -1081,7 +1053,7 @@ public class ServerTests { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); - Document doc = db.parse(new ByteArrayInputStream(sw.toString().getBytes(CharEncoding.UTF_8))); + Document doc = db.parse(new ByteArrayInputStream(sw.toString().getBytes(StandardCharsets.UTF_8))); Node juickNode = doc.getDocumentElement(); NamedNodeMap attrs = juickNode.getAttributes(); assertEquals("date should be in ts field", DateFormattersHolder.getMessageFormatterInstance().format(currentDate), @@ -1168,7 +1140,7 @@ public class ServerTests { } @Test public void cmykJpegShouldBeProcessedCorrectly() throws Exception { - CommandResult postJpgCmyk = commandsManager.processCommand(ugnich, "YO", new ClassPathResource("cmyk.jpg").getURI()); + CommandResult postJpgCmyk = commandsManager.processCommand(ugnich, "YO", cmykJpeg.getURI()); assertThat(postJpgCmyk.getNewMessage().isPresent(), is(true)); int mid = postJpgCmyk.getNewMessage().get().getMid(); File originalFile = Paths.get(imgDir, "p", String.format("%d.jpg", mid)).toFile(); @@ -1182,7 +1154,7 @@ public class ServerTests { } @Test public void JpegWithoutJfifShouldBeProcessedCorrectly() throws Exception { - CommandResult postJpgCmyk = commandsManager.processCommand(ugnich, "YO", new ClassPathResource("nojfif.jpg").getURI()); + CommandResult postJpgCmyk = commandsManager.processCommand(ugnich, "YO", nojfif.getURI()); assertThat(postJpgCmyk.getNewMessage().isPresent(), is(true)); int mid = postJpgCmyk.getNewMessage().get().getMid(); File originalFile = Paths.get(imgDir, "p", String.format("%d.jpg", mid)).toFile(); @@ -1210,12 +1182,19 @@ public class ServerTests { assertThat(postJpgiPhone.getNewMessage().get().getAttachment().getHeight(), is(1280)); assertThat(postJpgiPhone.getNewMessage().get().getAttachment().getMedium().getHeight(), is(1024)); assertThat(postJpgiPhone.getNewMessage().get().getAttachment().getSmall().getHeight(), is(512)); + CommandResult postNojfifTiff = commandsManager.processCommand(ugnich, "YO2", jpegNoJfifTiff.getURI()); + assertThat(postNojfifTiff.getNewMessage().isPresent(), is(true)); + int mid2 = postNojfifTiff.getNewMessage().get().getMid(); + File originalFile2 = Paths.get(imgDir, "p", String.format("%d.jpg", mid2)).toFile(); + assertThat(originalFile2.exists(), is(true)); + File mediumFile2 = Paths.get(imgDir, "photos-1024", String.format("%d.jpg", mid2)).toFile(); + assertThat(mediumFile2.exists(), is(true)); } @Test public void changeExtensionWhenReceiveFileWithWrongContentType() throws Exception { Path pngOutput = Paths.get(tmpDir, "cmyk.png"); Files.deleteIfExists(pngOutput); - Files.copy(Paths.get(new ClassPathResource("cmyk.jpg").getURI()), pngOutput); + Files.copy(Paths.get(cmykJpeg.getURI()), pngOutput); assertThat(pngOutput.toFile().exists(), is(true)); CommandResult postJpgCmyk = commandsManager.processCommand(ugnich, "YO", pngOutput.toUri()); assertThat(postJpgCmyk.getNewMessage().isPresent(), is(true)); @@ -1231,7 +1210,7 @@ public class ServerTests { Message original = jsonMapper.readValue(result.getResponse().getContentAsString(), CommandResult.class) .getNewMessage().get(); assertThat(original.getText(), equalTo("YO")); - assertThat(original.getUpdatedAt(), equalTo(original.getTimestamp())); + assertThat(original.getUpdatedAt(), equalTo(original.getCreated())); // to have updated_at greater than ts Thread.sleep(1000); result = mockMvc.perform(post("/api/update").with(httpBasic(ugnichName, ugnichPassword)) @@ -1240,7 +1219,7 @@ public class ServerTests { Message edited = jsonMapper.readValue(result.getResponse().getContentAsString(), CommandResult.class) .getNewMessage().get(); assertThat(edited.getText(), equalTo("PEOPLE")); - assertThat(edited.getUpdatedAt(), greaterThan(edited.getTimestamp())); + assertThat(edited.getUpdatedAt(), greaterThan(edited.getCreated())); mockMvc.perform(post("/api/update").with(httpBasic(freefdName, freefdPassword)) .param("mid", String.valueOf(original.getMid())) .param("body", "PEOPLE")).andExpect(status().is(403)); @@ -1249,7 +1228,7 @@ public class ServerTests { .param("body", "HEY")).andExpect(status().is2xxSuccessful()).andReturn(); CommandResult comment = jsonMapper.readValue(result.getResponse().getContentAsString(), CommandResult.class); assertThat(comment.getNewMessage().get().getText(), is("HEY")); - assertThat(comment.getNewMessage().get().getUpdatedAt(), is(comment.getNewMessage().get().getTimestamp())); + assertThat(comment.getNewMessage().get().getUpdatedAt(), is(comment.getNewMessage().get().getCreated())); // to have updated_at greater than ts Thread.sleep(1000); result = mockMvc.perform(post("/api/update").with(httpBasic(freefdName, freefdPassword)) @@ -1259,7 +1238,7 @@ public class ServerTests { Message editedComment = jsonMapper.readValue(result.getResponse().getContentAsString(), CommandResult.class) .getNewMessage().get(); assertThat(editedComment.getText(), is("HEY, JOE")); - assertThat(editedComment.getUpdatedAt(), greaterThan(editedComment.getTimestamp())); + assertThat(editedComment.getUpdatedAt(), greaterThan(editedComment.getCreated())); messagesService.deleteMessage(ugnich.getUid(), original.getMid()); } @Test @@ -1316,25 +1295,6 @@ public class ServerTests { assertThat(subscriptionService.getUsersSubscribedToComments(msg, reply).size(), is(0)); } @Test - public void xmppStatusApi() throws Exception { - Supplier<XMPPStatus> getStatus = () -> { - try { - MvcResult result = mockMvc.perform(get("/api/xmpp-status").with(httpBasic(ugnichName, ugnichPassword))) - .andExpect(status().isOk()).andReturn(); - return jsonMapper.readValue(result.getResponse().getContentAsString(), XMPPStatus.class); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - }; - assertThat(getStatus.get().getInbound(), is(nullValue())); - ConnectionIn test = new ConnectionIn(server, new Socket("localhost", server.getServerPort())); - test.from.add(Jid.of("test")); - server.getInConnections().clear(); - server.addConnectionIn(test); - assertThat(getStatus.get().getInbound().size(), is(1)); - } - @Test public void credentialsShouldNeverBeSerialized() throws Exception { int uid = userService.createUser("yyy", "xxxx"); User yyy = userService.getUserByUID(uid).get(); @@ -1405,11 +1365,18 @@ public class ServerTests { assertThat(messagesService.recommendMessage(mid, ermineId), is(MessagesService.RecommendStatus.Added)); assertThat(messagesService.recommendMessage(mid, fmapId), is(MessagesService.RecommendStatus.Added)); assertThat(messagesService.recommendMessage(mid, pogoId), is(MessagesService.RecommendStatus.Added)); - assertThat(messagesService.getMessage(mid).get().getLikes(), is(3)); - assertThat(CollectionUtils.isEqualCollection(messagesService.getMessageRecommendations(mid), Arrays.asList("fmap", "ermine", "pogo")), is(true)); - privacyQueriesService.blacklistUser(userService.getUserByName("monstreek"), userService.getUserByName("pogo")); - assertThat(messagesService.getMessage(mid).get().getLikes(), is(3)); - assertThat(CollectionUtils.isEqualCollection(messagesService.getMessageRecommendations(mid), Arrays.asList("fmap", "ermine")), is(true)); + jdbcTemplate.update("INSERT INTO favorites(user_id, user_uri, message_id, like_id, ts) " + + "values (0, 'http://example.com/u/test', ?, 1, now())", mid); + assertThat(messagesService.getMessage(mid).get().getLikes(), is(4)); + assertThat(CollectionUtils.isEqualCollection(messagesService.getMessageRecommendations(mid) + .stream().map(User::getName).collect(Collectors.toList()), + Arrays.asList("fmap", "ermine", "pogo", "Anonymous")), is(true)); + privacyQueriesService.blacklistUser(userService.getUserByName("monstreek"), + userService.getUserByName("pogo")); + assertThat(messagesService.getMessage(mid).get().getLikes(), is(4)); + assertThat(CollectionUtils.isEqualCollection(messagesService.getMessageRecommendations(mid) + .stream().map(User::getName).collect(Collectors.toList()), + Arrays.asList("fmap", "ermine", "Anonymous")), is(true)); } @Test public void bannedUserShouldNotBeVisibleToOthers() { @@ -1696,9 +1663,10 @@ public class ServerTests { CommandResult result = commandsManager.processCommand(ugnich, "*test1 *test2 *test1 test3", emptyUri); assertThat(result.getNewMessage().isPresent(), is(true)); Message msg = result.getNewMessage().get(); - assertThat(msg.getTags().size(), is (2)); - assertThat(msg.getTags().get(0).getName(), is("test1")); - assertThat(msg.getTags().get(1).getName(), is("test2")); + List<Tag> tags = new ArrayList<>(msg.getTags()); + assertThat(tags.size(), is (2)); + assertThat(tags.get(0).getName(), is("test1")); + assertThat(tags.get(1).getName(), is("test2")); assertThat(msg.getText(), is("test3")); } @Test @@ -1759,6 +1727,7 @@ public class ServerTests { replyNote.setTo(Collections.singletonList(activityPubManager.personUri(ugnich))); replyNote.setContent("HI"); Create create = new Create(); + create.setId(replyNote.getId()); create.setActor("http://localhost:8080/u/freefd"); create.setObject(replyNote); signatureManager.post((Person) signatureManager.getContext(URI.create("http://localhost:8080/u/freefd")).get(), @@ -1776,6 +1745,55 @@ public class ServerTests { signatureManager.post(from, to, follow); } @Test + public void serviceSignatureAuth() throws Exception { + String meUri = "/api/me"; + String testHost = "localhost:8080"; + Person ugnichPerson = (Person) signatureManager.discoverPerson("ugnich@localhost:8080").get(); + Instant now = Instant.now(); + String requestDate = DateFormattersHolder.getHttpDateFormatter().format(now); + String signatureString = signatureManager.addSignature(ugnichPerson, testHost, "GET", meUri, requestDate); + MvcResult me = mockMvc.perform(get("/api/me") + .header("Host", testHost) + .header("Date", requestDate) + .header("Signature", signatureString)) + .andExpect(status().isOk()) + .andReturn(); + User meUser = jsonMapper.readValue(me.getResponse().getContentAsString(), User.class); + assertThat(meUser, is(ugnich)); + String testuserResponseString = IOUtils.toString(testuserResponse.getInputStream(), StandardCharsets.UTF_8); + ClientHttpRequestFactory originalRequestFactory = apClient.getRequestFactory(); + URI testuserUri = URI.create("https://example.com/u/testuser"); + URI testuserkeyUri = URI.create("https://example.com/u/testuser#main-key"); + MockRestServiceServer restServiceServer = MockRestServiceServer.createServer(apClient); + restServiceServer.expect(times(3), requestTo(testuserUri)) + .andRespond(withSuccess(testuserResponseString, MediaType.APPLICATION_JSON_UTF8)); + restServiceServer.expect(times(3), requestTo(testuserkeyUri)) + .andRespond(withSuccess(testuserResponseString, MediaType.APPLICATION_JSON_UTF8)); + Person testuser = (Person)signatureManager.getContext(testuserUri).get(); + Assert.assertThat(testuser.getPublicKey().getPublicKeyPem(), is(testKeystoreManager.getPublicKeyPem())); + Instant now2 = Instant.now(); + String testRequestDate = DateFormattersHolder.getHttpDateFormatter().format(now2); + String inboxUri = "/api/inbox"; + String testSignatureString = + signatureManager.addSignature(testuser, testHost, "POST", + inboxUri, testRequestDate, testKeystoreManager); + mockMvc.perform(post(inboxUri) + .header("Host", testHost) + .header("Date", testRequestDate) + .header("Signature", testSignatureString) + .contentType(Context.LD_JSON_MEDIA_TYPE) + .content(IOUtils.toByteArray(testfollowRequest.getInputStream()))) + .andExpect(status().isAccepted()); + mockMvc.perform(post(inboxUri) + .header("Host", "wronghost") + .header("Date", testRequestDate) + .header("Signature", testSignatureString) + .contentType(Context.LD_JSON_MEDIA_TYPE) + .content(IOUtils.toByteArray(testfollowRequest.getInputStream()))) + .andExpect(status().isUnauthorized()); + apClient.setRequestFactory(originalRequestFactory); + } + @Test public void hostmeta() throws Exception { MvcResult result = mockMvc.perform(get("/.well-known/host-meta")) .andExpect(status().isOk()).andReturn(); @@ -1858,4 +1876,139 @@ public class ServerTests { jdbcTemplate.update("INSERT INTO facebook(user_id, fb_id) VALUES(?, ?)", ugnich.getUid(), "100001866137681"); assertThat(userService.getUserByName("ugnich").isVerified(), is(true)); } + @Test + public void avatarUploadOverApi() throws Exception { + ClassPathResource defaultAvatar = new ClassPathResource("static/av-96.png"); + String hash = DigestUtils.md5DigestAsHex(IOUtils.toByteArray(defaultAvatar.getInputStream())); + assertThat(webApp.getAvatarUrl(userService.getUserByName(freefdName)), is(String.format("http://localhost:8080/av-96-%s.png", hash))); + + ClassPathResource newAvatar = new ClassPathResource("static/durov.png"); + byte[] newAvatarData = IOUtils.toByteArray(newAvatar.getInputStream()); + mockMvc.perform(MockMvcRequestBuilders.multipart("/api/me/upload") + .file("avatar", newAvatarData) + .with(httpBasic(freefdName, freefdPassword)) + ).andExpect(status().isOk()); + String newHash = DigestUtils.md5DigestAsHex(newAvatarData); + URI newUri = Paths.get(imgDir, "ao", String.format("%d.png", freefd.getUid())).toUri(); + assertThat(DigestUtils.md5DigestAsHex(IOUtils.toByteArray(newUri)), is(newHash)); + } + @Test + public void varyMvcResponse() throws Exception { + mockMvc.perform(get("/")) + .andExpect(status().isOk()) + .andExpect(header().string("Vary", "Accept-Language")); + mockMvc.perform(get("/rss/ugnich/blog")) + .andExpect(status().isOk()) + .andExpect(header().string("Vary", "Accept-Language")); + mockMvc.perform(get("/api/messages")) + .andExpect(status().isOk()) + .andExpect(header().string("Vary", "Accept-Language")); + } + @Test + public void apiInfo() throws Exception { + userService.createUser("tst", "tst"); + MvcResult result = mockMvc.perform(get("/api/info/tst")) + .andExpect(status().isOk()) + .andReturn(); + User tst = jsonMapper.readValue(result.getResponse().getContentAsString(), User.class); + assertThat(tst.getReaders(), is(nullValue())); + commandsManager.processCommand(ugnich, "S @tst", emptyUri); + result = mockMvc.perform(get("/api/info/tst")) + .andExpect(status().isOk()) + .andReturn(); + tst = jsonMapper.readValue(result.getResponse().getContentAsString(), User.class); + assertThat(tst.getReaders().size(), is(1)); + } + @Test + public void federatedUserDeletionFlow() throws Exception { + String deleteJsonStr = IOUtils.toString(new ClassPathResource("delete_user.json").getURI(), StandardCharsets.UTF_8); + Delete delete = jsonMapper.readValue(deleteJsonStr, Delete.class); + ClientHttpRequestFactory originalRequestFactory = apClient.getRequestFactory(); + MockRestServiceServer restServiceServer = MockRestServiceServer.createServer(apClient); + restServiceServer.expect(times(2), requestTo((String) delete.getObject())) + .andRespond(withStatus(HttpStatus.GONE)); + restServiceServer.expect(requestTo((String) delete.getObject())) + .andRespond(response -> { + throw new ResourceAccessException("Connection reset"); + }); + mockMvc.perform(post("/api/inbox") + .contentType(ACTIVITY_MEDIA_TYPE) + .content(deleteJsonStr)) + .andExpect(status().isAccepted()); + mockMvc.perform(post("/api/inbox") + .contentType(ACTIVITY_MEDIA_TYPE) + .content(deleteJsonStr) + .header("Signature", "keyId=\"https://example.com/users/deleted#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"wHoU91JJBsIYcR1W1/57B0oG98t5Aa/TvGPw1B8KQlAp5KhpePnOzD1MZRgivBx7YKO6eYwDx+AX9dn6tjlAvzRLygv21H6UoDZFihWzeE1HM8pY2Pe4EhUgYBN0YuiKUi7W4TS9bDRAJ5vGNPUWATe+2o5Jcbux5cZYXFKKYbLBLD+/IlqPdHA2IXLZ52HFVVfBkPH5sSklV6XJtD/PHLK9R/I9w/mUpj9moUPQu44rR7KvxiGNuHla3vfDtJbkBqLMdScX91EG8373AulXPUiCCF7R2lJB0fFQedm2nSbcwBoJ32GEyOyOPFgPKG5zd9Fd5TfB1pmA8ZIE0sChfA==\"")) + .andExpect(status().isAccepted()); + apClient.setRequestFactory(originalRequestFactory); + } + @Test + public void handleIncorrectCertificates() throws Exception { + String deleteJsonStr = IOUtils.toString(new ClassPathResource("delete_user.json").getURI(), StandardCharsets.UTF_8); + Delete delete = jsonMapper.readValue(deleteJsonStr, Delete.class); + ClientHttpRequestFactory originalRequestFactory = apClient.getRequestFactory(); + MockRestServiceServer restServiceServer = MockRestServiceServer.createServer(apClient); + restServiceServer.expect(requestTo((String) delete.getObject())) + .andRespond(response -> { + throw new ResourceAccessException("Connection reset"); + }); + mockMvc.perform(post("/api/inbox") + .contentType(ACTIVITY_MEDIA_TYPE) + .content(deleteJsonStr) + .header("Signature", "keyId=\"https://example.com/users/deleted#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"wHoU91JJBsIYcR1W1/57B0oG98t5Aa/TvGPw1B8KQlAp5KhpePnOzD1MZRgivBx7YKO6eYwDx+AX9dn6tjlAvzRLygv21H6UoDZFihWzeE1HM8pY2Pe4EhUgYBN0YuiKUi7W4TS9bDRAJ5vGNPUWATe+2o5Jcbux5cZYXFKKYbLBLD+/IlqPdHA2IXLZ52HFVVfBkPH5sSklV6XJtD/PHLK9R/I9w/mUpj9moUPQu44rR7KvxiGNuHla3vfDtJbkBqLMdScX91EG8373AulXPUiCCF7R2lJB0fFQedm2nSbcwBoJ32GEyOyOPFgPKG5zd9Fd5TfB1pmA8ZIE0sChfA==\"")) + .andExpect(status().isAccepted()); + apClient.setRequestFactory(originalRequestFactory); + } + + @Test + public void legacyAvatarEndpoint() throws Exception { + mockMvc.perform(get("/api/avatar") + .param("uname", "unknown")) + .andExpect(status().isOk()) + .andExpect(content().bytes(IOUtils.toByteArray(defaultAvatar.getInputStream()))); + } + @Test + public void federatedAttachmentsAsLinks() throws Exception { + int mid = messagesService.createMessage(ugnich.getUid(), "test", StringUtils.EMPTY, Collections.emptyList()); + Message testMessage = MockUtils.mockMessage(mid, freefd, "reply"); + String activity = IOUtils.toString(noteWithDocument.getInputStream(), StandardCharsets.UTF_8); + Announce announce = jsonMapper.readValue(activity, Announce.class); + } + @Test + public void hubzillaActor() throws Exception { + String activity = IOUtils.toString(hubzillaActivity.getInputStream(), StandardCharsets.UTF_8); + Create create = jsonMapper.readValue(activity, Create.class); + String followData = IOUtils.toString(hubzillaFollow.getInputStream(), StandardCharsets.UTF_8); + Follow follow = jsonMapper.readValue(followData, Follow.class); + assertThat(follow.getActor(), is("https://ussr.win/channel/zlax")); + } + @Test + public void nodeinfo() throws Exception { + MvcResult nodeinfoXRD = mockMvc.perform(get("/.well-known/nodeinfo") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn(); + JsonNode node = jsonMapper.readTree(nodeinfoXRD.getResponse().getContentAsString()); + assertThat(node.get("links"), notNullValue()); + String nodeinfoUrl = node.get("links").get(0).get("href").textValue(); + MvcResult nodeinfoData = mockMvc.perform(get(nodeinfoUrl) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn(); + JsonNode nodeinfo = jsonMapper.readTree(nodeinfoData.getResponse().getContentAsString()); + assertThat(nodeinfo.get("software"), notNullValue()); + assertThat(nodeinfo.get("server"), nullValue()); + MvcResult xnodeinfoData = mockMvc.perform(get("/.well-known/x-nodeinfo2") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn(); + JsonNode xnodeinfo = jsonMapper.readTree(xnodeinfoData.getResponse().getContentAsString()); + assertThat(xnodeinfo.get("server"), notNullValue()); + assertThat(xnodeinfo.get("software"), nullValue()); + } + @Test + public void anonymousUserFromZero() { + User user = userService.getUserByUID(0).orElse(AnonymousUser.INSTANCE); + assertThat(user.isAnonymous(), is(true)); + } } diff --git a/src/test/java/com/juick/test/util/MockUtils.java b/src/test/java/com/juick/test/util/MockUtils.java index 017af4d1..8f6b821d 100644 --- a/src/test/java/com/juick/test/util/MockUtils.java +++ b/src/test/java/com/juick/test/util/MockUtils.java @@ -34,7 +34,7 @@ public class MockUtils { msg.setMid(mid); msg.setUser(user); msg.setText(messageText == null ? generator.generate(24) : messageText); - msg.setTimestamp(Instant.now()); + msg.setCreated(Instant.now()); return msg; } |