aboutsummaryrefslogtreecommitdiff
path: root/juick-server/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'juick-server/src/main/java')
-rw-r--r--juick-server/src/main/java/com/juick/server/ActivityPubManager.java9
-rw-r--r--juick-server/src/main/java/com/juick/server/SignatureManager.java26
-rw-r--r--juick-server/src/main/java/com/juick/server/api/activity/Profile.java18
-rw-r--r--juick-server/src/main/java/com/juick/server/api/activity/model/Context.java3
-rw-r--r--juick-server/src/main/java/com/juick/server/api/webfinger/Resource.java4
5 files changed, 43 insertions, 17 deletions
diff --git a/juick-server/src/main/java/com/juick/server/ActivityPubManager.java b/juick-server/src/main/java/com/juick/server/ActivityPubManager.java
index 0cb76a03..6f5163cc 100644
--- a/juick-server/src/main/java/com/juick/server/ActivityPubManager.java
+++ b/juick-server/src/main/java/com/juick/server/ActivityPubManager.java
@@ -262,6 +262,15 @@ public class ActivityPubManager implements ActivityListener, NotificationListene
} else if (MessageUtils.isReply(msg)) {
note.getTags().add(new Mention(personWebUri(msg.getTo()), msg.getTo().getName()));
}
+ MessageUtils.getGlobalMentions(msg).forEach(m -> {
+ // @user@server.tld -> user@server.tld
+ Optional<Context> personContext = signatureManager.discoverPerson(m.substring(1));
+ if (personContext.isPresent()) {
+ Person person = (Person) personContext.get();
+ note.getTags().add(new Mention(person.getUrl(), person.getPreferredUsername()));
+ note.getCc().add(person.getUrl());
+ }
+ });
if (msg.isHtml()) {
note.setContent(msg.getText());
} else {
diff --git a/juick-server/src/main/java/com/juick/server/SignatureManager.java b/juick-server/src/main/java/com/juick/server/SignatureManager.java
index 927a62a7..b3b7a301 100644
--- a/juick-server/src/main/java/com/juick/server/SignatureManager.java
+++ b/juick-server/src/main/java/com/juick/server/SignatureManager.java
@@ -3,22 +3,22 @@ package com.juick.server;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.juick.server.api.activity.model.Context;
import com.juick.server.api.activity.model.objects.Person;
-import com.juick.service.activities.DeleteUserEvent;
+import com.juick.server.api.webfinger.model.Account;
+import com.juick.server.api.webfinger.model.Link;
import com.juick.util.DateFormattersHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
-import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import org.tomitribe.auth.signatures.Signature;
import org.tomitribe.auth.signatures.Signer;
import org.tomitribe.auth.signatures.Verifier;
+import rocks.xmpp.addr.Jid;
import javax.inject.Inject;
import java.io.IOException;
@@ -27,12 +27,12 @@ import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.time.Instant;
-import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
+import static com.juick.server.api.activity.model.Context.ACTIVITY_MEDIA_TYPE;
+
@Component
public class SignatureManager {
private static final Logger logger = LoggerFactory.getLogger(ActivityPubManager.class);
@@ -58,7 +58,7 @@ public class SignatureManager {
headers.put("date", requestDate);
Signature signature = signer.sign("POST", inbox.getPath(), headers);
HttpHeaders requestHeaders = new HttpHeaders();
- requestHeaders.add("Content-Type", Context.ACTIVITY_JSON_MEDIA_TYPE);
+ requestHeaders.add("Content-Type", Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE);
requestHeaders.add("Date", requestDate);
requestHeaders.add("Signature", signature.toString().substring(10));
HttpEntity<Context> request = new HttpEntity<>(Context.build(data), requestHeaders);
@@ -96,4 +96,18 @@ public class SignatureManager {
}
return Optional.of(context);
}
+ public Optional<Context> discoverPerson(String acct) {
+ Jid acctId = Jid.of(acct);
+ URI resourceUri = UriComponentsBuilder.fromUriString(
+ String.format("https://%s/.well-known/webfinger?resource=acct:%s", acctId.getDomain(), acct)).build().toUri();
+ Account acctData = apClient.getForEntity(resourceUri, Account.class).getBody();
+ if (acctData != null) {
+ for (Link l : acctData.getLinks()) {
+ if (l.getRel().equals("self") && l.getType().equals(ACTIVITY_MEDIA_TYPE)) {
+ return getContext(URI.create(l.getHref()));
+ }
+ }
+ }
+ return Optional.empty();
+ }
}
diff --git a/juick-server/src/main/java/com/juick/server/api/activity/Profile.java b/juick-server/src/main/java/com/juick/server/api/activity/Profile.java
index ce09436d..10390ea1 100644
--- a/juick-server/src/main/java/com/juick/server/api/activity/Profile.java
+++ b/juick-server/src/main/java/com/juick/server/api/activity/Profile.java
@@ -82,7 +82,7 @@ public class Profile {
@Inject
private ObjectMapper jsonMapper;
- @GetMapping(value = "/u/{userName}", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_JSON_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
public Person getUser(@PathVariable String userName) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
@@ -111,7 +111,7 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/blog/toc", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_JSON_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/blog/toc", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
public OrderedCollection getOutbox(@PathVariable String userName) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
@@ -125,7 +125,7 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/blog", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_JSON_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/blog", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
public OrderedCollectionPage getOutboxPage(@PathVariable String userName,
@RequestParam(required = false, defaultValue = "0") int before) {
User visitor = UserUtils.getCurrentUser();
@@ -158,7 +158,7 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/followers/toc", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_JSON_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/followers/toc", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
public OrderedCollection getFollowers(@PathVariable String userName) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
@@ -172,7 +172,7 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/followers", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_JSON_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/followers", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
public OrderedCollectionPage getFollowersPage(@PathVariable String userName,
@RequestParam(required = false, defaultValue = "0") int page) {
User user = userService.getUserByName(userName);
@@ -200,7 +200,7 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/following/toc", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_JSON_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/following/toc", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
public OrderedCollection getFollowing(@PathVariable String userName) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
@@ -214,7 +214,7 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/u/{userName}/following", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_JSON_MEDIA_TYPE})
+ @GetMapping(value = "/u/{userName}/following", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
public OrderedCollectionPage getFollowingPage(@PathVariable String userName,
@RequestParam(required = false, defaultValue = "0") int page) {
User user = userService.getUserByName(userName);
@@ -242,7 +242,7 @@ public class Profile {
throw new HttpNotFoundException();
}
- @GetMapping(value = "/n/{mid}-{rid}", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_JSON_MEDIA_TYPE})
+ @GetMapping(value = "/n/{mid}-{rid}", produces = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
public Context showNote(@PathVariable int mid, @PathVariable int rid) {
if (rid > 0) {
// reply
@@ -253,7 +253,7 @@ public class Profile {
messagesService.getMessage(mid)));
}
- @PostMapping(value = "/api/inbox", consumes = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITY_JSON_MEDIA_TYPE})
+ @PostMapping(value = "/api/inbox", consumes = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE})
public ResponseEntity<Void> processInbox(@RequestBody Activity activity,
@RequestHeader(name = "Host") String host,
@RequestHeader(name = "Date") String date,
diff --git a/juick-server/src/main/java/com/juick/server/api/activity/model/Context.java b/juick-server/src/main/java/com/juick/server/api/activity/model/Context.java
index 544f1aa2..0df8f8c7 100644
--- a/juick-server/src/main/java/com/juick/server/api/activity/model/Context.java
+++ b/juick-server/src/main/java/com/juick/server/api/activity/model/Context.java
@@ -71,7 +71,8 @@ public abstract class Context {
public final static String ACTIVITY_STREAMS_URI = "https://www.w3.org/ns/activitystreams";
public final static String SECURITY_URI = "https://w3id.org/security/v1";
public final static String LD_JSON_MEDIA_TYPE = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"";
- public final static String ACTIVITY_JSON_MEDIA_TYPE = "application/activity+json; profile=\"https://www.w3.org/ns/activitystreams\"";
+ public final static String ACTIVITY_MEDIA_TYPE = "application/activity+json";
+ public final static String ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE = ACTIVITY_MEDIA_TYPE + "; profile=\"https://www.w3.org/ns/activitystreams\"";
public Instant getPublished() {
return published;
diff --git a/juick-server/src/main/java/com/juick/server/api/webfinger/Resource.java b/juick-server/src/main/java/com/juick/server/api/webfinger/Resource.java
index 2df895fd..71a0ca31 100644
--- a/juick-server/src/main/java/com/juick/server/api/webfinger/Resource.java
+++ b/juick-server/src/main/java/com/juick/server/api/webfinger/Resource.java
@@ -15,6 +15,8 @@ import rocks.xmpp.addr.Jid;
import javax.inject.Inject;
import java.util.Collections;
+import static com.juick.server.api.activity.model.Context.ACTIVITY_MEDIA_TYPE;
+
@RestController
public class Resource {
@Inject
@@ -35,7 +37,7 @@ public class Resource {
builder.path(String.format("/u/%s", user.getName()));
Link blog = new Link();
blog.setRel("self");
- blog.setType("application/activity+json");
+ blog.setType(ACTIVITY_MEDIA_TYPE);
blog.setHref(builder.toUriString());
Account result = new Account();
result.setSubject(resource);