diff options
Diffstat (limited to 'src/main/java/com/juick/server/api')
53 files changed, 0 insertions, 4471 deletions
diff --git a/src/main/java/com/juick/server/api/ApiSocialLogin.java b/src/main/java/com/juick/server/api/ApiSocialLogin.java deleted file mode 100644 index 24010dd2..00000000 --- a/src/main/java/com/juick/server/api/ApiSocialLogin.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -package com.juick.server.api; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.scribejava.apis.AppleClientSecretGenerator; -import com.github.scribejava.apis.AppleSignInApi; -import com.github.scribejava.apis.FacebookApi; -import com.github.scribejava.apis.VkontakteApi; -import com.github.scribejava.core.builder.ServiceBuilder; -import com.github.scribejava.core.model.OAuth2AccessToken; -import com.github.scribejava.core.model.OAuthRequest; -import com.github.scribejava.core.model.Verb; -import com.github.scribejava.core.oauth.OAuth20Service; -import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; -import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.juick.model.AuthResponse; -import com.juick.model.ext.facebook.User; -import com.juick.server.util.HttpBadRequestException; -import com.juick.service.CrosspostService; -import com.juick.service.EmailService; -import com.juick.service.UserService; -import com.juick.model.ext.vk.UsersResponse; -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.proc.BadJOSEException; -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.util.UriComponentsBuilder; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.text.ParseException; -import java.util.Collections; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -/** - * - * @author Ugnich Anton - */ -@Controller -public class ApiSocialLogin { - - private static final Logger logger = LoggerFactory.getLogger(ApiSocialLogin.class); - - @Value("${facebook_appid:appid}") - private String FACEBOOK_APPID; - @Value("${facebook_secret:secret}") - private String FACEBOOK_SECRET; - private static final String FACEBOOK_REDIRECT = "https://api.juick.com/_fblogin"; - private static final String VK_REDIRECT = "https://api.juick.com/_vklogin"; - private static final String TWITTER_VERIFY_URL = "https://api.twitter.com/1.1/account/verify_credentials.json"; - @Inject - private ObjectMapper jsonMapper; - private OAuth20Service facebookAuthService, vkAuthService, appleSignInService; - - @Value("${twitter_consumer_key:appid}") - private String twitterConsumerKey; - @Value("${twitter_consumer_secret:secret}") - private String twitterConsumerSecret; - @Value("${vk_appid:appid}") - private String VK_APPID; - @Value("${vk_secret:secret}") - private String VK_SECRET; - @Value("${google_client_id:}") - private String googleClientId; - @Value("${apple_app_id:appid}") - private String appleApplicationId; - @Value("${ap_base_uri:http://localhost:8080/}") - private String baseUri; - - @Inject - private CrosspostService crosspostService; - @Inject - private UserService userService; - @Inject - private EmailService emailService; - @Inject - private AppleClientSecretGenerator clientSecretGenerator; - @Inject - private Users users; - - private final HttpTransport transport = new NetHttpTransport(); - private final JsonFactory jsonFactory = new JacksonFactory(); - private GoogleIdTokenVerifier verifier; - - @PostConstruct - public void init() { - ServiceBuilder facebookBuilder = new ServiceBuilder(FACEBOOK_APPID); - ServiceBuilder twitterBuilder = new ServiceBuilder(twitterConsumerKey); - ServiceBuilder vkBuilder = new ServiceBuilder(VK_APPID); - verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) - .setAudience(Collections.singletonList(googleClientId)) - .build(); - facebookAuthService = facebookBuilder - .apiSecret(FACEBOOK_SECRET) - .callback(FACEBOOK_REDIRECT) - .defaultScope("email") - .build(FacebookApi.instance()); - vkAuthService = vkBuilder - .apiSecret(VK_SECRET) - .defaultScope("friends,wall,offline") - .callback(VK_REDIRECT) - .build(VkontakteApi.instance()); - ServiceBuilder appleSignInBuilder = new ServiceBuilder(appleApplicationId); - UriComponentsBuilder redirectBuilder = UriComponentsBuilder.fromUriString(baseUri); - String appleSignInRedirectUri = redirectBuilder.replacePath("/api/_applelogin").build().toUriString(); - appleSignInService = appleSignInBuilder - .callback(appleSignInRedirectUri) - .defaultScope("email") - .build(new AppleSignInApi(clientSecretGenerator)); - } - - @GetMapping("/api/_fblogin") - protected String doFacebookLogin(@RequestParam(required = false) String code, - @RequestParam(required = false) String state) throws IOException, ExecutionException, InterruptedException { - if (StringUtils.isBlank(code)) { - String fbstate = UUID.randomUUID().toString(); - crosspostService.addFacebookState(fbstate, state); - return "redirect:" + facebookAuthService.getAuthorizationUrl(fbstate); - } - - String redirectUrl = crosspostService.verifyFacebookState(state); - - if (StringUtils.isEmpty(redirectUrl)) { - logger.error("state is missing"); - throw new HttpBadRequestException(); - } - OAuth2AccessToken token = facebookAuthService.getAccessToken(code); - final OAuthRequest meRequest = new OAuthRequest(Verb.GET, "https://graph.facebook.com/v3.2/me?fields=id,name,email"); - facebookAuthService.signRequest(token, meRequest); - String graph = facebookAuthService.execute(meRequest).getBody(); - if (StringUtils.isBlank(graph)) { - logger.error("FACEBOOK GRAPH ERROR"); - throw new HttpBadRequestException(); - } - User fb = jsonMapper.readValue(graph, User.class); - long fbID = NumberUtils.toLong(fb.getId(), 0); - if (fbID == 0 || StringUtils.isBlank(fb.getName())) { - logger.error("Missing required fields, id: {}, name: {}", fbID, fb.getName()); - throw new HttpBadRequestException(); - } - - int uid = crosspostService.getUIDbyFBID(fbID); - if (uid > 0) { - if (!crosspostService.updateFacebookUser(fbID, token.getAccessToken(), fb.getName())) { - logger.error("error updating facebook user, id: {}, token: {}", fbID, token.getAccessToken()); - throw new HttpBadRequestException(); - } - UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(redirectUrl); - uriComponentsBuilder.queryParam("hash", userService.getHashByUID(uid)); - uriComponentsBuilder.queryParam("retpath", redirectUrl); - return "redirect:" + uriComponentsBuilder.build().toUriString(); - } else { - if (!crosspostService.createFacebookUser(fbID, state, token.getAccessToken(), fb.getName())) { - if (StringUtils.isNotEmpty(fb.getEmail())) { - logger.info("found {} for facebook user {}", fb.getEmail(), fb.getName()); - Integer userId = crosspostService.getUIDbyFBID(fbID); - if (!emailService.getEmails(userId, false).contains(fb.getEmail())) { - emailService.addEmail(userId, fb.getEmail()); - } - } - logger.info("email not found for facebook user {}", fb.getName()); - throw new HttpBadRequestException(); - } - return "redirect:/signup?type=fb&hash=" + state; - } - } - @GetMapping("/api/_vklogin") - protected String doVKLogin(@RequestParam(required = false) String code, - @RequestParam String state) throws IOException, ExecutionException, InterruptedException { - if (StringUtils.isBlank(code)) { - String vkstate = UUID.randomUUID().toString(); - crosspostService.addVKState(vkstate, state); - return "redirect:" + vkAuthService.getAuthorizationUrl(vkstate); - } - - String redirectUrl = crosspostService.verifyVKState(state); - if (StringUtils.isBlank(redirectUrl)) { - logger.error("state is missing"); - throw new HttpBadRequestException(); - } - OAuth2AccessToken token = vkAuthService.getAccessToken(code); - - OAuthRequest meRequest = new OAuthRequest(Verb.GET, "https://api.vk.com/method/users.get?fields=screen_name&v=5.73"); - vkAuthService.signRequest(token, meRequest); - String graph = vkAuthService.execute(meRequest).getBody(); - - com.juick.model.ext.vk.User jsonUser = jsonMapper.readValue(graph, UsersResponse.class).getUsers().get(0); - String vkName = jsonUser.getFirstName() + " " + jsonUser.getLastName(); - String vkLink = jsonUser.getScreenName(); - - if (vkName.length() == 1 || StringUtils.isBlank(vkLink)) { - logger.error("vk user error"); - throw new HttpBadRequestException(); - } - - long vkID = NumberUtils.toLong(jsonUser.getId(), 0); - int uid = crosspostService.getUIDbyVKID(vkID); - if (uid > 0) { - UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(redirectUrl); - uriComponentsBuilder.queryParam("hash", userService.getHashByUID(uid)); - uriComponentsBuilder.queryParam("retpath", redirectUrl); - return "redirect:" + uriComponentsBuilder.build().toUriString(); - } else { - String loginhash = UUID.randomUUID().toString(); - if (!crosspostService.createVKUser(vkID, loginhash, token.getAccessToken(), vkName, vkLink)) { - logger.error("create vk user error"); - throw new HttpBadRequestException(); - } - return "redirect:/signup?type=vk&hash=" + loginhash; - } - } - @ResponseBody - @PostMapping("/api/_google") - public ResponseEntity<AuthResponse> googleSignIn(@RequestParam(name = "idToken") String idTokenString) - throws GeneralSecurityException, IOException { - logger.info("Token: {}", idTokenString); - logger.info("Client: {}", googleClientId); - GoogleIdToken idToken = verifier.verify(idTokenString); - if (idToken != null) { - String email = idToken.getPayload().getEmail(); - com.juick.model.User visitor = userService.getUserByEmail(email); - if (visitor.isAnonymous()) { - String verificationCode = RandomStringUtils.randomAlphanumeric(8).toUpperCase(); - emailService.addVerificationCode(null, email, verificationCode); - return ResponseEntity.ok(new AuthResponse(null, email, verificationCode)); - } else { - return ResponseEntity.ok(new AuthResponse(users.getMe(visitor), null, null)); - } - } - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null); - } - @ResponseBody - @PostMapping("/api/signup") - public ResponseEntity<com.juick.model.User> signupWithEmail(String username, String password, String verificationCode) { - if (username.length() < 2 || username.length() > 16 || !username.matches("^[a-zA-Z0-9\\-]+$") - || password.length() < 6 || password.length() > 32) { - throw new HttpBadRequestException(); - } - - String verifiedEmail = emailService.getEmailByAuthCode(verificationCode); - if (StringUtils.isNotEmpty(verifiedEmail)) { - com.juick.model.User newUser = userService.createUser(username, password).orElseThrow(HttpBadRequestException::new); - emailService.addEmail(newUser.getUid(), verifiedEmail); - emailService.deleteAuthCode(verificationCode); - return ResponseEntity.ok(newUser); - } else { - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null); - } - } - @GetMapping("/api/_applelogin") - public String doAppleLogin(@RequestParam(required = false) String code, @RequestParam String state) { - if (StringUtils.isBlank(code)) { - String astate = UUID.randomUUID().toString(); - crosspostService.addVKState(astate, state); - return "redirect:" + appleSignInService.getAuthorizationUrl(astate); - } - throw new HttpBadRequestException(); - } - @PostMapping("/api/_applelogin") - public String doVerifyAppleResponse(@RequestParam Map<String, String> body) throws InterruptedException, ExecutionException, IOException, ParseException, JOSEException, BadJOSEException { - OAuth2AccessToken token = appleSignInService.getAccessToken(body.get("code")); - var jsonNode = jsonMapper.readTree(token.getRawResponse()); - var idToken = jsonNode.get("id_token").textValue(); - - AppleSignInApi api = (AppleSignInApi) appleSignInService.getApi(); - var email = api.validateToken(idToken); - - if (email.isPresent()) { - com.juick.model.User user = userService.getUserByEmail(email.get()); - if (!user.isAnonymous()) { - String redirectUrl = crosspostService.verifyVKState(body.get("state")); - if (StringUtils.isBlank(redirectUrl)) { - logger.error("state is missing"); - throw new HttpBadRequestException(); - } - UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(redirectUrl); - uriComponentsBuilder.queryParam("hash", userService.getHashByUID(user.getUid())); - uriComponentsBuilder.queryParam("retpath", redirectUrl); - return "redirect:" + uriComponentsBuilder.build().toUriString(); - } else { - String verificationCode = RandomStringUtils.randomAlphanumeric(8).toUpperCase(); - emailService.addVerificationCode(null, email.get(), verificationCode); - return "redirect:/signup?type=email&hash=" + verificationCode; - } - } - throw new HttpBadRequestException(); - } -} diff --git a/src/main/java/com/juick/server/api/Index.java b/src/main/java/com/juick/server/api/Index.java deleted file mode 100644 index 607536b3..00000000 --- a/src/main/java/com/juick/server/api/Index.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import springfox.documentation.annotations.ApiIgnore; - -import java.net.URI; - -/** - * Created by vitalyster on 25.07.2016. - */ -@RestController -public class Index { - - @ApiIgnore - @RequestMapping(value = { "/api/", "/ws/" }, method = RequestMethod.GET) - public ResponseEntity<Void> description() { - URI redirectUri = ServletUriComponentsBuilder.fromCurrentRequestUri().path("/swagger-ui.html").build().toUri(); - return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY).location(redirectUri).build(); - } -} diff --git a/src/main/java/com/juick/server/api/Messages.java b/src/main/java/com/juick/server/api/Messages.java deleted file mode 100644 index 5e0743dd..00000000 --- a/src/main/java/com/juick/server/api/Messages.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api; - -import com.juick.model.Message; -import com.juick.model.Tag; -import com.juick.model.User; -import com.juick.server.Utils; -import com.juick.www.WebApp; -import com.juick.model.CommandResult; -import com.juick.server.util.HttpBadRequestException; -import com.juick.service.MessagesService; -import com.juick.service.TagService; -import com.juick.service.UserService; -import com.juick.service.component.SystemEvent; -import com.juick.service.security.annotation.Visitor; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.core.io.Resource; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.*; - -import javax.inject.Inject; -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; - -/** - * @author ugnich - */ -@RestController -@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE) -public class Messages { - - private static final ResponseEntity<List<Message>> NOT_FOUND = ResponseEntity - .status(HttpStatus.NOT_FOUND) - .body(Collections.emptyList()); - - private static final ResponseEntity<List<Message>> FORBIDDEN = ResponseEntity - .status(HttpStatus.FORBIDDEN) - .body(Collections.emptyList()); - - @Inject - private MessagesService messagesService; - @Inject - private UserService userService; - @Inject - private TagService tagService; - @Inject - private ApplicationEventPublisher applicationEventPublisher; - @Inject - private WebApp webApp; - @Value("classpath:Transparent.gif") - private Resource invisiblePixel; - - // TODO: serialize image urls - - @GetMapping("/api/home") - public ResponseEntity<List<Message>> getHome( - @Visitor User visitor, - @RequestParam(defaultValue = "0") int before_mid) { - if (!visitor.isAnonymous()) { - int vuid = visitor.getUid(); - List<Integer> mids = messagesService.getMyFeed(vuid, before_mid, true); - List<Message> msgs = messagesService.getMessages(visitor, mids); - msgs.forEach(m -> m.getUser().setAvatar(webApp.getAvatarUrl(m.getUser()))); - return ResponseEntity.ok(msgs); - } - return FORBIDDEN; - } - - @GetMapping("/api/messages") - public ResponseEntity<List<Message>> getMessages( - @Visitor User visitor, - @RequestParam(required = false) String uname, - @RequestParam(name = "before_mid", defaultValue = "0") Integer before, - @RequestParam(required = false, defaultValue = "0") Integer daysback, - @RequestParam(required = false) String withrecommended, - @RequestParam(required = false) String popular, - @RequestParam(required = false) String search, - @RequestParam(required = false, defaultValue = "0") Integer page, - @RequestParam(required = false) String media, - @RequestParam(required = false) String tag) { - List<Integer> mids; - if (!StringUtils.isEmpty(uname)) { - User user = userService.getUserByName(uname); - if (!user.isAnonymous() && !user.isBanned()) { - if (!StringUtils.isEmpty(media)) { - mids = messagesService.getUserPhotos(user.getUid(), 0, before); - } else if (!StringUtils.isEmpty(tag)) { - Tag tagObject = tagService.getTag(tag, false); - if (tagObject != null) { - mids = messagesService.getUserTag(user.getUid(), tagObject.TID, 0, before); - } else { - return NOT_FOUND; - } - } else if (!StringUtils.isEmpty(withrecommended)) { - mids = messagesService.getUserBlogWithRecommendations(user.getUid(), 0, before); - } else if (daysback > 0) { - mids = messagesService.getUserBlogAtDay(user.getUid(), 0, daysback); - } else if (!StringUtils.isEmpty(search)) { - mids = messagesService.getUserSearch(visitor, user.getUid(), Utils.encodeSphinx(search), 0, page); - } else { - mids = messagesService.getUserBlog(user.getUid(), 0, before); - } - } else { - return NOT_FOUND; - } - } else { - if (!StringUtils.isEmpty(popular)) { - mids = messagesService.getPopular(visitor.getUid(), before); - } else if (!StringUtils.isEmpty(media)) { - mids = messagesService.getPhotos(visitor.getUid(), before); - } else if (!StringUtils.isEmpty(tag)) { - Tag tagObject = tagService.getTag(tag, false); - if (tagObject != null) { - mids = messagesService.getTag(tagObject.TID, visitor.getUid(), before, 20); - } else { - return NOT_FOUND; - } - } else if (!StringUtils.isEmpty(search)) { - mids = messagesService.getSearch(visitor, Utils.encodeSphinx(search), page); - } else { - mids = messagesService.getAll(visitor.getUid(), before); - } - } - List<Message> msgs = messagesService.getMessages(visitor, mids); - msgs.forEach(m -> m.getUser().setAvatar(webApp.getAvatarUrl(m.getUser()))); - return ResponseEntity.ok(msgs); - } - @DeleteMapping("/api/messages") - public CommandResult deleteMessage( - @Visitor User visitor, - @RequestParam int mid, @RequestParam(required = false, defaultValue = "0") int rid) { - if (rid > 0) { - if (messagesService.deleteReply(visitor.getUid(), mid, rid)) { - return CommandResult.fromString("Reply deleted"); - } - } - if (messagesService.deleteMessage(visitor.getUid(), mid)) { - return CommandResult.fromString("Message deleted"); - } - throw new HttpBadRequestException(); - } - - @GetMapping("/api/messages/discussions") - public List<Message> getDiscussions( - @Visitor User visitor, - @RequestParam(required = false, defaultValue = "0") Long to) { - List<Message> msgs = messagesService.getMessages(visitor, - messagesService.getDiscussions(visitor.getUid(), to)); - msgs.forEach(m -> m.getUser().setAvatar(webApp.getAvatarUrl(m.getUser()))); - return msgs; - } - @GetMapping("/api/thread") - public ResponseEntity<List<Message>> getThread( - @Visitor User visitor, - @RequestParam(defaultValue = "0") int mid) { - Optional<Message> message = messagesService.getMessage(mid); - if (message.isPresent()) { - Message msg = message.get(); - if (!messagesService.canViewThread(mid, visitor.getUid())) { - return FORBIDDEN; - } else { - msg.getUser().setAvatar(webApp.getAvatarUrl(msg.getUser())); - msg.setRecommendations(new HashSet<>(messagesService.getMessagesRecommendations( - Collections.singletonList(msg.getMid())) - .stream().map(Pair::getRight).collect(Collectors.toList()))); - msg.getRecommendations().forEach(r -> r.setAvatar(webApp.getAvatarUrl(r))); - List<Message> replies = messagesService.getReplies(visitor, mid); - replies.forEach(m -> m.getUser().setAvatar(webApp.getAvatarUrl(m.getUser()))); - if (!visitor.isAnonymous()) { - userService.updateLastSeen(visitor); - applicationEventPublisher.publishEvent( - new SystemEvent(this, SystemActivity.read(visitor, msg))); - } - replies.add(0, msg); - return ResponseEntity.ok(replies); - } - } - return NOT_FOUND; - } - @GetMapping(value = "/api/thread/mark_read/{mid}-{rid}.gif", produces = MediaType.IMAGE_GIF_VALUE) - public byte[] markThreadRead( - @Visitor User visitor, - @PathVariable int mid, @PathVariable int rid) throws IOException { - if (!visitor.isAnonymous()) { - messagesService.setLastReadComment(visitor, mid, rid); - Message msg = messagesService.getMessage(mid).orElseThrow(IllegalStateException::new); - userService.updateLastSeen(visitor); - applicationEventPublisher.publishEvent( - new SystemEvent(this, SystemActivity.read(visitor, msg))); - return IOUtils.toByteArray(invisiblePixel.getInputStream()); - } - throw new HttpBadRequestException(); - } -} diff --git a/src/main/java/com/juick/server/api/Notifications.java b/src/main/java/com/juick/server/api/Notifications.java deleted file mode 100644 index eb15917e..00000000 --- a/src/main/java/com/juick/server/api/Notifications.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api; - -import com.juick.model.ExternalToken; -import com.juick.model.Message; -import com.juick.model.Status; -import com.juick.model.User; -import com.juick.model.AnonymousUser; -import com.juick.server.util.HttpBadRequestException; -import com.juick.service.MessagesService; -import com.juick.service.PushQueriesService; -import com.juick.service.SubscriptionService; -import com.juick.service.TelegramService; -import com.juick.service.UserService; -import com.juick.service.security.annotation.Visitor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import springfox.documentation.annotations.ApiIgnore; - -import javax.inject.Inject; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Created by vitalyster on 24.10.2016. - */ -@RestController -public class Notifications { - - @Inject - private PushQueriesService pushQueriesService; - @Inject - private MessagesService messagesService; - @Inject - private SubscriptionService subscriptionService; - @Inject - private UserService userService; - @Inject - private TelegramService telegramService; - @Value("${api_user:juick}") - private String serviceUser; - - - private User collectTokens(Integer uid) { - User user = userService.getUserByUID(uid).orElse(AnonymousUser.INSTANCE); - user.setUnreadCount(messagesService.getUnread(user).size()); - pushQueriesService.getGCMRegID(uid).forEach(t -> user.getTokens().add(new ExternalToken(null, "gcm", t, null))); - pushQueriesService.getAPNSToken(uid).forEach(t -> user.getTokens().add(new ExternalToken(null, "apns", t, null))); - pushQueriesService.getMPNSURL(uid).forEach(t -> user.getTokens().add(new ExternalToken(null, "mpns", t, null))); - List<ExternalToken> xmppJids = userService.getJIDsbyUID(uid).stream() - .map(jid -> new ExternalToken(null, "xmpp", jid, null)) - .collect(Collectors.toList()); - user.getTokens().addAll(xmppJids); - List<ExternalToken> tgIds = telegramService.getTelegramIdentifiers(Collections.singletonList(user)).stream() - .map(tgId -> new ExternalToken(null, "durov", String.valueOf(tgId), null)) - .collect(Collectors.toList()); - user.getTokens().addAll(tgIds); - return user; - } - - @ApiIgnore - @RequestMapping(value = "/api/notifications", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity<List<User>> doGet( - @Visitor User visitor, - @RequestParam(required = false, defaultValue = "0") int uid, - @RequestParam(required = false, defaultValue = "0") int mid, - @RequestParam(required = false, defaultValue = "0") int rid) { - if (!(visitor.getName().equals(serviceUser))) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null); - } - if (uid > 0 && mid == 0) { - // PM - return ResponseEntity.ok(Collections.singletonList(collectTokens(uid))); - } else { - if (mid > 0) { - // reply - Message msg = messagesService.getMessage(mid).orElseThrow(IllegalStateException::new); - List<User> users; - if (rid > 0) { - Message op = messagesService.getMessage(mid).orElseThrow(IllegalStateException::new); - Message reply = messagesService.getReply(mid, rid); - users = subscriptionService.getUsersSubscribedToComments(op, reply); - } else { - users = subscriptionService.getSubscribedUsers(msg.getUser().getUid(), msg); - } - - return ResponseEntity.ok(users.stream().map(User::getUid) - .map(this::collectTokens).collect(Collectors.toList())); - } else { - // read - return ResponseEntity.ok(Collections.singletonList(collectTokens(uid))); - } - } - } - - @ApiIgnore - @RequestMapping(value = "/api/notifications", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity<Status> doDelete( - @Visitor User visitor, - @RequestBody List<ExternalToken> list) { - if (!visitor.getName().equals(serviceUser)) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null); - } - list.forEach(t -> { - switch (t.getType()) { - case "gcm": - pushQueriesService.deleteGCMToken(t.getToken()); - break; - case "apns": - pushQueriesService.deleteAPNSToken(t.getToken()); - break; - case "mpns": - pushQueriesService.deleteMPNSToken(t.getToken()); - break; - default: - throw new HttpBadRequestException(); - } - }); - - return ResponseEntity.ok(Status.OK); - } - @ApiIgnore - @RequestMapping(value = "/api/notifications/delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity<Status> doDeleteTokens( - @Visitor User visitor, - @RequestBody List<ExternalToken> list) { - if (!visitor.getName().equals(serviceUser)) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null); - } - list.forEach(t -> { - switch (t.getType()) { - case "gcm": - pushQueriesService.deleteGCMToken(t.getToken()); - break; - case "apns": - pushQueriesService.deleteAPNSToken(t.getToken()); - break; - case "mpns": - pushQueriesService.deleteMPNSToken(t.getToken()); - break; - default: - throw new HttpBadRequestException(); - } - }); - - return ResponseEntity.ok(Status.OK); - } - - @ApiIgnore - @RequestMapping(value = "/api/notifications", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE) - public Status doPut( - @Visitor User visitor, - @RequestBody List<ExternalToken> list) { - list.forEach(t -> { - switch (t.getType()) { - case "gcm": - pushQueriesService.addGCMToken(visitor.getUid(), t.getToken()); - break; - case "apns": - pushQueriesService.addAPNSToken(visitor.getUid(), t.getToken()); - break; - case "mpns": - pushQueriesService.addMPNSToken(visitor.getUid(), t.getToken()); - break; - default: - throw new HttpBadRequestException(); - } - }); - return Status.OK; - } - - @Deprecated - @RequestMapping(value = "/api/android/register", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public Status doAndroidRegister( - @Visitor User visitor, - @RequestParam(name = "regid") String regId) { - pushQueriesService.addGCMToken(visitor.getUid(), regId); - return Status.OK; - } - - @Deprecated - @RequestMapping(value = "/api/winphone/register", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public Status doWinphoneRegister( - @Visitor User visitor, - @RequestParam(name = "url") String regId) { - pushQueriesService.addMPNSToken(visitor.getUid(), regId); - return Status.OK; - } -} diff --git a/src/main/java/com/juick/server/api/PM.java b/src/main/java/com/juick/server/api/PM.java deleted file mode 100644 index a37cc85e..00000000 --- a/src/main/java/com/juick/server/api/PM.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api; - -import com.juick.model.Chat; -import com.juick.model.Message; -import com.juick.model.User; -import com.juick.model.AnonymousUser; -import com.juick.model.PrivateChats; -import com.juick.server.util.HttpBadRequestException; -import com.juick.server.util.HttpForbiddenException; -import com.juick.server.util.WebUtils; -import com.juick.www.WebApp; -import com.juick.service.PMQueriesService; -import com.juick.service.UserService; -import com.juick.service.component.SystemEvent; -import com.juick.service.security.annotation.Visitor; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import javax.inject.Inject; -import java.util.Collections; -import java.util.List; - -/** - * @author ugnich - */ -@RestController -public class PM { - @Inject - private UserService userService; - @Inject - private PMQueriesService pmQueriesService; - @Inject - private ApplicationEventPublisher applicationEventPublisher; - @Inject - private WebApp webApp; - - @RequestMapping(value = "/api/pm", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public List<Message> doGetPM( - @Visitor User visitor, - @RequestParam(required = false) String uname) { - int uid = 0; - if (uname != null && uname.matches("^[a-zA-Z0-9\\-]{2,16}$")) { - uid = userService.getUIDbyName(uname); - } - - if (uid == 0) { - throw new HttpBadRequestException(); - } - - List<Message> msgs = pmQueriesService.getPMMessages(visitor.getUid(), uid); - msgs.forEach(m -> m.getUser().setAvatar(webApp.getAvatarUrl(m.getUser()))); - return msgs; - } - - @RequestMapping(value = "/api/pm", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - public Message doPostPM( - @Visitor User visitor, - @RequestParam String uname, - @RequestParam String body) { - User userTo = AnonymousUser.INSTANCE; - if (WebUtils.isUserName(uname)) { - userTo = userService.getUserByName(uname); - } - - if (userTo.getUid() == 0 || body == null || body.length() < 1 || body.length() > 10240) { - throw new HttpBadRequestException(); - } - - if (userService.isInBLAny(userTo.getUid(), visitor.getUid())) { - throw new HttpForbiddenException(); - } - - if (pmQueriesService.createPM(visitor.getUid(), userTo.getUid(), body)) { - Message jmsg = new Message(); - jmsg.setUser(visitor); - jmsg.setText(body); - jmsg.setTo(userTo); - jmsg.getUser().setAvatar(webApp.getAvatarUrl(jmsg.getUser())); - applicationEventPublisher.publishEvent( - new SystemEvent(this, - SystemActivity.message(jmsg.getUser(), jmsg, Collections.singletonList(jmsg.getTo())))); - return jmsg; - - } - throw new HttpBadRequestException(); - } - @RequestMapping(value = "/api/groups_pms", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public PrivateChats doGetGroupsPMs( - @Visitor User visitor, - @RequestParam(defaultValue = "5") int cnt) { - // TODO: ignore cnt param for now but make sure paging param will not be cnt - - List<Chat> lastconv = pmQueriesService.getLastChats(visitor); - lastconv.forEach(c -> c.setAvatar(webApp.getAvatarUrl(c))); - PrivateChats pms = new PrivateChats(); - pms.setUsers(lastconv); - return pms; - } -} diff --git a/src/main/java/com/juick/server/api/Post.java b/src/main/java/com/juick/server/api/Post.java deleted file mode 100644 index 700249cc..00000000 --- a/src/main/java/com/juick/server/api/Post.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api; - -import com.juick.model.Message; -import com.juick.model.Reaction; -import com.juick.model.Status; -import com.juick.model.User; -import com.juick.model.CommandResult; -import com.juick.server.ActivityPubManager; -import com.juick.server.CommandsManager; -import com.juick.server.util.HttpBadRequestException; -import com.juick.server.util.HttpForbiddenException; -import com.juick.server.util.HttpNotFoundException; -import com.juick.server.util.HttpUtils; -import com.juick.service.MessagesService; -import com.juick.service.UserService; -import com.juick.service.activities.UpdateEvent; -import com.juick.service.security.annotation.Visitor; -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.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.inject.Inject; -import javax.validation.constraints.NotNull; -import java.net.URI; -import java.net.URL; -import java.util.List; -import java.util.Optional; - -/** - * Created by vt on 24/11/2016. - */ -@RestController -public class Post { - private final static Logger logger = LoggerFactory.getLogger("API"); - - @Inject - private UserService userService; - @Inject - private MessagesService messagesService; - @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") - private String tmpDir; - @Inject - CommandsManager commandsManager; - @Inject - ApplicationEventPublisher applicationEventPublisher; - @Inject - ActivityPubManager activityPubManager; - - @RequestMapping(value = "/api/post", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - @ResponseStatus(value = HttpStatus.OK) - public CommandResult doPostMessage( - @Visitor User visitor, - @RequestParam(required = false, defaultValue = StringUtils.EMPTY) String body, - @RequestParam(required = false) String img, - @RequestParam(required = false) MultipartFile attach) throws Exception { - body = body.replace("\r", StringUtils.EMPTY); - - URI attachmentFName = HttpUtils.receiveMultiPartFile(attach, tmpDir); - - if (StringUtils.isBlank(attachmentFName.toString()) && img != null && img.length() > 10) { - URI juickUri = URI.create(img); - if (juickUri.getScheme().equals("juick")) { - attachmentFName = juickUri; - } else { - try { - URL imgUrl = new URL(img); - attachmentFName = HttpUtils.downloadImage(imgUrl, tmpDir); - } catch (Exception e) { - logger.error("DOWNLOAD ERROR", e); - throw new HttpBadRequestException(); - } - } - } - if (StringUtils.isBlank(body) && StringUtils.isBlank(attachmentFName.toString())) { - // Should be there for compatibility - throw new HttpBadRequestException(); - } - return commandsManager.processCommand(visitor, body, attachmentFName); - } - - @RequestMapping(value = "/api/comment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) - public CommandResult doPostComment( - @Visitor User visitor, - @RequestParam(defaultValue = "0") int mid, - @RequestParam(defaultValue = "0") int rid, - @RequestParam(required = false, defaultValue = StringUtils.EMPTY) final String body, - @RequestParam(required = false) String img, - @RequestParam(required = false) MultipartFile attach) - throws Exception { - if (mid == 0) { - throw new HttpBadRequestException(); - } - Optional<Message> message = messagesService.getMessage(mid); - if (message.isEmpty()) { - throw new HttpNotFoundException(); - } - - Message msg = message.get(); - - Message reply = null; - if (rid > 0) { - reply = messagesService.getReply(mid, rid); - if (reply == null) { - throw new HttpNotFoundException(); - } - } - - if ((msg.ReadOnly && msg.getUser().getUid() != visitor.getUid()) - || userService.isInBLAny(msg.getUser().getUid(), visitor.getUid()) - || (reply != null && userService.isInBLAny(reply.getUser().getUid(), visitor.getUid()))) { - // TODO: validator - throw new HttpForbiddenException(); - } - - URI attachmentFName = HttpUtils.receiveMultiPartFile(attach, tmpDir); - - if (StringUtils.isBlank(attachmentFName.toString()) && img != null && img.length() > 10) { - try { - attachmentFName = HttpUtils.downloadImage(new URL(img), tmpDir); - } catch (Exception e) { - logger.error("DOWNLOAD ERROR", e); - throw new HttpBadRequestException(); - } - } - if (StringUtils.isBlank(body) && StringUtils.isBlank(attachmentFName.toString())) { - // Should be there for compatibility - throw new HttpBadRequestException(); - } - return commandsManager.processCommand(visitor, String.format("#%d/%d %s", mid, rid, body), - attachmentFName); - } - - @PostMapping("/api/like") - @ResponseStatus(value = HttpStatus.OK) - public Status doPostRecomm(@Visitor User visitor, @RequestParam Integer mid) throws Exception { - Optional<Message> message = messagesService.getMessage(mid); - if (message.isEmpty()) { - throw new HttpNotFoundException(); - } - Message msg = message.get(); - if (msg.getUser().getUid() == visitor.getUid()) { - throw new HttpForbiddenException(); - } - CommandResult status = commandsManager.processCommand(visitor, String.format("! #%d", mid), - URI.create(StringUtils.EMPTY)); - return Status.getStatus(status.getText()); - } - - @PostMapping("/api/subscribe") - @ResponseStatus(value = HttpStatus.OK) - public Status doPostSubscribe(@Visitor User visitor, - @RequestParam Integer mid) throws Exception { - Optional<Message> message = messagesService.getMessage(mid); - if (message.isEmpty()) { - throw new HttpNotFoundException(); - } - Message msg = message.get(); - if (msg.getUser().getUid() == visitor.getUid()) { - throw new HttpForbiddenException(); - } - CommandResult status = commandsManager.processCommand(visitor, String.format("S #%d", mid), - URI.create(StringUtils.EMPTY)); - return Status.getStatus(status.getText()); - } - - @GetMapping("/api/reactions") - @ResponseStatus(value = HttpStatus.OK) - public List<Reaction> reactionsList() { - return messagesService.listReactions(); - } - - @PostMapping("/api/react") - @ResponseStatus(value = HttpStatus.OK) - public Status doPostReact( - @Visitor User visitor, - @RequestParam Integer mid, @RequestParam @NotNull int reactionId, - @RequestParam(required = false, defaultValue = "1") int count) { - - logger.info("got reaction with type: {}", reactionId); - Optional<Message> message = messagesService.getMessage(mid); - if (message.isEmpty()) { - throw new HttpNotFoundException(); - } - Message msg = message.get(); - if (msg.getUser().getUid() == visitor.getUid()) { - throw new HttpForbiddenException(); - } - MessagesService.RecommendStatus recommendStatus = MessagesService.RecommendStatus.Error; - for (int i = 0; i < count; i++) - recommendStatus = messagesService.likeMessage(mid, visitor.getUid(), - reactionId); - - return recommendStatus == MessagesService.RecommendStatus.Error ? Status.ERROR :Status.OK; - } - - @PostMapping("/api/update") - public CommandResult updateMessage(@Visitor User visitor, - @RequestParam Integer mid, - @RequestParam(required = false, defaultValue = "0") Integer rid, - @RequestParam String body) { - User author = rid == 0 ? messagesService.getMessageAuthor(mid) : messagesService.getReply(mid, rid).getUser(); - if (visitor.equals(author)) { - if (messagesService.updateMessage(mid, rid, body)) { - Message result = rid == 0 ? - messagesService.getMessage(mid).orElseThrow(IllegalStateException::new) - : messagesService.getReply(mid, rid); - applicationEventPublisher.publishEvent( - new UpdateEvent(this, author, activityPubManager.messageUri(mid, rid))); - return CommandResult.build(result, "Message updated", StringUtils.EMPTY); - } - throw new HttpBadRequestException(); - } - throw new HttpForbiddenException(); - } -} diff --git a/src/main/java/com/juick/server/api/Service.java b/src/main/java/com/juick/server/api/Service.java deleted file mode 100644 index d056d9b0..00000000 --- a/src/main/java/com/juick/server/api/Service.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api; - -import com.juick.model.Message; -import com.juick.model.User; -import com.juick.model.CommandResult; -import com.juick.server.CommandsManager; -import com.juick.server.EmailManager; -import com.juick.server.ServerManager; -import com.juick.server.util.HttpBadRequestException; -import com.juick.server.util.HttpForbiddenException; -import com.juick.service.EmailService; -import com.juick.service.MessagesService; -import com.juick.service.UserService; -import com.juick.service.component.AccountVerificationEvent; -import com.juick.service.security.annotation.Visitor; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.mail.util.MimeMessageParser; -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.stereotype.Controller; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.context.request.async.AsyncRequestTimeoutException; -import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; -import springfox.documentation.annotations.ApiIgnore; - -import javax.inject.Inject; -import javax.mail.Session; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.nio.file.Paths; -import java.util.*; - -@Controller -public class Service { - private static Logger logger = LoggerFactory.getLogger("Session"); - @Inject - private UserService userService; - @Inject - private EmailService emailService; - @Inject - private MessagesService messagesService; - @Inject - private CommandsManager commandsManager; - @Inject - private ApplicationEventPublisher applicationEventPublisher; - @Value("${api_user:juick}") - private String serviceUser; - @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") - private String tmpDir; - @Value("${banned_emails:}") - private String[] ignoredEmails; - @Inject - private ServerManager serverManager; - - private Session session = Session.getDefaultInstance(new Properties()); - - @ApiIgnore - @PostMapping("/api/mail") - @ResponseStatus(value = HttpStatus.OK) - public void processMail(@Visitor User current, InputStream data) throws Exception { - if (current.getName().equals(serviceUser)) { - MimeMessage msg = new MimeMessage(session, data); - String[] returnPaths = msg.getHeader("Return-Path"); - if (returnPaths != null) { - logger.info("got msg with return path {}", returnPaths[0]); - if (returnPaths[0].equals("<>")) { - return; - } - } - String from = msg.getFrom() == null || msg.getFrom().length > 1 ? ((InternetAddress) msg.getSender()).getAddress() - : ((InternetAddress) msg.getFrom()[0]).getAddress(); - - User visitor = userService.getUserByEmail(from); - if (!visitor.isAnonymous()) { - MimeMessageParser parser = new MimeMessageParser(msg); - parser.parse(); - final String[] body = {parser.getPlainContent()}; - if (body[0] == null) { - parser.getAttachmentList().stream() - .filter(a -> a.getContentType().equals("text/plain")).findFirst() - .ifPresent(a -> { - try { - body[0] = IOUtils.toString(a.getInputStream(), StandardCharsets.UTF_8); - logger.info("got text: {}", body[0]); - } catch (IOException e) { - logger.info("attachment error", e); - } - }); - } - final String[] attachmentFName = new String[1]; - parser.getAttachmentList().stream().filter(a -> - a.getContentType().equals("image/jpeg") || a.getContentType().equals("image/png")) - .findFirst().ifPresent(a -> { - logger.info("got attachment: {}", a.getContentType()); - String attachmentType; - if (a.getContentType().equals("image/jpeg")) { - attachmentType = "jpg"; - } else { - attachmentType = "png"; - } - attachmentFName[0] = DigestUtils.md5Hex(UUID.randomUUID().toString()) + "." + attachmentType; - try { - logger.info("got inputstream: {}", a.getInputStream()); - FileOutputStream fos = new FileOutputStream(Paths.get(tmpDir, attachmentFName[0]).toString()); - IOUtils.copy(a.getInputStream(), fos); - fos.close(); - } catch (IOException e) { - logger.info("attachment error", e); - } - }); - String[] inReplyToHeaders = msg.getHeader("In-Reply-To"); - if (inReplyToHeaders != null && inReplyToHeaders.length > 0) { - int mid, rid; - var originalMessage = messagesService.findMessageByProperty("messageId", inReplyToHeaders[0]); - if (originalMessage.isPresent()) { - mid = originalMessage.get().getLeft(); - rid = originalMessage.get().getRight(); - } else { - Scanner inReplyToScanner = new Scanner(inReplyToHeaders[0].trim()).useDelimiter(EmailManager.MSGID_PATTERN); - mid = Integer.parseInt(inReplyToScanner.next()); - rid = Integer.parseInt(inReplyToScanner.next()); - } - logger.info("Message is reply to #{}/{}", mid, rid); - body[0] = rid > 0 ? String.format("#%d/%d %s", mid, rid, body[0]) - : String.format("#%d %s", mid, body[0]); - } - URI attachmentUri = StringUtils.isNotEmpty(attachmentFName[0]) ? URI.create(String.format("juick://%s", attachmentFName[0])) - : URI.create(StringUtils.EMPTY); - CommandResult result = commandsManager.processCommand(visitor, body[0], attachmentUri); - if (result.getNewMessage().isPresent()) { - String[] messageIds = msg.getHeader("Message-Id"); - if (messageIds.length == 1) { - Message message = result.getNewMessage().get(); - messagesService.setMessageProperty(message.getMid(), message.getRid(), "messageId", messageIds[0]); - } else { - logger.warn("Wrong number of Message-Id headers"); - } - } - } else { - if (!Arrays.asList(ignoredEmails).contains(from)) { - String verificationCode = RandomStringUtils.randomAlphanumeric(8).toUpperCase(); - emailService.addVerificationCode(null, from, verificationCode); - applicationEventPublisher.publishEvent(new AccountVerificationEvent(this, from, verificationCode)); - } - } - } else { - throw new HttpForbiddenException(); - } - } - @ApiIgnore - @PostMapping("/api/mail/unsubscribe") - @ResponseStatus(value = HttpStatus.OK) - public void processMailUnsubscribe(@Visitor User current, InputStream data) throws Exception { - if (current.getName().equals(serviceUser)) { - MimeMessage msg = new MimeMessage(session, data); - String from = msg.getFrom() == null || msg.getFrom().length > 1 ? ((InternetAddress) msg.getSender()).getAddress() - : ((InternetAddress) msg.getFrom()[0]).getAddress(); - - User visitor = userService.getUserByEmail(from); - if (!visitor.isAnonymous()) { - if (!emailService.disableEmail(visitor, from)) { - throw new HttpBadRequestException(); - } - } - } else { - throw new HttpForbiddenException(); - } - } - private void endSession(SseEmitter emitter) { - serverManager.getSessions().stream() - .filter(s -> s.getEmitter().equals(emitter)) - .forEach(session -> serverManager.getSessions().remove(session)); - } - @GetMapping("/api/events") - public SseEmitter handle(@Visitor User visitor) throws IOException { - logger.info("{} connected", visitor.getName()); - if (!visitor.isAnonymous()) { - userService.updateLastSeen(visitor); - } - SseEmitter emitter = new SseEmitter(600000L); - serverManager.getSessions().add(new ServerManager.EventSession(visitor, emitter)); - - emitter.onCompletion(() -> endSession(emitter)); - emitter.onTimeout(() -> endSession(emitter)); - - return emitter; - } - @ExceptionHandler(AsyncRequestTimeoutException.class) - public void eventErrorHandler(Exception ex) { - logger.debug("SSE timeout", ex); - } -} diff --git a/src/main/java/com/juick/server/api/SystemActivity.java b/src/main/java/com/juick/server/api/SystemActivity.java deleted file mode 100644 index 820f9307..00000000 --- a/src/main/java/com/juick/server/api/SystemActivity.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api; - -import com.juick.model.Message; -import com.juick.model.User; - -import java.util.Collections; -import java.util.List; - -public class SystemActivity { - public static SystemActivity like(User from, Message message, List<User> subscribers) { - var like = new SystemActivity(); - like.setType(ActivityType.like); - like.setFrom(from); - like.setMessage(message); - like.setTo(subscribers); - return like; - } - - public static SystemActivity message(User from, Message message, List<User> subscribers) { - var msg = new SystemActivity(); - msg.setType(ActivityType.message); - msg.setFrom(from); - msg.setMessage(message); - msg.setTo(subscribers); - return msg; - } - - public static SystemActivity read(User from, Message message) { - var read = new SystemActivity(); - read.setType(ActivityType.message); - read.setFrom(from); - read.setTo(Collections.emptyList()); - var msg = new Message(); - msg.setMid(message.getMid()); - msg.setUser(from); - msg.setService(true); - msg.setUnread(false); - read.setMessage(msg); - return read; - } - - public static SystemActivity follow(User from, List<User> to) { - var follow = new SystemActivity(); - follow.setFrom(from); - follow.setTo(to); - return follow; - } - - public enum ActivityType { - message, - like, - follow - } - - private ActivityType type; - private User from; - private List<User> to; - private Message message; - - public ActivityType getType() { - return type; - } - - public void setType(ActivityType type) { - this.type = type; - } - - public User getFrom() { - return from; - } - - public void setFrom(User from) { - this.from = from; - } - - public List<User> getTo() { - return to; - } - - public void setTo(List<User> to) { - this.to = to; - } - - public Message getMessage() { - return message; - } - - public void setMessage(Message message) { - this.message = message; - } -} diff --git a/src/main/java/com/juick/server/api/Tags.java b/src/main/java/com/juick/server/api/Tags.java deleted file mode 100644 index 6041adcf..00000000 --- a/src/main/java/com/juick/server/api/Tags.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api; - -import com.juick.model.User; -import com.juick.model.TagStats; -import com.juick.service.TagService; -import com.juick.service.security.annotation.Visitor; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import javax.inject.Inject; -import java.util.List; - -/** - * Created by vitalyster on 29.11.2016. - */ -@RestController -public class Tags { - @Inject - private TagService tagService; - - @RequestMapping(value = "/api/tags", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public List<TagStats> tags( - @Visitor User visitor, - @RequestParam(required = false, defaultValue = "0") int user_id - ) { - if (user_id == 0) { - user_id = visitor.getUid(); - } - if (user_id > 0) { - return tagService.getUserTagStats(user_id); - } - return tagService.getTagStats(); - } -} diff --git a/src/main/java/com/juick/server/api/Users.java b/src/main/java/com/juick/server/api/Users.java deleted file mode 100644 index 84ac5174..00000000 --- a/src/main/java/com/juick/server/api/Users.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api; - -import com.juick.model.User; -import com.juick.model.AnonymousUser; -import com.juick.model.ApplicationStatus; -import com.juick.server.util.HttpBadRequestException; -import com.juick.server.util.HttpNotFoundException; -import com.juick.server.util.HttpUtils; -import com.juick.server.util.WebUtils; -import com.juick.www.WebApp; -import com.juick.service.*; -import com.juick.service.component.MailVerificationEvent; -import com.juick.service.security.annotation.Visitor; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.inject.Inject; -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * @author ugnich - */ -@RestController -public class Users { - @Inject - private UserService userService; - @Inject - private MessagesService messagesService; - @Inject - private CrosspostService crosspostService; - @Inject - private TelegramService telegramService; - @Inject - private EmailService emailService; - @Inject - private TagService tagService; - @Inject - private WebApp webApp; - @Inject - private ImagesService imagesService; - @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") - private String tmpDir; - @Inject - private ApplicationEventPublisher applicationEventPublisher; - - @RequestMapping(value = "/api/auth", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public String getAuthToken(@Visitor User visitor) { - return userService.getHashByUID(visitor.getUid()); - } - - @RequestMapping(value = "/api/users", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public List<User> doGetUsers( - @Visitor User visitor, - @RequestParam(value = "uname", required = false) List<String> unames) { - List<User> users = new ArrayList<>(); - - if (unames != null) { - unames.removeIf(WebUtils::isNotUserName); - - if (!unames.isEmpty() && unames.size() < 20) - users.addAll(userService.getUsersByName(unames)); - } - users.forEach(u -> u.setAvatar(webApp.getAvatarUrl(u))); - if (!users.isEmpty()) - return users; - if (!visitor.isAnonymous()) { - visitor.setAvatar(webApp.getAvatarUrl(visitor)); - return Collections.singletonList(visitor); - } - - throw new HttpNotFoundException(); - } - - @GetMapping("/api/me") - public SecureUser getMe(@Visitor User visitor) { - SecureUser me = new SecureUser(); - me.setUid(visitor.getUid()); - me.setName(visitor.getName()); - me.setAuthHash(getAuthToken(visitor)); - List<Integer> unread = messagesService.getUnread(visitor); - me.setUnread(unread); - me.setUnreadCount(unread.size()); - var friends = userService.getUserFriends(visitor.getUid()); - friends.forEach(r -> r.setAvatar(webApp.getAvatarUrl(r))); - me.setRead(friends); - var readers = userService.getUserReaders(visitor.getUid()); - readers.forEach(r -> r.setAvatar(webApp.getAvatarUrl(r))); - me.setReaders(readers); - me.setAvatar(webApp.getAvatarUrl(visitor)); - me.getTagStats().addAll(tagService.getUserTagStats(me.getUid())); - return (SecureUser)userService.getUserInfo(me); - } - @PostMapping("/api/me") - public ResponseEntity<Void> updateMe(@Visitor User visitor, - @RequestParam(required = false) String password, - @RequestParam(value = "jid-del", required = false) String jidForDeletion, - @RequestParam(value = "email-add", required = false) String newEmail, - @RequestParam(value = "email-del", required = false) String emailForDeletion, - @RequestParam(value = "account-del", required = false) String accountToDelete) { - if (StringUtils.isNotEmpty(password)) { - if (!userService.updatePassword(visitor, password)) { - throw new HttpBadRequestException(); - } - } - if (StringUtils.isNotEmpty(jidForDeletion)) { - if (!userService.deleteJID(visitor.getUid(), jidForDeletion)) { - throw new HttpBadRequestException(); - } - } - if (StringUtils.isNotEmpty(newEmail)) { - if (!emailService.verifyAddressByCode(visitor.getUid(), newEmail)) { - String authCode = RandomStringUtils.randomAlphanumeric(8).toUpperCase(); - if (emailService.addVerificationCode(visitor.getUid(), newEmail, authCode)) { - applicationEventPublisher.publishEvent(new MailVerificationEvent(this, newEmail , authCode)); - } - } - } - if (StringUtils.isNotEmpty(emailForDeletion)) { - if (!emailService.deleteEmail(visitor.getUid(), emailForDeletion)) { - throw new HttpBadRequestException(); - } - } - if (StringUtils.isNotEmpty(accountToDelete)) { - switch (accountToDelete) { - case "twitter": - crosspostService.deleteTwitterToken(visitor.getUid()); - break; - case "vk": - crosspostService.deleteVKUser(visitor.getUid()); - break; - case "durov": - telegramService.deleteTelegramUser(visitor.getUid()); - break; - } - } - return ResponseEntity.ok().build(); - } - @PostMapping("/api/me/subscribe") - public ResponseEntity<Void> subscribeMe(@Visitor User visitor, String email) { - // TODO: check status - emailService.setNotificationsEmail(visitor.getUid(), email); - return ResponseEntity.ok().build(); - } - @PostMapping("/api/me/upload") - public void updateInfo(@Visitor User visitor, - @RequestParam MultipartFile avatar) throws IOException { - String avatarTmpPath = HttpUtils.receiveMultiPartFile(avatar, tmpDir).getHost(); - if (StringUtils.isNotEmpty(avatarTmpPath)) { - imagesService.saveAvatar(avatarTmpPath, visitor.getUid()); - } - } - - @RequestMapping(value = "/api/users/read", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public List<User> doGetUserRead( - @Visitor User visitor, - @RequestParam String uname) { - int uid = 0; - if (uname == null) { - uid = visitor.getUid(); - } else { - if (WebUtils.isUserName(uname)) { - User u = userService.getUserByName(uname); - if (!u.isAnonymous()) { - uid = u.getUid(); - } - } - } - - if (uid > 0) { - List<User> friends = userService.getUserFriends(uid); - friends.forEach(f -> f.setAvatar(webApp.getAvatarUrl(f))); - return friends; - } - throw new HttpNotFoundException(); - } - - @RequestMapping(value = "/api/users/readers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public List<User> doGetUserReaders( - @Visitor User visitor, - @RequestParam String uname) { - int uid = 0; - if (uname == null) { - uid = visitor.getUid(); - } else { - if (WebUtils.isUserName(uname)) { - User u = userService.getUserByName(uname); - if (!u.isAnonymous()) { - uid = u.getUid(); - } - } - } - - if (uid > 0) { - List<User> readers = userService.getUserReaders(uid); - readers.forEach(r -> r.setAvatar(webApp.getAvatarUrl(r))); - return readers; - } - throw new HttpNotFoundException(); - } - - @GetMapping("/api/info/{uname}") - public User getUserInfo(@Visitor User visitor, @PathVariable String uname) { - User user = userService.getUserByName(uname); - if (!user.isBanned()) { - user.setRead(doGetUserRead(visitor, uname)); - user.setReaders(doGetUserReaders(visitor, uname)); - user.setAvatar(webApp.getAvatarUrl(user)); - return userService.getUserInfo(user); - } - throw new HttpNotFoundException(); - } - - @Deprecated - @GetMapping(value = "/api/avatar", produces = MediaType.IMAGE_PNG_VALUE) - public byte[] getAvatarUrl( - @RequestParam(required = false) String uname, - @RequestParam(required = false) String jid) - throws IOException { - User user = AnonymousUser.INSTANCE; - if (StringUtils.isNotEmpty(uname)) { - user = userService.getUserByName(uname); - } - if (user.isAnonymous() && StringUtils.isNotEmpty(jid)) { - user = userService.getUserByJID(jid); - } - return IOUtils.toByteArray(URI.create(webApp.getAvatarUrl(user))); - } - public class SecureUser extends User { - public String getHash() { - return getAuthHash(); - } - public List<String> getJIDs() { - return userService.getAllJIDs(this); - } - public List<String> getEmails() { - return userService.getEmails(this); - } - public String getActiveEmail() { - return emailService.getNotificationsEmail(this.getUid()); - } - public String getTwitterName() { - return crosspostService.getTwitterName(this.getUid()); - } - public String getTelegramName() { - return crosspostService.getTelegramName(this.getUid()); - } - public ApplicationStatus getFacebookStatus() { - return crosspostService.getFbCrossPostStatus(this.getUid()); - } - } -} diff --git a/src/main/java/com/juick/server/api/activity/Profile.java b/src/main/java/com/juick/server/api/activity/Profile.java deleted file mode 100644 index bbe3c0af..00000000 --- a/src/main/java/com/juick/server/api/activity/Profile.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.juick.model.Message; -import com.juick.model.User; -import com.juick.formatters.PlainTextFormatter; -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.Like; -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.HttpNotFoundException; -import com.juick.www.WebApp; -import com.juick.service.MessagesService; -import com.juick.service.UserService; -import com.juick.service.activities.AnnounceEvent; -import com.juick.service.activities.FollowEvent; -import com.juick.service.activities.UndoAnnounceEvent; -import com.juick.service.activities.UndoFollowEvent; -import com.juick.service.security.annotation.Visitor; -import com.overzealous.remark.Remark; -import org.apache.commons.io.IOUtils; -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.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import org.springframework.web.util.UriComponentsBuilder; - -import javax.inject.Inject; -import java.io.InputStream; -import java.net.URI; -import java.nio.charset.StandardCharsets; -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("ActivityPub"); - @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; - @Inject - private ObjectMapper jsonMapper; - @Inject - private WebApp webApp; - @Inject - private Remark remarkConverter; - - @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)); - Image avatar = new Image(); - avatar.setUrl(webApp.getAvatarUrl(user)); - 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(@Visitor User visitor, @PathVariable String userName, - @RequestParam(required = false, defaultValue = "0") int before) { - User user = userService.getUserByName(userName); - if (!user.isAnonymous() && !user.isBanned()) { - 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).orElseThrow(IllegalStateException::new))); - } - - @PostMapping(value = "/api/inbox", consumes = {Context.LD_JSON_MEDIA_TYPE, Context.ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE}) - public ResponseEntity<CommandResult> processInbox( - @Visitor User visitor, - InputStream inboxData) throws Exception { - String inbox = IOUtils.toString(inboxData, StandardCharsets.UTF_8); - logger.info("Inbox: {}", inbox); - Activity activity = jsonMapper.readValue(inbox, Activity.class); - if ((StringUtils.isNotEmpty(visitor.getUri().toString()) - && visitor.getUri().equals(URI.create(activity.getActor()))) - || !visitor.isAnonymous()) { - if (activity instanceof Follow) { - Follow followRequest = (Follow) activity; - applicationEventPublisher.publishEvent( - new FollowEvent(this, followRequest)); - return new ResponseEntity<>(CommandResult.fromString("Follow request accepted"), HttpStatus.ACCEPTED); - - } - if (activity instanceof Undo) { - Map object = (Map) activity.getObject(); - String objectType = (String) object.get("type"); - String objectObject = (String) object.get("object"); - if (objectType.equals("Follow")) { - applicationEventPublisher.publishEvent(new UndoFollowEvent(this, activity.getActor(), objectObject)); - return new ResponseEntity<>(CommandResult.fromString("Undo follow request accepted"), HttpStatus.OK); - } else if (objectType.equals("Like") || objectType.equals("Announce")) { - applicationEventPublisher.publishEvent(new UndoAnnounceEvent(this, activity.getActor(), objectObject)); - return new ResponseEntity<>(CommandResult.fromString("Undo like/announce request accepted"), 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<>(CommandResult.fromString("Reply already exists"), HttpStatus.OK); - } else { - String inReplyTo = (String) note.get("inReplyTo"); - if (StringUtils.isNotBlank(inReplyTo)) { - if (inReplyTo.startsWith(baseUri)) { - String postId = activityPubManager.postId(inReplyTo); - User user = new User(); - user.setUri(URI.create(activity.getActor())); - String markdown = remarkConverter.convertFragment((String) note.get("content")); - String commandBody = note.get("attachment") == null ? markdown : - ((List<Object>) note.get("attachment")).stream().map(attachmentObj -> { - Map<String, String> attachment = (Map<String, String>) attachmentObj; - String attachmentUrl = attachment.get("url"); - String attachmentName = attachment.get("name"); - return PlainTextFormatter.markdownUrl(attachmentUrl, attachmentName); - }).reduce(markdown, (currentUrl, nextUrl) -> String.format("%s\n%s", currentUrl, nextUrl)); - - CommandResult result = commandsManager.processCommand( - user, String.format("#%s %s", postId, commandBody), - URI.create(StringUtils.EMPTY)); - logger.info(jsonMapper.writeValueAsString(result)); - if (result.getNewMessage().isPresent()) { - messagesService.updateReplyUri(result.getNewMessage().get(), noteId); - return new ResponseEntity<>(result, HttpStatus.OK); - } else { - return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST); - } - } else { - Message reply = messagesService.getReplyByUri(inReplyTo); - if (reply != null) { - User user = new User(); - user.setUri(URI.create(activity.getActor())); - String markdown = remarkConverter.convertFragment((String)note.get("content")); - // combine note text with attachment urls - String commandBody = note.get("attachment") == null ? markdown : - ((List<Object>) note.get("attachment")).stream().map(attachmentObj -> { - Map<String, String> attachment = (Map<String, String>) attachmentObj; - String attachmentUrl = attachment.get("url"); - String attachmentName = attachment.get("name"); - return PlainTextFormatter.markdownUrl(attachmentUrl, attachmentName); - }).reduce(markdown, (currentUrl, nextUrl) -> String.format("%s\n%s", currentUrl, nextUrl)); - CommandResult result = commandsManager.processCommand( - user, - String.format("#%d/%d %s", reply.getMid(), reply.getRid(), commandBody), - URI.create(StringUtils.EMPTY)); - logger.info(jsonMapper.writeValueAsString(result)); - if (result.getNewMessage().isPresent()) { - messagesService.updateReplyUri(result.getNewMessage().get(), noteId); - return new ResponseEntity<>(result, HttpStatus.OK); - } else { - return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST); - } - } - } - } - } - } - } - } - if (activity instanceof Delete) { - if (activity.getObject() instanceof String) { - // Delete gone user - // TODO: check if it is really deleted and remove copy-paste - if (activity.getActor().equals(activity.getObject())) { - return new ResponseEntity<>(CommandResult.fromString("Delete request accepted"), HttpStatus.ACCEPTED); - } - } - 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<>(CommandResult.fromString("Delete request accepted"), HttpStatus.OK); - } - } - if (activity instanceof Like || activity instanceof Announce) { - String messageUri = activity.getObject() instanceof String ? (String) activity.getObject() - : activity.getObject() instanceof Context ? ((Context) activity.getObject()).getId() - : (String) ((Map)activity.getObject()).get("id"); - applicationEventPublisher.publishEvent(new AnnounceEvent(this, activity.getActor(), messageUri)); - return new ResponseEntity<>(CommandResult.fromString("Like/announce request accepted"), HttpStatus.OK); - } - logger.warn("Unknown activity: {}", jsonMapper.writeValueAsString(activity)); - return new ResponseEntity<>(CommandResult.fromString("Unknown activity"), HttpStatus.NOT_IMPLEMENTED); - } - if (activity instanceof Delete) { - if (activity.getObject() instanceof String) { - // Delete gone user - if (activity.getActor().equals(activity.getObject())) { - return new ResponseEntity<>(CommandResult.fromString("Delete request accepted"), HttpStatus.ACCEPTED); - } - } - } - return new ResponseEntity<>(CommandResult.fromString("Can not authenticate"), HttpStatus.UNAUTHORIZED); - } - @PostMapping(value = "/u/", produces = MediaType.APPLICATION_JSON_VALUE) - public User fetchUser(@RequestParam URI uri) { - return activityPubManager.personToUser(uri); - } -} diff --git a/src/main/java/com/juick/server/api/activity/helpers/ActivityIdDeserializer.java b/src/main/java/com/juick/server/api/activity/helpers/ActivityIdDeserializer.java deleted file mode 100644 index 46b7ebab..00000000 --- a/src/main/java/com/juick/server/api/activity/helpers/ActivityIdDeserializer.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.helpers; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import java.io.IOException; - -public class ActivityIdDeserializer extends JsonDeserializer<String> { - @Override - public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - JsonToken jsonToken = p.getCurrentToken(); - if (jsonToken == JsonToken.START_OBJECT) { - JsonNode node = p.getCodec().readTree(p); - return node.get("id").textValue(); - } - return p.getValueAsString(); - } -} diff --git a/src/main/java/com/juick/server/api/activity/helpers/LinkValueDeserializer.java b/src/main/java/com/juick/server/api/activity/helpers/LinkValueDeserializer.java deleted file mode 100644 index 81d66088..00000000 --- a/src/main/java/com/juick/server/api/activity/helpers/LinkValueDeserializer.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.helpers; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import java.io.IOException; - -public class LinkValueDeserializer extends JsonDeserializer<String> { - @Override - public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - JsonToken jsonToken = p.getCurrentToken(); - if (jsonToken == JsonToken.VALUE_STRING) { - return p.getValueAsString(); - } - JsonNode node = p.getCodec().readTree(p); - return node.get("href").textValue(); - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/Activity.java b/src/main/java/com/juick/server/api/activity/model/Activity.java deleted file mode 100644 index 1462aadd..00000000 --- a/src/main/java/com/juick/server/api/activity/model/Activity.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.juick.server.api.activity.helpers.ActivityIdDeserializer; -import org.apache.commons.lang3.StringUtils; - -import java.util.UUID; - -public abstract class Activity extends Context { - - @JsonDeserialize(using = ActivityIdDeserializer.class) - private String actor; - private Object object; - - public String getActor() { - return actor; - } - - public void setActor(String actor) { - this.actor = actor; - if (StringUtils.isEmpty(getId())) { - setId(String.format("%s#%s", this.actor, UUID.randomUUID().toString())); - } - } - - public Object getObject() { - return object; - } - - public void setObject(Object object) { - this.object = object; - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/Context.java b/src/main/java/com/juick/server/api/activity/model/Context.java deleted file mode 100644 index 14b65e25..00000000 --- a/src/main/java/com/juick/server/api/activity/model/Context.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model; - -import com.fasterxml.jackson.annotation.*; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.juick.server.api.activity.helpers.LinkValueDeserializer; -import com.juick.server.api.activity.model.activities.*; -import com.juick.server.api.activity.model.objects.*; - -import java.time.Instant; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property="type") -@JsonSubTypes({ - @JsonSubTypes.Type(value = Create.class, name = "Create"), - @JsonSubTypes.Type(value = Update.class, name = "Update"), - @JsonSubTypes.Type(value = Delete.class, name = "Delete"), - @JsonSubTypes.Type(value = Follow.class, name = "Follow"), - @JsonSubTypes.Type(value = Accept.class, name = "Accept"), - @JsonSubTypes.Type(value = Undo.class, name = "Undo"), - @JsonSubTypes.Type(value = Like.class, name = "Like"), - @JsonSubTypes.Type(value = Block.class, name = "Block"), - @JsonSubTypes.Type(value = Announce.class, name = "Announce"), - @JsonSubTypes.Type(value = Activity.class, name = "Activity"), - @JsonSubTypes.Type(value = Image.class, name = "Image"), - @JsonSubTypes.Type(value = Key.class, name = "Key"), - @JsonSubTypes.Type(value = Link.class, name = "Link"), - @JsonSubTypes.Type(value = Hashtag.class, name = "Hashtag"), - @JsonSubTypes.Type(value = Mention.class, name = "Mention"), - @JsonSubTypes.Type(value = Emoji.class, name = "Emoji"), - @JsonSubTypes.Type(value = Note.class, name = "Note"), - @JsonSubTypes.Type(value = OrderedCollection.class, name = "OrderedCollection"), - @JsonSubTypes.Type(value = OrderedCollectionPage.class, name = "OrderedCollectionPage"), - @JsonSubTypes.Type(value = Person.class, name = "Person") -}) -public abstract class Context { - - private List<Object> context; - - private String id; - - private String name; - - private Instant published; - - @JsonDeserialize(using = LinkValueDeserializer.class) - private String url; - - private List<String> to; - - private List<Context> tags; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getType() { - return getClass().getSimpleName(); - } - - @JsonProperty("@context") - @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - public List<Object> getContext() { - return 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_MEDIA_TYPE = "application/activity+json"; - public final static String ACTIVITYSTREAMS_PROFILE_MEDIA_TYPE = ACTIVITY_MEDIA_TYPE + "; profile=\"https://www.w3.org/ns/activitystreams\""; - public final static String ACTIVITYSTREAMS_PUBLIC = "https://www.w3.org/ns/activitystreams#Public"; - - public Instant getPublished() { - return published; - } - - public void setPublished(Instant published) { - this.published = published; - } - - public List<String> getTo() { - return to; - } - - public void setTo(List<String> to) { - this.to = to; - } - - public static Context build(Context response) { - response.context = new ArrayList<>(Arrays.asList(ACTIVITY_STREAMS_URI, SECURITY_URI)); - response.context.add(Collections.singletonMap("Hashtag", "as:Hashtag")); - return response; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - @JsonProperty("tag") - public List<Context> getTags() { - return tags; - } - - public void setTags(List<Context> tags) { - this.tags = tags; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/activities/Accept.java b/src/main/java/com/juick/server/api/activity/model/activities/Accept.java deleted file mode 100644 index 376f76fc..00000000 --- a/src/main/java/com/juick/server/api/activity/model/activities/Accept.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.activities; - -import com.juick.server.api.activity.model.Activity; - -public class Accept extends Activity { -} diff --git a/src/main/java/com/juick/server/api/activity/model/activities/Announce.java b/src/main/java/com/juick/server/api/activity/model/activities/Announce.java deleted file mode 100644 index 7d3298f9..00000000 --- a/src/main/java/com/juick/server/api/activity/model/activities/Announce.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.activities; - -import com.juick.server.api.activity.model.Activity; - -public class Announce extends Activity { -} diff --git a/src/main/java/com/juick/server/api/activity/model/activities/Block.java b/src/main/java/com/juick/server/api/activity/model/activities/Block.java deleted file mode 100644 index 54c8c485..00000000 --- a/src/main/java/com/juick/server/api/activity/model/activities/Block.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.activities; - -import com.juick.server.api.activity.model.Activity; - -public class Block extends Activity { -} diff --git a/src/main/java/com/juick/server/api/activity/model/activities/Create.java b/src/main/java/com/juick/server/api/activity/model/activities/Create.java deleted file mode 100644 index 6ac6ad23..00000000 --- a/src/main/java/com/juick/server/api/activity/model/activities/Create.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.activities; - -import com.juick.server.api.activity.model.Activity; - -public class Create extends Activity { -} diff --git a/src/main/java/com/juick/server/api/activity/model/activities/Delete.java b/src/main/java/com/juick/server/api/activity/model/activities/Delete.java deleted file mode 100644 index 253627c2..00000000 --- a/src/main/java/com/juick/server/api/activity/model/activities/Delete.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.activities; - -import com.juick.server.api.activity.model.Activity; - -public class Delete extends Activity { -} diff --git a/src/main/java/com/juick/server/api/activity/model/activities/Follow.java b/src/main/java/com/juick/server/api/activity/model/activities/Follow.java deleted file mode 100644 index 9475b4a1..00000000 --- a/src/main/java/com/juick/server/api/activity/model/activities/Follow.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.activities; - -import com.juick.server.api.activity.model.Activity; - -public class Follow extends Activity { -} diff --git a/src/main/java/com/juick/server/api/activity/model/activities/Like.java b/src/main/java/com/juick/server/api/activity/model/activities/Like.java deleted file mode 100644 index efd25e24..00000000 --- a/src/main/java/com/juick/server/api/activity/model/activities/Like.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.activities; - -import com.juick.server.api.activity.model.Activity; - -public class Like extends Activity { -} diff --git a/src/main/java/com/juick/server/api/activity/model/activities/Undo.java b/src/main/java/com/juick/server/api/activity/model/activities/Undo.java deleted file mode 100644 index bfaddaee..00000000 --- a/src/main/java/com/juick/server/api/activity/model/activities/Undo.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.activities; - -import com.juick.server.api.activity.model.Activity; - -public class Undo extends Activity { -} diff --git a/src/main/java/com/juick/server/api/activity/model/activities/Update.java b/src/main/java/com/juick/server/api/activity/model/activities/Update.java deleted file mode 100644 index 17dfc105..00000000 --- a/src/main/java/com/juick/server/api/activity/model/activities/Update.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.activities; - -import com.juick.server.api.activity.model.Activity; - -public class Update extends Activity { -} diff --git a/src/main/java/com/juick/server/api/activity/model/objects/Emoji.java b/src/main/java/com/juick/server/api/activity/model/objects/Emoji.java deleted file mode 100644 index 8cb69ee4..00000000 --- a/src/main/java/com/juick/server/api/activity/model/objects/Emoji.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.objects; - -import com.juick.server.api.activity.model.Context; - -public class Emoji extends Context { -} diff --git a/src/main/java/com/juick/server/api/activity/model/objects/Hashtag.java b/src/main/java/com/juick/server/api/activity/model/objects/Hashtag.java deleted file mode 100644 index 8cfd2d71..00000000 --- a/src/main/java/com/juick/server/api/activity/model/objects/Hashtag.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.objects; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class Hashtag extends Mention { - @JsonCreator - public Hashtag(@JsonProperty("href") String href, @JsonProperty("name") String name) { - super(href, name); - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/objects/Image.java b/src/main/java/com/juick/server/api/activity/model/objects/Image.java deleted file mode 100644 index 6b9be752..00000000 --- a/src/main/java/com/juick/server/api/activity/model/objects/Image.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.objects; - -import com.juick.server.api.activity.model.Context; - -public class Image extends Context { - private String mediaType; - - public String getMediaType() { - return mediaType; - } - - public void setMediaType(String mediaType) { - this.mediaType = mediaType; - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/objects/Key.java b/src/main/java/com/juick/server/api/activity/model/objects/Key.java deleted file mode 100644 index 8af232da..00000000 --- a/src/main/java/com/juick/server/api/activity/model/objects/Key.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.objects; - -import com.juick.server.api.activity.model.Context; - -public class Key extends Context { - private String owner; - private String publicKeyPem; - - public String getOwner() { - return owner; - } - - public void setOwner(String owner) { - this.owner = owner; - } - - public String getPublicKeyPem() { - return publicKeyPem; - } - - public void setPublicKeyPem(String publicKeyPem) { - this.publicKeyPem = publicKeyPem; - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/objects/Link.java b/src/main/java/com/juick/server/api/activity/model/objects/Link.java deleted file mode 100644 index 9014baff..00000000 --- a/src/main/java/com/juick/server/api/activity/model/objects/Link.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.objects; - -import com.juick.server.api.activity.model.Context; - -public class Link extends Context { - private String href; - - public String getHref() { - return href; - } - - public void setHref(String href) { - this.href = href; - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/objects/Mention.java b/src/main/java/com/juick/server/api/activity/model/objects/Mention.java deleted file mode 100644 index 9f471664..00000000 --- a/src/main/java/com/juick/server/api/activity/model/objects/Mention.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.objects; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class Mention extends Link { - @JsonCreator - public Mention(@JsonProperty("href") String href, @JsonProperty("name") String name) { - this.setHref(href); - this.setName(name); - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/objects/Note.java b/src/main/java/com/juick/server/api/activity/model/objects/Note.java deleted file mode 100644 index 9cb2c945..00000000 --- a/src/main/java/com/juick/server/api/activity/model/objects/Note.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.objects; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.juick.server.api.activity.model.Context; - -import java.util.List; - -public class Note extends Context { - private String content; - private String attributedTo; - private String inReplyTo; - private List<Image> attachment; - private List<String> to; - private List<String> cc; - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getAttributedTo() { - return attributedTo; - } - - public void setAttributedTo(String attributedTo) { - this.attributedTo = attributedTo; - } - - @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - public List<Image> getAttachment() { - return attachment; - } - - public void setAttachment(List<Image> attachment) { - this.attachment = attachment; - } - - public List<String> getTo() { - return to; - } - - public void setTo(List<String> to) { - this.to = to; - } - - public List<String> getCc() { - return cc; - } - - public void setCc(List<String> cc) { - this.cc = cc; - } - - public String getInReplyTo() { - return inReplyTo; - } - - public void setInReplyTo(String inReplyTo) { - this.inReplyTo = inReplyTo; - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/objects/OrderedCollection.java b/src/main/java/com/juick/server/api/activity/model/objects/OrderedCollection.java deleted file mode 100644 index 7060f15b..00000000 --- a/src/main/java/com/juick/server/api/activity/model/objects/OrderedCollection.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.objects; - -import com.juick.server.api.activity.model.Context; - -public class OrderedCollection extends Context { - - private int totalItems; - - public int getTotalItems() { - return totalItems; - } - - public void setTotalItems(int totalItems) { - this.totalItems = totalItems; - } - private String first; - - public String getFirst() { - return first; - } - - public void setFirst(String first) { - this.first = first; - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/objects/OrderedCollectionPage.java b/src/main/java/com/juick/server/api/activity/model/objects/OrderedCollectionPage.java deleted file mode 100644 index 22e655c8..00000000 --- a/src/main/java/com/juick/server/api/activity/model/objects/OrderedCollectionPage.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.objects; - -import com.juick.server.api.activity.model.Context; - -import java.util.List; - -public class OrderedCollectionPage extends Context { - - private String partOf; - - private String first; - - private String next; - - private String last; - - private List<? extends Context> orderedItems; - - public String getNext() { - return next; - } - - public void setNext(String next) { - this.next = next; - } - - public List<? extends Context> getOrderedItems() { - return orderedItems; - } - - public void setOrderedItems(List<? extends Context> orderedItems) { - this.orderedItems = orderedItems; - } - - public String getPartOf() { - return partOf; - } - - public void setPartOf(String partOf) { - this.partOf = partOf; - } - - public String getFirst() { - return first; - } - - public void setFirst(String first) { - this.first = first; - } - - public String getLast() { - return last; - } - - public void setLast(String last) { - this.last = last; - } -} diff --git a/src/main/java/com/juick/server/api/activity/model/objects/Person.java b/src/main/java/com/juick/server/api/activity/model/objects/Person.java deleted file mode 100644 index 0ac13017..00000000 --- a/src/main/java/com/juick/server/api/activity/model/objects/Person.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.activity.model.objects; - -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.juick.server.api.activity.model.Context; - -public class Person extends Context { - - private String name; - private String preferredUsername; - private Image icon; - private String inbox; - private String outbox; - private String following; - private String followers; - private Key publicKey; - - @Override - public String getType() { - return "Person"; - } - - 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; - } - - @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) - public Key getPublicKey() { - return publicKey; - } - - public void setPublicKey(Key publicKey) { - this.publicKey = publicKey; - } - - public String getPreferredUsername() { - return preferredUsername; - } - - public void setPreferredUsername(String preferredUsername) { - this.preferredUsername = preferredUsername; - } -} diff --git a/src/main/java/com/juick/server/api/apple/AppSiteAssociation.java b/src/main/java/com/juick/server/api/apple/AppSiteAssociation.java deleted file mode 100644 index f4a6fa06..00000000 --- a/src/main/java/com/juick/server/api/apple/AppSiteAssociation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.apple; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Collections; -import java.util.List; - -@RestController -public class AppSiteAssociation { - @Value("${ios_app_id:}") - private String appId; - - @GetMapping("/.well-known/apple-app-site-association") - @ResponseBody - public SiteAssociations appSiteAssociations() { - WebCredentials webCredentials = new WebCredentials(); - webCredentials.setApps(Collections.singletonList(appId)); - SiteAssociations siteAssociations = new SiteAssociations(); - siteAssociations.setWebcredentials(webCredentials); - return siteAssociations; - } - - private class SiteAssociations { - private WebCredentials webcredentials; - - public WebCredentials getWebcredentials() { - return webcredentials; - } - - public void setWebcredentials(WebCredentials webcredentials) { - this.webcredentials = webcredentials; - } - } - - private class WebCredentials { - private List<String> apps; - - public List<String> getApps() { - return apps; - } - - public void setApps(List<String> apps) { - this.apps = apps; - } - } -} diff --git a/src/main/java/com/juick/server/api/hostmeta/HostMeta.java b/src/main/java/com/juick/server/api/hostmeta/HostMeta.java deleted file mode 100644 index 688a848a..00000000 --- a/src/main/java/com/juick/server/api/hostmeta/HostMeta.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.hostmeta; - -import com.cliqset.xrd.Link; -import com.cliqset.xrd.XRD; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Collections; - -import static com.cliqset.xrd.XRDConstants.XRD_MEDIA_TYPE; - -@RestController -public class HostMeta { - @Value("${ap_base_uri:http://localhost:8080/}") - private String baseUri; - @GetMapping(value = "/.well-known/host-meta", produces = XRD_MEDIA_TYPE) - public XRD hostMetaResponse() { - Link webfinger = new Link(); - webfinger.setTemplate(String.format("%swebfinger?resource={uri}", baseUri)); - XRD xrd = new XRD(); - xrd.setLinks(Collections.singletonList(webfinger)); - return xrd; - } -} diff --git a/src/main/java/com/juick/server/api/rss/Feeds.java b/src/main/java/com/juick/server/api/rss/Feeds.java deleted file mode 100644 index 76c2b217..00000000 --- a/src/main/java/com/juick/server/api/rss/Feeds.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.rss; - -import com.juick.model.User; -import com.juick.server.util.HttpNotFoundException; -import com.juick.service.MessagesService; -import com.juick.service.UserService; -import com.juick.service.security.annotation.Visitor; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.servlet.ModelAndView; - -import javax.inject.Inject; -import java.util.List; - -/** - * Created by vitalyster on 13.12.2016. - */ -@Controller -public class Feeds { - - @Inject - private MessagesService messagesService; - @Inject - private UserService userService; - - @GetMapping("/rss/{userName}/blog") - public ModelAndView getBlog(@Visitor User visitor, @PathVariable String userName) { - User user = userService.getUserByName(userName); - if (!user.isAnonymous() && !user.isBanned()) { - List<Integer> mids = messagesService.getUserBlog(user.getUid(), 0, 0); - ModelAndView modelAndView = new ModelAndView(); - modelAndView.setViewName("messagesView"); - modelAndView.addObject("user", user); - modelAndView.addObject("messages", messagesService.getMessages(visitor, mids)); - return modelAndView; - } - throw new HttpNotFoundException(); - } - - @GetMapping("/rss/") - public ModelAndView getLast( - @Visitor User visitor, - @RequestParam(value = "hours", required = false, defaultValue = "0") Integer hours) { - List<Integer> mids = messagesService.getLastMessages(hours); - ModelAndView modelAndView = new ModelAndView(); - modelAndView.setViewName("messagesView"); - modelAndView.addObject("messages", messagesService.getMessages(visitor, mids)); - return modelAndView; - } - @GetMapping("/rss/comments") - public ModelAndView getLastReplies(@RequestParam(value = "hours", required = false, defaultValue = "0") Integer hours) { - ModelAndView modelAndView = new ModelAndView(); - modelAndView.setViewName("repliesView"); - modelAndView.addObject("messages", messagesService.getLastReplies(hours)); - return modelAndView; - } -} diff --git a/src/main/java/com/juick/server/api/rss/MessagesView.java b/src/main/java/com/juick/server/api/rss/MessagesView.java deleted file mode 100644 index a03dd723..00000000 --- a/src/main/java/com/juick/server/api/rss/MessagesView.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.rss; - -import com.juick.model.Message; -import com.juick.model.User; -import com.juick.server.api.rss.extension.JuickModule; -import com.juick.server.api.rss.extension.JuickModuleImpl; -import com.juick.www.WebApp; -import com.juick.util.MessageUtils; -import com.rometools.modules.atom.modules.AtomLinkModule; -import com.rometools.modules.atom.modules.AtomLinkModuleImpl; -import com.rometools.modules.mediarss.MediaEntryModuleImpl; -import com.rometools.modules.mediarss.MediaModule; -import com.rometools.modules.mediarss.MediaModuleImpl; -import com.rometools.modules.mediarss.types.MediaContent; -import com.rometools.modules.mediarss.types.Metadata; -import com.rometools.modules.mediarss.types.Thumbnail; -import com.rometools.modules.mediarss.types.UrlReference; -import com.rometools.rome.feed.atom.Link; -import com.rometools.rome.feed.rss.*; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.servlet.view.feed.AbstractRssFeedView; - -import javax.annotation.Nonnull; -import javax.annotation.PostConstruct; -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Created by vitalyster on 13.12.2016. - */ -public class MessagesView extends AbstractRssFeedView { - - private static final Logger logger = LoggerFactory.getLogger(MessagesView.class); - - @Inject - private WebApp webApp; - - @PostConstruct - public void init() { - setContentType("application/rss+xml;charset=UTF-8"); - } - - @SuppressWarnings("unchecked") - @Override - protected List<Item> buildFeedItems(@Nonnull Map<String, Object> model, - @Nonnull HttpServletRequest request, - @Nonnull HttpServletResponse response) { - List<Message> msgs = (List<Message>)model.get("messages"); - return msgs.stream().map(this::createRssItem).collect(Collectors.toList()); - } - - @Override - protected void buildFeedMetadata(Map<String, Object> model, Channel feed, HttpServletRequest request) { - Object userObj = model.get("user"); - if (userObj != null) { - User user = (User) userObj; - feed.setDescription(String.format("The latest messages by @%s at Juick", user.getName())); - String title = String.format("%s - Juick", user.getName()); - feed.setTitle(title); - String link = String.format("http://juick.com/%s/", user.getName()); - feed.setLink(link); - Image rssImage = new Image(); - rssImage.setUrl(webApp.getAvatarUrl(user)); - rssImage.setTitle(title); - rssImage.setLink(link); - feed.setImage(rssImage); - String href = String.format("http://rss.juick.com/%s/blog", user.getName()); - AtomLinkModule atomLinkModule = new AtomLinkModuleImpl(); - Link atomLink = new Link(); - atomLink.setHref(href); - atomLink.setType("application/rss+xml"); - atomLink.setRel("self"); - atomLinkModule.setLinks(Collections.singletonList(atomLink)); - - feed.getModules().add(atomLinkModule); - } else { - feed.setDescription("The latest messages at Juick"); - feed.setLink("http://juick.com/"); - feed.setTitle("Juick"); - } - - MediaModule mediaModule = new MediaModuleImpl(); - feed.getModules().add(mediaModule); - - - } - - private Item createRssItem(Message msg) { - Item item = new Item(); - String messageUrl = String.format("http://juick.com/%s/%d", msg.getUser().getName(), msg.getMid()); - String messageTitle = String.format("@%s: %s", msg.getUser().getName(), MessageUtils.getTagsString(msg)); - boolean isCode = msg.getTags().stream().anyMatch(t -> t.getName().equals("code")); - String messageDescription = isCode ? MessageUtils.formatMessageCode(StringUtils.defaultString(msg.getText())) - : MessageUtils.formatMessage(StringUtils.defaultString(msg.getText())); - item.setLink(messageUrl); - //item.setGuid(messageUrl); - item.setTitle(messageTitle); - Description description = new Description(); - description.setType("text/html"); - description.setValue(messageDescription); - item.setDescription(description); - item.setPubDate(Date.from(msg.getCreated())); - item.setComments(messageUrl); - msg.getTags().stream().map(t -> { - Category category = new Category(); - category.setValue(t.getName()); - return category; - }).forEach(c -> item.getCategories().add(c)); - JuickModule juickModule = new JuickModuleImpl(); - juickModule.setUid(msg.getUser().getUid()); - item.getModules().add(juickModule); - if (StringUtils.isNotEmpty(msg.getAttachmentType())) { - String type = msg.getAttachmentType().equals("jpg") ? "image/jpeg" : "image/png"; - MediaEntryModuleImpl module = new MediaEntryModuleImpl(); - try { - UrlReference reference = new UrlReference(MessageUtils.attachmentUrl(msg)); - MediaContent mediaContent = new MediaContent(reference); - mediaContent.setType(type); - Metadata metadata = new Metadata(); - metadata.setThumbnail(new Thumbnail[]{new Thumbnail(new URI(msg.getPhoto().getThumbnail()))}); - module.setMetadata(metadata); - module.setMediaContents(new MediaContent[]{mediaContent}); - item.getModules().add(module); - } catch (URISyntaxException e) { - logger.error("Invalid URI", e); - } - - } - return item; - } -} diff --git a/src/main/java/com/juick/server/api/rss/RepliesView.java b/src/main/java/com/juick/server/api/rss/RepliesView.java deleted file mode 100644 index c848217a..00000000 --- a/src/main/java/com/juick/server/api/rss/RepliesView.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.rss; - -import com.juick.model.ResponseReply; -import com.juick.util.MessageUtils; -import com.rometools.modules.mediarss.MediaEntryModuleImpl; -import com.rometools.modules.mediarss.MediaModule; -import com.rometools.modules.mediarss.MediaModuleImpl; -import com.rometools.modules.mediarss.types.MediaContent; -import com.rometools.modules.mediarss.types.Metadata; -import com.rometools.modules.mediarss.types.Thumbnail; -import com.rometools.modules.mediarss.types.UrlReference; -import com.rometools.rome.feed.rss.Channel; -import com.rometools.rome.feed.rss.Description; -import com.rometools.rome.feed.rss.Item; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.servlet.view.feed.AbstractRssFeedView; - -import javax.annotation.Nonnull; -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Created by vitalyster on 13.12.2016. - */ -public class RepliesView extends AbstractRssFeedView { - - private static final Logger logger = LoggerFactory.getLogger(RepliesView.class); - - @PostConstruct - public void init() { - setContentType("application/rss+xml;charset=UTF-8"); - } - - @SuppressWarnings("unchecked") - @Override - protected @Nonnull List<Item> buildFeedItems(@Nonnull Map<String, Object> model, - @Nonnull HttpServletRequest request, - @Nonnull HttpServletResponse response) { - List<ResponseReply> msgs = (List<ResponseReply>)model.get("messages"); - return msgs.stream().map(this::createRssItem).collect(Collectors.toList()); - } - - @Override - protected void buildFeedMetadata(Map<String, Object> model, Channel feed, HttpServletRequest request) { - feed.setTitle("Juick"); - feed.setLink("http://juick.com/"); - feed.setDescription("The latest comments at Juick"); - MediaModule mediaModule = new MediaModuleImpl(); - feed.getModules().add(mediaModule); - } - - private Item createRssItem(ResponseReply msg) { - Item item = new Item(); - String messageUrl = String.format("http://juick.com/m/%d#%d", msg.getMid(), msg.getRid()); - String messageTitle = String.format("@%s:", msg.getUname()); - String messageDescription = msg.isHtml() ? msg.getDescription() : MessageUtils.formatMessage(msg.getDescription()); - item.setLink(messageUrl); - //item.setGuid(messageUrl); - item.setTitle(messageTitle); - Description description = new Description(); - description.setType("text/html"); - description.setValue(messageDescription); - item.setDescription(description); - item.setPubDate(msg.getPubDate()); - if (StringUtils.isNotEmpty(msg.getAttachmentType())) { - String type = msg.getAttachmentType().equals("jpg") ? "image/jpeg" : "image/png"; - MediaEntryModuleImpl module = new MediaEntryModuleImpl(); - try { - UrlReference reference = new UrlReference( - String.format("http://i.juick.com/photos-1024/%d-%d.%s", msg.getMid(), msg.getRid(), type)); - MediaContent mediaContent = new MediaContent(reference); - mediaContent.setType(type); - Metadata metadata = new Metadata(); - metadata.setThumbnail(new Thumbnail[]{new Thumbnail( - new URI(String.format("http://i.juick.com/ps/%d-%d.%s", msg.getMid(), msg.getRid(), type)))}); - module.setMetadata(metadata); - module.setMediaContents(new MediaContent[]{mediaContent}); - item.getModules().add(module); - } catch (URISyntaxException e) { - logger.error("Invalid URI", e); - } - - } - return item; - } -} diff --git a/src/main/java/com/juick/server/api/rss/extension/JuickModule.java b/src/main/java/com/juick/server/api/rss/extension/JuickModule.java deleted file mode 100644 index b9b659c8..00000000 --- a/src/main/java/com/juick/server/api/rss/extension/JuickModule.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.rss.extension; - -import com.rometools.rome.feed.module.Module; - -/** - * Created by vitalyster on 13.12.2016. - */ -public interface JuickModule extends Module { - - String URI = "http://juick.com/"; - - Integer getUid(); - - void setUid(Integer uid); - -} diff --git a/src/main/java/com/juick/server/api/rss/extension/JuickModuleGenerator.java b/src/main/java/com/juick/server/api/rss/extension/JuickModuleGenerator.java deleted file mode 100644 index fc8586ea..00000000 --- a/src/main/java/com/juick/server/api/rss/extension/JuickModuleGenerator.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.rss.extension; - -import com.rometools.rome.feed.module.Module; -import com.rometools.rome.io.ModuleGenerator; -import org.jdom2.Element; -import org.jdom2.Namespace; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * Created by vt on 13/12/2016. - */ -public class JuickModuleGenerator implements ModuleGenerator { - - private static final Namespace JUICK_NS = Namespace.getNamespace("juick", JuickModule.URI); - - @Override - public String getNamespaceUri() { - return JuickModule.URI; - } - - private static final Set<Namespace> NAMESPACES; - - static { - NAMESPACES = Set.of(JUICK_NS); - } - - @Override - public Set<Namespace> getNamespaces() { - return NAMESPACES; - } - - @Override - public void generate(Module module, Element element) { - // this is not necessary, it is done to avoid the namespace definition in every item. - Element root = element; - while (root.getParent()!=null && root.getParent() instanceof Element) { - root = element.getParentElement(); - } - root.addNamespaceDeclaration(JUICK_NS); - - JuickModule juickModule = (JuickModule) module; - if (juickModule.getUid() > 0) { - Element user = new Element("user", JUICK_NS); - user.setAttribute("uid", String.valueOf(juickModule.getUid()), JUICK_NS); - element.addContent(user); - } - } -} diff --git a/src/main/java/com/juick/server/api/rss/extension/JuickModuleImpl.java b/src/main/java/com/juick/server/api/rss/extension/JuickModuleImpl.java deleted file mode 100644 index a32f2794..00000000 --- a/src/main/java/com/juick/server/api/rss/extension/JuickModuleImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.rss.extension; - -import com.rometools.rome.feed.CopyFrom; -import com.rometools.rome.feed.module.ModuleImpl; - -/** - * Created by vitalyster on 13.12.2016. - */ -public class JuickModuleImpl extends ModuleImpl implements JuickModule { - - private Integer uid; - - public JuickModuleImpl() { - super(JuickModule.class, JuickModule.URI); - } - - @Override - public Integer getUid() { - return uid; - } - - @Override - public void setUid(Integer uid) { - this.uid = uid; - } - - @Override - public Class<? extends CopyFrom> getInterface() { - return JuickModule.class; - } - - @Override - public void copyFrom(CopyFrom obj) { - JuickModule juickModule = (JuickModule) obj; - setUid(juickModule.getUid()); - } -} diff --git a/src/main/java/com/juick/server/api/rss/extension/JuickModuleParser.java b/src/main/java/com/juick/server/api/rss/extension/JuickModuleParser.java deleted file mode 100644 index 445815a6..00000000 --- a/src/main/java/com/juick/server/api/rss/extension/JuickModuleParser.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.rss.extension; - -import com.rometools.rome.feed.module.Module; -import com.rometools.rome.io.ModuleParser; -import org.apache.commons.lang3.math.NumberUtils; -import org.jdom2.Element; - -import java.util.Locale; - -/** - * Created by vitalyster on 13.12.2016. - */ -public class JuickModuleParser implements ModuleParser { - @Override - public String getNamespaceUri() { - return JuickModule.URI; - } - - @Override - public Module parse(Element element, Locale locale) { - JuickModuleImpl juickModule = new JuickModuleImpl(); - juickModule.setUid(NumberUtils.toInt(element.getAttributeValue("uid", JuickModule.URI), 0)); - return juickModule; - } -} diff --git a/src/main/java/com/juick/server/api/webfinger/Resource.java b/src/main/java/com/juick/server/api/webfinger/Resource.java deleted file mode 100644 index 8fb808b1..00000000 --- a/src/main/java/com/juick/server/api/webfinger/Resource.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.webfinger; - -import com.juick.model.User; -import com.juick.server.api.webfinger.model.Account; -import com.juick.server.api.webfinger.model.Link; -import com.juick.server.util.HttpNotFoundException; -import com.juick.service.UserService; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.util.UriComponentsBuilder; -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 - private UserService userService; - @Value("${web_domain:localhost}") - private String domain; - @Value("${ap_base_uri:http://localhost:8080/}") - private String baseUri; - - @GetMapping(value = "/.well-known/webfinger", produces = "application/jrd+json;charset=utf-8") - public Account getWebResource(@RequestParam String resource) { - if (resource.startsWith("acct:")) { - Jid account = Jid.of(resource.substring(5)); - if (account.getDomain().equals(domain)) { - User user = userService.getUserByName(account.getLocal()); - if (!user.isAnonymous()) { - UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseUri); - builder.path(String.format("/u/%s", user.getName())); - Link blog = new Link(); - blog.setRel("self"); - blog.setType(ACTIVITY_MEDIA_TYPE); - blog.setHref(builder.toUriString()); - Account result = new Account(); - result.setSubject(resource); - result.setLinks(Collections.singletonList(blog)); - return result; - } - } - } - throw new HttpNotFoundException(); - } -} diff --git a/src/main/java/com/juick/server/api/webfinger/model/Account.java b/src/main/java/com/juick/server/api/webfinger/model/Account.java deleted file mode 100644 index 8683af5c..00000000 --- a/src/main/java/com/juick/server/api/webfinger/model/Account.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.webfinger.model; - -import java.util.List; - -public class Account { - private String subject; - private List<Link> links; - - public String getSubject() { - return subject; - } - - public void setSubject(String subject) { - this.subject = subject; - } - - public List<Link> getLinks() { - return links; - } - - public void setLinks(List<Link> links) { - this.links = links; - } -} diff --git a/src/main/java/com/juick/server/api/webfinger/model/Link.java b/src/main/java/com/juick/server/api/webfinger/model/Link.java deleted file mode 100644 index 59d0ad80..00000000 --- a/src/main/java/com/juick/server/api/webfinger/model/Link.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.webfinger.model; - -public class Link { - private String rel; - private String type; - private String href; - - public String getRel() { - return rel; - } - - public void setRel(String rel) { - this.rel = rel; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getHref() { - return href; - } - - public void setHref(String href) { - this.href = href; - } -} diff --git a/src/main/java/com/juick/server/api/webhooks/TelegramWebhook.java b/src/main/java/com/juick/server/api/webhooks/TelegramWebhook.java deleted file mode 100644 index 1a7c73bb..00000000 --- a/src/main/java/com/juick/server/api/webhooks/TelegramWebhook.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.webhooks; - -import com.juick.server.TelegramBotManager; -import com.pengrad.telegrambot.BotUtils; -import com.pengrad.telegrambot.model.Update; -import org.apache.commons.io.IOUtils; -import org.apache.commons.text.StringEscapeUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import springfox.documentation.annotations.ApiIgnore; - -import javax.inject.Inject; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - -/** - * Created by vt on 24/11/2016. - */ -@ApiIgnore -@RestController -@ConditionalOnProperty({"telegram_token"}) -public class TelegramWebhook { - private static final Logger logger = LoggerFactory.getLogger("Telegram"); - @Inject - private TelegramBotManager telegramBotManager; - - @RequestMapping(value = "/api/tlgmbtwbhk", method = RequestMethod.POST) - @ResponseStatus(value = HttpStatus.OK) - public void processUpdate(InputStream body) throws Exception { - String data = IOUtils.toString(body, StandardCharsets.UTF_8); - logger.debug("Telegram update: {}", StringEscapeUtils.unescapeJava(data)); - Update update = BotUtils.parseUpdate(data); - telegramBotManager.processUpdate(update); - } -} diff --git a/src/main/java/com/juick/server/api/xnodeinfo2/Info.java b/src/main/java/com/juick/server/api/xnodeinfo2/Info.java deleted file mode 100644 index fe12ee30..00000000 --- a/src/main/java/com/juick/server/api/xnodeinfo2/Info.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.xnodeinfo2; - -import com.cliqset.xrd.Link; -import com.cliqset.xrd.XRD; -import com.fasterxml.jackson.annotation.JsonView; -import com.juick.server.api.xnodeinfo2.model.*; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.MediaType; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.util.UriComponentsBuilder; - -import javax.inject.Inject; -import java.net.URI; -import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -@RestController -public class Info { - @Value("${ap_base_uri:http://localhost:8080/}") - private String baseUri; - @Inject - private JdbcTemplate jdbcTemplate; - - private NodeInfo getCurrentNodeInfo(String version) { - NodeInfo nodeInfo = new NodeInfo(); - nodeInfo.setVersion(version); - Server server = new Server(); - server.setBaseUrl(baseUri); - server.setName("Juick"); - server.setSoftware("Juick"); - server.setVersion("2.x"); - nodeInfo.setServer(server); - nodeInfo.setProtocols(Arrays.asList("xmpp", "activitypub", "smtp")); - Map<String, String> metadata = new HashMap<>(); - metadata.put("email", "support@juick.com"); - nodeInfo.setMetadata(metadata); - ServiceInfo serviceInfo = new ServiceInfo(); - serviceInfo.setInbound(Arrays.asList("jabber", "mastodon", "email", "telegram")); - serviceInfo.setOutbound(Arrays.asList("jabber", "mastodon", "telegram", "twitter", "email", "rss")); - nodeInfo.setServices(serviceInfo); - UserStats userStats = new UserStats(); - userStats.setTotal(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM users WHERE banned=0", Integer.class)); - userStats.setActiveMonth(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM users WHERE banned=0 AND last_seen > ?", - Integer.class, ZonedDateTime.now().minus(1, ChronoUnit.MONTHS).toLocalDateTime())); - userStats.setActiveHalfyear(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM users WHERE banned=0 AND last_seen > ?", - Integer.class, ZonedDateTime.now().minus(6, ChronoUnit.MONTHS).toLocalDateTime())); - Usage usage = new Usage(); - usage.setUsers(userStats); - usage.setLocalPosts(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM messages", - Integer.class)); - usage.setLocalComments(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM replies", - Integer.class)); - nodeInfo.setUsage(usage); - return nodeInfo; - } - - @GetMapping(value = "/.well-known/x-nodeinfo2", produces = MediaType.APPLICATION_JSON_VALUE) - @JsonView(NodeInfo.XNodeInfoView.class) - public NodeInfo showXNodeInfo() { - return getCurrentNodeInfo("1.0"); - } - - @GetMapping(value = "/.well-known/nodeinfo", produces = MediaType.APPLICATION_JSON_VALUE) - public XRD getNodeInfoLinks() { - Link nodeinfo = new Link(); - nodeinfo.setRel(URI.create("http://nodeinfo.diaspora.software/ns/schema/2.0")); - UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUri); - uriComponentsBuilder.replacePath("/api/nodeinfo/2.0"); - nodeinfo.setHref(uriComponentsBuilder.build().toUri()); - XRD xrd = new XRD(); - xrd.setLinks(Collections.singletonList(nodeinfo)); - return xrd; - } - - @GetMapping(value = "/api/nodeinfo/2.0", produces = MediaType.APPLICATION_JSON_VALUE) - @JsonView(NodeInfo.NodeInfoView.class) - public NodeInfo showNodeInfo() { - return getCurrentNodeInfo("2.0"); - } -} diff --git a/src/main/java/com/juick/server/api/xnodeinfo2/model/NodeInfo.java b/src/main/java/com/juick/server/api/xnodeinfo2/model/NodeInfo.java deleted file mode 100644 index 33fb9e95..00000000 --- a/src/main/java/com/juick/server/api/xnodeinfo2/model/NodeInfo.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.xnodeinfo2.model; - -import com.fasterxml.jackson.annotation.JsonView; - -import java.util.List; -import java.util.Map; - -public class NodeInfo { - - private String version; - - private Server server; - - private List<String> protocols; - - private ServiceInfo services; - - private Map<String, String> metadata; - - @JsonView({XNodeInfoView.class, NodeInfoView.class}) - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - @JsonView(XNodeInfoView.class) - public Server getServer() { - return server; - } - @JsonView(NodeInfoView.class) - public Server getSoftware() { - return server; - } - - public void setServer(Server server) { - this.server = server; - } - - @JsonView({XNodeInfoView.class, NodeInfoView.class}) - public List<String> getProtocols() { - return protocols; - } - - public void setProtocols(List<String> protocols) { - this.protocols = protocols; - } - - @JsonView({XNodeInfoView.class, NodeInfoView.class}) - public ServiceInfo getServices() { - return services; - } - - public void setServices(ServiceInfo services) { - this.services = services; - } - - @JsonView({XNodeInfoView.class, NodeInfoView.class}) - public boolean getOpenRegistrations() { - return true; - } - - private Usage usage; - - @JsonView({XNodeInfoView.class, NodeInfoView.class}) - public Usage getUsage() { - return usage; - } - - public void setUsage(Usage usage) { - this.usage = usage; - } - - @JsonView(NodeInfoView.class) - public Map<String, String> getMetadata() { - return metadata; - } - - public void setMetadata(Map<String, String> metadata) { - this.metadata = metadata; - } - - public interface NodeInfoView {} - public interface XNodeInfoView {} -} diff --git a/src/main/java/com/juick/server/api/xnodeinfo2/model/Server.java b/src/main/java/com/juick/server/api/xnodeinfo2/model/Server.java deleted file mode 100644 index 77c5d54a..00000000 --- a/src/main/java/com/juick/server/api/xnodeinfo2/model/Server.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.xnodeinfo2.model; - -import com.fasterxml.jackson.annotation.JsonView; - -public class Server { - private String baseUrl; - private String name; - private String software; - private String version; - - @JsonView(NodeInfo.XNodeInfoView.class) - public String getBaseUrl() { - return baseUrl; - } - - public void setBaseUrl(String baseUrl) { - this.baseUrl = baseUrl; - } - - @JsonView({NodeInfo.NodeInfoView.class, NodeInfo.XNodeInfoView.class}) - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @JsonView(NodeInfo.XNodeInfoView.class) - public String getSoftware() { - return software; - } - - public void setSoftware(String software) { - this.software = software; - } - - @JsonView({NodeInfo.NodeInfoView.class, NodeInfo.XNodeInfoView.class}) - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } -} diff --git a/src/main/java/com/juick/server/api/xnodeinfo2/model/ServiceInfo.java b/src/main/java/com/juick/server/api/xnodeinfo2/model/ServiceInfo.java deleted file mode 100644 index 9f8bdec3..00000000 --- a/src/main/java/com/juick/server/api/xnodeinfo2/model/ServiceInfo.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.xnodeinfo2.model; - -import com.fasterxml.jackson.annotation.JsonView; - -import java.util.List; - -@JsonView({NodeInfo.NodeInfoView.class, NodeInfo.XNodeInfoView.class}) -public class ServiceInfo { - private List<String> inbound; - private List<String> outbound; - - public List<String> getInbound() { - return inbound; - } - - public void setInbound(List<String> inbound) { - this.inbound = inbound; - } - - public List<String> getOutbound() { - return outbound; - } - - public void setOutbound(List<String> outbound) { - this.outbound = outbound; - } -} diff --git a/src/main/java/com/juick/server/api/xnodeinfo2/model/Usage.java b/src/main/java/com/juick/server/api/xnodeinfo2/model/Usage.java deleted file mode 100644 index 7bd4337c..00000000 --- a/src/main/java/com/juick/server/api/xnodeinfo2/model/Usage.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.xnodeinfo2.model; - -import com.fasterxml.jackson.annotation.JsonView; - -@JsonView({NodeInfo.NodeInfoView.class, NodeInfo.XNodeInfoView.class}) -public class Usage { - private UserStats users; - private int localPosts; - private int localComments; - - public UserStats getUsers() { - return users; - } - - public void setUsers(UserStats users) { - this.users = users; - } - - public int getLocalPosts() { - return localPosts; - } - - public void setLocalPosts(int localPosts) { - this.localPosts = localPosts; - } - - public int getLocalComments() { - return localComments; - } - - public void setLocalComments(int localComments) { - this.localComments = localComments; - } -} diff --git a/src/main/java/com/juick/server/api/xnodeinfo2/model/UserStats.java b/src/main/java/com/juick/server/api/xnodeinfo2/model/UserStats.java deleted file mode 100644 index f8388b5f..00000000 --- a/src/main/java/com/juick/server/api/xnodeinfo2/model/UserStats.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.juick.server.api.xnodeinfo2.model; - -import com.fasterxml.jackson.annotation.JsonView; - -@JsonView({NodeInfo.NodeInfoView.class, NodeInfo.XNodeInfoView.class}) -public class UserStats { - private int total; - private int activeHalfyear; - private int activeMonth; - - public int getTotal() { - return total; - } - - public void setTotal(int total) { - this.total = total; - } - - public int getActiveHalfyear() { - return activeHalfyear; - } - - public void setActiveHalfyear(int activeHalfyear) { - this.activeHalfyear = activeHalfyear; - } - - public int getActiveMonth() { - return activeMonth; - } - - public void setActiveMonth(int activeMonth) { - this.activeMonth = activeMonth; - } -} |