aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2021-08-22 06:55:37 +0300
committerGravatar Vitaly Takmazov2021-08-22 06:55:37 +0300
commit03d42d6e6ccaee4ff9d2a0808e51e5f9f0dc18c3 (patch)
treea3a6f5ef310b2130ff6fdf541f34facecd8bf2b3 /src
parent9100b5bda037fcd1b051b98585744077132320bc (diff)
ActivityPub: return Application profile for service user
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/juick/KeystoreManager.java4
-rw-r--r--src/main/java/com/juick/SignatureManager.java10
-rw-r--r--src/main/java/com/juick/service/UserService.java2
-rw-r--r--src/main/java/com/juick/service/UserServiceImpl.java8
-rw-r--r--src/main/java/com/juick/www/api/activity/Profile.java32
-rw-r--r--src/main/java/com/juick/www/api/activity/model/Context.java13
-rw-r--r--src/main/java/com/juick/www/api/activity/model/objects/Actor.java (renamed from src/main/java/com/juick/www/api/activity/model/objects/SecurityObject.java)47
-rw-r--r--src/main/java/com/juick/www/api/activity/model/objects/Application.java2
-rw-r--r--src/main/java/com/juick/www/api/activity/model/objects/Person.java68
-rw-r--r--src/test/java/com/juick/server/tests/ServerTests.java11
10 files changed, 102 insertions, 95 deletions
diff --git a/src/main/java/com/juick/KeystoreManager.java b/src/main/java/com/juick/KeystoreManager.java
index f968f627..32596170 100644
--- a/src/main/java/com/juick/KeystoreManager.java
+++ b/src/main/java/com/juick/KeystoreManager.java
@@ -17,7 +17,7 @@
package com.juick;
-import com.juick.www.api.activity.model.objects.SecurityObject;
+import com.juick.www.api.activity.model.objects.Actor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
@@ -74,7 +74,7 @@ public class KeystoreManager {
return String.format("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n",
String.join("\n", key));
}
- public static PublicKey publicKeyOf(SecurityObject person) {
+ public static PublicKey publicKeyOf(Actor person) {
String pubkeyPem = person.getPublicKey().getPublicKeyPem();
String[] rawKey = pubkeyPem.split("\\n");
String pubkeyData = String.join("", Arrays.asList(rawKey).subList(1, rawKey.length - 1));
diff --git a/src/main/java/com/juick/SignatureManager.java b/src/main/java/com/juick/SignatureManager.java
index d14eedd1..668669f1 100644
--- a/src/main/java/com/juick/SignatureManager.java
+++ b/src/main/java/com/juick/SignatureManager.java
@@ -24,7 +24,7 @@ import com.juick.service.UserService;
import com.juick.util.DateFormattersHolder;
import com.juick.www.api.activity.model.Context;
import com.juick.www.api.activity.model.objects.Person;
-import com.juick.www.api.activity.model.objects.SecurityObject;
+import com.juick.www.api.activity.model.objects.Actor;
import com.juick.www.api.webfinger.model.Account;
import com.juick.www.api.webfinger.model.Link;
import org.apache.commons.lang3.StringUtils;
@@ -94,14 +94,14 @@ public class SignatureManager {
logger.info("Remote response: {}", response.getStatusCodeValue());
}
- public String addSignature(SecurityObject from, String host, String method,
+ public String addSignature(Actor from, String host, String method,
String path, String dateString, String digestHeader)
throws IOException {
return addSignature(from, host, method, path, dateString,
digestHeader, keystoreManager);
}
- public String addSignature(SecurityObject from, String host, String method,
+ public String addSignature(Actor from, String host, String method,
String path, String dateString, String digestHeader,
KeystoreManager keystoreManager) throws IOException {
List<String> requiredHeaders = StringUtils.isEmpty(digestHeader) ?
@@ -127,8 +127,8 @@ public class SignatureManager {
Signature signature = Signature.fromString(signatureString);
Optional<Context> context = getContext(UriComponentsBuilder.fromUriString(signature.getKeyId())
.fragment(null).build().toUri());
- if (context.isPresent() && context.get() instanceof SecurityObject) {
- SecurityObject securityObject = (SecurityObject) context.get();
+ if (context.isPresent() && context.get() instanceof Actor) {
+ Actor securityObject = (Actor) context.get();
Key key = KeystoreManager.publicKeyOf(securityObject);
Verifier verifier = new Verifier(key, signature);
diff --git a/src/main/java/com/juick/service/UserService.java b/src/main/java/com/juick/service/UserService.java
index 4b1cd127..e1f53abb 100644
--- a/src/main/java/com/juick/service/UserService.java
+++ b/src/main/java/com/juick/service/UserService.java
@@ -126,4 +126,6 @@ public interface UserService {
void updateLastSeen(User user);
boolean isAdminUser(User user);
+
+ boolean isServiceUser(User user);
}
diff --git a/src/main/java/com/juick/service/UserServiceImpl.java b/src/main/java/com/juick/service/UserServiceImpl.java
index 7d215260..1594936a 100644
--- a/src/main/java/com/juick/service/UserServiceImpl.java
+++ b/src/main/java/com/juick/service/UserServiceImpl.java
@@ -57,6 +57,9 @@ public class UserServiceImpl extends BaseJdbcService implements UserService {
@Value("${juick.admin_users:}")
List<String> adminUsers;
+ @Value("${service_user:juick}")
+ private String serviceUser;
+
private class UserMapper implements RowMapper<User> {
@Override
public User mapRow(@Nonnull ResultSet rs, int rowNum) throws SQLException {
@@ -663,4 +666,9 @@ public class UserServiceImpl extends BaseJdbcService implements UserService {
public boolean isAdminUser(User user) {
return adminUsers.contains(user.getName());
}
+
+ @Override
+ public boolean isServiceUser(User user) {
+ return user.getName().equals(serviceUser);
+ }
}
diff --git a/src/main/java/com/juick/www/api/activity/Profile.java b/src/main/java/com/juick/www/api/activity/Profile.java
index 751d0cff..724e0747 100644
--- a/src/main/java/com/juick/www/api/activity/Profile.java
+++ b/src/main/java/com/juick/www/api/activity/Profile.java
@@ -34,6 +34,8 @@ import com.juick.www.api.activity.model.activities.Flag;
import com.juick.www.api.activity.model.activities.Follow;
import com.juick.www.api.activity.model.activities.Like;
import com.juick.www.api.activity.model.activities.Undo;
+import com.juick.www.api.activity.model.objects.Actor;
+import com.juick.www.api.activity.model.objects.Application;
import com.juick.www.api.activity.model.objects.Image;
import com.juick.www.api.activity.model.objects.Key;
import com.juick.www.api.activity.model.objects.Note;
@@ -106,28 +108,28 @@ public class Profile {
@GetMapping(value = "/u/{userName}", produces = { Context.LD_JSON_MEDIA_TYPE,
Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE, Context.FALLBACK_JSON_MEDIA_TYPE })
- public Person getUser(@PathVariable String userName) {
+ public Actor getUser(@PathVariable String userName) {
User user = userService.getUserByName(userName);
if (!user.isAnonymous()) {
- Person person = new Person();
- person.setId(activityPubManager.personUri(user));
- person.setUrl(activityPubManager.personWebUri(user));
- person.setName(userName);
- person.setPreferredUsername(userName);
+ Actor profile = userService.isServiceUser(user) ? new Application() : new Person();
+ profile.setId(activityPubManager.personUri(user));
+ profile.setUrl(activityPubManager.personWebUri(user));
+ profile.setName(userName);
+ profile.setPreferredUsername(userName);
Key publicKey = new Key();
- publicKey.setId(person.getId() + "#main-key");
- publicKey.setOwner(person.getId());
+ publicKey.setId(profile.getId() + "#main-key");
+ publicKey.setOwner(profile.getId());
publicKey.setPublicKeyPem(keystoreManager.getPublicKeyPem());
- person.setPublicKey(publicKey);
- person.setInbox(activityPubManager.inboxUri());
- person.setOutbox(activityPubManager.outboxUri(user));
- person.setFollowers(activityPubManager.followersUri(user));
- person.setFollowing(activityPubManager.followingUri(user));
+ profile.setPublicKey(publicKey);
+ profile.setInbox(activityPubManager.inboxUri());
+ profile.setOutbox(activityPubManager.outboxUri(user));
+ profile.setFollowers(activityPubManager.followersUri(user));
+ profile.setFollowing(activityPubManager.followingUri(user));
Image avatar = new Image();
avatar.setUrl(webApp.getAvatarUrl(user));
avatar.setMediaType("image/png");
- person.setIcon(avatar);
- return (Person) Context.build(person);
+ profile.setIcon(avatar);
+ return (Actor) Context.build(profile);
}
throw new HttpNotFoundException();
}
diff --git a/src/main/java/com/juick/www/api/activity/model/Context.java b/src/main/java/com/juick/www/api/activity/model/Context.java
index edfa89b1..f5d95d24 100644
--- a/src/main/java/com/juick/www/api/activity/model/Context.java
+++ b/src/main/java/com/juick/www/api/activity/model/Context.java
@@ -58,11 +58,9 @@ import java.util.Map;
public class Context {
private List<Object> context;
-
private String id;
-
private String name;
-
+ private Image icon;
private Instant published;
@JsonDeserialize(using = LinkValueDeserializer.class)
@@ -150,4 +148,13 @@ public class Context {
public void setName(String name) {
this.name = name;
}
+
+ @JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
+ public Image getIcon() {
+ return icon;
+ }
+
+ public void setIcon(Image icon) {
+ this.icon = icon;
+ }
}
diff --git a/src/main/java/com/juick/www/api/activity/model/objects/SecurityObject.java b/src/main/java/com/juick/www/api/activity/model/objects/Actor.java
index 8d17aa29..f8bd63e0 100644
--- a/src/main/java/com/juick/www/api/activity/model/objects/SecurityObject.java
+++ b/src/main/java/com/juick/www/api/activity/model/objects/Actor.java
@@ -20,7 +20,13 @@ package com.juick.www.api.activity.model.objects;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.juick.www.api.activity.model.Context;
-public class SecurityObject extends Context {
+public class Actor extends Context {
+
+ private String preferredUsername;
+ private String inbox;
+ private String outbox;
+ private String following;
+ private String followers;
private Key publicKey;
@@ -33,4 +39,43 @@ public class SecurityObject extends Context {
this.publicKey = publicKey;
}
+ public String getOutbox() {
+ return outbox;
+ }
+
+ public void setOutbox(String outbox) {
+ this.outbox = outbox;
+ }
+
+ public String getInbox() {
+ return inbox;
+ }
+
+ public void setInbox(String inbox) {
+ this.inbox = inbox;
+ }
+
+ public String getFollowing() {
+ return following;
+ }
+
+ public void setFollowing(String following) {
+ this.following = following;
+ }
+
+ public String getFollowers() {
+ return followers;
+ }
+
+ public void setFollowers(String followers) {
+ this.followers = followers;
+ }
+
+ public String getPreferredUsername() {
+ return preferredUsername;
+ }
+
+ public void setPreferredUsername(String preferredUsername) {
+ this.preferredUsername = preferredUsername;
+ }
}
diff --git a/src/main/java/com/juick/www/api/activity/model/objects/Application.java b/src/main/java/com/juick/www/api/activity/model/objects/Application.java
index 29361b33..d30d36c9 100644
--- a/src/main/java/com/juick/www/api/activity/model/objects/Application.java
+++ b/src/main/java/com/juick/www/api/activity/model/objects/Application.java
@@ -17,5 +17,5 @@
package com.juick.www.api.activity.model.objects;
-public class Application extends SecurityObject {
+public class Application extends Actor {
}
diff --git a/src/main/java/com/juick/www/api/activity/model/objects/Person.java b/src/main/java/com/juick/www/api/activity/model/objects/Person.java
index 84844510..e59c793a 100644
--- a/src/main/java/com/juick/www/api/activity/model/objects/Person.java
+++ b/src/main/java/com/juick/www/api/activity/model/objects/Person.java
@@ -17,72 +17,6 @@
package com.juick.www.api.activity.model.objects;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
+public class Person extends Actor {
-public class Person extends SecurityObject {
-
- private String name;
- private String preferredUsername;
- private Image icon;
- private String inbox;
- private String outbox;
- private String following;
- private String followers;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
- public Image getIcon() {
- return icon;
- }
-
- public void setIcon(Image icon) {
- this.icon = icon;
- }
-
- public String getOutbox() {
- return outbox;
- }
-
- public void setOutbox(String outbox) {
- this.outbox = outbox;
- }
-
- public String getInbox() {
- return inbox;
- }
-
- public void setInbox(String inbox) {
- this.inbox = inbox;
- }
-
- public String getFollowing() {
- return following;
- }
-
- public void setFollowing(String following) {
- this.following = following;
- }
-
- public String getFollowers() {
- return followers;
- }
-
- public void setFollowers(String followers) {
- this.followers = followers;
- }
-
- public String getPreferredUsername() {
- return preferredUsername;
- }
-
- public void setPreferredUsername(String preferredUsername) {
- this.preferredUsername = preferredUsername;
- }
}
diff --git a/src/test/java/com/juick/server/tests/ServerTests.java b/src/test/java/com/juick/server/tests/ServerTests.java
index c11dfb46..bcdb4af3 100644
--- a/src/test/java/com/juick/server/tests/ServerTests.java
+++ b/src/test/java/com/juick/server/tests/ServerTests.java
@@ -39,6 +39,7 @@ import com.juick.www.api.Users;
import com.juick.www.api.activity.Profile;
import com.juick.www.api.activity.model.Context;
import com.juick.www.api.activity.model.activities.*;
+import com.juick.www.api.activity.model.objects.Actor;
import com.juick.www.api.activity.model.objects.Application;
import com.juick.www.api.activity.model.objects.Image;
import com.juick.www.api.activity.model.objects.Note;
@@ -1863,7 +1864,7 @@ public class ServerTests {
String requestDate = DateFormattersHolder.getHttpDateFormatter().format(now);
mockMvc.perform(get("/api/me").header("Date", requestDate)).andExpect(status().isUnauthorized());
String testHost = "localhost";
- Person ugnichPerson = profileController.getUser("ugnich");
+ Actor ugnichPerson = profileController.getUser("ugnich");
now = Instant.now();
requestDate = DateFormattersHolder.getHttpDateFormatter().format(now);
String signatureString = signatureManager.addSignature(ugnichPerson, testHost, "GET", meUri, requestDate,
@@ -1925,6 +1926,14 @@ public class ServerTests {
}
@Test
+ public void serviceUserProfileIsApplicationProfile() throws Exception {
+ MvcResult response = mockMvc.perform(get("/u/juick")
+ .accept(Context.ACTIVITY_MEDIA_TYPE)).andReturn();
+ Actor actor = jsonMapper.readValue(response.getResponse().getContentAsString(), Actor.class);
+ assertThat(actor, is(instanceOf(Application.class)));
+ }
+
+ @Test
public void hostmeta() throws Exception {
MvcResult result = mockMvc.perform(get("/.well-known/host-meta")).andExpect(status().isOk()).andReturn();
String xrd = result.getResponse().getContentAsString();