aboutsummaryrefslogtreecommitdiff
path: root/juick-server/src/main/java/com/juick/server/api/activity/Profile.java
diff options
context:
space:
mode:
Diffstat (limited to 'juick-server/src/main/java/com/juick/server/api/activity/Profile.java')
-rw-r--r--juick-server/src/main/java/com/juick/server/api/activity/Profile.java379
1 files changed, 0 insertions, 379 deletions
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
deleted file mode 100644
index 10390ea1..00000000
--- a/juick-server/src/main/java/com/juick/server/api/activity/Profile.java
+++ /dev/null
@@ -1,379 +0,0 @@
-package com.juick.server.api.activity;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.juick.Message;
-import com.juick.User;
-import com.juick.model.CommandResult;
-import com.juick.server.ActivityPubManager;
-import com.juick.server.CommandsManager;
-import com.juick.server.KeystoreManager;
-import com.juick.server.SignatureManager;
-import com.juick.server.api.activity.model.Activity;
-import com.juick.server.api.activity.model.Context;
-import com.juick.server.api.activity.model.activities.Announce;
-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.Undo;
-import com.juick.server.api.activity.model.objects.Image;
-import com.juick.server.api.activity.model.objects.Key;
-import com.juick.server.api.activity.model.objects.Note;
-import com.juick.server.api.activity.model.objects.OrderedCollection;
-import com.juick.server.api.activity.model.objects.OrderedCollectionPage;
-import com.juick.server.api.activity.model.objects.Person;
-import com.juick.server.util.HttpBadRequestException;
-import com.juick.server.util.HttpNotFoundException;
-import com.juick.server.util.UserUtils;
-import com.juick.service.MessagesService;
-import com.juick.service.UserService;
-import com.juick.service.activities.DeleteUserEvent;
-import com.juick.service.activities.FollowEvent;
-import com.juick.service.activities.UndoFollowEvent;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
-import org.springframework.web.util.UriComponents;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import javax.inject.Inject;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-@RestController
-public class Profile {
- private static final Logger logger = LoggerFactory.getLogger(Profile.class);
- @Inject
- private UserService userService;
- @Inject
- private MessagesService messagesService;
- @Inject
- private KeystoreManager keystoreManager;
- @Inject
- private SignatureManager signatureManager;
- @Inject
- private ActivityPubManager activityPubManager;
- @Inject
- private ApplicationEventPublisher applicationEventPublisher;
- @Inject
- private CommandsManager commandsManager;
- @Value("${web_domain:localhost}")
- private String domain;
- @Value("${ap_base_uri:http://localhost:8080/}")
- private String baseUri;
- @Value("${img_url:http://localhost:8080/i/}")
- private String baseImagesUri;
- @Inject
- private ObjectMapper jsonMapper;
-
- @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()) {
- Person person = new Person();
- person.setId(activityPubManager.personUri(user));
- person.setUrl(activityPubManager.personWebUri(user));
- person.setName(userName);
- person.setPreferredUsername(userName);
- Key publicKey = new Key();
- publicKey.setId(person.getId() + "#main-key");
- publicKey.setOwner(person.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));
- UriComponentsBuilder image = UriComponentsBuilder.fromUriString(baseImagesUri);
- image.path(String.format("/a/%d.png", user.getUid()));
- Image avatar = new Image();
- avatar.setUrl(image.toUriString());
- avatar.setMediaType("image/png");
- person.setIcon(avatar);
- return (Person) Context.build(person);
- }
- throw new HttpNotFoundException();
- }
-
- @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()) {
- UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUri);
- OrderedCollection blog = new OrderedCollection();
- blog.setId(ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString());
- blog.setTotalItems(userService.getStatsMessages(user.getUid()));
- blog.setFirst(uriComponentsBuilder.path(String.format("/u/%s/blog", userName)).toUriString());
- return (OrderedCollection) Context.build(blog);
- }
- throw new HttpNotFoundException();
- }
-
- @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();
- User user = userService.getUserByName(userName);
- if (!user.isAnonymous()) {
- UriComponentsBuilder uri = UriComponentsBuilder.fromUriString(baseUri);
- String personUri = uri.path(String.format("/u/%s", userName)).toUriString();
- List<Integer> mids = messagesService.getUserBlog(user.getUid(), 0, before);
- List<Note> notes = messagesService.getMessages(visitor, mids).stream().map(activityPubManager::makeNote).collect(Collectors.toList());
- OrderedCollectionPage page = new OrderedCollectionPage();
- page.setPartOf(uri.replacePath(String.format("/u/%s/blog/toc", userName)).toUriString());
- page.setFirst(uri.replacePath(String.format("/u/%s/blog", userName)).toUriString());
- page.setId(ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString());
- page.setOrderedItems(notes.stream().map(a -> {
- Create create = new Create();
- create.setId(a.getId() + "#Create");
- create.setTo(a.getTo());
- create.setActor(personUri);
- create.setObject(a);
- create.setPublished(a.getPublished());
- return create;
- }).collect(Collectors.toList()));
- int beforeNext = mids.stream().reduce((fst, second) -> second).orElse(0);
- if (beforeNext > 0) {
- page.setNext(uri.queryParam("before", beforeNext).toUriString());
- }
- page.setLast(uri.replaceQueryParam("before", "1").toUriString());
- return (OrderedCollectionPage) Context.build(page);
- }
- throw new HttpNotFoundException();
- }
-
- @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()) {
- UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUri);
- OrderedCollection followers = new OrderedCollection();
- followers.setId(ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString());
- followers.setTotalItems(userService.getStatsMyReaders(user.getUid()));
- followers.setFirst(uriComponentsBuilder.path(String.format("/u/%s/followers", userName)).toUriString());
- return (OrderedCollection) Context.build(followers);
- }
- throw new HttpNotFoundException();
- }
-
- @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);
- if (!user.isAnonymous()) {
- UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUri);
- uriComponentsBuilder.path(String.format("/u/%s/followers", userName));
- List<User> followers = userService.getUserReaders(user.getUid());
- Stream<User> followersPage = followers.stream().skip(20 * page).limit(20);
-
- OrderedCollectionPage result = new OrderedCollectionPage();
- result.setId(ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString());
- result.setOrderedItems(followersPage.map(a -> {
- Person follower = new Person();
- follower.setName(a.getName());
- follower.setPreferredUsername(a.getName());
- follower.setUrl(activityPubManager.personWebUri(a));
- return follower;
- }).collect(Collectors.toList()));
- boolean hasNext = followers.size() <= 20 * page;
- if (hasNext) {
- result.setNext(uriComponentsBuilder.queryParam("page", page + 1).toUriString());
- }
- return (OrderedCollectionPage) Context.build(result);
- }
- throw new HttpNotFoundException();
- }
-
- @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()) {
- UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUri);
- OrderedCollection following = new OrderedCollection();
- following.setId(ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString());
- following.setTotalItems(userService.getUserFriends(user.getUid()).size());
- following.setFirst(uriComponentsBuilder.path(String.format("/u/%s/followers", userName)).toUriString());
- return (OrderedCollection) Context.build(following);
- }
- throw new HttpNotFoundException();
- }
-
- @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);
- if (!user.isAnonymous()) {
- UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUri);
- uriComponentsBuilder.path(String.format("/u/%s/following", userName));
- List<User> following = userService.getUserFriends(user.getUid());
- Stream<User> followingPage = following.stream().skip(20 * page).limit(20);
-
- OrderedCollectionPage result = new OrderedCollectionPage();
- result.setId(ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString());
- result.setOrderedItems(followingPage.map(a -> {
- Person follower = new Person();
- follower.setName(a.getName());
- follower.setPreferredUsername(a.getName());
- follower.setUrl(activityPubManager.personWebUri(a));
- return follower;
- }).collect(Collectors.toList()));
- boolean hasNext = following.size() <= 20 * page;
- if (hasNext) {
- result.setNext(uriComponentsBuilder.queryParam("page", page + 1).toUriString());
- }
- return (OrderedCollectionPage) Context.build(result);
- }
- throw new HttpNotFoundException();
- }
-
- @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
- return Context.build(activityPubManager.makeNote(
- messagesService.getReply(mid, rid)));
- }
- return Context.build(activityPubManager.makeNote(
- messagesService.getMessage(mid)));
- }
-
- @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,
- @RequestHeader(name = "Digest", required = false) String digest,
- @RequestHeader(name = "Content-Type") String contentType,
- @RequestHeader(name = "User-Agent", required = false) String userAgent,
- @RequestHeader(name = "Accept-Encoding", required = false) String acceptEncoding,
- @RequestHeader(name = "Signature", required = false) String signature) throws Exception {
- UriComponents componentsBuilder = ServletUriComponentsBuilder.fromCurrentRequestUri().build();
- Map<String, String> headers = new HashMap<>();
- headers.put("host", host.split(":", 2)[0]);
- headers.put("date", date);
- headers.put("digest", digest);
- headers.put("content-type", contentType);
- headers.put("user-agent", userAgent);
- headers.put("accept-encoding", acceptEncoding);
- boolean valid = signatureManager.verifySignature(signature, URI.create(activity.getActor()), "POST",
- componentsBuilder.getPath(), headers);
- if (valid) {
- if (activity instanceof Follow) {
- Follow followRequest = (Follow) activity;
- String actor = followRequest.getActor();
- Person follower = (Person) signatureManager.getContext(URI.create(actor)).orElseThrow(HttpBadRequestException::new);
- applicationEventPublisher.publishEvent(
- new FollowEvent(this, followRequest));
- return new ResponseEntity<>(HttpStatus.ACCEPTED);
-
- }
- if (activity instanceof Undo) {
- String follower = (String) ((Map) activity.getObject()).get("object");
- applicationEventPublisher.publishEvent(new UndoFollowEvent(this, activity.getActor(), follower));
- return new ResponseEntity<>(HttpStatus.OK);
- }
- if (activity instanceof Delete) {
- if (activity.getObject() instanceof String) {
- // Delete user
- applicationEventPublisher.publishEvent(new DeleteUserEvent(this, (String)activity.getObject()));
- return new ResponseEntity<>(HttpStatus.OK);
- }
- }
- if (activity instanceof Create) {
- if (activity.getObject() instanceof Map) {
- Map<String, Object> note = (Map<String, Object>) activity.getObject();
- if (note.get("type").equals("Note")) {
- URI noteId = URI.create((String) note.get("id"));
- if (messagesService.replyExists(noteId)) {
- return new ResponseEntity<>(HttpStatus.OK);
- } else {
- String inReplyTo = (String) note.get("inReplyTo");
- if (StringUtils.isNotBlank(inReplyTo)) {
- if (inReplyTo.startsWith(baseUri)) {
- UriComponents uri = UriComponentsBuilder.fromUriString(inReplyTo).build();
- String postId = uri.getPath().substring(uri.getPath().lastIndexOf('/') + 1).replace("-", "/");
- User user = new User();
- user.setUri(URI.create(activity.getActor()));
- String attachment = StringUtils.EMPTY;
- if (note.get("attachment") != null && ((List) note.get("attachment")).size() > 0) {
- Map<String, Object> attachmentObj = (Map<String, Object>) ((List<Object>) note.get("attachment")).get(0);
- attachment = (String) attachmentObj.get("url");
- }
- CommandResult result = commandsManager.processCommand(user, String.format("#%s %s", postId, note.get("content")), URI.create(attachment));
- logger.info(jsonMapper.writeValueAsString(result));
- if (result.getNewMessage().isPresent()) {
- messagesService.updateReplyUri(result.getNewMessage().get(), noteId);
- return new ResponseEntity<>(HttpStatus.OK);
- } else {
- return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
- }
- } else {
- Message reply = messagesService.getReplyByUri(inReplyTo);
- if (reply != null) {
- User user = new User();
- user.setUri(URI.create(activity.getActor()));
- String attachment = StringUtils.EMPTY;
- if (note.get("attachment") != null && ((List) note.get("attachment")).size() > 0) {
- Map<String, Object> attachmentObj = (Map<String, Object>) ((List<Object>) note.get("attachment")).get(0);
- attachment = (String) attachmentObj.get("url");
- }
- CommandResult result = commandsManager.processCommand(user, String.format("#%d/%d %s", reply.getMid(), reply.getRid(), note.get("content")), URI.create(attachment));
- logger.info(jsonMapper.writeValueAsString(result));
- if (result.getNewMessage().isPresent()) {
- messagesService.updateReplyUri(result.getNewMessage().get(), noteId);
- return new ResponseEntity<>(HttpStatus.OK);
- } else {
- return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
- }
- }
- }
- }
- }
- }
- }
- }
- if (activity instanceof Delete) {
- Map<String, Object> tombstone = (Map<String, Object>) activity.getObject();
- if (tombstone.get("type").equals("Tombstone")) {
- URI actor = URI.create(activity.getActor());
- URI reply = URI.create((String)tombstone.get("id"));
- messagesService.deleteReply(actor, reply);
- return new ResponseEntity<>(HttpStatus.OK);
- }
- }
- if (activity instanceof Announce) {
- logger.info("Announce: {}", jsonMapper.writeValueAsString(activity));
- return new ResponseEntity<>(HttpStatus.OK);
- }
- logger.warn("Unknown activity: {}", jsonMapper.writeValueAsString(activity));
- return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
- }
- return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
- }
- @PostMapping(value = "/u/", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
- public User fetchUser(@RequestParam URI uri) {
- Person person = (Person) signatureManager.getContext(uri).orElseThrow(HttpBadRequestException::new);
- User user = new User();
- user.setUri(URI.create(person.getUrl()));
- user.setName(person.getPreferredUsername());
- if (person.getIcon() != null) {
- user.setAvatar(person.getIcon().getUrl());
- }
- return user;
- }
-}