From cdd03aa64548810591e043fb59a287a1b36c92ba Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Thu, 5 Jan 2023 11:00:50 +0300 Subject: ActivityPub: signed GET requests, fix Signature verification --- src/main/java/com/juick/ActivityPubManager.java | 48 ++++++++++++++----------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'src/main/java/com/juick/ActivityPubManager.java') diff --git a/src/main/java/com/juick/ActivityPubManager.java b/src/main/java/com/juick/ActivityPubManager.java index a487afb1..db8a1acb 100644 --- a/src/main/java/com/juick/ActivityPubManager.java +++ b/src/main/java/com/juick/ActivityPubManager.java @@ -19,12 +19,13 @@ package com.juick; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.json.JsonMapper; import com.juick.model.Message; import com.juick.model.Reaction; import com.juick.model.User; +import com.juick.service.ActivityPubService; import com.juick.service.MessagesService; import com.juick.service.SocialService; +import com.juick.service.WebfingerService; import com.juick.service.activities.*; import com.juick.service.component.NotificationListener; import com.juick.service.component.PingEvent; @@ -45,6 +46,7 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.convert.ConversionService; +import org.springframework.http.MediaType; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; @@ -62,7 +64,9 @@ import java.util.stream.Collectors; public class ActivityPubManager implements ActivityListener, NotificationListener { private static final Logger logger = LoggerFactory.getLogger("ActivityPub"); @Inject - private SignatureManager signatureManager; + private ActivityPubService activityPubService; + @Inject + private WebfingerService webfingerService; @Inject private SocialService socialService; @Inject @@ -84,12 +88,12 @@ public class ActivityPubManager implements ActivityListener, NotificationListene if (!followedUser.isAnonymous()) { // automatically accept follower requests Actor me = conversionService.convert(followedUser, Actor.class); - Actor follower = (Actor) signatureManager.getContext(URI.create(followEvent.getRequest().getActor())).get(); + Actor follower = (Actor) activityPubService.get(URI.create(followEvent.getRequest().getActor())).get(); Accept accept = new Accept(); accept.setActor(me.getId()); accept.setObject(followEvent.getRequest()); try { - signatureManager.post(me, follower, accept); + activityPubService.post(me, follower, accept); socialService.addFollower(followedUser, follower.getId()); logger.info("Follower added for {}", followedUser.getName()); } catch (IOException | NoSuchAlgorithmException e) { @@ -124,14 +128,14 @@ public class ActivityPubManager implements ActivityListener, NotificationListene Actor me = conversionService.convert(user, Actor.class); socialService.getFollowers(user).forEach(acct -> { try { - Actor follower = (Actor) signatureManager.getContext(URI.create(acct)).orElseThrow(); + Actor follower = (Actor) activityPubService.get(URI.create(acct)).orElseThrow(); Delete delete = new Delete(); delete.setId(note.getId()); delete.setActor(me.getId()); delete.setPublished(note.getPublished()); delete.setObject(note); logger.info("Deletion to follower {}", follower.getId()); - signatureManager.post(me, follower, delete); + activityPubService.post(me, follower, delete); } catch (IOException | NoSuchAlgorithmException e) { logger.warn("activitypub exception", e); } catch (NoSuchElementException ex) { @@ -196,12 +200,12 @@ public class ActivityPubManager implements ActivityListener, NotificationListene private void activityToFollowers(User user, Actor from, Activity activity) { socialService.getFollowers(user).forEach(acct -> { - var context = signatureManager.getContext(URI.create(acct)); + var context = activityPubService.get(URI.create(acct)); context.ifPresentOrElse((follower) -> { if (follower instanceof Actor) { var to = (Actor) follower; try { - signatureManager.post(from, to, activity); + activityPubService.post(from, to, activity); } catch (Exception e) { logger.warn("Delivery to {} failed: {}", to, e.getMessage()); } @@ -251,7 +255,7 @@ public class ActivityPubManager implements ActivityListener, NotificationListene subscribers.addAll(note.getCc()); subscribers.forEach(acct -> { if (!acct.equals(profileUriBuilder.followersUri(user))) { - var context = signatureManager.getContext(URI.create(acct)); + var context = activityPubService.get(URI.create(acct)); context.ifPresentOrElse((follower) -> { if (follower instanceof Actor) { var to = (Actor) follower; @@ -261,7 +265,7 @@ public class ActivityPubManager implements ActivityListener, NotificationListene create.setPublished(note.getPublished()); create.setObject(note); try { - signatureManager.post(me, to, create); + activityPubService.post(me, to, create); } catch (IOException | NoSuchAlgorithmException e) { logger.warn("Delivery to {} failed: {}", to, e.getMessage()); } @@ -308,10 +312,10 @@ public class ActivityPubManager implements ActivityListener, NotificationListene note.setTags(msg.getTags().stream().map(t -> new Hashtag(profileUriBuilder.tagUri(t), t.getName())) .collect(Collectors.toList())); if (msg.getReplyToUri() != null && msg.getReplyToUri().toASCIIString().length() > 0) { - Optional noteContext = signatureManager.getContext(msg.getReplyToUri()); + Optional noteContext = activityPubService.get(msg.getReplyToUri()); if (noteContext.isPresent()) { Note activity = (Note) noteContext.get(); - Optional personContext = signatureManager.getContext(URI.create(activity.getAttributedTo())); + Optional personContext = activityPubService.get(URI.create(activity.getAttributedTo())); if (personContext.isPresent()) { Actor person = (Actor) personContext.get(); note.getTags().add(new Mention(person.getUrl(), person.getPreferredUsername())); @@ -324,13 +328,17 @@ public class ActivityPubManager implements ActivityListener, NotificationListene } MessageUtils.getGlobalMentions(msg).forEach(m -> { // @user@server.tld -> user@server.tld - Optional personContext = signatureManager.discoverPerson(m.substring(1)); - if (personContext.isPresent()) { - Actor person = (Actor) personContext.get(); - note.getTags().add(new Mention(person.getUrl(), person.getPreferredUsername())); - List cc = new ArrayList<>(note.getCc()); - cc.add(person.getId()); - note.setCc(cc); + var personURI = webfingerService.discoverAccountURI(m.substring(1), + MediaType.valueOf(Context.ACTIVITY_MEDIA_TYPE)); + if (!personURI.toASCIIString().isEmpty()) { + var personContext = activityPubService.get(personURI); + if (personContext.isPresent()) { + Actor person = (Actor) personContext.get(); + note.getTags().add(new Mention(person.getUrl(), person.getPreferredUsername())); + List cc = new ArrayList<>(note.getCc()); + cc.add(person.getId()); + note.setCc(cc); + } } }); note.setSensitive(MessageUtils.isSensitive(msg)); @@ -371,7 +379,7 @@ public class ActivityPubManager implements ActivityListener, NotificationListene } public User actorToUser(URI uri) throws HttpBadRequestException, JsonProcessingException { - var context = signatureManager.getContext(uri); + var context = activityPubService.get(uri); if (context.isPresent() && context.get() instanceof Actor actor) { User user = new User(); user.setUri(URI.create(actor.getId())); -- cgit v1.2.3