From ae76024011a8442ae7eab953e0b97e9fe2c7c201 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Tue, 25 Sep 2018 11:53:37 +0300 Subject: reorganize layout --- juick-common/build.gradle | 5 +- .../src/main/java/com/juick/facebook/User.java | 125 ----- .../main/java/com/juick/model/AnonymousUser.java | 129 +++++ .../java/com/juick/model/ApplicationStatus.java | 52 ++ .../src/main/java/com/juick/model/Auth.java | 39 ++ .../main/java/com/juick/model/CommandResult.java | 35 ++ .../src/main/java/com/juick/model/NotifyOpts.java | 51 ++ .../src/main/java/com/juick/model/PrivacyOpts.java | 46 ++ .../main/java/com/juick/model/PrivateChats.java | 39 ++ .../main/java/com/juick/model/ResponseReply.java | 89 ++++ .../src/main/java/com/juick/model/TagStats.java | 46 ++ .../src/main/java/com/juick/model/UserInfo.java | 60 +++ .../main/java/com/juick/model/facebook/User.java | 125 +++++ .../main/java/com/juick/model/twitter/User.java | 38 ++ .../src/main/java/com/juick/model/vk/Token.java | 56 +++ .../src/main/java/com/juick/model/vk/User.java | 65 +++ .../java/com/juick/model/vk/UsersResponse.java | 38 ++ .../java/com/juick/server/CommandsManager.java | 532 --------------------- .../juick/server/component/DisconnectedEvent.java | 14 - .../java/com/juick/server/component/LikeEvent.java | 36 -- .../com/juick/server/component/MessageEvent.java | 31 -- .../juick/server/component/MessageReadEvent.java | 28 -- .../java/com/juick/server/component/PingEvent.java | 21 - .../com/juick/server/component/SubscribeEvent.java | 27 -- .../juick/server/component/UserUpdatedEvent.java | 23 - .../server/configuration/BaseWebConfiguration.java | 63 --- .../server/configuration/StorageConfiguration.java | 20 - .../com/juick/server/helpers/AnonymousUser.java | 129 ----- .../juick/server/helpers/ApplicationStatus.java | 52 -- .../main/java/com/juick/server/helpers/Auth.java | 39 -- .../com/juick/server/helpers/CommandResult.java | 36 -- .../java/com/juick/server/helpers/NotifyOpts.java | 51 -- .../java/com/juick/server/helpers/PrivacyOpts.java | 46 -- .../com/juick/server/helpers/PrivateChats.java | 39 -- .../com/juick/server/helpers/ResponseReply.java | 89 ---- .../java/com/juick/server/helpers/TagStats.java | 46 -- .../java/com/juick/server/helpers/UserInfo.java | 60 --- .../server/helpers/annotation/UserCommand.java | 50 -- .../juick/server/util/HttpBadRequestException.java | 32 -- .../juick/server/util/HttpForbiddenException.java | 33 -- .../juick/server/util/HttpNotFoundException.java | 32 -- .../main/java/com/juick/server/util/HttpUtils.java | 110 ----- .../java/com/juick/server/util/ImageUtils.java | 175 ------- .../main/java/com/juick/server/util/TagUtils.java | 42 -- .../main/java/com/juick/server/util/UserUtils.java | 55 --- .../main/java/com/juick/server/util/WebUtils.java | 62 --- .../java/com/juick/service/CrosspostService.java | 2 +- .../java/com/juick/service/ImagesServiceImpl.java | 82 ---- .../java/com/juick/service/MessagesService.java | 3 +- .../com/juick/service/SubscriptionService.java | 2 +- .../main/java/com/juick/service/TagService.java | 2 +- .../main/java/com/juick/service/UserService.java | 4 +- .../juick/service/component/DisconnectedEvent.java | 14 + .../com/juick/service/component/LikeEvent.java | 36 ++ .../com/juick/service/component/MessageEvent.java | 31 ++ .../juick/service/component/MessageReadEvent.java | 28 ++ .../com/juick/service/component/PingEvent.java | 21 + .../juick/service/component/SubscribeEvent.java | 27 ++ .../juick/service/component/UserUpdatedEvent.java | 23 + .../security/HashParamAuthenticationFilter.java | 103 ---- .../service/security/JuickUserDetailsService.java | 53 -- .../service/security/NullUserDetailsService.java | 33 -- .../CookieSimpleHashRememberMeServices.java | 130 ----- .../RequestParamHashRememberMeServices.java | 88 ---- .../juick/service/security/entities/JuickUser.java | 93 ---- .../src/main/java/com/juick/twitter/User.java | 38 -- juick-common/src/main/java/com/juick/vk/Token.java | 56 --- juick-common/src/main/java/com/juick/vk/User.java | 65 --- .../src/main/java/com/juick/vk/UsersResponse.java | 38 -- juick-notifications/build.gradle | 5 +- .../java/com/juick/components/Notifications.java | 2 +- .../service/JuickServerReconnectManager.java | 2 +- juick-server/build.gradle | 3 + .../java/com/juick/server/CommandsManager.java | 531 ++++++++++++++++++++ .../main/java/com/juick/server/EmailManager.java | 3 +- .../java/com/juick/server/MessengerManager.java | 5 +- .../com/juick/server/NotificationListener.java | 2 +- .../main/java/com/juick/server/ServerManager.java | 2 +- .../java/com/juick/server/TelegramBotManager.java | 8 +- .../main/java/com/juick/server/TwitterManager.java | 5 +- .../java/com/juick/server/WebsocketManager.java | 5 +- .../main/java/com/juick/server/XMPPConnection.java | 8 +- .../java/com/juick/server/api/ApiSocialLogin.java | 6 +- .../main/java/com/juick/server/api/Messages.java | 5 +- .../java/com/juick/server/api/Notifications.java | 2 +- .../src/main/java/com/juick/server/api/PM.java | 6 +- .../src/main/java/com/juick/server/api/Post.java | 2 +- .../src/main/java/com/juick/server/api/Tags.java | 2 +- .../src/main/java/com/juick/server/api/Users.java | 4 +- .../java/com/juick/server/api/rss/RepliesView.java | 2 +- .../server/configuration/BaseWebConfiguration.java | 63 +++ .../server/configuration/StorageConfiguration.java | 20 + .../server/configuration/WwwAppConfiguration.java | 2 - .../server/helpers/annotation/UserCommand.java | 50 ++ .../juick/server/util/HttpBadRequestException.java | 32 ++ .../juick/server/util/HttpForbiddenException.java | 33 ++ .../juick/server/util/HttpNotFoundException.java | 32 ++ .../main/java/com/juick/server/util/HttpUtils.java | 110 +++++ .../java/com/juick/server/util/ImageUtils.java | 175 +++++++ .../main/java/com/juick/server/util/TagUtils.java | 42 ++ .../main/java/com/juick/server/util/UserUtils.java | 55 +++ .../main/java/com/juick/server/util/WebUtils.java | 62 +++ .../juick/server/www/controllers/NewMessage.java | 4 +- .../com/juick/server/www/controllers/Settings.java | 6 +- .../juick/server/www/controllers/SocialLogin.java | 10 +- .../com/juick/service/CrosspostServiceImpl.java | 2 +- .../java/com/juick/service/ImagesServiceImpl.java | 82 ++++ .../com/juick/service/MessagesServiceImpl.java | 5 +- .../com/juick/service/SubscriptionServiceImpl.java | 2 +- .../java/com/juick/service/TagServiceImpl.java | 2 +- .../java/com/juick/service/UserServiceImpl.java | 6 +- .../security/HashParamAuthenticationFilter.java | 103 ++++ .../service/security/JuickUserDetailsService.java | 53 ++ .../service/security/NullUserDetailsService.java | 33 ++ .../CookieSimpleHashRememberMeServices.java | 130 +++++ .../RequestParamHashRememberMeServices.java | 88 ++++ .../juick/service/security/entities/JuickUser.java | 93 ++++ .../java/com/juick/server/tests/ServerTests.java | 8 +- 118 files changed, 2940 insertions(+), 2956 deletions(-) delete mode 100644 juick-common/src/main/java/com/juick/facebook/User.java create mode 100644 juick-common/src/main/java/com/juick/model/AnonymousUser.java create mode 100644 juick-common/src/main/java/com/juick/model/ApplicationStatus.java create mode 100644 juick-common/src/main/java/com/juick/model/Auth.java create mode 100644 juick-common/src/main/java/com/juick/model/CommandResult.java create mode 100644 juick-common/src/main/java/com/juick/model/NotifyOpts.java create mode 100644 juick-common/src/main/java/com/juick/model/PrivacyOpts.java create mode 100644 juick-common/src/main/java/com/juick/model/PrivateChats.java create mode 100644 juick-common/src/main/java/com/juick/model/ResponseReply.java create mode 100644 juick-common/src/main/java/com/juick/model/TagStats.java create mode 100644 juick-common/src/main/java/com/juick/model/UserInfo.java create mode 100644 juick-common/src/main/java/com/juick/model/facebook/User.java create mode 100644 juick-common/src/main/java/com/juick/model/twitter/User.java create mode 100644 juick-common/src/main/java/com/juick/model/vk/Token.java create mode 100644 juick-common/src/main/java/com/juick/model/vk/User.java create mode 100644 juick-common/src/main/java/com/juick/model/vk/UsersResponse.java delete mode 100644 juick-common/src/main/java/com/juick/server/CommandsManager.java delete mode 100644 juick-common/src/main/java/com/juick/server/component/DisconnectedEvent.java delete mode 100644 juick-common/src/main/java/com/juick/server/component/LikeEvent.java delete mode 100644 juick-common/src/main/java/com/juick/server/component/MessageEvent.java delete mode 100644 juick-common/src/main/java/com/juick/server/component/MessageReadEvent.java delete mode 100644 juick-common/src/main/java/com/juick/server/component/PingEvent.java delete mode 100644 juick-common/src/main/java/com/juick/server/component/SubscribeEvent.java delete mode 100644 juick-common/src/main/java/com/juick/server/component/UserUpdatedEvent.java delete mode 100644 juick-common/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java delete mode 100644 juick-common/src/main/java/com/juick/server/configuration/StorageConfiguration.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/AnonymousUser.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/ApplicationStatus.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/Auth.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/CommandResult.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/NotifyOpts.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/PrivacyOpts.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/PrivateChats.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/ResponseReply.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/TagStats.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/UserInfo.java delete mode 100644 juick-common/src/main/java/com/juick/server/helpers/annotation/UserCommand.java delete mode 100644 juick-common/src/main/java/com/juick/server/util/HttpBadRequestException.java delete mode 100644 juick-common/src/main/java/com/juick/server/util/HttpForbiddenException.java delete mode 100644 juick-common/src/main/java/com/juick/server/util/HttpNotFoundException.java delete mode 100644 juick-common/src/main/java/com/juick/server/util/HttpUtils.java delete mode 100644 juick-common/src/main/java/com/juick/server/util/ImageUtils.java delete mode 100644 juick-common/src/main/java/com/juick/server/util/TagUtils.java delete mode 100644 juick-common/src/main/java/com/juick/server/util/UserUtils.java delete mode 100644 juick-common/src/main/java/com/juick/server/util/WebUtils.java delete mode 100644 juick-common/src/main/java/com/juick/service/ImagesServiceImpl.java create mode 100644 juick-common/src/main/java/com/juick/service/component/DisconnectedEvent.java create mode 100644 juick-common/src/main/java/com/juick/service/component/LikeEvent.java create mode 100644 juick-common/src/main/java/com/juick/service/component/MessageEvent.java create mode 100644 juick-common/src/main/java/com/juick/service/component/MessageReadEvent.java create mode 100644 juick-common/src/main/java/com/juick/service/component/PingEvent.java create mode 100644 juick-common/src/main/java/com/juick/service/component/SubscribeEvent.java create mode 100644 juick-common/src/main/java/com/juick/service/component/UserUpdatedEvent.java delete mode 100644 juick-common/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java delete mode 100644 juick-common/src/main/java/com/juick/service/security/JuickUserDetailsService.java delete mode 100644 juick-common/src/main/java/com/juick/service/security/NullUserDetailsService.java delete mode 100644 juick-common/src/main/java/com/juick/service/security/deprecated/CookieSimpleHashRememberMeServices.java delete mode 100644 juick-common/src/main/java/com/juick/service/security/deprecated/RequestParamHashRememberMeServices.java delete mode 100644 juick-common/src/main/java/com/juick/service/security/entities/JuickUser.java delete mode 100644 juick-common/src/main/java/com/juick/twitter/User.java delete mode 100644 juick-common/src/main/java/com/juick/vk/Token.java delete mode 100644 juick-common/src/main/java/com/juick/vk/User.java delete mode 100644 juick-common/src/main/java/com/juick/vk/UsersResponse.java create mode 100644 juick-server/src/main/java/com/juick/server/CommandsManager.java create mode 100644 juick-server/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java create mode 100644 juick-server/src/main/java/com/juick/server/configuration/StorageConfiguration.java create mode 100644 juick-server/src/main/java/com/juick/server/helpers/annotation/UserCommand.java create mode 100644 juick-server/src/main/java/com/juick/server/util/HttpBadRequestException.java create mode 100644 juick-server/src/main/java/com/juick/server/util/HttpForbiddenException.java create mode 100644 juick-server/src/main/java/com/juick/server/util/HttpNotFoundException.java create mode 100644 juick-server/src/main/java/com/juick/server/util/HttpUtils.java create mode 100644 juick-server/src/main/java/com/juick/server/util/ImageUtils.java create mode 100644 juick-server/src/main/java/com/juick/server/util/TagUtils.java create mode 100644 juick-server/src/main/java/com/juick/server/util/UserUtils.java create mode 100644 juick-server/src/main/java/com/juick/server/util/WebUtils.java create mode 100644 juick-server/src/main/java/com/juick/service/ImagesServiceImpl.java create mode 100644 juick-server/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java create mode 100644 juick-server/src/main/java/com/juick/service/security/JuickUserDetailsService.java create mode 100644 juick-server/src/main/java/com/juick/service/security/NullUserDetailsService.java create mode 100644 juick-server/src/main/java/com/juick/service/security/deprecated/CookieSimpleHashRememberMeServices.java create mode 100644 juick-server/src/main/java/com/juick/service/security/deprecated/RequestParamHashRememberMeServices.java create mode 100644 juick-server/src/main/java/com/juick/service/security/entities/JuickUser.java diff --git a/juick-common/build.gradle b/juick-common/build.gradle index e7ee0720..6c70c580 100644 --- a/juick-common/build.gradle +++ b/juick-common/build.gradle @@ -1,10 +1,7 @@ apply plugin: 'java' dependencies { - compile("org.springframework.boot:spring-boot-starter-mail") - compile("org.springframework.boot:spring-boot-starter-security") - compile("org.springframework.boot:spring-boot-starter-web") - compile("org.springframework.boot:spring-boot-starter-websocket") + compile("org.springframework.boot:spring-boot-starter-json") compile "org.apache.commons:commons-lang3:3.8.1" compile "org.apache.commons:commons-collections4:4.2" compile 'org.apache.commons:commons-text:1.4' diff --git a/juick-common/src/main/java/com/juick/facebook/User.java b/juick-common/src/main/java/com/juick/facebook/User.java deleted file mode 100644 index ebd427b4..00000000 --- a/juick-common/src/main/java/com/juick/facebook/User.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.facebook; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Created by vitalyster on 28.11.2016. - */ -@JsonIgnoreProperties(ignoreUnknown = true) -public class User { - private String id; - private String name; - private String link; - private boolean verified; - private String firstName; - private String lastName; - private String gender; - private String locale; - private String timezone; - private String updatedTime; - private String email; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLink() { - return link; - } - - public void setLink(String link) { - this.link = link; - } - - public boolean getVerified() { - return verified; - } - - public void setVerified(boolean verified) { - this.verified = verified; - } - - @JsonProperty("first_name") - public String getFirstName() { - return firstName; - } - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getGender() { - return gender; - } - - public void setGender(String gender) { - this.gender = gender; - } - - @JsonProperty("last_name") - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getLocale() { - return locale; - } - - public void setLocale(String locale) { - this.locale = locale; - } - - public String getTimezone() { - return timezone; - } - - public void setTimezone(String timezone) { - this.timezone = timezone; - } - - @JsonProperty("updated_time") - public String getUpdatedTime() { - return updatedTime; - } - - public void setUpdatedTime(String updatedTime) { - this.updatedTime = updatedTime; - } - - public String getEmail() { - return email; - } -} diff --git a/juick-common/src/main/java/com/juick/model/AnonymousUser.java b/juick-common/src/main/java/com/juick/model/AnonymousUser.java new file mode 100644 index 00000000..f4511194 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/AnonymousUser.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model; + +import com.juick.User; + +/** + * Created by aalexeev on 12/11/16. + */ +public final class AnonymousUser extends User { + public static final AnonymousUser INSTANCE = new AnonymousUser(); + + private AnonymousUser() { + super.setUid(getUid()); + super.setName(getName()); + super.setAvatar(getAvatar()); + super.setFullName(getFullName()); + super.setMessagesCount(getMessagesCount()); + super.setAuthHash(getAuthHash()); + super.setBanned(isBanned()); + super.setCredentials(getCredentials()); + } + + @Override + public boolean equals(Object obj) { + return obj == this || obj instanceof AnonymousUser; + } + + @Override + public int getUid() { + return 0; + } + + @Override + public String getName() { + return "Anonymous"; + } + + @Override + public String getFullName() { + return getName(); + } + + @Override + public String getAuthHash() { + return null; + } + + @Override + public Integer getUnreadCount() { + return 0; + } + + @Override + public boolean isBanned() { + return false; + } + + @Override + public Object getAvatar() { + return null; + } + + @Override + public String getCredentials() { + return null; + } + + @Override + public int getMessagesCount() { + return 0; + } + + @Override + public boolean isAnonymous() { + return true; + } + + @Override + public void setUid(int uid) { + } + + @Override + public void setName(String name) { + } + + @Override + public void setFullName(String fullName) { + } + + @Override + public void setAuthHash(String authHash) { + } + + @Override + public void setUnreadCount(Integer count) { + } + + @Override + public void setBanned(boolean banned) { + } + + @Override + public void setAvatar(Object avatar) { + } + + @Override + public void setCredentials(String credentials) { + } + + @Override + public void setMessagesCount(int messagesCount) { + } +} diff --git a/juick-common/src/main/java/com/juick/model/ApplicationStatus.java b/juick-common/src/main/java/com/juick/model/ApplicationStatus.java new file mode 100644 index 00000000..b18e12bf --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/ApplicationStatus.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +/** + * Created by vt on 03/09/16. + */ +public class ApplicationStatus { + private boolean connected; + private boolean crosspostEnabled; + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("connected", connected) + .append("crosspostEnabled", crosspostEnabled) + .toString(); + } + + public boolean isConnected() { + return connected; + } + + public void setConnected(boolean connected) { + this.connected = connected; + } + + public boolean isCrosspostEnabled() { + return crosspostEnabled; + } + + public void setCrosspostEnabled(boolean crosspostEnabled) { + this.crosspostEnabled = crosspostEnabled; + } +} diff --git a/juick-common/src/main/java/com/juick/model/Auth.java b/juick-common/src/main/java/com/juick/model/Auth.java new file mode 100644 index 00000000..66125567 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/Auth.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model; + +/** + * Created by vt on 09/02/16. + */ +public class Auth { + private String account; + private String authCode; + + public Auth(String account, String authCode) { + this.account = account; + this.authCode = authCode; + } + + public String getAccount() { + return account; + } + + public String getAuthCode() { + return authCode; + } +} \ No newline at end of file diff --git a/juick-common/src/main/java/com/juick/model/CommandResult.java b/juick-common/src/main/java/com/juick/model/CommandResult.java new file mode 100644 index 00000000..c310756c --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/CommandResult.java @@ -0,0 +1,35 @@ +package com.juick.model; + +import com.juick.Message; + +import java.util.Optional; + +public class CommandResult { + private String text; + private String markdown; + private Message newMessage; + + public String getText() { + return text; + } + public String getMarkdown() { + return markdown; + } + + public Optional getNewMessage() { + return Optional.ofNullable(newMessage); + } + public static CommandResult build(Message newMessage, String text, String markdown) { + CommandResult result = new CommandResult(); + result.newMessage = newMessage; + result.text = text; + result.markdown = markdown; + return result; + } + public static CommandResult fromString(String text) { + CommandResult result = new CommandResult(); + result.text = text; + return result; + } + +} diff --git a/juick-common/src/main/java/com/juick/model/NotifyOpts.java b/juick-common/src/main/java/com/juick/model/NotifyOpts.java new file mode 100644 index 00000000..1c0e0aac --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/NotifyOpts.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model; + +/** + * Created by vt on 03/09/16. + */ +public class NotifyOpts { + private boolean repliesEnabled; + private boolean subscriptionsEnabled; + private boolean recommendationsEnabled; + + public boolean isRepliesEnabled() { + return repliesEnabled; + } + + public void setRepliesEnabled(boolean repliesEnabled) { + this.repliesEnabled = repliesEnabled; + } + + public boolean isSubscriptionsEnabled() { + return subscriptionsEnabled; + } + + public void setSubscriptionsEnabled(boolean subscriptionsEnabled) { + this.subscriptionsEnabled = subscriptionsEnabled; + } + + public boolean isRecommendationsEnabled() { + return recommendationsEnabled; + } + + public void setRecommendationsEnabled(boolean recommendationsEnabled) { + this.recommendationsEnabled = recommendationsEnabled; + } +} diff --git a/juick-common/src/main/java/com/juick/model/PrivacyOpts.java b/juick-common/src/main/java/com/juick/model/PrivacyOpts.java new file mode 100644 index 00000000..52cbe588 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/PrivacyOpts.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model; + +/** + * Created by vt on 16/01/16. + */ +public class PrivacyOpts { + private int uid; + private int privacy; + + public PrivacyOpts() { + + } + + public int getUid() { + return uid; + } + + public void setUid(int uid) { + this.uid = uid; + } + + public int getPrivacy() { + return privacy; + } + + public void setPrivacy(int privacy) { + this.privacy = privacy; + } +} diff --git a/juick-common/src/main/java/com/juick/model/PrivateChats.java b/juick-common/src/main/java/com/juick/model/PrivateChats.java new file mode 100644 index 00000000..ad04e649 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/PrivateChats.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.juick.User; + +import java.util.List; + +/** + * Created by vt on 24/11/2016. + */ +public class PrivateChats { + private List users; + + @JsonProperty("pms") + public List getUsers() { + return users; + } + + public void setUsers(List users) { + this.users = users; + } +} diff --git a/juick-common/src/main/java/com/juick/model/ResponseReply.java b/juick-common/src/main/java/com/juick/model/ResponseReply.java new file mode 100644 index 00000000..acc5db71 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/ResponseReply.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model; + +import java.util.Date; + +/** + * Created by vitalyster on 13.12.2016. + */ +public class ResponseReply { + private String muname; + private int mid; + private int rid; + private String uname; + private String description; + private Date pubDate; + private String attachmentType; + + public String getMuname() { + return muname; + } + + public void setMuname(String muname) { + this.muname = muname; + } + + public int getMid() { + return mid; + } + + public void setMid(int mid) { + this.mid = mid; + } + + public int getRid() { + return rid; + } + + public void setRid(int rid) { + this.rid = rid; + } + + public String getUname() { + return uname; + } + + public void setUname(String uname) { + this.uname = uname; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Date getPubDate() { + return pubDate; + } + + public void setPubDate(Date pubDate) { + this.pubDate = pubDate; + } + + public String getAttachmentType() { + return attachmentType; + } + + public void setAttachmentType(String attachmentType) { + this.attachmentType = attachmentType; + } +} diff --git a/juick-common/src/main/java/com/juick/model/TagStats.java b/juick-common/src/main/java/com/juick/model/TagStats.java new file mode 100644 index 00000000..da2f3f92 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/TagStats.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.juick.Tag; + +/** + * Created by vitalyster on 01.12.2016. + */ +public class TagStats { + private Tag tag; + private int usageCount; + + public Tag getTag() { + return tag; + } + + public void setTag(Tag tag) { + this.tag = tag; + } + + @JsonProperty("messages") + public int getUsageCount() { + return usageCount; + } + + public void setUsageCount(int usageCount) { + this.usageCount = usageCount; + } +} diff --git a/juick-common/src/main/java/com/juick/model/UserInfo.java b/juick-common/src/main/java/com/juick/model/UserInfo.java new file mode 100644 index 00000000..ca5d75e0 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/UserInfo.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model; + +/** + * Created by vt on 03/09/16. + */ +public class UserInfo { + private String fullName; + private String country; + private String url; + private String description; + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/juick-common/src/main/java/com/juick/model/facebook/User.java b/juick-common/src/main/java/com/juick/model/facebook/User.java new file mode 100644 index 00000000..80838de6 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/facebook/User.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model.facebook; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Created by vitalyster on 28.11.2016. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class User { + private String id; + private String name; + private String link; + private boolean verified; + private String firstName; + private String lastName; + private String gender; + private String locale; + private String timezone; + private String updatedTime; + private String email; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLink() { + return link; + } + + public void setLink(String link) { + this.link = link; + } + + public boolean getVerified() { + return verified; + } + + public void setVerified(boolean verified) { + this.verified = verified; + } + + @JsonProperty("first_name") + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + @JsonProperty("last_name") + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getLocale() { + return locale; + } + + public void setLocale(String locale) { + this.locale = locale; + } + + public String getTimezone() { + return timezone; + } + + public void setTimezone(String timezone) { + this.timezone = timezone; + } + + @JsonProperty("updated_time") + public String getUpdatedTime() { + return updatedTime; + } + + public void setUpdatedTime(String updatedTime) { + this.updatedTime = updatedTime; + } + + public String getEmail() { + return email; + } +} diff --git a/juick-common/src/main/java/com/juick/model/twitter/User.java b/juick-common/src/main/java/com/juick/model/twitter/User.java new file mode 100644 index 00000000..3c80eff4 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/twitter/User.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model.twitter; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Created by vitalyster on 28.11.2016. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class User { + private String screenName; + + @JsonProperty("screen_name") + public String getScreenName() { + return screenName; + } + + public void setScreenName(String screenName) { + this.screenName = screenName; + } +} diff --git a/juick-common/src/main/java/com/juick/model/vk/Token.java b/juick-common/src/main/java/com/juick/model/vk/Token.java new file mode 100644 index 00000000..ed93a3ab --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/vk/Token.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model.vk; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Created by vitalyster on 28.11.2016. + */ +public class Token { + private Long userId; + private String accessToken; + private String expiresIn; + + @JsonProperty("user_id") + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + @JsonProperty("access_token") + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + @JsonProperty("expires_in") + public String getExpiresIn() { + return expiresIn; + } + + public void setExpiresIn(String expiresIn) { + this.expiresIn = expiresIn; + } +} diff --git a/juick-common/src/main/java/com/juick/model/vk/User.java b/juick-common/src/main/java/com/juick/model/vk/User.java new file mode 100644 index 00000000..aeb18285 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/vk/User.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model.vk; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Created by vitalyster on 28.11.2016. + */ +public class User { + private String id; + private String firstName; + private String lastName; + private String screenName; + + @JsonProperty("first_name") + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + @JsonProperty("last_name") + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @JsonProperty("screen_name") + public String getScreenName() { + return screenName; + } + + public void setScreenName(String screenName) { + this.screenName = screenName; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/juick-common/src/main/java/com/juick/model/vk/UsersResponse.java b/juick-common/src/main/java/com/juick/model/vk/UsersResponse.java new file mode 100644 index 00000000..67505703 --- /dev/null +++ b/juick-common/src/main/java/com/juick/model/vk/UsersResponse.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.model.vk; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Created by vitalyster on 28.11.2016. + */ +public class UsersResponse { + private List users; + + @JsonProperty("response") + public List getUsers() { + return users; + } + + public void setUsers(List users) { + this.users = users; + } +} diff --git a/juick-common/src/main/java/com/juick/server/CommandsManager.java b/juick-common/src/main/java/com/juick/server/CommandsManager.java deleted file mode 100644 index 7c4692d2..00000000 --- a/juick-common/src/main/java/com/juick/server/CommandsManager.java +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server; - -import com.juick.Message; -import com.juick.Tag; -import com.juick.User; -import com.juick.formatters.PlainTextFormatter; -import com.juick.server.component.*; -import com.juick.server.helpers.CommandResult; -import com.juick.server.helpers.TagStats; -import com.juick.server.helpers.annotation.UserCommand; -import com.juick.server.util.HttpUtils; -import com.juick.server.util.TagUtils; -import com.juick.service.*; -import com.juick.util.MessageUtils; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.lang3.reflect.MethodUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.stereotype.Component; - -import javax.annotation.Nonnull; -import javax.inject.Inject; -import java.lang.reflect.Method; -import java.net.URI; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -/** - * - * @author ugnich - */ -@Component -public class CommandsManager { - @Inject - private MessagesService messagesService; - @Inject - private UserService userService; - @Inject - private TagService tagService; - @Inject - private PMQueriesService pmQueriesService; - @Inject - private ShowQueriesService showQueriesService; - @Inject - private PrivacyQueriesService privacyQueriesService; - @Inject - private SubscriptionService subscriptionService; - @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") - private String tmpDir; - @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}") - private String imgDir; - @Inject - private ApplicationEventPublisher applicationEventPublisher; - @Inject - private ImagesService imagesService; - - public CommandResult processCommand(User user, String data, @Nonnull URI attachment) throws Exception { - String strippedData = StringUtils.stripStart(data, null); - if (strippedData.startsWith("?OTR")) { - return CommandResult.fromString("?OTR Error: we are not using OTR"); - } - String input = MessageUtils.stripNonSafeUrls(strippedData); - Optional cmd = MethodUtils.getMethodsListWithAnnotation(getClass(), UserCommand.class).stream() - .filter(m -> Pattern.compile(m.getAnnotation(UserCommand.class).pattern(), - m.getAnnotation(UserCommand.class).patternFlags()).matcher(input).matches()) - .findFirst(); - if (cmd.isPresent()) { - Matcher matcher = Pattern.compile(cmd.get().getAnnotation(UserCommand.class).pattern(), - cmd.get().getAnnotation(UserCommand.class).patternFlags()).matcher(input); - List groups = new ArrayList<>(); - while (matcher.find()) { - for (int i = 1; i <= matcher.groupCount(); i++) { - groups.add(matcher.group(i)); - } - } - CommandResult commandResult = (CommandResult) getClass().getMethod(cmd.get().getName(), User.class, URI.class, String[].class) - .invoke(this, user, attachment, groups.toArray(new String[groups.size()])); - if (StringUtils.isNotEmpty(commandResult.getText())) { - return commandResult; - } - } - Pair> tags = tagService.fromString(input); - if (tags.getRight().size() > 5) { - return CommandResult.fromString("Sorry, 5 tags maximum."); - } - // new message - String body = tags.getLeft().trim(); - boolean haveAttachment = StringUtils.isNotEmpty(attachment.toString()); - String attachmentFName = null; - String attachmentType = null; - if (haveAttachment) { - attachmentFName = attachment.getScheme().equals("juick") ? attachment.getHost() - : HttpUtils.downloadImage(attachment.toURL(), tmpDir).getHost(); - attachmentType = attachmentFName.substring(attachmentFName.length() - 3); - } - int mid = messagesService.createMessage(user.getUid(), body, attachmentType, tags.getRight()); - if (haveAttachment) { - String fname = String.format("%d.%s", mid, attachmentType); - imagesService.saveImageWithPreviews(attachmentFName, fname); - } - Message msg = messagesService.getMessage(mid); - subscriptionService.subscribeMessage(msg, user); - - applicationEventPublisher.publishEvent(new MessageReadEvent(this, user, msg)); - applicationEventPublisher.publishEvent(new MessageEvent(this, msg, subscriptionService.getSubscribedUsers(msg.getUser().getUid(), msg.getMid()))); - return CommandResult.build(msg, "New message posted.\n#" + msg.getMid() + " https://juick.com/m/" + msg.getMid(), String.format("[New message](%s) posted", PlainTextFormatter.formatUrl(msg))); - } - - @UserCommand(pattern = "^ping$", patternFlags = Pattern.CASE_INSENSITIVE, - help = "PING - returns you a PONG") - public CommandResult commandPing(User user, URI attachment, String[] input) { - applicationEventPublisher.publishEvent(new PingEvent(this, user)); - return CommandResult.fromString("PONG"); - } - - @UserCommand(pattern = "^help$", patternFlags = Pattern.CASE_INSENSITIVE, - help = "HELP - returns this help message") - public CommandResult commandHelp(User user, URI attachment, String[] input) { - return CommandResult.fromString(Arrays.stream(getClass().getDeclaredMethods()) - .filter(m -> m.isAnnotationPresent(UserCommand.class)) - .map(m -> m.getAnnotation(UserCommand.class).help()) - .collect(Collectors.joining("\n"))); - } - - @UserCommand(pattern = "^login$", patternFlags = Pattern.CASE_INSENSITIVE, - help = "LOGIN - log in to Juick website") - public CommandResult commandLogin(User user_from, URI attachment, String[] input) { - return CommandResult.fromString("http://juick.com/login?hash=" + userService.getHashByUID(user_from.getUid())); - } - @UserCommand(pattern = "^\\@(\\S+)\\s+([\\s\\S]+)$", help = "@username message - send PM to username") - public CommandResult commandPM(User user_from, URI attachment, String... arguments) { - String body = arguments[1]; - - User user_to = userService.getUserByName(arguments[0]); - - if (!user_to.isAnonymous()) { - if (!userService.isInBLAny(user_to.getUid(), user_from.getUid())) { - if (pmQueriesService.createPM(user_from.getUid(), user_to.getUid(), body)) { - com.juick.Message jmsg = new com.juick.Message(); - jmsg.setUser(user_from); - jmsg.setTo(user_to); - jmsg.setText(body); - applicationEventPublisher.publishEvent(new MessageEvent(this, jmsg, Collections.singletonList(user_to))); - return CommandResult.fromString("Private message sent"); - } - } - } - return CommandResult.fromString("Error"); - } - @UserCommand(pattern = "^bl$", patternFlags = Pattern.CASE_INSENSITIVE, - help = "BL - Show your blacklist") - public CommandResult commandBLShow(User user_from, URI attachment, String... arguments) { - List blusers = userService.getUserBLUsers(user_from.getUid()); - List bltags = tagService.getUserBLTags(user_from.getUid()); - - String txt = StringUtils.EMPTY; - if (bltags.size() > 0) { - for (String bltag : bltags) { - txt += "*" + bltag + "\n"; - } - - if (blusers.size() > 0) { - txt += "\n"; - } - } - if (blusers.size() > 0) { - for (User bluser : blusers) { - txt += "@" + bluser.getName() + "\n"; - } - } - if (txt.isEmpty()) { - txt = "You don't have any users or tags in your blacklist."; - } - - return CommandResult.fromString(txt); - } - - @UserCommand(pattern = "^#\\+$", help = "#+ - Show last Juick messages") - public CommandResult commandLast(User user_from, URI attachment, String... arguments) { - return CommandResult.fromString("Last messages:\n" - + printMessages(user_from, messagesService.getAll(user_from.getUid(), 0), true)); - } - - @UserCommand(pattern = "@", help = "@ - Show recommendations and popular personal blogs") - public CommandResult commandUsers(User user_from, URI attachment, String... arguments) { - StringBuilder msg = new StringBuilder(); - msg.append("Recommended blogs"); - List recommendedUsers = showQueriesService.getRecommendedUsers(user_from); - if (recommendedUsers.size() > 0) { - for (String user : recommendedUsers) { - msg.append("\n@").append(user); - } - } else { - msg.append("\nNo recommendations now. Subscribe to more blogs. ;)"); - } - msg.append("\n\nTop 10 personal blogs:"); - List topUsers = showQueriesService.getTopUsers(); - if (topUsers.size() > 0) { - for (String user : topUsers) { - msg.append("\n@").append(user); - } - } else { - msg.append("\nNo top users. Empty DB? ;)"); - } - return CommandResult.fromString(msg.toString()); - } - @UserCommand(pattern = "^bl\\s+@([^\\s\\n\\+]+)", patternFlags = Pattern.CASE_INSENSITIVE, - help = "BL @username - add @username to your blacklist") - public CommandResult blacklistUser(User user_from, URI attachment, String... arguments) { - User blUser = userService.getUserByName(arguments[0]); - if (!blUser.isAnonymous()) { - PrivacyQueriesService.PrivacyResult result = privacyQueriesService.blacklistUser(user_from, blUser); - if (result == PrivacyQueriesService.PrivacyResult.Added) { - return CommandResult.fromString("User added to your blacklist"); - } else { - return CommandResult.fromString("User removed from your blacklist"); - } - } - return CommandResult.fromString("User not found"); - } - @UserCommand(pattern = "^bl\\s\\*(\\S+)$", patternFlags = Pattern.CASE_INSENSITIVE, - help = "BL *tag - add *tag to your blacklist") - public CommandResult blacklistTag(User user_from, URI attachment, String... arguments) { - if (!user_from.isAnonymous()) { - Tag tag = tagService.getTag(arguments[0], false); - if (tag != null) { - PrivacyQueriesService.PrivacyResult result = privacyQueriesService.blacklistTag(user_from, tag); - if (result == PrivacyQueriesService.PrivacyResult.Added) { - return CommandResult.fromString("Tag added to your blacklist"); - } else { - return CommandResult.fromString("Tag removed from your blacklist"); - } - } - } - return CommandResult.fromString("Tag not found"); - } - @UserCommand(pattern = "\\*", help = "* - Show your tags") - public CommandResult commandTags(User currentUser, URI attachment, String... args) { - List tags = tagService.getUserTagStats(currentUser.getUid()); - String msg = "Your tags: (tag - messages)\n" + - tags.stream() - .map(t -> String.format("\n*%s - %d", t.getTag().getName(), t.getUsageCount())).collect(Collectors.joining()); - return CommandResult.fromString(msg); - } - @UserCommand(pattern = "S", help = "S - Show your subscriptions", patternFlags = Pattern.CASE_INSENSITIVE) - public CommandResult commandSubscriptions(User currentUser, URI attachment, String... args) { - List friends = userService.getUserFriends(currentUser.getUid()); - List tags = subscriptionService.getSubscribedTags(currentUser); - String msg = friends.size() > 0 ? "You are subscribed to users:" + friends.stream().map(u -> "\n@" + u.getName()) - .collect(Collectors.joining()) - : "You are not subscribed to any user."; - msg += tags.size() > 0 ? "\nYou are subscribed to tags:" + tags.stream().map(t -> "\n*" + t) - .collect(Collectors.joining()) - : "\nYou are not subscribed to any tag."; - return CommandResult.fromString(msg); - } - @UserCommand(pattern = "!", help = "! - Show your favorite messages") - public CommandResult commandFavorites(User currentUser, URI attachment, String... args) { - List mids = messagesService.getUserRecommendations(currentUser.getUid(), 0); - if (mids.size() > 0) { - return CommandResult.fromString("Favorite messages: \n" + printMessages(currentUser, mids, false)); - } - return CommandResult.fromString("No favorite messages, try to \"like\" something ;)"); - } - @UserCommand(pattern = "^\\!\\s+#(\\d+)", help = "! #12345 - recommend message") - public CommandResult commandRecommend(User user, URI attachment, String... arguments) { - int mid = NumberUtils.toInt(arguments[0], 0); - if (mid > 0) { - com.juick.Message msg = messagesService.getMessage(mid); - if (msg != null) { - if (msg.getUser() == user) { - return CommandResult.fromString("You can't recommend your own messages."); - } - MessagesService.RecommendStatus status = messagesService.recommendMessage(mid, user.getUid()); - switch (status) { - case Added: - applicationEventPublisher.publishEvent(new LikeEvent(this, user, msg, - subscriptionService.getUsersSubscribedToUserRecommendations( - user.getUid(), msg))); - return CommandResult.fromString("Message is added to your recommendations"); - case Deleted: - return CommandResult.fromString("Message deleted from your recommendations."); - } - } - return CommandResult.fromString("Message not found"); - } - return CommandResult.fromString("Message not found"); - } - // TODO: target notification - @UserCommand(pattern = "^(s|u)\\s+\\@(\\S+)$", help = "S @username - subscribe to user" + - "\nU @username - unsubscribe from user", patternFlags = Pattern.CASE_INSENSITIVE) - public CommandResult commandSubscribeUser(User user, URI attachment, String... args) { - boolean subscribe = args[0].equalsIgnoreCase("s"); - User toUser = userService.getUserByName(args[1]); - if (toUser.isAnonymous()) { - return CommandResult.fromString("User not found"); - } - if (subscribe) { - if (subscriptionService.subscribeUser(user, toUser)) { - // TODO: already subscribed case - applicationEventPublisher.publishEvent(new SubscribeEvent(this, user, toUser)); - return CommandResult.fromString("Subscribed to @" + toUser.getName()); - } - } else { - if (subscriptionService.unSubscribeUser(user, toUser)) { - return CommandResult.fromString("Unsubscribed from @" + toUser.getName()); - } - return CommandResult.fromString("You was not subscribed to @" + toUser.getName()); - } - return CommandResult.fromString("Error"); - } - @UserCommand(pattern = "^(s|u)\\s+\\*(\\S+)$", help = "S *tag - subscribe to tag" + - "\nU *tag - unsubscribe from tag", patternFlags = Pattern.CASE_INSENSITIVE) - public CommandResult commandSubscribeTag(User user, URI attachment, String... args) { - boolean subscribe = args[0].equalsIgnoreCase("s"); - Tag tag = tagService.getTag(args[1], true); - if (subscribe) { - if (subscriptionService.subscribeTag(user, tag)) { - return CommandResult.fromString("Subscribed"); - } - } else { - if (subscriptionService.unSubscribeTag(user, tag)) { - return CommandResult.fromString("Unsubscribed from " + tag.getName()); - } - return CommandResult.fromString("You was not subscribed to " + tag.getName()); - } - return CommandResult.fromString("Error"); - } - @UserCommand(pattern = "^(s|u)\\s+#(\\d+)$", help = "S #1234 - subscribe to comments" + - "\nU #1234 - unsubscribe from comments", patternFlags = Pattern.CASE_INSENSITIVE) - public CommandResult commandSubscribeMessage(User user, URI attachment, String... args) { - boolean subscribe = args[0].equalsIgnoreCase("s"); - int mid = NumberUtils.toInt(args[1], 0); - Message msg = messagesService.getMessage(mid); - if (msg != null) { - if (subscribe) { - if (subscriptionService.subscribeMessage(msg, user)) { - applicationEventPublisher.publishEvent(new MessageReadEvent(this, user, msg)); - return CommandResult.fromString("Subscribed"); - } - } else { - if (subscriptionService.unSubscribeMessage(mid, user.getUid())) { - return CommandResult.fromString("Unsubscribed from #" + mid); - } - return CommandResult.fromString("You was not subscribed to #" + mid); - } - } - return CommandResult.fromString("Error"); - } - @UserCommand(pattern = "^(on|off)$", patternFlags = Pattern.CASE_INSENSITIVE, - help = "ON/OFF - Enable/disable subscriptions delivery") - public CommandResult commandOnOff(User user, URI attachment, String[] input) { - UserService.ActiveStatus newStatus; - String retValUpdated; - if (input[0].toLowerCase().equals("on")) { - newStatus = UserService.ActiveStatus.Active; - retValUpdated = "XMPP notifications are activated"; - } else { - newStatus = UserService.ActiveStatus.Inactive; - retValUpdated = "XMPP notifications are disabled"; - } - if (userService.getAllJIDs(user).stream().allMatch(jid -> userService.setActiveStatusForJID(jid, newStatus))) { - return CommandResult.fromString(retValUpdated); - } - return CommandResult.fromString("Error"); - } - @UserCommand(pattern = "^\\@([^\\s\\n\\+]+)(\\+?)$", - help = "@username+ - Show user's info and last 20 messages") - public CommandResult commandUser(User user, URI attachment, String... arguments) { - User blogUser = userService.getUserByName(arguments[0]); - int page = arguments[1].length(); - if (!blogUser.isAnonymous()) { - List mids = messagesService.getUserBlog(blogUser.getUid(), 0, 0); - return CommandResult.fromString(String.format("Last messages from @%s:\n%s", arguments[0], - printMessages(user, mids, false))); - } - return CommandResult.fromString("User not found"); - } - @UserCommand(pattern = "^#(\\d+)(\\+?)$", help = "#1234 - Show message (#1234+ - message with replies)") - public CommandResult commandShow(User user, URI attachment, String... arguments) { - boolean showReplies = arguments[1].length() > 0; - int mid = NumberUtils.toInt(arguments[0], 0); - if (mid == 0) { - return CommandResult.fromString("Error"); - } - com.juick.Message msg = messagesService.getMessage(mid); - if (msg != null) { - if (showReplies) { - List replies = messagesService.getReplies(user, mid); - applicationEventPublisher.publishEvent(new MessageReadEvent(this, user, msg)); - replies.add(0, msg); - return CommandResult.fromString(String.join("\n", - replies.stream().map(PlainTextFormatter::formatPostSummary).collect(Collectors.toList()))); - } - return CommandResult.fromString(PlainTextFormatter.formatPost(msg)); - } - return CommandResult.fromString("Message not found"); - } - @UserCommand(pattern = "^#(\\d+)\\/(\\d+)$", help = "#1234/5 - Show reply") - public CommandResult commandShowReply(User user, URI attachment, String... arguments) { - int mid = NumberUtils.toInt(arguments[0], 0); - int rid = NumberUtils.toInt(arguments[1], 0); - com.juick.Message reply = messagesService.getReply(mid, rid); - if (reply != null) { - return CommandResult.fromString(PlainTextFormatter.formatPost(reply)); - } - return CommandResult.fromString("Reply not found"); - } - @UserCommand(pattern = "^\\*(\\S+)(\\+?)$", help = "*tag - Show last messages with tag") - public CommandResult commandShowTag(User user, URI attachment, String... arguments) { - if (StringUtils.isNotEmpty(attachment.toString())) { - // new message with tag - return CommandResult.fromString(StringUtils.EMPTY); - } - Tag tag = tagService.getTag(arguments[0], false); - if (tag != null) { - // TODO: synonyms - List mids = messagesService.getTag(tag.TID, user.getUid(), 0, 10); - return CommandResult.fromString("Last messages with *" + tag.getName() + ":\n" + printMessages(user, mids, true)); - } - return CommandResult.fromString("Tag not found"); - } - @UserCommand(pattern = "^D #(\\d+)$", help = "D #1234 - Delete post", patternFlags = Pattern.CASE_INSENSITIVE) - public CommandResult commandDeletePost(User user, URI attachment, String... args) { - int mid = Integer.valueOf(args[0]); - if (messagesService.deleteMessage(user.getUid(), mid)) { - return CommandResult.fromString("Message deleted"); - } - return CommandResult.fromString("This is not your message"); - } - @UserCommand(pattern = "^D #(\\d+)(\\.|\\-|\\/)(\\d+)$", help = "D #1234/5 - Delete comment", patternFlags = Pattern.CASE_INSENSITIVE) - public CommandResult commandDeleteReply(User user, URI attachment, String... args) { - int mid = Integer.valueOf(args[0]); - int rid = Integer.valueOf(args[2]); - if (messagesService.deleteReply(user.getUid(), mid, rid)) { - return CommandResult.fromString("Reply deleted"); - } else { - return CommandResult.fromString("This is not your reply"); - } - } - @UserCommand(pattern = "^(D L|DL|D LAST)$", help = "D L - Delete last message", patternFlags = Pattern.CASE_INSENSITIVE) - public CommandResult commandDeleteLast(User user, URI attachment, String... args) { - return CommandResult.fromString("Temporarily unavailable"); - } - @UserCommand(pattern = "^\\?\\s+\\@([a-zA-Z0-9\\-\\.\\@]+)\\s+([\\s\\S]+)$", help = "? @user string - search in user messages") - public CommandResult commandSearch(User user, URI attachment, String... args) { - return CommandResult.fromString("Temporarily unavailable"); - } - @UserCommand(pattern = "^\\?\\s+([\\s\\S]+)$", help = "? string - search in all messages") - public CommandResult commandSearchAll(User user, URI attachment, String... args) { - return CommandResult.fromString("Temporarily unavailable"); - } - @UserCommand(pattern = "^(#+)$", help = "# - Show last messages from your feed (## - second page, ...)") - public CommandResult commandMyFeed(User user, URI attachment, String... arguments) { - // number of # is the page count - int page = arguments[0].length() - 1; - List mids = messagesService.getMyFeed(user.getUid(), page, false); - if (mids.size() > 0) { - return CommandResult.fromString("Your feed: \n" + printMessages(user, mids, true)); - } - return CommandResult.fromString("Your feed is empty"); - } - @UserCommand(pattern = "^(#|\\.)(\\d+)((\\.|\\-|\\/)(\\d+))?\\s([\\s\\S]+)?", - help = "#1234 *tag *tag2 - edit tags\n#1234 text - reply to message") - public CommandResult EditOrReply(User user, @Nonnull URI attachment, String... args) throws Exception { - int mid = NumberUtils.toInt(args[1]); - int rid = NumberUtils.toInt(args[4], 0); - String txt = StringUtils.defaultString(args[5]); - Message msg = messagesService.getMessage(mid); - Pair> messageTags = tagService.fromString(txt); - if (messageTags.getRight().size() > 0) { - if (user.getUid() != msg.getUser().getUid()) { - return CommandResult.fromString("It is not your message"); - } - if (!CollectionUtils.isEqualCollection(tagService.updateTags(mid, messageTags.getRight()), msg.getTags())) { - return CommandResult.fromString("Tags are updated"); - } else { - return CommandResult.fromString("Tags are NOT updated (5 tags maximum?)"); - } - } else { - boolean haveAttachment = StringUtils.isNotEmpty(attachment.toString()); - String attachmentFName = null; - String attachmentType = null; - if (haveAttachment) { - attachmentFName = attachment.getScheme().equals("juick") ? attachment.getHost() - : HttpUtils.downloadImage(attachment.toURL(), tmpDir).getHost(); - attachmentType = attachmentFName.substring(attachmentFName.length() - 3); - } - int newrid = messagesService.createReply(mid, rid, user, txt, attachmentType); - applicationEventPublisher.publishEvent(new MessageReadEvent(this, user, msg)); - if (haveAttachment) { - String fname = String.format("%d-%d.%s", mid, newrid, attachmentType); - imagesService.saveImageWithPreviews(attachmentFName, fname); - } - Message original = messagesService.getMessage(mid); - subscriptionService.subscribeMessage(original, user); - Message reply = messagesService.getReply(mid, newrid); - applicationEventPublisher.publishEvent(new MessageEvent(this, reply, subscriptionService.getUsersSubscribedToComments(original, reply))); - return CommandResult.build(reply,"Reply posted.\n#" + mid + "/" + newrid + " " - + "https://juick.com/m/" + mid + "#" + newrid, - String.format("[Reply](%s) posted", PlainTextFormatter.formatUrl(reply))); - } - } - - String printMessages(User visitor, List mids, boolean crop) { - return messagesService.getMessages(visitor, mids).stream() - .sorted(Collections.reverseOrder()) - .map(PlainTextFormatter::formatPostSummary).collect(Collectors.joining("\n\n")); - } -} diff --git a/juick-common/src/main/java/com/juick/server/component/DisconnectedEvent.java b/juick-common/src/main/java/com/juick/server/component/DisconnectedEvent.java deleted file mode 100644 index 9da6d7a9..00000000 --- a/juick-common/src/main/java/com/juick/server/component/DisconnectedEvent.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.juick.server.component; - -import org.springframework.context.ApplicationEvent; - -public class DisconnectedEvent extends ApplicationEvent { - /** - * Create a new ApplicationEvent. - * - * @param source the object on which the event initially occurred (never {@code null}) - */ - public DisconnectedEvent(Object source) { - super(source); - } -} diff --git a/juick-common/src/main/java/com/juick/server/component/LikeEvent.java b/juick-common/src/main/java/com/juick/server/component/LikeEvent.java deleted file mode 100644 index 678a84a9..00000000 --- a/juick-common/src/main/java/com/juick/server/component/LikeEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.juick.server.component; - -import com.juick.Message; -import com.juick.User; -import org.springframework.context.ApplicationEvent; - -import java.util.List; - -public class LikeEvent extends ApplicationEvent { - private User user; - private Message message; - private List subscribers; - /** - * Create a new ApplicationEvent. - * - * @param source the object on which the event initially occurred (never {@code null}) - */ - public LikeEvent(Object source, User user, Message message, List subscribers) { - super(source); - this.message = message; - this.user = user; - this.subscribers = subscribers; - } - - public User getUser() { - return user; - } - - public Message getMessage() { - return message; - } - - public List getSubscribers() { - return subscribers; - } -} diff --git a/juick-common/src/main/java/com/juick/server/component/MessageEvent.java b/juick-common/src/main/java/com/juick/server/component/MessageEvent.java deleted file mode 100644 index c0c60228..00000000 --- a/juick-common/src/main/java/com/juick/server/component/MessageEvent.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.juick.server.component; - -import com.juick.Message; -import com.juick.User; -import org.springframework.context.ApplicationEvent; - -import java.util.List; - -public class MessageEvent extends ApplicationEvent { - private Message message; - private List users; - /** - * Create a new ApplicationEvent. - * - * @param source the object on which the event initially occurred (never {@code null}) - * @param message app message - * @param interestedUsers users interested in notification - */ - public MessageEvent(Object source, Message message, List interestedUsers) { - super(source); - this.message = message; - this.users = interestedUsers; - } - - public Message getMessage() { - return message; - } - public List getUsers() { - return users; - } -} diff --git a/juick-common/src/main/java/com/juick/server/component/MessageReadEvent.java b/juick-common/src/main/java/com/juick/server/component/MessageReadEvent.java deleted file mode 100644 index e75d3636..00000000 --- a/juick-common/src/main/java/com/juick/server/component/MessageReadEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.juick.server.component; - -import com.juick.Message; -import com.juick.User; -import org.springframework.context.ApplicationEvent; - -public class MessageReadEvent extends ApplicationEvent { - private User user; - private Message message; - /** - * Create a new ApplicationEvent. - * - * @param source the object on which the event initially occurred (never {@code null}) - */ - public MessageReadEvent(Object source, User user, Message message) { - super(source); - this.user = user; - this.message = message; - } - - public User getUser() { - return user; - } - - public Message getMessage() { - return message; - } -} diff --git a/juick-common/src/main/java/com/juick/server/component/PingEvent.java b/juick-common/src/main/java/com/juick/server/component/PingEvent.java deleted file mode 100644 index abda5b85..00000000 --- a/juick-common/src/main/java/com/juick/server/component/PingEvent.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.juick.server.component; - -import com.juick.User; -import org.springframework.context.ApplicationEvent; - -public class PingEvent extends ApplicationEvent { - private User pinger; - /** - * Create a new ApplicationEvent. - * - * @param source the object on which the event initially occurred (never {@code null}) - */ - public PingEvent(Object source, User pinger) { - super(source); - this.pinger = pinger; - } - - public User getPinger() { - return pinger; - } -} diff --git a/juick-common/src/main/java/com/juick/server/component/SubscribeEvent.java b/juick-common/src/main/java/com/juick/server/component/SubscribeEvent.java deleted file mode 100644 index 2d3ceddb..00000000 --- a/juick-common/src/main/java/com/juick/server/component/SubscribeEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.juick.server.component; - -import com.juick.User; -import org.springframework.context.ApplicationEvent; - -public class SubscribeEvent extends ApplicationEvent { - private User user; - private User toUser; - /** - * Create a new ApplicationEvent. - * - * @param source the object on which the event initially occurred (never {@code null}) - */ - public SubscribeEvent(Object source, User user, User toUser) { - super(source); - this.user = user; - this.toUser = toUser; - } - - public User getUser() { - return user; - } - - public User getToUser() { - return toUser; - } -} diff --git a/juick-common/src/main/java/com/juick/server/component/UserUpdatedEvent.java b/juick-common/src/main/java/com/juick/server/component/UserUpdatedEvent.java deleted file mode 100644 index 059aeefd..00000000 --- a/juick-common/src/main/java/com/juick/server/component/UserUpdatedEvent.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.juick.server.component; - -import com.juick.User; -import org.springframework.context.ApplicationEvent; -import org.springframework.lang.NonNull; - -public class UserUpdatedEvent extends ApplicationEvent { - private User user; - /** - * Generated when user is updated (avatar changed, etc). - * - * @param source the object on which the event initially occurred (never {@code null}) - * @param user updated user - */ - public UserUpdatedEvent(@NonNull Object source, User user) { - super(source); - this.user = user; - } - - public User getUser() { - return user; - } -} diff --git a/juick-common/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java b/juick-common/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java deleted file mode 100644 index 23a35384..00000000 --- a/juick-common/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.configuration; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.SchedulingConfigurer; -import org.springframework.scheduling.config.ScheduledTaskRegistrar; -import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter; - -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Created by vitalyster on 28.06.2016. - */ -@Configuration -public class BaseWebConfiguration implements WebMvcConfigurer, SchedulingConfigurer { - - - @Override - public void configurePathMatch(PathMatchConfigurer configurer) { - configurer.setUseSuffixPatternMatch(false); - } - - @Bean - public ResourceUrlEncodingFilter resourceUrlEncodingFilter() { - return new ResourceUrlEncodingFilter(); - } - - @Override - public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { - taskRegistrar.setScheduler(taskExecutor()); - } - - @Bean(destroyMethod="shutdown") - public Executor taskExecutor() { - return Executors.newScheduledThreadPool(100); - } - - @Bean - public ExecutorService executorService() { - return Executors.newCachedThreadPool(); - } -} diff --git a/juick-common/src/main/java/com/juick/server/configuration/StorageConfiguration.java b/juick-common/src/main/java/com/juick/server/configuration/StorageConfiguration.java deleted file mode 100644 index 4101f37d..00000000 --- a/juick-common/src/main/java/com/juick/server/configuration/StorageConfiguration.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.juick.server.configuration; - -import com.juick.service.ImagesService; -import com.juick.service.ImagesServiceImpl; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class StorageConfiguration { - - @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") - private String tmpDir; - @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}") - private String imgDir; - @Bean - public ImagesService imagesService() { - return new ImagesServiceImpl(imgDir, tmpDir); - } -} diff --git a/juick-common/src/main/java/com/juick/server/helpers/AnonymousUser.java b/juick-common/src/main/java/com/juick/server/helpers/AnonymousUser.java deleted file mode 100644 index 9a201552..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/AnonymousUser.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.helpers; - -import com.juick.User; - -/** - * Created by aalexeev on 12/11/16. - */ -public final class AnonymousUser extends User { - public static final AnonymousUser INSTANCE = new AnonymousUser(); - - private AnonymousUser() { - super.setUid(getUid()); - super.setName(getName()); - super.setAvatar(getAvatar()); - super.setFullName(getFullName()); - super.setMessagesCount(getMessagesCount()); - super.setAuthHash(getAuthHash()); - super.setBanned(isBanned()); - super.setCredentials(getCredentials()); - } - - @Override - public boolean equals(Object obj) { - return obj == this || obj instanceof AnonymousUser; - } - - @Override - public int getUid() { - return 0; - } - - @Override - public String getName() { - return "Anonymous"; - } - - @Override - public String getFullName() { - return getName(); - } - - @Override - public String getAuthHash() { - return null; - } - - @Override - public Integer getUnreadCount() { - return 0; - } - - @Override - public boolean isBanned() { - return false; - } - - @Override - public Object getAvatar() { - return null; - } - - @Override - public String getCredentials() { - return null; - } - - @Override - public int getMessagesCount() { - return 0; - } - - @Override - public boolean isAnonymous() { - return true; - } - - @Override - public void setUid(int uid) { - } - - @Override - public void setName(String name) { - } - - @Override - public void setFullName(String fullName) { - } - - @Override - public void setAuthHash(String authHash) { - } - - @Override - public void setUnreadCount(Integer count) { - } - - @Override - public void setBanned(boolean banned) { - } - - @Override - public void setAvatar(Object avatar) { - } - - @Override - public void setCredentials(String credentials) { - } - - @Override - public void setMessagesCount(int messagesCount) { - } -} diff --git a/juick-common/src/main/java/com/juick/server/helpers/ApplicationStatus.java b/juick-common/src/main/java/com/juick/server/helpers/ApplicationStatus.java deleted file mode 100644 index 8f57b2a6..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/ApplicationStatus.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.helpers; - -import org.apache.commons.lang3.builder.ToStringBuilder; - -/** - * Created by vt on 03/09/16. - */ -public class ApplicationStatus { - private boolean connected; - private boolean crosspostEnabled; - - @Override - public String toString() { - return new ToStringBuilder(this) - .append("connected", connected) - .append("crosspostEnabled", crosspostEnabled) - .toString(); - } - - public boolean isConnected() { - return connected; - } - - public void setConnected(boolean connected) { - this.connected = connected; - } - - public boolean isCrosspostEnabled() { - return crosspostEnabled; - } - - public void setCrosspostEnabled(boolean crosspostEnabled) { - this.crosspostEnabled = crosspostEnabled; - } -} diff --git a/juick-common/src/main/java/com/juick/server/helpers/Auth.java b/juick-common/src/main/java/com/juick/server/helpers/Auth.java deleted file mode 100644 index d01efadd..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/Auth.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.helpers; - -/** - * Created by vt on 09/02/16. - */ -public class Auth { - private String account; - private String authCode; - - public Auth(String account, String authCode) { - this.account = account; - this.authCode = authCode; - } - - public String getAccount() { - return account; - } - - public String getAuthCode() { - return authCode; - } -} \ No newline at end of file diff --git a/juick-common/src/main/java/com/juick/server/helpers/CommandResult.java b/juick-common/src/main/java/com/juick/server/helpers/CommandResult.java deleted file mode 100644 index a5baaee0..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/CommandResult.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.juick.server.helpers; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.juick.Message; - -import java.util.Optional; - -public class CommandResult { - private String text; - private String markdown; - private Message newMessage; - - public String getText() { - return text; - } - public String getMarkdown() { - return markdown; - } - - public Optional getNewMessage() { - return Optional.ofNullable(newMessage); - } - public static CommandResult build(Message newMessage, String text, String markdown) { - CommandResult result = new CommandResult(); - result.newMessage = newMessage; - result.text = text; - result.markdown = markdown; - return result; - } - public static CommandResult fromString(String text) { - CommandResult result = new CommandResult(); - result.text = text; - return result; - } - -} diff --git a/juick-common/src/main/java/com/juick/server/helpers/NotifyOpts.java b/juick-common/src/main/java/com/juick/server/helpers/NotifyOpts.java deleted file mode 100644 index 0e49a424..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/NotifyOpts.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.helpers; - -/** - * Created by vt on 03/09/16. - */ -public class NotifyOpts { - private boolean repliesEnabled; - private boolean subscriptionsEnabled; - private boolean recommendationsEnabled; - - public boolean isRepliesEnabled() { - return repliesEnabled; - } - - public void setRepliesEnabled(boolean repliesEnabled) { - this.repliesEnabled = repliesEnabled; - } - - public boolean isSubscriptionsEnabled() { - return subscriptionsEnabled; - } - - public void setSubscriptionsEnabled(boolean subscriptionsEnabled) { - this.subscriptionsEnabled = subscriptionsEnabled; - } - - public boolean isRecommendationsEnabled() { - return recommendationsEnabled; - } - - public void setRecommendationsEnabled(boolean recommendationsEnabled) { - this.recommendationsEnabled = recommendationsEnabled; - } -} diff --git a/juick-common/src/main/java/com/juick/server/helpers/PrivacyOpts.java b/juick-common/src/main/java/com/juick/server/helpers/PrivacyOpts.java deleted file mode 100644 index 86281d4a..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/PrivacyOpts.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.helpers; - -/** - * Created by vt on 16/01/16. - */ -public class PrivacyOpts { - private int uid; - private int privacy; - - public PrivacyOpts() { - - } - - public int getUid() { - return uid; - } - - public void setUid(int uid) { - this.uid = uid; - } - - public int getPrivacy() { - return privacy; - } - - public void setPrivacy(int privacy) { - this.privacy = privacy; - } -} diff --git a/juick-common/src/main/java/com/juick/server/helpers/PrivateChats.java b/juick-common/src/main/java/com/juick/server/helpers/PrivateChats.java deleted file mode 100644 index 6e446f98..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/PrivateChats.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.helpers; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.juick.User; - -import java.util.List; - -/** - * Created by vt on 24/11/2016. - */ -public class PrivateChats { - private List users; - - @JsonProperty("pms") - public List getUsers() { - return users; - } - - public void setUsers(List users) { - this.users = users; - } -} diff --git a/juick-common/src/main/java/com/juick/server/helpers/ResponseReply.java b/juick-common/src/main/java/com/juick/server/helpers/ResponseReply.java deleted file mode 100644 index 91ba2b8a..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/ResponseReply.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.helpers; - -import java.util.Date; - -/** - * Created by vitalyster on 13.12.2016. - */ -public class ResponseReply { - private String muname; - private int mid; - private int rid; - private String uname; - private String description; - private Date pubDate; - private String attachmentType; - - public String getMuname() { - return muname; - } - - public void setMuname(String muname) { - this.muname = muname; - } - - public int getMid() { - return mid; - } - - public void setMid(int mid) { - this.mid = mid; - } - - public int getRid() { - return rid; - } - - public void setRid(int rid) { - this.rid = rid; - } - - public String getUname() { - return uname; - } - - public void setUname(String uname) { - this.uname = uname; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Date getPubDate() { - return pubDate; - } - - public void setPubDate(Date pubDate) { - this.pubDate = pubDate; - } - - public String getAttachmentType() { - return attachmentType; - } - - public void setAttachmentType(String attachmentType) { - this.attachmentType = attachmentType; - } -} diff --git a/juick-common/src/main/java/com/juick/server/helpers/TagStats.java b/juick-common/src/main/java/com/juick/server/helpers/TagStats.java deleted file mode 100644 index ab24983f..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/TagStats.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.helpers; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.juick.Tag; - -/** - * Created by vitalyster on 01.12.2016. - */ -public class TagStats { - private Tag tag; - private int usageCount; - - public Tag getTag() { - return tag; - } - - public void setTag(Tag tag) { - this.tag = tag; - } - - @JsonProperty("messages") - public int getUsageCount() { - return usageCount; - } - - public void setUsageCount(int usageCount) { - this.usageCount = usageCount; - } -} diff --git a/juick-common/src/main/java/com/juick/server/helpers/UserInfo.java b/juick-common/src/main/java/com/juick/server/helpers/UserInfo.java deleted file mode 100644 index 284cd2e8..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/UserInfo.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.helpers; - -/** - * Created by vt on 03/09/16. - */ -public class UserInfo { - private String fullName; - private String country; - private String url; - private String description; - - public String getFullName() { - return fullName; - } - - public void setFullName(String fullName) { - this.fullName = fullName; - } - - public String getCountry() { - return country; - } - - public void setCountry(String country) { - this.country = country; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } -} diff --git a/juick-common/src/main/java/com/juick/server/helpers/annotation/UserCommand.java b/juick-common/src/main/java/com/juick/server/helpers/annotation/UserCommand.java deleted file mode 100644 index 4f07001c..00000000 --- a/juick-common/src/main/java/com/juick/server/helpers/annotation/UserCommand.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.helpers.annotation; - -import org.apache.commons.lang3.StringUtils; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Created by oxpa on 22.03.16. - */ -@Target({ElementType.TYPE, ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface UserCommand { - /** - * - * @return a command pattern - */ - String pattern() default StringUtils.EMPTY; - - /** - * - * @return pattern flags - */ - int patternFlags() default 0; - - /** - * - * @return a string used in HELP command output. Basically, only 1 string - */ - String help() default StringUtils.EMPTY; -} diff --git a/juick-common/src/main/java/com/juick/server/util/HttpBadRequestException.java b/juick-common/src/main/java/com/juick/server/util/HttpBadRequestException.java deleted file mode 100644 index 242f2b09..00000000 --- a/juick-common/src/main/java/com/juick/server/util/HttpBadRequestException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.util; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -/** - * Created by vt on 24/11/2016. - */ -@ResponseStatus(value = HttpStatus.BAD_REQUEST) -public class HttpBadRequestException extends RuntimeException { - public HttpBadRequestException() { - super("the request was bad", null, false, false); - } -} diff --git a/juick-common/src/main/java/com/juick/server/util/HttpForbiddenException.java b/juick-common/src/main/java/com/juick/server/util/HttpForbiddenException.java deleted file mode 100644 index 3251ca38..00000000 --- a/juick-common/src/main/java/com/juick/server/util/HttpForbiddenException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.util; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -/** - * Created by vt on 24/11/2016. - */ -@ResponseStatus(value = HttpStatus.FORBIDDEN) -public class HttpForbiddenException extends RuntimeException { - public HttpForbiddenException() { - super(StringUtils.EMPTY, null, false, false); - } - -} diff --git a/juick-common/src/main/java/com/juick/server/util/HttpNotFoundException.java b/juick-common/src/main/java/com/juick/server/util/HttpNotFoundException.java deleted file mode 100644 index f66ece8b..00000000 --- a/juick-common/src/main/java/com/juick/server/util/HttpNotFoundException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.util; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -/** - * Created by vt on 24/11/2016. - */ -@ResponseStatus(value = HttpStatus.NOT_FOUND) -public class HttpNotFoundException extends RuntimeException { - public HttpNotFoundException() { - super(StringUtils.EMPTY, null, false, false); - } -} diff --git a/juick-common/src/main/java/com/juick/server/util/HttpUtils.java b/juick-common/src/main/java/com/juick/server/util/HttpUtils.java deleted file mode 100644 index 9f356aa5..00000000 --- a/juick-common/src/main/java/com/juick/server/util/HttpUtils.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ -package com.juick.server.util; - -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.multipart.MultipartFile; - -import javax.imageio.ImageIO; -import javax.imageio.ImageReader; -import javax.imageio.stream.ImageInputStream; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; -import java.net.URLConnection; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Iterator; -import java.util.UUID; - -/** - * - * @author Ugnich Anton - */ -public class HttpUtils { - private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class); - - public static URI receiveMultiPartFile(MultipartFile attach, String tmpDir) throws IOException { - if (attach != null && !attach.isEmpty()) { - ImageInputStream iis = ImageIO.createImageInputStream(attach.getInputStream()); - Iterator readers = ImageIO.getImageReaders(iis); - - String format = StringUtils.EMPTY; - while (readers.hasNext()) { - ImageReader read = readers.next(); - format = read.getFormatName(); - } - String attachmentType = attachmentTypeFromFormat(format); - if (attachmentType.equals("jpg") || attachmentType.equals("png")) { - String attachmentFName = DigestUtils.md5Hex(UUID.randomUUID().toString()) + "." + attachmentType; - try { - Files.write(Paths.get(tmpDir, attachmentFName), - attach.getBytes()); - return URI.create(String.format("juick://%s", attachmentFName)); - } catch (IOException e) { - logger.warn("file receive error", e); - } - } - logger.warn("file type is unknown: {}", attach.getOriginalFilename()); - } - return URI.create(StringUtils.EMPTY); - } - - private static String attachmentTypeFromFormat(String format) throws IOException { - if (format != null && format.equals("JPEG")) { - return "jpg"; - } else if (format != null && format.equals("png")) { - return "png"; - } else { - throw new IOException("Wrong file type: " + format); - } - } - - public static URI downloadImage(URL url, String tmpDir) throws IOException { - ImageInputStream iis = ImageIO.createImageInputStream(url.openStream()); - Iterator readers = ImageIO.getImageReaders(iis); - - String format = StringUtils.EMPTY; - while (readers.hasNext()) { - ImageReader read = readers.next(); - format = read.getFormatName(); - } - URLConnection urlConn; - try { - urlConn = url.openConnection(); - } catch (IOException e) { - logger.error(String.format("Failed open url: %s", url.toString())); - throw e; - } - - try (InputStream is = new BufferedInputStream(urlConn.getInputStream())) { - String attachmentType = attachmentTypeFromFormat(format); - - String attachmentFName = DigestUtils.md5Hex(UUID.randomUUID().toString()) + "." + attachmentType; - Files.copy(is, Paths.get(tmpDir, attachmentFName)); - return URI.create(String.format("juick://%s", attachmentFName)); - } catch (IOException e) { - logger.error(String.format("Failed download image by url: %s", url.toString()), e); - throw e; - } - } -} diff --git a/juick-common/src/main/java/com/juick/server/util/ImageUtils.java b/juick-common/src/main/java/com/juick/server/util/ImageUtils.java deleted file mode 100644 index d16faf8f..00000000 --- a/juick-common/src/main/java/com/juick/server/util/ImageUtils.java +++ /dev/null @@ -1,175 +0,0 @@ - -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.util; - -import com.juick.Attachment; -import org.apache.commons.imaging.ImageReadException; -import org.apache.commons.imaging.Imaging; -import org.apache.commons.imaging.common.ImageMetadata; -import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata; -import org.apache.commons.imaging.formats.tiff.TiffField; -import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.imgscalr.Scalr; -import org.imgscalr.Scalr.Rotation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.imageio.ImageIO; -import javax.imageio.ImageReader; -import javax.imageio.stream.FileImageInputStream; -import javax.imageio.stream.ImageInputStream; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.Iterator; - -public class ImageUtils { - private static final Logger logger = LoggerFactory.getLogger(ImageUtils.class); - - private String imgDir; - private String tmpDir; - - public ImageUtils(String imgDir, String tmpDir) { - this.imgDir = imgDir; - this.tmpDir = tmpDir; - } -/** - * Returns BufferedImage, same as ImageIO.read() does. - * - *

JPEG images with EXIF metadata are rotated according to Orientation tag. - * - * @param imageFile a File to read from. - */ - private static BufferedImage readImageWithOrientation(File imageFile) - throws IOException { - - BufferedImage image = ImageIO.read(imageFile); - if (!FilenameUtils.getExtension(imageFile.getName()).equals("jpg")) { - return image; - } - - try { - ImageMetadata metadata = Imaging.getMetadata(imageFile); - - if (metadata instanceof JpegImageMetadata) { - JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata; - TiffField orientationField = jpegMetadata.findEXIFValue(TiffTagConstants.TIFF_TAG_ORIENTATION); - - if (orientationField != null) { - int orientation = orientationField.getIntValue(); - switch (orientation) { - case TiffTagConstants.ORIENTATION_VALUE_ROTATE_90_CW: - image = Scalr.rotate(image, Rotation.CW_90); - break; - case TiffTagConstants.ORIENTATION_VALUE_ROTATE_180: - image = Scalr.rotate(image, Rotation.CW_180); - break; - case TiffTagConstants.ORIENTATION_VALUE_ROTATE_270_CW: - image = Scalr.rotate(image, Rotation.CW_270); - break; - case TiffTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL: - image = Scalr.rotate(image, Rotation.FLIP_HORZ); - break; - case TiffTagConstants.ORIENTATION_VALUE_MIRROR_VERTICAL: - image = Scalr.rotate(image, Rotation.FLIP_VERT); - break; - case TiffTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL_AND_ROTATE_90_CW: - image = Scalr.rotate(Scalr.rotate(image, Rotation.FLIP_HORZ), Rotation.CW_90); - break; - case TiffTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL_AND_ROTATE_270_CW: - image = Scalr.rotate(Scalr.rotate(image, Rotation.FLIP_HORZ), Rotation.CW_270); - break; - case TiffTagConstants.ORIENTATION_VALUE_HORIZONTAL_NORMAL: - default: - // do nothing - break; - } - } - } - } catch (ImageReadException e) { - // failed to read metadata. - // nothing to do here, return image as is. - } - - return image; - } - - public void saveImageWithPreviews(String tempFilename, String outputFilename) - throws IOException { - String ext = FilenameUtils.getExtension(outputFilename); - - Path outputImagePath = Paths.get(imgDir, "p", outputFilename); - // this throws strange exceptions - // Files.move(Paths.get(tmpDir, tempFilename), outputImagePath); - FileUtils.moveFile(Paths.get(tmpDir, tempFilename).toFile(), outputImagePath.toFile()); - BufferedImage originalImage = readImageWithOrientation(outputImagePath.toFile()); - - int width = originalImage.getWidth(); - int height = originalImage.getHeight(); - int maxDimension = (width > height) ? width : height; - BufferedImage image1024 = (maxDimension > 1024) ? Scalr.resize(originalImage, 1024) : originalImage; - BufferedImage image0512 = (maxDimension > 512) ? Scalr.resize(originalImage, 512) : originalImage; - BufferedImage image0160 = (maxDimension > 160) ? Scalr.resize(originalImage, 160) : originalImage; - ImageIO.write(image1024, ext, Paths.get(imgDir, "photos-1024", outputFilename).toFile()); - ImageIO.write(image0512, ext, Paths.get(imgDir, "photos-512", outputFilename).toFile()); - ImageIO.write(image0160, ext, Paths.get(imgDir, "ps", outputFilename).toFile()); - } - - public void saveAvatar(String tempFilename, int uid) - throws IOException { - String ext = FilenameUtils.getExtension(tempFilename); - String originalName = String.format("%s.%s", uid, ext); - Path originalPath = Paths.get(imgDir, "ao", originalName); - Files.move(Paths.get(tmpDir, tempFilename), originalPath, StandardCopyOption.REPLACE_EXISTING); - BufferedImage originalImage = ImageIO.read(originalPath.toFile()); - - String targetExt = "png"; - String targetName = String.format("%s.%s", uid, targetExt); - ImageIO.write(Scalr.resize(originalImage, 96), targetExt, Paths.get(imgDir, "a", targetName).toFile()); - ImageIO.write(Scalr.resize(originalImage, 32), targetExt, Paths.get(imgDir, "as", targetName).toFile()); - } - public Attachment getAttachment(File imgFile) throws IOException { - Attachment attachment = new Attachment(); - try (ImageInputStream stream = ImageIO.createImageInputStream(imgFile)) { - Iterator iter = ImageIO.getImageReaders(stream); - while (iter.hasNext()) { - ImageReader reader = iter.next(); - try { - reader.setInput(stream); - attachment.setWidth(reader.getWidth(reader.getMinIndex())); - attachment.setHeight(reader.getHeight(reader.getMinIndex())); - return attachment; - } catch (Exception e) { - logger.debug("Error reading {}, trying next reader", imgFile.getAbsolutePath()); - } finally { - reader.dispose(); - } - } - } - - logger.warn("Not a known image file {}", imgFile.getAbsolutePath()); - return attachment; - } -} \ No newline at end of file diff --git a/juick-common/src/main/java/com/juick/server/util/TagUtils.java b/juick-common/src/main/java/com/juick/server/util/TagUtils.java deleted file mode 100644 index cb828933..00000000 --- a/juick-common/src/main/java/com/juick/server/util/TagUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.util; - -import com.juick.Tag; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * Created by aalexeev on 11/13/16. - */ -public class TagUtils { - private TagUtils() { - throw new IllegalStateException(); - } - - public static String toString(final List tags) { - if (CollectionUtils.isEmpty(tags)) - return StringUtils.EMPTY; - - return tags.stream().map(t -> "*" + t.getName()) - .collect(Collectors.joining(" ")); - } -} diff --git a/juick-common/src/main/java/com/juick/server/util/UserUtils.java b/juick-common/src/main/java/com/juick/server/util/UserUtils.java deleted file mode 100644 index ab5c320b..00000000 --- a/juick-common/src/main/java/com/juick/server/util/UserUtils.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.util; - -import com.juick.User; -import com.juick.server.helpers.AnonymousUser; -import com.juick.service.security.entities.JuickUser; -import javax.annotation.Nonnull; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; - -/** - * Created by aalexeev on 11/14/16. - */ -public class UserUtils { - private UserUtils() { - throw new IllegalStateException(); - } - - public static Authentication getAuthentication() { - return SecurityContextHolder.getContext().getAuthentication(); - } - - public static Object getPrincipal(final Authentication authentication) { - return authentication == null ? null : authentication.getPrincipal(); - } - - @Nonnull - public static User getCurrentUser() { - Object principal = getPrincipal(getAuthentication()); - - if (principal instanceof JuickUser) - return ((JuickUser) principal).getUser(); - - if (principal instanceof User) - return (User) principal; - - return AnonymousUser.INSTANCE; - } -} diff --git a/juick-common/src/main/java/com/juick/server/util/WebUtils.java b/juick-common/src/main/java/com/juick/server/util/WebUtils.java deleted file mode 100644 index 9dd628ee..00000000 --- a/juick-common/src/main/java/com/juick/server/util/WebUtils.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.server.util; - -import java.util.regex.Pattern; - -/** - * Created by aalexeev on 11/28/16. - */ -public class WebUtils { - private WebUtils() { - throw new IllegalStateException(); - } - - private static final Pattern USER_NAME_PATTERN = Pattern.compile("[a-zA-Z-_\\d]{2,16}"); - - private static final Pattern POST_NUMBER_PATTERN = Pattern.compile("-?\\d+"); - - private static final Pattern JID_PATTERN = Pattern.compile("^[a-zA-Z0-9\\\\-\\\\_\\\\@\\\\.]{6,64}$"); - - - public static boolean isPostNumber(final String aString) { - return aString != null && POST_NUMBER_PATTERN.matcher(aString).matches(); - } - - public static boolean isNotPostNumber(final String aString) { - return !isPostNumber(aString); - } - - public static boolean isUserName(final String aString) { - return aString != null && USER_NAME_PATTERN.matcher(aString).matches(); - } - - public static boolean isNotUserName(final String aString) { - return !isUserName(aString); - } - - public static boolean isJid(final String aString) { - return aString != null && JID_PATTERN.matcher(aString).matches(); - } - - public static boolean isNotJid(final String aString) { - return !isJid(aString); - } - - -} diff --git a/juick-common/src/main/java/com/juick/service/CrosspostService.java b/juick-common/src/main/java/com/juick/service/CrosspostService.java index 38481d72..99911250 100644 --- a/juick-common/src/main/java/com/juick/service/CrosspostService.java +++ b/juick-common/src/main/java/com/juick/service/CrosspostService.java @@ -18,7 +18,7 @@ package com.juick.service; import com.juick.ExternalToken; -import com.juick.server.helpers.ApplicationStatus; +import com.juick.model.ApplicationStatus; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nonnull; diff --git a/juick-common/src/main/java/com/juick/service/ImagesServiceImpl.java b/juick-common/src/main/java/com/juick/service/ImagesServiceImpl.java deleted file mode 100644 index 67c8360e..00000000 --- a/juick-common/src/main/java/com/juick/service/ImagesServiceImpl.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.juick.service; - -import com.juick.Attachment; -import com.juick.Message; -import com.juick.Photo; -import com.juick.server.util.ImageUtils; -import org.springframework.util.StringUtils; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Paths; - -public class ImagesServiceImpl implements ImagesService { - private ImageUtils imageUtils; - private String imgDir; - private String tmpDir; - public ImagesServiceImpl(String imgDir, String tmpDir) { - this.imgDir = imgDir; - this.tmpDir = tmpDir; - imageUtils = new ImageUtils(imgDir, tmpDir); - } - @Override - public void setAttachmentMetadata(String baseUrl, Message msg) throws Exception { - if (!StringUtils.isEmpty(msg.getAttachmentType())) { - Photo photo = new Photo(); - if (msg.getRid()> 0) { - photo.setSmall(String.format("%sphotos-512/%d-%d.%s", baseUrl, msg.getMid(), msg.getRid(), msg.getAttachmentType())); - photo.setMedium(String.format("%sphotos-1024/%d-%d.%s", baseUrl, msg.getMid(), msg.getRid(), msg.getAttachmentType())); - photo.setThumbnail(String.format("%sps/%d-%d.%s", baseUrl, msg.getMid(), msg.getRid(), msg.getAttachmentType())); - } else { - photo.setSmall(String.format("%sphotos-512/%d.%s", baseUrl, msg.getMid(), msg.getAttachmentType())); - photo.setMedium(String.format("%sphotos-1024/%d.%s", baseUrl, msg.getMid(), msg.getAttachmentType())); - photo.setThumbnail(String.format("%sps/%d.%s", baseUrl, msg.getMid(), msg.getAttachmentType())); - } - msg.setPhoto(photo); - String imageName = String.format("%s.%s", msg.getMid(), msg.getAttachmentType()); - if (msg.getRid() > 0) { - imageName = String.format("%s-%s.%s", msg.getMid(), msg.getRid(), msg.getAttachmentType()); - } - File fullImage = Paths.get(imgDir, "p", imageName).toFile(); - File mediumImage = Paths.get(imgDir, "photos-1024", imageName).toFile(); - File smallImage = Paths.get(imgDir, "photos-512", imageName).toFile(); - File thumbnailImage = Paths.get(imgDir, "ps", imageName).toFile(); - StringBuilder builder = new StringBuilder(); - builder.append(baseUrl); - builder.append(msg.getAttachmentType().equals("mp4") ? "video" : "p"); - builder.append("/").append(msg.getMid()); - if (msg.getRid() > 0) { - builder.append("-").append(msg.getRid()); - } - builder.append(".").append(msg.getAttachmentType()); - String originalUrl = builder.toString(); - - Attachment original = imageUtils.getAttachment(fullImage); - original.setUrl(originalUrl); - - Attachment medium = imageUtils.getAttachment(mediumImage); - medium.setUrl(photo.getMedium()); - original.setMedium(medium); - - Attachment small = imageUtils.getAttachment(smallImage); - small.setUrl(photo.getSmall()); - original.setSmall(small); - - Attachment thumb = imageUtils.getAttachment(thumbnailImage); - thumb.setUrl(photo.getMedium()); - original.setThumbnail(thumb); - - msg.setAttachment(original); - } - } - - @Override - public void saveImageWithPreviews(String tempFilename, String outputFilename) throws IOException { - imageUtils.saveImageWithPreviews(tempFilename, outputFilename); - } - - @Override - public void saveAvatar(String tempFilename, int uid) throws IOException { - imageUtils.saveAvatar(tempFilename, uid); - } -} diff --git a/juick-common/src/main/java/com/juick/service/MessagesService.java b/juick-common/src/main/java/com/juick/service/MessagesService.java index 77ded81e..5a3ff30a 100644 --- a/juick-common/src/main/java/com/juick/service/MessagesService.java +++ b/juick-common/src/main/java/com/juick/service/MessagesService.java @@ -17,10 +17,9 @@ package com.juick.service; -import com.juick.Message; import com.juick.Reaction; import com.juick.User; -import com.juick.server.helpers.ResponseReply; +import com.juick.model.ResponseReply; import java.util.Collection; import java.util.List; diff --git a/juick-common/src/main/java/com/juick/service/SubscriptionService.java b/juick-common/src/main/java/com/juick/service/SubscriptionService.java index d2ff9962..8132ec10 100644 --- a/juick-common/src/main/java/com/juick/service/SubscriptionService.java +++ b/juick-common/src/main/java/com/juick/service/SubscriptionService.java @@ -20,7 +20,7 @@ package com.juick.service; import com.juick.Message; import com.juick.Tag; import com.juick.User; -import com.juick.server.helpers.NotifyOpts; +import com.juick.model.NotifyOpts; import java.util.List; diff --git a/juick-common/src/main/java/com/juick/service/TagService.java b/juick-common/src/main/java/com/juick/service/TagService.java index 7f89b478..489f405a 100644 --- a/juick-common/src/main/java/com/juick/service/TagService.java +++ b/juick-common/src/main/java/com/juick/service/TagService.java @@ -19,7 +19,7 @@ package com.juick.service; import com.juick.Tag; import com.juick.User; -import com.juick.server.helpers.TagStats; +import com.juick.model.TagStats; import org.apache.commons.lang3.tuple.Pair; import java.util.Collection; diff --git a/juick-common/src/main/java/com/juick/service/UserService.java b/juick-common/src/main/java/com/juick/service/UserService.java index 0c3709da..d59f71ef 100644 --- a/juick-common/src/main/java/com/juick/service/UserService.java +++ b/juick-common/src/main/java/com/juick/service/UserService.java @@ -19,8 +19,8 @@ package com.juick.service; import com.juick.Message; import com.juick.User; -import com.juick.server.helpers.Auth; -import com.juick.server.helpers.UserInfo; +import com.juick.model.Auth; +import com.juick.model.UserInfo; import javax.annotation.Nonnull; import java.util.Collection; diff --git a/juick-common/src/main/java/com/juick/service/component/DisconnectedEvent.java b/juick-common/src/main/java/com/juick/service/component/DisconnectedEvent.java new file mode 100644 index 00000000..552c3e66 --- /dev/null +++ b/juick-common/src/main/java/com/juick/service/component/DisconnectedEvent.java @@ -0,0 +1,14 @@ +package com.juick.service.component; + +import org.springframework.context.ApplicationEvent; + +public class DisconnectedEvent extends ApplicationEvent { + /** + * Create a new ApplicationEvent. + * + * @param source the object on which the event initially occurred (never {@code null}) + */ + public DisconnectedEvent(Object source) { + super(source); + } +} diff --git a/juick-common/src/main/java/com/juick/service/component/LikeEvent.java b/juick-common/src/main/java/com/juick/service/component/LikeEvent.java new file mode 100644 index 00000000..0d4df70c --- /dev/null +++ b/juick-common/src/main/java/com/juick/service/component/LikeEvent.java @@ -0,0 +1,36 @@ +package com.juick.service.component; + +import com.juick.Message; +import com.juick.User; +import org.springframework.context.ApplicationEvent; + +import java.util.List; + +public class LikeEvent extends ApplicationEvent { + private User user; + private Message message; + private List subscribers; + /** + * Create a new ApplicationEvent. + * + * @param source the object on which the event initially occurred (never {@code null}) + */ + public LikeEvent(Object source, User user, Message message, List subscribers) { + super(source); + this.message = message; + this.user = user; + this.subscribers = subscribers; + } + + public User getUser() { + return user; + } + + public Message getMessage() { + return message; + } + + public List getSubscribers() { + return subscribers; + } +} diff --git a/juick-common/src/main/java/com/juick/service/component/MessageEvent.java b/juick-common/src/main/java/com/juick/service/component/MessageEvent.java new file mode 100644 index 00000000..82911a58 --- /dev/null +++ b/juick-common/src/main/java/com/juick/service/component/MessageEvent.java @@ -0,0 +1,31 @@ +package com.juick.service.component; + +import com.juick.Message; +import com.juick.User; +import org.springframework.context.ApplicationEvent; + +import java.util.List; + +public class MessageEvent extends ApplicationEvent { + private Message message; + private List users; + /** + * Create a new ApplicationEvent. + * + * @param source the object on which the event initially occurred (never {@code null}) + * @param message app message + * @param interestedUsers users interested in notification + */ + public MessageEvent(Object source, Message message, List interestedUsers) { + super(source); + this.message = message; + this.users = interestedUsers; + } + + public Message getMessage() { + return message; + } + public List getUsers() { + return users; + } +} diff --git a/juick-common/src/main/java/com/juick/service/component/MessageReadEvent.java b/juick-common/src/main/java/com/juick/service/component/MessageReadEvent.java new file mode 100644 index 00000000..82cfadd5 --- /dev/null +++ b/juick-common/src/main/java/com/juick/service/component/MessageReadEvent.java @@ -0,0 +1,28 @@ +package com.juick.service.component; + +import com.juick.Message; +import com.juick.User; +import org.springframework.context.ApplicationEvent; + +public class MessageReadEvent extends ApplicationEvent { + private User user; + private Message message; + /** + * Create a new ApplicationEvent. + * + * @param source the object on which the event initially occurred (never {@code null}) + */ + public MessageReadEvent(Object source, User user, Message message) { + super(source); + this.user = user; + this.message = message; + } + + public User getUser() { + return user; + } + + public Message getMessage() { + return message; + } +} diff --git a/juick-common/src/main/java/com/juick/service/component/PingEvent.java b/juick-common/src/main/java/com/juick/service/component/PingEvent.java new file mode 100644 index 00000000..8e3f3fa7 --- /dev/null +++ b/juick-common/src/main/java/com/juick/service/component/PingEvent.java @@ -0,0 +1,21 @@ +package com.juick.service.component; + +import com.juick.User; +import org.springframework.context.ApplicationEvent; + +public class PingEvent extends ApplicationEvent { + private User pinger; + /** + * Create a new ApplicationEvent. + * + * @param source the object on which the event initially occurred (never {@code null}) + */ + public PingEvent(Object source, User pinger) { + super(source); + this.pinger = pinger; + } + + public User getPinger() { + return pinger; + } +} diff --git a/juick-common/src/main/java/com/juick/service/component/SubscribeEvent.java b/juick-common/src/main/java/com/juick/service/component/SubscribeEvent.java new file mode 100644 index 00000000..9b644f2f --- /dev/null +++ b/juick-common/src/main/java/com/juick/service/component/SubscribeEvent.java @@ -0,0 +1,27 @@ +package com.juick.service.component; + +import com.juick.User; +import org.springframework.context.ApplicationEvent; + +public class SubscribeEvent extends ApplicationEvent { + private User user; + private User toUser; + /** + * Create a new ApplicationEvent. + * + * @param source the object on which the event initially occurred (never {@code null}) + */ + public SubscribeEvent(Object source, User user, User toUser) { + super(source); + this.user = user; + this.toUser = toUser; + } + + public User getUser() { + return user; + } + + public User getToUser() { + return toUser; + } +} diff --git a/juick-common/src/main/java/com/juick/service/component/UserUpdatedEvent.java b/juick-common/src/main/java/com/juick/service/component/UserUpdatedEvent.java new file mode 100644 index 00000000..af2f579a --- /dev/null +++ b/juick-common/src/main/java/com/juick/service/component/UserUpdatedEvent.java @@ -0,0 +1,23 @@ +package com.juick.service.component; + +import com.juick.User; +import org.springframework.context.ApplicationEvent; +import org.springframework.lang.NonNull; + +public class UserUpdatedEvent extends ApplicationEvent { + private User user; + /** + * Generated when user is updated (avatar changed, etc). + * + * @param source the object on which the event initially occurred (never {@code null}) + * @param user updated user + */ + public UserUpdatedEvent(@NonNull Object source, User user) { + super(source); + this.user = user; + } + + public User getUser() { + return user; + } +} diff --git a/juick-common/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java b/juick-common/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java deleted file mode 100644 index 9215d09a..00000000 --- a/juick-common/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service.security; - -import com.juick.User; -import com.juick.service.security.entities.JuickUser; -import com.juick.service.UserService; -import org.springframework.security.authentication.AnonymousAuthenticationToken; -import org.springframework.security.authentication.RememberMeAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.RememberMeServices; -import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; -import org.springframework.util.Assert; -import org.springframework.web.filter.OncePerRequestFilter; -import org.springframework.web.util.WebUtils; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Created by aalexeev on 4/5/17. - */ -public class HashParamAuthenticationFilter extends OncePerRequestFilter { - public static final String PARAM_NAME = "hash"; - - private final UserService userService; - private final RememberMeServices rememberMeServices; - - - public HashParamAuthenticationFilter( - final UserService userService, - final RememberMeServices rememberMeServices) { - Assert.notNull(userService, "userService should not be null"); - Assert.notNull(rememberMeServices, "rememberMeServices should not be null"); - - this.userService = userService; - this.rememberMeServices = rememberMeServices; - } - - @Override - protected void doFilterInternal( - HttpServletRequest request, - HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { - - String hash = getHashFromRequest(request); - - if (hash != null && authenticationIsRequired()) { - User user = userService.getUserByHash(hash); - - if (!user.isAnonymous()) { - User userWithPassword = userService.getUserByName(user.getName()); - userWithPassword.setAuthHash(userService.getHashByUID(userWithPassword.getUid())); - Authentication authentication = new RememberMeAuthenticationToken( - ((AbstractRememberMeServices)rememberMeServices).getKey(), new JuickUser(userWithPassword), JuickUser.USER_AUTHORITY); - - SecurityContextHolder.getContext().setAuthentication(authentication); - - rememberMeServices.loginSuccess(request, response, authentication); - } - } - - filterChain.doFilter(request, response); - } - - private boolean authenticationIsRequired() { - Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication(); - - return existingAuth == null || - !existingAuth.isAuthenticated() || - existingAuth instanceof AnonymousAuthenticationToken; - } - - private String getHashFromRequest(HttpServletRequest request) { - String paramHash = request.getParameter(PARAM_NAME); - Cookie cookieHash = WebUtils.getCookie(request, PARAM_NAME); - - if (paramHash == null && cookieHash != null) { - return cookieHash.getValue(); - } - return paramHash; - } -} diff --git a/juick-common/src/main/java/com/juick/service/security/JuickUserDetailsService.java b/juick-common/src/main/java/com/juick/service/security/JuickUserDetailsService.java deleted file mode 100644 index 59425fab..00000000 --- a/juick-common/src/main/java/com/juick/service/security/JuickUserDetailsService.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service.security; - -import com.juick.service.UserService; -import com.juick.service.security.entities.JuickUser; -import org.apache.commons.lang3.StringUtils; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.util.Assert; - -/** - * Created by aalexeev on 11/28/16. - */ -public class JuickUserDetailsService implements UserDetailsService { - private final UserService userService; - - public JuickUserDetailsService(final UserService userService) { - Assert.notNull(userService, "UserService must be initialized"); - this.userService = userService; - } - - @Override - public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { - if (StringUtils.isBlank(username)) - throw new UsernameNotFoundException("Invalid user name " + username); - - com.juick.User user = userService.getUserByName(username); - - if (!user.isAnonymous()) { - user.setAuthHash(userService.getHashByUID(user.getUid())); - return new JuickUser(user); - } - - throw new UsernameNotFoundException("The username " + username + " is not found"); - } -} diff --git a/juick-common/src/main/java/com/juick/service/security/NullUserDetailsService.java b/juick-common/src/main/java/com/juick/service/security/NullUserDetailsService.java deleted file mode 100644 index 91acefa3..00000000 --- a/juick-common/src/main/java/com/juick/service/security/NullUserDetailsService.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service.security; - -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; - -/** - * Created by aalexeev on 11/28/16. - */ -public class NullUserDetailsService implements UserDetailsService { - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - throw new UsernameNotFoundException( - "loadUserByUsername called for NullUserDetailsService, user " + username + "can not be found"); - } -} diff --git a/juick-common/src/main/java/com/juick/service/security/deprecated/CookieSimpleHashRememberMeServices.java b/juick-common/src/main/java/com/juick/service/security/deprecated/CookieSimpleHashRememberMeServices.java deleted file mode 100644 index e385d7dd..00000000 --- a/juick-common/src/main/java/com/juick/service/security/deprecated/CookieSimpleHashRememberMeServices.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service.security.deprecated; - -import com.juick.User; -import com.juick.service.security.entities.JuickUser; -import com.juick.service.UserService; -import com.juick.service.security.NullUserDetailsService; -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.env.Environment; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.web.authentication.RememberMeServices; -import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; -import org.springframework.security.web.authentication.rememberme.InvalidCookieException; -import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException; -import org.springframework.util.Assert; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.Optional; - -/** - * Created by aalexeev on 11/28/16. - * - * @deprecated not recommended use for secure reasons - */ -@Deprecated -public class CookieSimpleHashRememberMeServices extends AbstractRememberMeServices implements RememberMeServices { - private static final Logger logger = LoggerFactory.getLogger(CookieSimpleHashRememberMeServices.class); - - private static final String COOKIE_PARAM_NAME = "hash"; - - private final UserService userService; - - public CookieSimpleHashRememberMeServices( - final String key, final UserService userService, final Environment environment) { - super(key, new NullUserDetailsService()); - - Assert.notNull(userService); - Assert.notNull(environment); - - this.userService = userService; - - setCookieName(COOKIE_PARAM_NAME); - setCookieDomain(environment.getProperty("web_domain", "localhost")); - setAlwaysRemember(true); - } - - @Override - public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { - super.logout(request, response, authentication); - userService.deleteLoginForUser(authentication.getName()); - } - - @Override - protected void onLoginSuccess( - HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { - String username = successfulAuthentication.getName(); - - logger.debug("Creating new persistent login for user {}", username); - - try { - int uid = userService.getUIDbyName(username); - - Assert.isTrue(uid > 0); - - String hash = RandomStringUtils.randomAlphanumeric(16).toUpperCase(); - - userService.setLoginForUser(uid, hash); - - setCookie(new String[]{hash}, getTokenValiditySeconds(), request, response); - } catch (Exception e) { - logger.error("Failed to save cookies", e); - } - } - - @Override - protected UserDetails processAutoLoginCookie( - String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) - throws RememberMeAuthenticationException, UsernameNotFoundException { - String hash = cookieTokens[0]; - - if (StringUtils.isBlank(hash)) { - hash = request.getParameter("hash"); - } - if (StringUtils.isBlank(hash)) { - throw new InvalidCookieException("Cookie is invalid and hash parameter not found"); - } - - int uid = userService.getUIDbyHash(hash); - if (uid <= 0) - throw new UsernameNotFoundException("User not found by hash, cookies" + cookieTokens); - - Optional userOptional = userService.getUserByUID(uid); - - Assert.isTrue(userOptional.isPresent()); - - return new JuickUser(userService.getUserByName(userOptional.get().getName())); - } - - @Override - protected String[] decodeCookie(String cookieValue) throws InvalidCookieException { - return new String[]{cookieValue}; - } - - @Override - protected String encodeCookie(String[] cookieTokens) { - return cookieTokens != null && cookieTokens.length > 0 ? cookieTokens[0] : StringUtils.EMPTY; - } -} diff --git a/juick-common/src/main/java/com/juick/service/security/deprecated/RequestParamHashRememberMeServices.java b/juick-common/src/main/java/com/juick/service/security/deprecated/RequestParamHashRememberMeServices.java deleted file mode 100644 index 3631e5a4..00000000 --- a/juick-common/src/main/java/com/juick/service/security/deprecated/RequestParamHashRememberMeServices.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service.security.deprecated; - -import com.juick.User; -import com.juick.service.security.entities.JuickUser; -import com.juick.service.UserService; -import com.juick.service.security.NullUserDetailsService; -import org.apache.commons.lang3.StringUtils; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.web.authentication.RememberMeServices; -import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; -import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException; -import org.springframework.util.Assert; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * Created by aalexeev on 11/30/16. - * - * @deprecated for security reasons - */ -@Deprecated -public class RequestParamHashRememberMeServices extends AbstractRememberMeServices implements RememberMeServices { - private static final String PARAM_NAME = "hash"; - - private final UserService userService; - - public RequestParamHashRememberMeServices(String key, UserService userService) { - super(key, new NullUserDetailsService()); - - Assert.notNull(userService); - this.userService = userService; - setAlwaysRemember(false); - } - - @Override - protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { - // do nothing - } - - @Override - protected boolean rememberMeRequested(HttpServletRequest request, String parameter) { - return false; // always false - } - - @Override - protected void cancelCookie(HttpServletRequest request, HttpServletResponse response) { - // do nothing - } - - @Override - protected String extractRememberMeCookie(HttpServletRequest request) { - return PARAM_NAME; // return any not blank value - } - - @Override - protected UserDetails processAutoLoginCookie( - String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) - throws RememberMeAuthenticationException, UsernameNotFoundException { - String hash = request.getParameter(PARAM_NAME); - - if (StringUtils.isNotBlank(hash)) { - User user = userService.getUserByHash(hash); - if (!user.isAnonymous()) - return new JuickUser(userService.getUserByName(user.getName())); - } - throw new UsernameNotFoundException("User not found by hash " + hash); - } -} diff --git a/juick-common/src/main/java/com/juick/service/security/entities/JuickUser.java b/juick-common/src/main/java/com/juick/service/security/entities/JuickUser.java deleted file mode 100644 index 606a5688..00000000 --- a/juick-common/src/main/java/com/juick/service/security/entities/JuickUser.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.service.security.entities; - -import com.juick.User; -import com.juick.server.helpers.AnonymousUser; -import org.apache.commons.lang3.StringUtils; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Created by aalexeev on 11/21/16. - */ -public class JuickUser implements UserDetails { - static final GrantedAuthority ROLE_USER = new SimpleGrantedAuthority("ROLE_USER"); - static final GrantedAuthority ROLE_ANONYMOUS = new SimpleGrantedAuthority("ROLE_ANONYMOUS"); - - public static final List USER_AUTHORITY = Collections.singletonList(ROLE_USER); - public static final List ANONYMOUS_AUTHORITY = Collections.singletonList(ROLE_ANONYMOUS); - - public static final JuickUser ANONYMOUS_USER = new JuickUser(AnonymousUser.INSTANCE, ANONYMOUS_AUTHORITY); - - private final com.juick.User user; - private final Collection authorities; - - public JuickUser(com.juick.User user) { - this(user, USER_AUTHORITY); - } - - public JuickUser(com.juick.User user, Collection authorities) { - this.user = user; - this.authorities = authorities; - } - - @Override - public Collection getAuthorities() { - return authorities; - } - - @Override - public String getPassword() { - return "{noop}" + user.getCredentials(); - } - - @Override - public String getUsername() { - return user.getName(); - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return StringUtils.isNotBlank(user.getCredentials()); - } - - @Override - public boolean isCredentialsNonExpired() { - return isAccountNonLocked(); - } - - @Override - public boolean isEnabled() { - return !user.isBanned() && isCredentialsNonExpired(); - } - - public User getUser() { - return user; - } -} diff --git a/juick-common/src/main/java/com/juick/twitter/User.java b/juick-common/src/main/java/com/juick/twitter/User.java deleted file mode 100644 index 0b4b9c87..00000000 --- a/juick-common/src/main/java/com/juick/twitter/User.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.twitter; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Created by vitalyster on 28.11.2016. - */ -@JsonIgnoreProperties(ignoreUnknown = true) -public class User { - private String screenName; - - @JsonProperty("screen_name") - public String getScreenName() { - return screenName; - } - - public void setScreenName(String screenName) { - this.screenName = screenName; - } -} diff --git a/juick-common/src/main/java/com/juick/vk/Token.java b/juick-common/src/main/java/com/juick/vk/Token.java deleted file mode 100644 index 979c572c..00000000 --- a/juick-common/src/main/java/com/juick/vk/Token.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.vk; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Created by vitalyster on 28.11.2016. - */ -public class Token { - private Long userId; - private String accessToken; - private String expiresIn; - - @JsonProperty("user_id") - public Long getUserId() { - return userId; - } - - public void setUserId(Long userId) { - this.userId = userId; - } - - @JsonProperty("access_token") - public String getAccessToken() { - return accessToken; - } - - public void setAccessToken(String accessToken) { - this.accessToken = accessToken; - } - - @JsonProperty("expires_in") - public String getExpiresIn() { - return expiresIn; - } - - public void setExpiresIn(String expiresIn) { - this.expiresIn = expiresIn; - } -} diff --git a/juick-common/src/main/java/com/juick/vk/User.java b/juick-common/src/main/java/com/juick/vk/User.java deleted file mode 100644 index 00025497..00000000 --- a/juick-common/src/main/java/com/juick/vk/User.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.vk; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Created by vitalyster on 28.11.2016. - */ -public class User { - private String id; - private String firstName; - private String lastName; - private String screenName; - - @JsonProperty("first_name") - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - @JsonProperty("last_name") - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - @JsonProperty("screen_name") - public String getScreenName() { - return screenName; - } - - public void setScreenName(String screenName) { - this.screenName = screenName; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } -} diff --git a/juick-common/src/main/java/com/juick/vk/UsersResponse.java b/juick-common/src/main/java/com/juick/vk/UsersResponse.java deleted file mode 100644 index 83092c99..00000000 --- a/juick-common/src/main/java/com/juick/vk/UsersResponse.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2008-2017, 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 . - */ - -package com.juick.vk; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.util.List; - -/** - * Created by vitalyster on 28.11.2016. - */ -public class UsersResponse { - private List users; - - @JsonProperty("response") - public List getUsers() { - return users; - } - - public void setUsers(List users) { - this.users = users; - } -} diff --git a/juick-notifications/build.gradle b/juick-notifications/build.gradle index 10207a7f..b5b7bd89 100644 --- a/juick-notifications/build.gradle +++ b/juick-notifications/build.gradle @@ -1,9 +1,12 @@ apply plugin: 'java' apply plugin: 'org.springframework.boot' -apply plugin: 'io.spring.dependency-management' dependencies { compile project(':juick-common') + compile("org.springframework.boot:spring-boot-starter-websocket") { + exclude module: "spring-boot-starter-tomcat" + exclude module: "spring-boot-starter-web" + } compile 'com.ganyo:gcm-server:1.1.0' compile 'com.turo:pushy:0.13.4' } diff --git a/juick-notifications/src/main/java/com/juick/components/Notifications.java b/juick-notifications/src/main/java/com/juick/components/Notifications.java index 79afe8fa..1842593a 100644 --- a/juick-notifications/src/main/java/com/juick/components/Notifications.java +++ b/juick-notifications/src/main/java/com/juick/components/Notifications.java @@ -22,7 +22,7 @@ import com.google.android.gcm.server.*; import com.juick.ExternalToken; import com.juick.User; import com.juick.formatters.PlainTextFormatter; -import com.juick.server.component.DisconnectedEvent; +import com.juick.service.component.DisconnectedEvent; import com.juick.util.MessageUtils; import com.turo.pushy.apns.ApnsClient; import com.turo.pushy.apns.PushNotificationResponse; diff --git a/juick-notifications/src/main/java/com/juick/components/service/JuickServerReconnectManager.java b/juick-notifications/src/main/java/com/juick/components/service/JuickServerReconnectManager.java index 1f19eec9..b490c154 100644 --- a/juick-notifications/src/main/java/com/juick/components/service/JuickServerReconnectManager.java +++ b/juick-notifications/src/main/java/com/juick/components/service/JuickServerReconnectManager.java @@ -1,6 +1,6 @@ package com.juick.components.service; -import com.juick.server.component.DisconnectedEvent; +import com.juick.service.component.DisconnectedEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationListener; diff --git a/juick-server/build.gradle b/juick-server/build.gradle index 722ff09d..9a6196da 100644 --- a/juick-server/build.gradle +++ b/juick-server/build.gradle @@ -65,6 +65,9 @@ dependencies { compile("org.springframework.boot:spring-boot-starter-cache") compile ('org.springframework.boot:spring-boot-starter-security') compile ('org.springframework.boot:spring-boot-starter-jdbc') + compile("org.springframework.boot:spring-boot-starter-security") + compile("org.springframework.boot:spring-boot-starter-web") + compile("org.springframework.boot:spring-boot-starter-websocket") compileOnly 'io.springfox:springfox-core:2.9.2' diff --git a/juick-server/src/main/java/com/juick/server/CommandsManager.java b/juick-server/src/main/java/com/juick/server/CommandsManager.java new file mode 100644 index 00000000..018cef15 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/CommandsManager.java @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server; + +import com.juick.Message; +import com.juick.Tag; +import com.juick.User; +import com.juick.formatters.PlainTextFormatter; +import com.juick.service.component.*; +import com.juick.model.CommandResult; +import com.juick.model.TagStats; +import com.juick.server.helpers.annotation.UserCommand; +import com.juick.server.util.HttpUtils; +import com.juick.service.*; +import com.juick.util.MessageUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.lang3.reflect.MethodUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +import javax.annotation.Nonnull; +import javax.inject.Inject; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * + * @author ugnich + */ +@Component +public class CommandsManager { + @Inject + private MessagesService messagesService; + @Inject + private UserService userService; + @Inject + private TagService tagService; + @Inject + private PMQueriesService pmQueriesService; + @Inject + private ShowQueriesService showQueriesService; + @Inject + private PrivacyQueriesService privacyQueriesService; + @Inject + private SubscriptionService subscriptionService; + @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") + private String tmpDir; + @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}") + private String imgDir; + @Inject + private ApplicationEventPublisher applicationEventPublisher; + @Inject + private ImagesService imagesService; + + public CommandResult processCommand(User user, String data, @Nonnull URI attachment) throws Exception { + String strippedData = StringUtils.stripStart(data, null); + if (strippedData.startsWith("?OTR")) { + return CommandResult.fromString("?OTR Error: we are not using OTR"); + } + String input = MessageUtils.stripNonSafeUrls(strippedData); + Optional cmd = MethodUtils.getMethodsListWithAnnotation(getClass(), UserCommand.class).stream() + .filter(m -> Pattern.compile(m.getAnnotation(UserCommand.class).pattern(), + m.getAnnotation(UserCommand.class).patternFlags()).matcher(input).matches()) + .findFirst(); + if (cmd.isPresent()) { + Matcher matcher = Pattern.compile(cmd.get().getAnnotation(UserCommand.class).pattern(), + cmd.get().getAnnotation(UserCommand.class).patternFlags()).matcher(input); + List groups = new ArrayList<>(); + while (matcher.find()) { + for (int i = 1; i <= matcher.groupCount(); i++) { + groups.add(matcher.group(i)); + } + } + CommandResult commandResult = (CommandResult) getClass().getMethod(cmd.get().getName(), User.class, URI.class, String[].class) + .invoke(this, user, attachment, groups.toArray(new String[groups.size()])); + if (StringUtils.isNotEmpty(commandResult.getText())) { + return commandResult; + } + } + Pair> tags = tagService.fromString(input); + if (tags.getRight().size() > 5) { + return CommandResult.fromString("Sorry, 5 tags maximum."); + } + // new message + String body = tags.getLeft().trim(); + boolean haveAttachment = StringUtils.isNotEmpty(attachment.toString()); + String attachmentFName = null; + String attachmentType = null; + if (haveAttachment) { + attachmentFName = attachment.getScheme().equals("juick") ? attachment.getHost() + : HttpUtils.downloadImage(attachment.toURL(), tmpDir).getHost(); + attachmentType = attachmentFName.substring(attachmentFName.length() - 3); + } + int mid = messagesService.createMessage(user.getUid(), body, attachmentType, tags.getRight()); + if (haveAttachment) { + String fname = String.format("%d.%s", mid, attachmentType); + imagesService.saveImageWithPreviews(attachmentFName, fname); + } + Message msg = messagesService.getMessage(mid); + subscriptionService.subscribeMessage(msg, user); + + applicationEventPublisher.publishEvent(new MessageReadEvent(this, user, msg)); + applicationEventPublisher.publishEvent(new MessageEvent(this, msg, subscriptionService.getSubscribedUsers(msg.getUser().getUid(), msg.getMid()))); + return CommandResult.build(msg, "New message posted.\n#" + msg.getMid() + " https://juick.com/m/" + msg.getMid(), String.format("[New message](%s) posted", PlainTextFormatter.formatUrl(msg))); + } + + @UserCommand(pattern = "^ping$", patternFlags = Pattern.CASE_INSENSITIVE, + help = "PING - returns you a PONG") + public CommandResult commandPing(User user, URI attachment, String[] input) { + applicationEventPublisher.publishEvent(new PingEvent(this, user)); + return CommandResult.fromString("PONG"); + } + + @UserCommand(pattern = "^help$", patternFlags = Pattern.CASE_INSENSITIVE, + help = "HELP - returns this help message") + public CommandResult commandHelp(User user, URI attachment, String[] input) { + return CommandResult.fromString(Arrays.stream(getClass().getDeclaredMethods()) + .filter(m -> m.isAnnotationPresent(UserCommand.class)) + .map(m -> m.getAnnotation(UserCommand.class).help()) + .collect(Collectors.joining("\n"))); + } + + @UserCommand(pattern = "^login$", patternFlags = Pattern.CASE_INSENSITIVE, + help = "LOGIN - log in to Juick website") + public CommandResult commandLogin(User user_from, URI attachment, String[] input) { + return CommandResult.fromString("http://juick.com/login?hash=" + userService.getHashByUID(user_from.getUid())); + } + @UserCommand(pattern = "^\\@(\\S+)\\s+([\\s\\S]+)$", help = "@username message - send PM to username") + public CommandResult commandPM(User user_from, URI attachment, String... arguments) { + String body = arguments[1]; + + User user_to = userService.getUserByName(arguments[0]); + + if (!user_to.isAnonymous()) { + if (!userService.isInBLAny(user_to.getUid(), user_from.getUid())) { + if (pmQueriesService.createPM(user_from.getUid(), user_to.getUid(), body)) { + com.juick.Message jmsg = new com.juick.Message(); + jmsg.setUser(user_from); + jmsg.setTo(user_to); + jmsg.setText(body); + applicationEventPublisher.publishEvent(new MessageEvent(this, jmsg, Collections.singletonList(user_to))); + return CommandResult.fromString("Private message sent"); + } + } + } + return CommandResult.fromString("Error"); + } + @UserCommand(pattern = "^bl$", patternFlags = Pattern.CASE_INSENSITIVE, + help = "BL - Show your blacklist") + public CommandResult commandBLShow(User user_from, URI attachment, String... arguments) { + List blusers = userService.getUserBLUsers(user_from.getUid()); + List bltags = tagService.getUserBLTags(user_from.getUid()); + + String txt = StringUtils.EMPTY; + if (bltags.size() > 0) { + for (String bltag : bltags) { + txt += "*" + bltag + "\n"; + } + + if (blusers.size() > 0) { + txt += "\n"; + } + } + if (blusers.size() > 0) { + for (User bluser : blusers) { + txt += "@" + bluser.getName() + "\n"; + } + } + if (txt.isEmpty()) { + txt = "You don't have any users or tags in your blacklist."; + } + + return CommandResult.fromString(txt); + } + + @UserCommand(pattern = "^#\\+$", help = "#+ - Show last Juick messages") + public CommandResult commandLast(User user_from, URI attachment, String... arguments) { + return CommandResult.fromString("Last messages:\n" + + printMessages(user_from, messagesService.getAll(user_from.getUid(), 0), true)); + } + + @UserCommand(pattern = "@", help = "@ - Show recommendations and popular personal blogs") + public CommandResult commandUsers(User user_from, URI attachment, String... arguments) { + StringBuilder msg = new StringBuilder(); + msg.append("Recommended blogs"); + List recommendedUsers = showQueriesService.getRecommendedUsers(user_from); + if (recommendedUsers.size() > 0) { + for (String user : recommendedUsers) { + msg.append("\n@").append(user); + } + } else { + msg.append("\nNo recommendations now. Subscribe to more blogs. ;)"); + } + msg.append("\n\nTop 10 personal blogs:"); + List topUsers = showQueriesService.getTopUsers(); + if (topUsers.size() > 0) { + for (String user : topUsers) { + msg.append("\n@").append(user); + } + } else { + msg.append("\nNo top users. Empty DB? ;)"); + } + return CommandResult.fromString(msg.toString()); + } + @UserCommand(pattern = "^bl\\s+@([^\\s\\n\\+]+)", patternFlags = Pattern.CASE_INSENSITIVE, + help = "BL @username - add @username to your blacklist") + public CommandResult blacklistUser(User user_from, URI attachment, String... arguments) { + User blUser = userService.getUserByName(arguments[0]); + if (!blUser.isAnonymous()) { + PrivacyQueriesService.PrivacyResult result = privacyQueriesService.blacklistUser(user_from, blUser); + if (result == PrivacyQueriesService.PrivacyResult.Added) { + return CommandResult.fromString("User added to your blacklist"); + } else { + return CommandResult.fromString("User removed from your blacklist"); + } + } + return CommandResult.fromString("User not found"); + } + @UserCommand(pattern = "^bl\\s\\*(\\S+)$", patternFlags = Pattern.CASE_INSENSITIVE, + help = "BL *tag - add *tag to your blacklist") + public CommandResult blacklistTag(User user_from, URI attachment, String... arguments) { + if (!user_from.isAnonymous()) { + Tag tag = tagService.getTag(arguments[0], false); + if (tag != null) { + PrivacyQueriesService.PrivacyResult result = privacyQueriesService.blacklistTag(user_from, tag); + if (result == PrivacyQueriesService.PrivacyResult.Added) { + return CommandResult.fromString("Tag added to your blacklist"); + } else { + return CommandResult.fromString("Tag removed from your blacklist"); + } + } + } + return CommandResult.fromString("Tag not found"); + } + @UserCommand(pattern = "\\*", help = "* - Show your tags") + public CommandResult commandTags(User currentUser, URI attachment, String... args) { + List tags = tagService.getUserTagStats(currentUser.getUid()); + String msg = "Your tags: (tag - messages)\n" + + tags.stream() + .map(t -> String.format("\n*%s - %d", t.getTag().getName(), t.getUsageCount())).collect(Collectors.joining()); + return CommandResult.fromString(msg); + } + @UserCommand(pattern = "S", help = "S - Show your subscriptions", patternFlags = Pattern.CASE_INSENSITIVE) + public CommandResult commandSubscriptions(User currentUser, URI attachment, String... args) { + List friends = userService.getUserFriends(currentUser.getUid()); + List tags = subscriptionService.getSubscribedTags(currentUser); + String msg = friends.size() > 0 ? "You are subscribed to users:" + friends.stream().map(u -> "\n@" + u.getName()) + .collect(Collectors.joining()) + : "You are not subscribed to any user."; + msg += tags.size() > 0 ? "\nYou are subscribed to tags:" + tags.stream().map(t -> "\n*" + t) + .collect(Collectors.joining()) + : "\nYou are not subscribed to any tag."; + return CommandResult.fromString(msg); + } + @UserCommand(pattern = "!", help = "! - Show your favorite messages") + public CommandResult commandFavorites(User currentUser, URI attachment, String... args) { + List mids = messagesService.getUserRecommendations(currentUser.getUid(), 0); + if (mids.size() > 0) { + return CommandResult.fromString("Favorite messages: \n" + printMessages(currentUser, mids, false)); + } + return CommandResult.fromString("No favorite messages, try to \"like\" something ;)"); + } + @UserCommand(pattern = "^\\!\\s+#(\\d+)", help = "! #12345 - recommend message") + public CommandResult commandRecommend(User user, URI attachment, String... arguments) { + int mid = NumberUtils.toInt(arguments[0], 0); + if (mid > 0) { + com.juick.Message msg = messagesService.getMessage(mid); + if (msg != null) { + if (msg.getUser() == user) { + return CommandResult.fromString("You can't recommend your own messages."); + } + MessagesService.RecommendStatus status = messagesService.recommendMessage(mid, user.getUid()); + switch (status) { + case Added: + applicationEventPublisher.publishEvent(new LikeEvent(this, user, msg, + subscriptionService.getUsersSubscribedToUserRecommendations( + user.getUid(), msg))); + return CommandResult.fromString("Message is added to your recommendations"); + case Deleted: + return CommandResult.fromString("Message deleted from your recommendations."); + } + } + return CommandResult.fromString("Message not found"); + } + return CommandResult.fromString("Message not found"); + } + // TODO: target notification + @UserCommand(pattern = "^(s|u)\\s+\\@(\\S+)$", help = "S @username - subscribe to user" + + "\nU @username - unsubscribe from user", patternFlags = Pattern.CASE_INSENSITIVE) + public CommandResult commandSubscribeUser(User user, URI attachment, String... args) { + boolean subscribe = args[0].equalsIgnoreCase("s"); + User toUser = userService.getUserByName(args[1]); + if (toUser.isAnonymous()) { + return CommandResult.fromString("User not found"); + } + if (subscribe) { + if (subscriptionService.subscribeUser(user, toUser)) { + // TODO: already subscribed case + applicationEventPublisher.publishEvent(new SubscribeEvent(this, user, toUser)); + return CommandResult.fromString("Subscribed to @" + toUser.getName()); + } + } else { + if (subscriptionService.unSubscribeUser(user, toUser)) { + return CommandResult.fromString("Unsubscribed from @" + toUser.getName()); + } + return CommandResult.fromString("You was not subscribed to @" + toUser.getName()); + } + return CommandResult.fromString("Error"); + } + @UserCommand(pattern = "^(s|u)\\s+\\*(\\S+)$", help = "S *tag - subscribe to tag" + + "\nU *tag - unsubscribe from tag", patternFlags = Pattern.CASE_INSENSITIVE) + public CommandResult commandSubscribeTag(User user, URI attachment, String... args) { + boolean subscribe = args[0].equalsIgnoreCase("s"); + Tag tag = tagService.getTag(args[1], true); + if (subscribe) { + if (subscriptionService.subscribeTag(user, tag)) { + return CommandResult.fromString("Subscribed"); + } + } else { + if (subscriptionService.unSubscribeTag(user, tag)) { + return CommandResult.fromString("Unsubscribed from " + tag.getName()); + } + return CommandResult.fromString("You was not subscribed to " + tag.getName()); + } + return CommandResult.fromString("Error"); + } + @UserCommand(pattern = "^(s|u)\\s+#(\\d+)$", help = "S #1234 - subscribe to comments" + + "\nU #1234 - unsubscribe from comments", patternFlags = Pattern.CASE_INSENSITIVE) + public CommandResult commandSubscribeMessage(User user, URI attachment, String... args) { + boolean subscribe = args[0].equalsIgnoreCase("s"); + int mid = NumberUtils.toInt(args[1], 0); + Message msg = messagesService.getMessage(mid); + if (msg != null) { + if (subscribe) { + if (subscriptionService.subscribeMessage(msg, user)) { + applicationEventPublisher.publishEvent(new MessageReadEvent(this, user, msg)); + return CommandResult.fromString("Subscribed"); + } + } else { + if (subscriptionService.unSubscribeMessage(mid, user.getUid())) { + return CommandResult.fromString("Unsubscribed from #" + mid); + } + return CommandResult.fromString("You was not subscribed to #" + mid); + } + } + return CommandResult.fromString("Error"); + } + @UserCommand(pattern = "^(on|off)$", patternFlags = Pattern.CASE_INSENSITIVE, + help = "ON/OFF - Enable/disable subscriptions delivery") + public CommandResult commandOnOff(User user, URI attachment, String[] input) { + UserService.ActiveStatus newStatus; + String retValUpdated; + if (input[0].toLowerCase().equals("on")) { + newStatus = UserService.ActiveStatus.Active; + retValUpdated = "XMPP notifications are activated"; + } else { + newStatus = UserService.ActiveStatus.Inactive; + retValUpdated = "XMPP notifications are disabled"; + } + if (userService.getAllJIDs(user).stream().allMatch(jid -> userService.setActiveStatusForJID(jid, newStatus))) { + return CommandResult.fromString(retValUpdated); + } + return CommandResult.fromString("Error"); + } + @UserCommand(pattern = "^\\@([^\\s\\n\\+]+)(\\+?)$", + help = "@username+ - Show user's info and last 20 messages") + public CommandResult commandUser(User user, URI attachment, String... arguments) { + User blogUser = userService.getUserByName(arguments[0]); + int page = arguments[1].length(); + if (!blogUser.isAnonymous()) { + List mids = messagesService.getUserBlog(blogUser.getUid(), 0, 0); + return CommandResult.fromString(String.format("Last messages from @%s:\n%s", arguments[0], + printMessages(user, mids, false))); + } + return CommandResult.fromString("User not found"); + } + @UserCommand(pattern = "^#(\\d+)(\\+?)$", help = "#1234 - Show message (#1234+ - message with replies)") + public CommandResult commandShow(User user, URI attachment, String... arguments) { + boolean showReplies = arguments[1].length() > 0; + int mid = NumberUtils.toInt(arguments[0], 0); + if (mid == 0) { + return CommandResult.fromString("Error"); + } + com.juick.Message msg = messagesService.getMessage(mid); + if (msg != null) { + if (showReplies) { + List replies = messagesService.getReplies(user, mid); + applicationEventPublisher.publishEvent(new MessageReadEvent(this, user, msg)); + replies.add(0, msg); + return CommandResult.fromString(String.join("\n", + replies.stream().map(PlainTextFormatter::formatPostSummary).collect(Collectors.toList()))); + } + return CommandResult.fromString(PlainTextFormatter.formatPost(msg)); + } + return CommandResult.fromString("Message not found"); + } + @UserCommand(pattern = "^#(\\d+)\\/(\\d+)$", help = "#1234/5 - Show reply") + public CommandResult commandShowReply(User user, URI attachment, String... arguments) { + int mid = NumberUtils.toInt(arguments[0], 0); + int rid = NumberUtils.toInt(arguments[1], 0); + com.juick.Message reply = messagesService.getReply(mid, rid); + if (reply != null) { + return CommandResult.fromString(PlainTextFormatter.formatPost(reply)); + } + return CommandResult.fromString("Reply not found"); + } + @UserCommand(pattern = "^\\*(\\S+)(\\+?)$", help = "*tag - Show last messages with tag") + public CommandResult commandShowTag(User user, URI attachment, String... arguments) { + if (StringUtils.isNotEmpty(attachment.toString())) { + // new message with tag + return CommandResult.fromString(StringUtils.EMPTY); + } + Tag tag = tagService.getTag(arguments[0], false); + if (tag != null) { + // TODO: synonyms + List mids = messagesService.getTag(tag.TID, user.getUid(), 0, 10); + return CommandResult.fromString("Last messages with *" + tag.getName() + ":\n" + printMessages(user, mids, true)); + } + return CommandResult.fromString("Tag not found"); + } + @UserCommand(pattern = "^D #(\\d+)$", help = "D #1234 - Delete post", patternFlags = Pattern.CASE_INSENSITIVE) + public CommandResult commandDeletePost(User user, URI attachment, String... args) { + int mid = Integer.valueOf(args[0]); + if (messagesService.deleteMessage(user.getUid(), mid)) { + return CommandResult.fromString("Message deleted"); + } + return CommandResult.fromString("This is not your message"); + } + @UserCommand(pattern = "^D #(\\d+)(\\.|\\-|\\/)(\\d+)$", help = "D #1234/5 - Delete comment", patternFlags = Pattern.CASE_INSENSITIVE) + public CommandResult commandDeleteReply(User user, URI attachment, String... args) { + int mid = Integer.valueOf(args[0]); + int rid = Integer.valueOf(args[2]); + if (messagesService.deleteReply(user.getUid(), mid, rid)) { + return CommandResult.fromString("Reply deleted"); + } else { + return CommandResult.fromString("This is not your reply"); + } + } + @UserCommand(pattern = "^(D L|DL|D LAST)$", help = "D L - Delete last message", patternFlags = Pattern.CASE_INSENSITIVE) + public CommandResult commandDeleteLast(User user, URI attachment, String... args) { + return CommandResult.fromString("Temporarily unavailable"); + } + @UserCommand(pattern = "^\\?\\s+\\@([a-zA-Z0-9\\-\\.\\@]+)\\s+([\\s\\S]+)$", help = "? @user string - search in user messages") + public CommandResult commandSearch(User user, URI attachment, String... args) { + return CommandResult.fromString("Temporarily unavailable"); + } + @UserCommand(pattern = "^\\?\\s+([\\s\\S]+)$", help = "? string - search in all messages") + public CommandResult commandSearchAll(User user, URI attachment, String... args) { + return CommandResult.fromString("Temporarily unavailable"); + } + @UserCommand(pattern = "^(#+)$", help = "# - Show last messages from your feed (## - second page, ...)") + public CommandResult commandMyFeed(User user, URI attachment, String... arguments) { + // number of # is the page count + int page = arguments[0].length() - 1; + List mids = messagesService.getMyFeed(user.getUid(), page, false); + if (mids.size() > 0) { + return CommandResult.fromString("Your feed: \n" + printMessages(user, mids, true)); + } + return CommandResult.fromString("Your feed is empty"); + } + @UserCommand(pattern = "^(#|\\.)(\\d+)((\\.|\\-|\\/)(\\d+))?\\s([\\s\\S]+)?", + help = "#1234 *tag *tag2 - edit tags\n#1234 text - reply to message") + public CommandResult EditOrReply(User user, @Nonnull URI attachment, String... args) throws Exception { + int mid = NumberUtils.toInt(args[1]); + int rid = NumberUtils.toInt(args[4], 0); + String txt = StringUtils.defaultString(args[5]); + Message msg = messagesService.getMessage(mid); + Pair> messageTags = tagService.fromString(txt); + if (messageTags.getRight().size() > 0) { + if (user.getUid() != msg.getUser().getUid()) { + return CommandResult.fromString("It is not your message"); + } + if (!CollectionUtils.isEqualCollection(tagService.updateTags(mid, messageTags.getRight()), msg.getTags())) { + return CommandResult.fromString("Tags are updated"); + } else { + return CommandResult.fromString("Tags are NOT updated (5 tags maximum?)"); + } + } else { + boolean haveAttachment = StringUtils.isNotEmpty(attachment.toString()); + String attachmentFName = null; + String attachmentType = null; + if (haveAttachment) { + attachmentFName = attachment.getScheme().equals("juick") ? attachment.getHost() + : HttpUtils.downloadImage(attachment.toURL(), tmpDir).getHost(); + attachmentType = attachmentFName.substring(attachmentFName.length() - 3); + } + int newrid = messagesService.createReply(mid, rid, user, txt, attachmentType); + applicationEventPublisher.publishEvent(new MessageReadEvent(this, user, msg)); + if (haveAttachment) { + String fname = String.format("%d-%d.%s", mid, newrid, attachmentType); + imagesService.saveImageWithPreviews(attachmentFName, fname); + } + Message original = messagesService.getMessage(mid); + subscriptionService.subscribeMessage(original, user); + Message reply = messagesService.getReply(mid, newrid); + applicationEventPublisher.publishEvent(new MessageEvent(this, reply, subscriptionService.getUsersSubscribedToComments(original, reply))); + return CommandResult.build(reply,"Reply posted.\n#" + mid + "/" + newrid + " " + + "https://juick.com/m/" + mid + "#" + newrid, + String.format("[Reply](%s) posted", PlainTextFormatter.formatUrl(reply))); + } + } + + String printMessages(User visitor, List mids, boolean crop) { + return messagesService.getMessages(visitor, mids).stream() + .sorted(Collections.reverseOrder()) + .map(PlainTextFormatter::formatPostSummary).collect(Collectors.joining("\n\n")); + } +} diff --git a/juick-server/src/main/java/com/juick/server/EmailManager.java b/juick-server/src/main/java/com/juick/server/EmailManager.java index 6e8d0d76..d6c2bb3f 100644 --- a/juick-server/src/main/java/com/juick/server/EmailManager.java +++ b/juick-server/src/main/java/com/juick/server/EmailManager.java @@ -2,10 +2,9 @@ package com.juick.server; import com.juick.Message; import com.juick.User; -import com.juick.server.component.MessageEvent; +import com.juick.service.component.MessageEvent; import com.juick.service.EmailService; import com.juick.service.MessagesService; -import com.juick.service.SubscriptionService; import com.juick.service.UserService; import com.juick.util.MessageUtils; import org.apache.commons.lang3.StringUtils; diff --git a/juick-server/src/main/java/com/juick/server/MessengerManager.java b/juick-server/src/main/java/com/juick/server/MessengerManager.java index c58380c5..1283d8b2 100644 --- a/juick-server/src/main/java/com/juick/server/MessengerManager.java +++ b/juick-server/src/main/java/com/juick/server/MessengerManager.java @@ -17,11 +17,10 @@ import com.github.messenger4j.userprofile.UserProfile; import com.github.messenger4j.webhook.event.TextMessageEvent; import com.juick.Message; import com.juick.User; -import com.juick.server.component.MessageEvent; -import com.juick.server.helpers.AnonymousUser; +import com.juick.service.component.MessageEvent; +import com.juick.model.AnonymousUser; import com.juick.service.MessagesService; import com.juick.service.MessengerService; -import com.juick.service.SubscriptionService; import com.juick.service.UserService; import com.juick.util.MessageUtils; import org.apache.commons.lang3.StringUtils; diff --git a/juick-server/src/main/java/com/juick/server/NotificationListener.java b/juick-server/src/main/java/com/juick/server/NotificationListener.java index 47b350c1..750c8b18 100644 --- a/juick-server/src/main/java/com/juick/server/NotificationListener.java +++ b/juick-server/src/main/java/com/juick/server/NotificationListener.java @@ -1,6 +1,6 @@ package com.juick.server; -import com.juick.server.component.*; +import com.juick.service.component.*; import org.springframework.context.event.EventListener; public interface NotificationListener { diff --git a/juick-server/src/main/java/com/juick/server/ServerManager.java b/juick-server/src/main/java/com/juick/server/ServerManager.java index f762b0e7..a50571e6 100644 --- a/juick-server/src/main/java/com/juick/server/ServerManager.java +++ b/juick-server/src/main/java/com/juick/server/ServerManager.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.juick.Message; import com.juick.User; -import com.juick.server.component.*; +import com.juick.service.component.*; import com.juick.service.MessagesService; import com.juick.service.SubscriptionService; import com.juick.service.UserService; diff --git a/juick-server/src/main/java/com/juick/server/TelegramBotManager.java b/juick-server/src/main/java/com/juick/server/TelegramBotManager.java index ac2febf7..3c9bb46a 100644 --- a/juick-server/src/main/java/com/juick/server/TelegramBotManager.java +++ b/juick-server/src/main/java/com/juick/server/TelegramBotManager.java @@ -18,15 +18,14 @@ package com.juick.server; import com.juick.User; -import com.juick.server.component.*; -import com.juick.server.helpers.AnonymousUser; -import com.juick.server.helpers.CommandResult; +import com.juick.service.component.*; +import com.juick.model.AnonymousUser; +import com.juick.model.CommandResult; import com.juick.server.util.HttpUtils; import com.juick.service.MessagesService; import com.juick.service.TelegramService; import com.juick.service.UserService; import com.juick.util.MessageUtils; -import com.pengrad.telegrambot.BotUtils; import com.pengrad.telegrambot.Callback; import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.UpdatesListener; @@ -46,7 +45,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.stereotype.Component; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; diff --git a/juick-server/src/main/java/com/juick/server/TwitterManager.java b/juick-server/src/main/java/com/juick/server/TwitterManager.java index 9b83b197..eeef2b91 100644 --- a/juick-server/src/main/java/com/juick/server/TwitterManager.java +++ b/juick-server/src/main/java/com/juick/server/TwitterManager.java @@ -17,20 +17,17 @@ package com.juick.server; import com.juick.Message; -import com.juick.server.component.*; +import com.juick.service.component.*; import com.juick.service.CrosspostService; import com.juick.util.MessageUtils; 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.event.EventListener; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import twitter4j.TwitterFactory; import twitter4j.conf.ConfigurationBuilder; -import javax.annotation.Nonnull; import javax.inject.Inject; /** diff --git a/juick-server/src/main/java/com/juick/server/WebsocketManager.java b/juick-server/src/main/java/com/juick/server/WebsocketManager.java index 8974a49f..1b62b984 100644 --- a/juick-server/src/main/java/com/juick/server/WebsocketManager.java +++ b/juick-server/src/main/java/com/juick/server/WebsocketManager.java @@ -18,8 +18,8 @@ package com.juick.server; import com.juick.User; -import com.juick.server.helpers.AnonymousUser; -import com.juick.server.helpers.CommandResult; +import com.juick.model.AnonymousUser; +import com.juick.model.CommandResult; import com.juick.server.util.HttpForbiddenException; import com.juick.server.util.HttpNotFoundException; import com.juick.service.MessagesService; @@ -28,7 +28,6 @@ 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.HttpHeaders; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; diff --git a/juick-server/src/main/java/com/juick/server/XMPPConnection.java b/juick-server/src/main/java/com/juick/server/XMPPConnection.java index 692ed3fe..ba155fe7 100644 --- a/juick-server/src/main/java/com/juick/server/XMPPConnection.java +++ b/juick-server/src/main/java/com/juick/server/XMPPConnection.java @@ -19,9 +19,9 @@ package com.juick.server; import com.juick.User; import com.juick.formatters.PlainTextFormatter; -import com.juick.server.component.*; -import com.juick.server.helpers.CommandResult; -import com.juick.server.helpers.UserInfo; +import com.juick.service.component.*; +import com.juick.model.CommandResult; +import com.juick.model.UserInfo; import com.juick.server.xmpp.iq.MessageQuery; import com.juick.server.xmpp.s2s.BasicXmppSession; import com.juick.server.xmpp.s2s.StanzaListener; @@ -35,8 +35,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.annotation.DependsOn; -import org.springframework.stereotype.Component; import rocks.xmpp.addr.Jid; import rocks.xmpp.core.XmppException; import rocks.xmpp.core.session.XmppSession; diff --git a/juick-server/src/main/java/com/juick/server/api/ApiSocialLogin.java b/juick-server/src/main/java/com/juick/server/api/ApiSocialLogin.java index 2e484e3d..8d9f9402 100644 --- a/juick-server/src/main/java/com/juick/server/api/ApiSocialLogin.java +++ b/juick-server/src/main/java/com/juick/server/api/ApiSocialLogin.java @@ -24,13 +24,13 @@ 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.juick.facebook.User; +import com.juick.model.facebook.User; import com.juick.server.util.HttpBadRequestException; import com.juick.service.CrosspostService; import com.juick.service.EmailService; import com.juick.service.TelegramService; import com.juick.service.UserService; -import com.juick.vk.UsersResponse; +import com.juick.model.vk.UsersResponse; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; @@ -244,7 +244,7 @@ public class ApiSocialLogin { vkService.signRequest(token, meRequest); String graph = vkService.execute(meRequest).getBody(); - com.juick.vk.User jsonUser = jsonMapper.readValue(graph, UsersResponse.class).getUsers().get(0); + com.juick.model.vk.User jsonUser = jsonMapper.readValue(graph, UsersResponse.class).getUsers().get(0); String vkName = jsonUser.getFirstName() + " " + jsonUser.getLastName(); String vkLink = jsonUser.getScreenName(); diff --git a/juick-server/src/main/java/com/juick/server/api/Messages.java b/juick-server/src/main/java/com/juick/server/api/Messages.java index e900810f..86f9a20d 100644 --- a/juick-server/src/main/java/com/juick/server/api/Messages.java +++ b/juick-server/src/main/java/com/juick/server/api/Messages.java @@ -21,15 +21,14 @@ import com.juick.Message; import com.juick.Tag; import com.juick.User; import com.juick.server.Utils; -import com.juick.server.component.MessageReadEvent; -import com.juick.server.helpers.CommandResult; +import com.juick.service.component.MessageReadEvent; +import com.juick.model.CommandResult; import com.juick.server.util.HttpBadRequestException; import com.juick.server.util.HttpNotFoundException; import com.juick.server.util.UserUtils; import com.juick.service.MessagesService; import com.juick.service.TagService; import com.juick.service.UserService; -import com.juick.service.security.entities.JuickUser; import org.apache.commons.io.IOUtils; import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatus; diff --git a/juick-server/src/main/java/com/juick/server/api/Notifications.java b/juick-server/src/main/java/com/juick/server/api/Notifications.java index 0b34f275..b0d64292 100644 --- a/juick-server/src/main/java/com/juick/server/api/Notifications.java +++ b/juick-server/src/main/java/com/juick/server/api/Notifications.java @@ -21,7 +21,7 @@ import com.juick.Message; import com.juick.Status; import com.juick.ExternalToken; import com.juick.User; -import com.juick.server.helpers.AnonymousUser; +import com.juick.model.AnonymousUser; import com.juick.server.util.HttpBadRequestException; import com.juick.server.util.HttpForbiddenException; import com.juick.service.MessagesService; diff --git a/juick-server/src/main/java/com/juick/server/api/PM.java b/juick-server/src/main/java/com/juick/server/api/PM.java index d3619662..80be92f0 100644 --- a/juick-server/src/main/java/com/juick/server/api/PM.java +++ b/juick-server/src/main/java/com/juick/server/api/PM.java @@ -18,9 +18,9 @@ package com.juick.server.api; import com.juick.User; -import com.juick.server.component.MessageEvent; -import com.juick.server.helpers.AnonymousUser; -import com.juick.server.helpers.PrivateChats; +import com.juick.service.component.MessageEvent; +import com.juick.model.AnonymousUser; +import com.juick.model.PrivateChats; import com.juick.server.util.*; import com.juick.service.PMQueriesService; import com.juick.service.UserService; diff --git a/juick-server/src/main/java/com/juick/server/api/Post.java b/juick-server/src/main/java/com/juick/server/api/Post.java index 99d118c3..d6f085bb 100644 --- a/juick-server/src/main/java/com/juick/server/api/Post.java +++ b/juick-server/src/main/java/com/juick/server/api/Post.java @@ -22,7 +22,7 @@ import com.juick.Reaction; import com.juick.Status; import com.juick.User; import com.juick.server.CommandsManager; -import com.juick.server.helpers.CommandResult; +import com.juick.model.CommandResult; import com.juick.server.util.*; import com.juick.service.MessagesService; import com.juick.service.SubscriptionService; diff --git a/juick-server/src/main/java/com/juick/server/api/Tags.java b/juick-server/src/main/java/com/juick/server/api/Tags.java index 38e71e3a..7a8e572a 100644 --- a/juick-server/src/main/java/com/juick/server/api/Tags.java +++ b/juick-server/src/main/java/com/juick/server/api/Tags.java @@ -18,7 +18,7 @@ package com.juick.server.api; import com.juick.User; -import com.juick.server.helpers.TagStats; +import com.juick.model.TagStats; import com.juick.server.util.UserUtils; import com.juick.service.TagService; import org.springframework.http.MediaType; diff --git a/juick-server/src/main/java/com/juick/server/api/Users.java b/juick-server/src/main/java/com/juick/server/api/Users.java index de5c05c2..7686d722 100644 --- a/juick-server/src/main/java/com/juick/server/api/Users.java +++ b/juick-server/src/main/java/com/juick/server/api/Users.java @@ -18,8 +18,8 @@ package com.juick.server.api; import com.juick.User; -import com.juick.server.helpers.ApplicationStatus; -import com.juick.server.helpers.UserInfo; +import com.juick.model.ApplicationStatus; +import com.juick.model.UserInfo; import com.juick.server.util.HttpForbiddenException; import com.juick.server.util.HttpNotFoundException; import com.juick.service.CrosspostService; diff --git a/juick-server/src/main/java/com/juick/server/api/rss/RepliesView.java b/juick-server/src/main/java/com/juick/server/api/rss/RepliesView.java index b67e8b44..f9d7109e 100644 --- a/juick-server/src/main/java/com/juick/server/api/rss/RepliesView.java +++ b/juick-server/src/main/java/com/juick/server/api/rss/RepliesView.java @@ -17,7 +17,7 @@ package com.juick.server.api.rss; -import com.juick.server.helpers.ResponseReply; +import com.juick.model.ResponseReply; import com.juick.util.MessageUtils; import com.rometools.modules.mediarss.MediaEntryModuleImpl; import com.rometools.modules.mediarss.MediaModule; diff --git a/juick-server/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java b/juick-server/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java new file mode 100644 index 00000000..23a35384 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; +import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter; + +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Created by vitalyster on 28.06.2016. + */ +@Configuration +public class BaseWebConfiguration implements WebMvcConfigurer, SchedulingConfigurer { + + + @Override + public void configurePathMatch(PathMatchConfigurer configurer) { + configurer.setUseSuffixPatternMatch(false); + } + + @Bean + public ResourceUrlEncodingFilter resourceUrlEncodingFilter() { + return new ResourceUrlEncodingFilter(); + } + + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(taskExecutor()); + } + + @Bean(destroyMethod="shutdown") + public Executor taskExecutor() { + return Executors.newScheduledThreadPool(100); + } + + @Bean + public ExecutorService executorService() { + return Executors.newCachedThreadPool(); + } +} diff --git a/juick-server/src/main/java/com/juick/server/configuration/StorageConfiguration.java b/juick-server/src/main/java/com/juick/server/configuration/StorageConfiguration.java new file mode 100644 index 00000000..4101f37d --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/configuration/StorageConfiguration.java @@ -0,0 +1,20 @@ +package com.juick.server.configuration; + +import com.juick.service.ImagesService; +import com.juick.service.ImagesServiceImpl; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class StorageConfiguration { + + @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") + private String tmpDir; + @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}") + private String imgDir; + @Bean + public ImagesService imagesService() { + return new ImagesServiceImpl(imgDir, tmpDir); + } +} diff --git a/juick-server/src/main/java/com/juick/server/configuration/WwwAppConfiguration.java b/juick-server/src/main/java/com/juick/server/configuration/WwwAppConfiguration.java index 16d32ee4..f829a999 100644 --- a/juick-server/src/main/java/com/juick/server/configuration/WwwAppConfiguration.java +++ b/juick-server/src/main/java/com/juick/server/configuration/WwwAppConfiguration.java @@ -47,8 +47,6 @@ import java.util.Collections; */ @Configuration @EnableCaching -@Import({ BaseWebConfiguration.class, SecurityConfig.class, SapeConfiguration.class, - StorageConfiguration.class}) public class WwwAppConfiguration implements WebMvcConfigurer { @Inject private UserService userService; diff --git a/juick-server/src/main/java/com/juick/server/helpers/annotation/UserCommand.java b/juick-server/src/main/java/com/juick/server/helpers/annotation/UserCommand.java new file mode 100644 index 00000000..4f07001c --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/helpers/annotation/UserCommand.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.helpers.annotation; + +import org.apache.commons.lang3.StringUtils; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Created by oxpa on 22.03.16. + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface UserCommand { + /** + * + * @return a command pattern + */ + String pattern() default StringUtils.EMPTY; + + /** + * + * @return pattern flags + */ + int patternFlags() default 0; + + /** + * + * @return a string used in HELP command output. Basically, only 1 string + */ + String help() default StringUtils.EMPTY; +} diff --git a/juick-server/src/main/java/com/juick/server/util/HttpBadRequestException.java b/juick-server/src/main/java/com/juick/server/util/HttpBadRequestException.java new file mode 100644 index 00000000..242f2b09 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/util/HttpBadRequestException.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.util; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +/** + * Created by vt on 24/11/2016. + */ +@ResponseStatus(value = HttpStatus.BAD_REQUEST) +public class HttpBadRequestException extends RuntimeException { + public HttpBadRequestException() { + super("the request was bad", null, false, false); + } +} diff --git a/juick-server/src/main/java/com/juick/server/util/HttpForbiddenException.java b/juick-server/src/main/java/com/juick/server/util/HttpForbiddenException.java new file mode 100644 index 00000000..3251ca38 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/util/HttpForbiddenException.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.util; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +/** + * Created by vt on 24/11/2016. + */ +@ResponseStatus(value = HttpStatus.FORBIDDEN) +public class HttpForbiddenException extends RuntimeException { + public HttpForbiddenException() { + super(StringUtils.EMPTY, null, false, false); + } + +} diff --git a/juick-server/src/main/java/com/juick/server/util/HttpNotFoundException.java b/juick-server/src/main/java/com/juick/server/util/HttpNotFoundException.java new file mode 100644 index 00000000..f66ece8b --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/util/HttpNotFoundException.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.util; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +/** + * Created by vt on 24/11/2016. + */ +@ResponseStatus(value = HttpStatus.NOT_FOUND) +public class HttpNotFoundException extends RuntimeException { + public HttpNotFoundException() { + super(StringUtils.EMPTY, null, false, false); + } +} diff --git a/juick-server/src/main/java/com/juick/server/util/HttpUtils.java b/juick-server/src/main/java/com/juick/server/util/HttpUtils.java new file mode 100644 index 00000000..9f356aa5 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/util/HttpUtils.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ +package com.juick.server.util; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.multipart.MultipartFile; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Iterator; +import java.util.UUID; + +/** + * + * @author Ugnich Anton + */ +public class HttpUtils { + private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class); + + public static URI receiveMultiPartFile(MultipartFile attach, String tmpDir) throws IOException { + if (attach != null && !attach.isEmpty()) { + ImageInputStream iis = ImageIO.createImageInputStream(attach.getInputStream()); + Iterator readers = ImageIO.getImageReaders(iis); + + String format = StringUtils.EMPTY; + while (readers.hasNext()) { + ImageReader read = readers.next(); + format = read.getFormatName(); + } + String attachmentType = attachmentTypeFromFormat(format); + if (attachmentType.equals("jpg") || attachmentType.equals("png")) { + String attachmentFName = DigestUtils.md5Hex(UUID.randomUUID().toString()) + "." + attachmentType; + try { + Files.write(Paths.get(tmpDir, attachmentFName), + attach.getBytes()); + return URI.create(String.format("juick://%s", attachmentFName)); + } catch (IOException e) { + logger.warn("file receive error", e); + } + } + logger.warn("file type is unknown: {}", attach.getOriginalFilename()); + } + return URI.create(StringUtils.EMPTY); + } + + private static String attachmentTypeFromFormat(String format) throws IOException { + if (format != null && format.equals("JPEG")) { + return "jpg"; + } else if (format != null && format.equals("png")) { + return "png"; + } else { + throw new IOException("Wrong file type: " + format); + } + } + + public static URI downloadImage(URL url, String tmpDir) throws IOException { + ImageInputStream iis = ImageIO.createImageInputStream(url.openStream()); + Iterator readers = ImageIO.getImageReaders(iis); + + String format = StringUtils.EMPTY; + while (readers.hasNext()) { + ImageReader read = readers.next(); + format = read.getFormatName(); + } + URLConnection urlConn; + try { + urlConn = url.openConnection(); + } catch (IOException e) { + logger.error(String.format("Failed open url: %s", url.toString())); + throw e; + } + + try (InputStream is = new BufferedInputStream(urlConn.getInputStream())) { + String attachmentType = attachmentTypeFromFormat(format); + + String attachmentFName = DigestUtils.md5Hex(UUID.randomUUID().toString()) + "." + attachmentType; + Files.copy(is, Paths.get(tmpDir, attachmentFName)); + return URI.create(String.format("juick://%s", attachmentFName)); + } catch (IOException e) { + logger.error(String.format("Failed download image by url: %s", url.toString()), e); + throw e; + } + } +} diff --git a/juick-server/src/main/java/com/juick/server/util/ImageUtils.java b/juick-server/src/main/java/com/juick/server/util/ImageUtils.java new file mode 100644 index 00000000..d16faf8f --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/util/ImageUtils.java @@ -0,0 +1,175 @@ + +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.util; + +import com.juick.Attachment; +import org.apache.commons.imaging.ImageReadException; +import org.apache.commons.imaging.Imaging; +import org.apache.commons.imaging.common.ImageMetadata; +import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata; +import org.apache.commons.imaging.formats.tiff.TiffField; +import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.imgscalr.Scalr; +import org.imgscalr.Scalr.Rotation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.FileImageInputStream; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Iterator; + +public class ImageUtils { + private static final Logger logger = LoggerFactory.getLogger(ImageUtils.class); + + private String imgDir; + private String tmpDir; + + public ImageUtils(String imgDir, String tmpDir) { + this.imgDir = imgDir; + this.tmpDir = tmpDir; + } +/** + * Returns BufferedImage, same as ImageIO.read() does. + * + *

JPEG images with EXIF metadata are rotated according to Orientation tag. + * + * @param imageFile a File to read from. + */ + private static BufferedImage readImageWithOrientation(File imageFile) + throws IOException { + + BufferedImage image = ImageIO.read(imageFile); + if (!FilenameUtils.getExtension(imageFile.getName()).equals("jpg")) { + return image; + } + + try { + ImageMetadata metadata = Imaging.getMetadata(imageFile); + + if (metadata instanceof JpegImageMetadata) { + JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata; + TiffField orientationField = jpegMetadata.findEXIFValue(TiffTagConstants.TIFF_TAG_ORIENTATION); + + if (orientationField != null) { + int orientation = orientationField.getIntValue(); + switch (orientation) { + case TiffTagConstants.ORIENTATION_VALUE_ROTATE_90_CW: + image = Scalr.rotate(image, Rotation.CW_90); + break; + case TiffTagConstants.ORIENTATION_VALUE_ROTATE_180: + image = Scalr.rotate(image, Rotation.CW_180); + break; + case TiffTagConstants.ORIENTATION_VALUE_ROTATE_270_CW: + image = Scalr.rotate(image, Rotation.CW_270); + break; + case TiffTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL: + image = Scalr.rotate(image, Rotation.FLIP_HORZ); + break; + case TiffTagConstants.ORIENTATION_VALUE_MIRROR_VERTICAL: + image = Scalr.rotate(image, Rotation.FLIP_VERT); + break; + case TiffTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL_AND_ROTATE_90_CW: + image = Scalr.rotate(Scalr.rotate(image, Rotation.FLIP_HORZ), Rotation.CW_90); + break; + case TiffTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL_AND_ROTATE_270_CW: + image = Scalr.rotate(Scalr.rotate(image, Rotation.FLIP_HORZ), Rotation.CW_270); + break; + case TiffTagConstants.ORIENTATION_VALUE_HORIZONTAL_NORMAL: + default: + // do nothing + break; + } + } + } + } catch (ImageReadException e) { + // failed to read metadata. + // nothing to do here, return image as is. + } + + return image; + } + + public void saveImageWithPreviews(String tempFilename, String outputFilename) + throws IOException { + String ext = FilenameUtils.getExtension(outputFilename); + + Path outputImagePath = Paths.get(imgDir, "p", outputFilename); + // this throws strange exceptions + // Files.move(Paths.get(tmpDir, tempFilename), outputImagePath); + FileUtils.moveFile(Paths.get(tmpDir, tempFilename).toFile(), outputImagePath.toFile()); + BufferedImage originalImage = readImageWithOrientation(outputImagePath.toFile()); + + int width = originalImage.getWidth(); + int height = originalImage.getHeight(); + int maxDimension = (width > height) ? width : height; + BufferedImage image1024 = (maxDimension > 1024) ? Scalr.resize(originalImage, 1024) : originalImage; + BufferedImage image0512 = (maxDimension > 512) ? Scalr.resize(originalImage, 512) : originalImage; + BufferedImage image0160 = (maxDimension > 160) ? Scalr.resize(originalImage, 160) : originalImage; + ImageIO.write(image1024, ext, Paths.get(imgDir, "photos-1024", outputFilename).toFile()); + ImageIO.write(image0512, ext, Paths.get(imgDir, "photos-512", outputFilename).toFile()); + ImageIO.write(image0160, ext, Paths.get(imgDir, "ps", outputFilename).toFile()); + } + + public void saveAvatar(String tempFilename, int uid) + throws IOException { + String ext = FilenameUtils.getExtension(tempFilename); + String originalName = String.format("%s.%s", uid, ext); + Path originalPath = Paths.get(imgDir, "ao", originalName); + Files.move(Paths.get(tmpDir, tempFilename), originalPath, StandardCopyOption.REPLACE_EXISTING); + BufferedImage originalImage = ImageIO.read(originalPath.toFile()); + + String targetExt = "png"; + String targetName = String.format("%s.%s", uid, targetExt); + ImageIO.write(Scalr.resize(originalImage, 96), targetExt, Paths.get(imgDir, "a", targetName).toFile()); + ImageIO.write(Scalr.resize(originalImage, 32), targetExt, Paths.get(imgDir, "as", targetName).toFile()); + } + public Attachment getAttachment(File imgFile) throws IOException { + Attachment attachment = new Attachment(); + try (ImageInputStream stream = ImageIO.createImageInputStream(imgFile)) { + Iterator iter = ImageIO.getImageReaders(stream); + while (iter.hasNext()) { + ImageReader reader = iter.next(); + try { + reader.setInput(stream); + attachment.setWidth(reader.getWidth(reader.getMinIndex())); + attachment.setHeight(reader.getHeight(reader.getMinIndex())); + return attachment; + } catch (Exception e) { + logger.debug("Error reading {}, trying next reader", imgFile.getAbsolutePath()); + } finally { + reader.dispose(); + } + } + } + + logger.warn("Not a known image file {}", imgFile.getAbsolutePath()); + return attachment; + } +} \ No newline at end of file diff --git a/juick-server/src/main/java/com/juick/server/util/TagUtils.java b/juick-server/src/main/java/com/juick/server/util/TagUtils.java new file mode 100644 index 00000000..cb828933 --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/util/TagUtils.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.util; + +import com.juick.Tag; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Created by aalexeev on 11/13/16. + */ +public class TagUtils { + private TagUtils() { + throw new IllegalStateException(); + } + + public static String toString(final List tags) { + if (CollectionUtils.isEmpty(tags)) + return StringUtils.EMPTY; + + return tags.stream().map(t -> "*" + t.getName()) + .collect(Collectors.joining(" ")); + } +} diff --git a/juick-server/src/main/java/com/juick/server/util/UserUtils.java b/juick-server/src/main/java/com/juick/server/util/UserUtils.java new file mode 100644 index 00000000..1adc85ab --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/util/UserUtils.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.util; + +import com.juick.User; +import com.juick.model.AnonymousUser; +import com.juick.service.security.entities.JuickUser; +import javax.annotation.Nonnull; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * Created by aalexeev on 11/14/16. + */ +public class UserUtils { + private UserUtils() { + throw new IllegalStateException(); + } + + public static Authentication getAuthentication() { + return SecurityContextHolder.getContext().getAuthentication(); + } + + public static Object getPrincipal(final Authentication authentication) { + return authentication == null ? null : authentication.getPrincipal(); + } + + @Nonnull + public static User getCurrentUser() { + Object principal = getPrincipal(getAuthentication()); + + if (principal instanceof JuickUser) + return ((JuickUser) principal).getUser(); + + if (principal instanceof User) + return (User) principal; + + return AnonymousUser.INSTANCE; + } +} diff --git a/juick-server/src/main/java/com/juick/server/util/WebUtils.java b/juick-server/src/main/java/com/juick/server/util/WebUtils.java new file mode 100644 index 00000000..9dd628ee --- /dev/null +++ b/juick-server/src/main/java/com/juick/server/util/WebUtils.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.server.util; + +import java.util.regex.Pattern; + +/** + * Created by aalexeev on 11/28/16. + */ +public class WebUtils { + private WebUtils() { + throw new IllegalStateException(); + } + + private static final Pattern USER_NAME_PATTERN = Pattern.compile("[a-zA-Z-_\\d]{2,16}"); + + private static final Pattern POST_NUMBER_PATTERN = Pattern.compile("-?\\d+"); + + private static final Pattern JID_PATTERN = Pattern.compile("^[a-zA-Z0-9\\\\-\\\\_\\\\@\\\\.]{6,64}$"); + + + public static boolean isPostNumber(final String aString) { + return aString != null && POST_NUMBER_PATTERN.matcher(aString).matches(); + } + + public static boolean isNotPostNumber(final String aString) { + return !isPostNumber(aString); + } + + public static boolean isUserName(final String aString) { + return aString != null && USER_NAME_PATTERN.matcher(aString).matches(); + } + + public static boolean isNotUserName(final String aString) { + return !isUserName(aString); + } + + public static boolean isJid(final String aString) { + return aString != null && JID_PATTERN.matcher(aString).matches(); + } + + public static boolean isNotJid(final String aString) { + return !isJid(aString); + } + + +} diff --git a/juick-server/src/main/java/com/juick/server/www/controllers/NewMessage.java b/juick-server/src/main/java/com/juick/server/www/controllers/NewMessage.java index 9e364ff8..c476e5c2 100644 --- a/juick-server/src/main/java/com/juick/server/www/controllers/NewMessage.java +++ b/juick-server/src/main/java/com/juick/server/www/controllers/NewMessage.java @@ -19,8 +19,8 @@ package com.juick.server.www.controllers; import com.fasterxml.jackson.databind.ObjectMapper; import com.juick.Message; import com.juick.User; -import com.juick.server.helpers.AnonymousUser; -import com.juick.server.helpers.CommandResult; +import com.juick.model.AnonymousUser; +import com.juick.model.CommandResult; import com.juick.server.util.*; import com.juick.server.www.WebApp; import com.juick.service.*; diff --git a/juick-server/src/main/java/com/juick/server/www/controllers/Settings.java b/juick-server/src/main/java/com/juick/server/www/controllers/Settings.java index f2ecccf6..6405b3bd 100644 --- a/juick-server/src/main/java/com/juick/server/www/controllers/Settings.java +++ b/juick-server/src/main/java/com/juick/server/www/controllers/Settings.java @@ -16,8 +16,8 @@ */ package com.juick.server.www.controllers; -import com.juick.server.helpers.NotifyOpts; -import com.juick.server.helpers.UserInfo; +import com.juick.model.NotifyOpts; +import com.juick.model.UserInfo; import com.juick.server.util.*; import com.juick.service.*; import org.apache.commons.lang3.RandomStringUtils; @@ -25,7 +25,6 @@ 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.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.GetMapping; @@ -45,7 +44,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; diff --git a/juick-server/src/main/java/com/juick/server/www/controllers/SocialLogin.java b/juick-server/src/main/java/com/juick/server/www/controllers/SocialLogin.java index 93d3946a..3cea3e34 100644 --- a/juick-server/src/main/java/com/juick/server/www/controllers/SocialLogin.java +++ b/juick-server/src/main/java/com/juick/server/www/controllers/SocialLogin.java @@ -24,7 +24,7 @@ import com.github.scribejava.core.builder.ServiceBuilder; import com.github.scribejava.core.model.*; import com.github.scribejava.core.oauth.OAuth10aService; import com.github.scribejava.core.oauth.OAuth20Service; -import com.juick.facebook.User; +import com.juick.model.facebook.User; import com.juick.server.util.HttpBadRequestException; import com.juick.server.util.UserUtils; import com.juick.service.CrosspostService; @@ -32,7 +32,7 @@ import com.juick.service.EmailService; import com.juick.service.TelegramService; import com.juick.service.UserService; import com.juick.server.www.Utils; -import com.juick.vk.UsersResponse; +import com.juick.model.vk.UsersResponse; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.HmacAlgorithms; import org.apache.commons.codec.digest.HmacUtils; @@ -216,8 +216,8 @@ public class SocialLogin { OAuth1AccessToken accessToken = oAuthService.getAccessToken(requestToken, verifier); OAuthRequest oAuthRequest = new OAuthRequest(Verb.GET, TWITTER_VERIFY_URL); oAuthService.signRequest(accessToken, oAuthRequest); - com.juick.twitter.User twitterUser = jsonMapper.readValue(oAuthService.execute(oAuthRequest).getBody(), - com.juick.twitter.User.class); + com.juick.model.twitter.User twitterUser = jsonMapper.readValue(oAuthService.execute(oAuthRequest).getBody(), + com.juick.model.twitter.User.class); if (userService.linkTwitterAccount(user, accessToken.getToken(), accessToken.getTokenSecret(), twitterUser.getScreenName())) { response.setStatus(HttpServletResponse.SC_FOUND); @@ -265,7 +265,7 @@ public class SocialLogin { vkService.signRequest(token, meRequest); String graph = vkService.execute(meRequest).getBody(); - com.juick.vk.User jsonUser = jsonMapper.readValue(graph, UsersResponse.class).getUsers().get(0); + com.juick.model.vk.User jsonUser = jsonMapper.readValue(graph, UsersResponse.class).getUsers().get(0); String vkName = jsonUser.getFirstName() + " " + jsonUser.getLastName(); String vkLink = jsonUser.getScreenName(); diff --git a/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java b/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java index 14bdc7e2..47d1870b 100644 --- a/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java +++ b/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java @@ -18,7 +18,7 @@ package com.juick.service; import com.juick.ExternalToken; -import com.juick.server.helpers.ApplicationStatus; +import com.juick.model.ApplicationStatus; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.springframework.dao.EmptyResultDataAccessException; diff --git a/juick-server/src/main/java/com/juick/service/ImagesServiceImpl.java b/juick-server/src/main/java/com/juick/service/ImagesServiceImpl.java new file mode 100644 index 00000000..67c8360e --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/ImagesServiceImpl.java @@ -0,0 +1,82 @@ +package com.juick.service; + +import com.juick.Attachment; +import com.juick.Message; +import com.juick.Photo; +import com.juick.server.util.ImageUtils; +import org.springframework.util.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; + +public class ImagesServiceImpl implements ImagesService { + private ImageUtils imageUtils; + private String imgDir; + private String tmpDir; + public ImagesServiceImpl(String imgDir, String tmpDir) { + this.imgDir = imgDir; + this.tmpDir = tmpDir; + imageUtils = new ImageUtils(imgDir, tmpDir); + } + @Override + public void setAttachmentMetadata(String baseUrl, Message msg) throws Exception { + if (!StringUtils.isEmpty(msg.getAttachmentType())) { + Photo photo = new Photo(); + if (msg.getRid()> 0) { + photo.setSmall(String.format("%sphotos-512/%d-%d.%s", baseUrl, msg.getMid(), msg.getRid(), msg.getAttachmentType())); + photo.setMedium(String.format("%sphotos-1024/%d-%d.%s", baseUrl, msg.getMid(), msg.getRid(), msg.getAttachmentType())); + photo.setThumbnail(String.format("%sps/%d-%d.%s", baseUrl, msg.getMid(), msg.getRid(), msg.getAttachmentType())); + } else { + photo.setSmall(String.format("%sphotos-512/%d.%s", baseUrl, msg.getMid(), msg.getAttachmentType())); + photo.setMedium(String.format("%sphotos-1024/%d.%s", baseUrl, msg.getMid(), msg.getAttachmentType())); + photo.setThumbnail(String.format("%sps/%d.%s", baseUrl, msg.getMid(), msg.getAttachmentType())); + } + msg.setPhoto(photo); + String imageName = String.format("%s.%s", msg.getMid(), msg.getAttachmentType()); + if (msg.getRid() > 0) { + imageName = String.format("%s-%s.%s", msg.getMid(), msg.getRid(), msg.getAttachmentType()); + } + File fullImage = Paths.get(imgDir, "p", imageName).toFile(); + File mediumImage = Paths.get(imgDir, "photos-1024", imageName).toFile(); + File smallImage = Paths.get(imgDir, "photos-512", imageName).toFile(); + File thumbnailImage = Paths.get(imgDir, "ps", imageName).toFile(); + StringBuilder builder = new StringBuilder(); + builder.append(baseUrl); + builder.append(msg.getAttachmentType().equals("mp4") ? "video" : "p"); + builder.append("/").append(msg.getMid()); + if (msg.getRid() > 0) { + builder.append("-").append(msg.getRid()); + } + builder.append(".").append(msg.getAttachmentType()); + String originalUrl = builder.toString(); + + Attachment original = imageUtils.getAttachment(fullImage); + original.setUrl(originalUrl); + + Attachment medium = imageUtils.getAttachment(mediumImage); + medium.setUrl(photo.getMedium()); + original.setMedium(medium); + + Attachment small = imageUtils.getAttachment(smallImage); + small.setUrl(photo.getSmall()); + original.setSmall(small); + + Attachment thumb = imageUtils.getAttachment(thumbnailImage); + thumb.setUrl(photo.getMedium()); + original.setThumbnail(thumb); + + msg.setAttachment(original); + } + } + + @Override + public void saveImageWithPreviews(String tempFilename, String outputFilename) throws IOException { + imageUtils.saveImageWithPreviews(tempFilename, outputFilename); + } + + @Override + public void saveAvatar(String tempFilename, int uid) throws IOException { + imageUtils.saveAvatar(tempFilename, uid); + } +} diff --git a/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java b/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java index 0abe9309..b0707232 100644 --- a/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java +++ b/juick-server/src/main/java/com/juick/service/MessagesServiceImpl.java @@ -18,10 +18,9 @@ package com.juick.service; import com.juick.*; -import com.juick.server.helpers.PrivacyOpts; -import com.juick.server.helpers.ResponseReply; +import com.juick.model.PrivacyOpts; +import com.juick.model.ResponseReply; import com.juick.server.util.HttpNotFoundException; -import com.juick.service.security.entities.JuickUser; import com.juick.util.MessageUtils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; diff --git a/juick-server/src/main/java/com/juick/service/SubscriptionServiceImpl.java b/juick-server/src/main/java/com/juick/service/SubscriptionServiceImpl.java index 1dee379f..492fef1c 100644 --- a/juick-server/src/main/java/com/juick/service/SubscriptionServiceImpl.java +++ b/juick-server/src/main/java/com/juick/service/SubscriptionServiceImpl.java @@ -20,7 +20,7 @@ package com.juick.service; import com.juick.Message; import com.juick.Tag; import com.juick.User; -import com.juick.server.helpers.NotifyOpts; +import com.juick.model.NotifyOpts; import org.apache.commons.lang3.StringUtils; import org.springframework.dao.DuplicateKeyException; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; diff --git a/juick-server/src/main/java/com/juick/service/TagServiceImpl.java b/juick-server/src/main/java/com/juick/service/TagServiceImpl.java index aa6c3713..42159d3b 100644 --- a/juick-server/src/main/java/com/juick/service/TagServiceImpl.java +++ b/juick-server/src/main/java/com/juick/service/TagServiceImpl.java @@ -19,7 +19,7 @@ package com.juick.service; import com.juick.Tag; import com.juick.User; -import com.juick.server.helpers.TagStats; +import com.juick.model.TagStats; import com.juick.util.StreamUtils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; diff --git a/juick-server/src/main/java/com/juick/service/UserServiceImpl.java b/juick-server/src/main/java/com/juick/service/UserServiceImpl.java index bd72bed9..82e9a124 100644 --- a/juick-server/src/main/java/com/juick/service/UserServiceImpl.java +++ b/juick-server/src/main/java/com/juick/service/UserServiceImpl.java @@ -19,9 +19,9 @@ package com.juick.service; import com.juick.Message; import com.juick.User; -import com.juick.server.helpers.AnonymousUser; -import com.juick.server.helpers.Auth; -import com.juick.server.helpers.UserInfo; +import com.juick.model.AnonymousUser; +import com.juick.model.Auth; +import com.juick.model.UserInfo; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; diff --git a/juick-server/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java b/juick-server/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java new file mode 100644 index 00000000..9215d09a --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/security/HashParamAuthenticationFilter.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service.security; + +import com.juick.User; +import com.juick.service.security.entities.JuickUser; +import com.juick.service.UserService; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.authentication.RememberMeAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.RememberMeServices; +import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; +import org.springframework.util.Assert; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.WebUtils; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * Created by aalexeev on 4/5/17. + */ +public class HashParamAuthenticationFilter extends OncePerRequestFilter { + public static final String PARAM_NAME = "hash"; + + private final UserService userService; + private final RememberMeServices rememberMeServices; + + + public HashParamAuthenticationFilter( + final UserService userService, + final RememberMeServices rememberMeServices) { + Assert.notNull(userService, "userService should not be null"); + Assert.notNull(rememberMeServices, "rememberMeServices should not be null"); + + this.userService = userService; + this.rememberMeServices = rememberMeServices; + } + + @Override + protected void doFilterInternal( + HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + + String hash = getHashFromRequest(request); + + if (hash != null && authenticationIsRequired()) { + User user = userService.getUserByHash(hash); + + if (!user.isAnonymous()) { + User userWithPassword = userService.getUserByName(user.getName()); + userWithPassword.setAuthHash(userService.getHashByUID(userWithPassword.getUid())); + Authentication authentication = new RememberMeAuthenticationToken( + ((AbstractRememberMeServices)rememberMeServices).getKey(), new JuickUser(userWithPassword), JuickUser.USER_AUTHORITY); + + SecurityContextHolder.getContext().setAuthentication(authentication); + + rememberMeServices.loginSuccess(request, response, authentication); + } + } + + filterChain.doFilter(request, response); + } + + private boolean authenticationIsRequired() { + Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication(); + + return existingAuth == null || + !existingAuth.isAuthenticated() || + existingAuth instanceof AnonymousAuthenticationToken; + } + + private String getHashFromRequest(HttpServletRequest request) { + String paramHash = request.getParameter(PARAM_NAME); + Cookie cookieHash = WebUtils.getCookie(request, PARAM_NAME); + + if (paramHash == null && cookieHash != null) { + return cookieHash.getValue(); + } + return paramHash; + } +} diff --git a/juick-server/src/main/java/com/juick/service/security/JuickUserDetailsService.java b/juick-server/src/main/java/com/juick/service/security/JuickUserDetailsService.java new file mode 100644 index 00000000..59425fab --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/security/JuickUserDetailsService.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service.security; + +import com.juick.service.UserService; +import com.juick.service.security.entities.JuickUser; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.util.Assert; + +/** + * Created by aalexeev on 11/28/16. + */ +public class JuickUserDetailsService implements UserDetailsService { + private final UserService userService; + + public JuickUserDetailsService(final UserService userService) { + Assert.notNull(userService, "UserService must be initialized"); + this.userService = userService; + } + + @Override + public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { + if (StringUtils.isBlank(username)) + throw new UsernameNotFoundException("Invalid user name " + username); + + com.juick.User user = userService.getUserByName(username); + + if (!user.isAnonymous()) { + user.setAuthHash(userService.getHashByUID(user.getUid())); + return new JuickUser(user); + } + + throw new UsernameNotFoundException("The username " + username + " is not found"); + } +} diff --git a/juick-server/src/main/java/com/juick/service/security/NullUserDetailsService.java b/juick-server/src/main/java/com/juick/service/security/NullUserDetailsService.java new file mode 100644 index 00000000..91acefa3 --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/security/NullUserDetailsService.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service.security; + +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +/** + * Created by aalexeev on 11/28/16. + */ +public class NullUserDetailsService implements UserDetailsService { + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + throw new UsernameNotFoundException( + "loadUserByUsername called for NullUserDetailsService, user " + username + "can not be found"); + } +} diff --git a/juick-server/src/main/java/com/juick/service/security/deprecated/CookieSimpleHashRememberMeServices.java b/juick-server/src/main/java/com/juick/service/security/deprecated/CookieSimpleHashRememberMeServices.java new file mode 100644 index 00000000..e385d7dd --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/security/deprecated/CookieSimpleHashRememberMeServices.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service.security.deprecated; + +import com.juick.User; +import com.juick.service.security.entities.JuickUser; +import com.juick.service.UserService; +import com.juick.service.security.NullUserDetailsService; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.web.authentication.RememberMeServices; +import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; +import org.springframework.security.web.authentication.rememberme.InvalidCookieException; +import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException; +import org.springframework.util.Assert; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Optional; + +/** + * Created by aalexeev on 11/28/16. + * + * @deprecated not recommended use for secure reasons + */ +@Deprecated +public class CookieSimpleHashRememberMeServices extends AbstractRememberMeServices implements RememberMeServices { + private static final Logger logger = LoggerFactory.getLogger(CookieSimpleHashRememberMeServices.class); + + private static final String COOKIE_PARAM_NAME = "hash"; + + private final UserService userService; + + public CookieSimpleHashRememberMeServices( + final String key, final UserService userService, final Environment environment) { + super(key, new NullUserDetailsService()); + + Assert.notNull(userService); + Assert.notNull(environment); + + this.userService = userService; + + setCookieName(COOKIE_PARAM_NAME); + setCookieDomain(environment.getProperty("web_domain", "localhost")); + setAlwaysRemember(true); + } + + @Override + public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { + super.logout(request, response, authentication); + userService.deleteLoginForUser(authentication.getName()); + } + + @Override + protected void onLoginSuccess( + HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { + String username = successfulAuthentication.getName(); + + logger.debug("Creating new persistent login for user {}", username); + + try { + int uid = userService.getUIDbyName(username); + + Assert.isTrue(uid > 0); + + String hash = RandomStringUtils.randomAlphanumeric(16).toUpperCase(); + + userService.setLoginForUser(uid, hash); + + setCookie(new String[]{hash}, getTokenValiditySeconds(), request, response); + } catch (Exception e) { + logger.error("Failed to save cookies", e); + } + } + + @Override + protected UserDetails processAutoLoginCookie( + String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) + throws RememberMeAuthenticationException, UsernameNotFoundException { + String hash = cookieTokens[0]; + + if (StringUtils.isBlank(hash)) { + hash = request.getParameter("hash"); + } + if (StringUtils.isBlank(hash)) { + throw new InvalidCookieException("Cookie is invalid and hash parameter not found"); + } + + int uid = userService.getUIDbyHash(hash); + if (uid <= 0) + throw new UsernameNotFoundException("User not found by hash, cookies" + cookieTokens); + + Optional userOptional = userService.getUserByUID(uid); + + Assert.isTrue(userOptional.isPresent()); + + return new JuickUser(userService.getUserByName(userOptional.get().getName())); + } + + @Override + protected String[] decodeCookie(String cookieValue) throws InvalidCookieException { + return new String[]{cookieValue}; + } + + @Override + protected String encodeCookie(String[] cookieTokens) { + return cookieTokens != null && cookieTokens.length > 0 ? cookieTokens[0] : StringUtils.EMPTY; + } +} diff --git a/juick-server/src/main/java/com/juick/service/security/deprecated/RequestParamHashRememberMeServices.java b/juick-server/src/main/java/com/juick/service/security/deprecated/RequestParamHashRememberMeServices.java new file mode 100644 index 00000000..3631e5a4 --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/security/deprecated/RequestParamHashRememberMeServices.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service.security.deprecated; + +import com.juick.User; +import com.juick.service.security.entities.JuickUser; +import com.juick.service.UserService; +import com.juick.service.security.NullUserDetailsService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.web.authentication.RememberMeServices; +import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices; +import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException; +import org.springframework.util.Assert; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Created by aalexeev on 11/30/16. + * + * @deprecated for security reasons + */ +@Deprecated +public class RequestParamHashRememberMeServices extends AbstractRememberMeServices implements RememberMeServices { + private static final String PARAM_NAME = "hash"; + + private final UserService userService; + + public RequestParamHashRememberMeServices(String key, UserService userService) { + super(key, new NullUserDetailsService()); + + Assert.notNull(userService); + this.userService = userService; + setAlwaysRemember(false); + } + + @Override + protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { + // do nothing + } + + @Override + protected boolean rememberMeRequested(HttpServletRequest request, String parameter) { + return false; // always false + } + + @Override + protected void cancelCookie(HttpServletRequest request, HttpServletResponse response) { + // do nothing + } + + @Override + protected String extractRememberMeCookie(HttpServletRequest request) { + return PARAM_NAME; // return any not blank value + } + + @Override + protected UserDetails processAutoLoginCookie( + String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) + throws RememberMeAuthenticationException, UsernameNotFoundException { + String hash = request.getParameter(PARAM_NAME); + + if (StringUtils.isNotBlank(hash)) { + User user = userService.getUserByHash(hash); + if (!user.isAnonymous()) + return new JuickUser(userService.getUserByName(user.getName())); + } + throw new UsernameNotFoundException("User not found by hash " + hash); + } +} diff --git a/juick-server/src/main/java/com/juick/service/security/entities/JuickUser.java b/juick-server/src/main/java/com/juick/service/security/entities/JuickUser.java new file mode 100644 index 00000000..c43f112f --- /dev/null +++ b/juick-server/src/main/java/com/juick/service/security/entities/JuickUser.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2008-2017, 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 . + */ + +package com.juick.service.security.entities; + +import com.juick.User; +import com.juick.model.AnonymousUser; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * Created by aalexeev on 11/21/16. + */ +public class JuickUser implements UserDetails { + static final GrantedAuthority ROLE_USER = new SimpleGrantedAuthority("ROLE_USER"); + static final GrantedAuthority ROLE_ANONYMOUS = new SimpleGrantedAuthority("ROLE_ANONYMOUS"); + + public static final List USER_AUTHORITY = Collections.singletonList(ROLE_USER); + public static final List ANONYMOUS_AUTHORITY = Collections.singletonList(ROLE_ANONYMOUS); + + public static final JuickUser ANONYMOUS_USER = new JuickUser(AnonymousUser.INSTANCE, ANONYMOUS_AUTHORITY); + + private final com.juick.User user; + private final Collection authorities; + + public JuickUser(com.juick.User user) { + this(user, USER_AUTHORITY); + } + + public JuickUser(com.juick.User user, Collection authorities) { + this.user = user; + this.authorities = authorities; + } + + @Override + public Collection getAuthorities() { + return authorities; + } + + @Override + public String getPassword() { + return "{noop}" + user.getCredentials(); + } + + @Override + public String getUsername() { + return user.getName(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return StringUtils.isNotBlank(user.getCredentials()); + } + + @Override + public boolean isCredentialsNonExpired() { + return isAccountNonLocked(); + } + + @Override + public boolean isEnabled() { + return !user.isBanned() && isCredentialsNonExpired(); + } + + public User getUser() { + return user; + } +} diff --git a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java index 924864f6..56434d1e 100644 --- a/juick-server/src/test/java/com/juick/server/tests/ServerTests.java +++ b/juick-server/src/test/java/com/juick/server/tests/ServerTests.java @@ -29,10 +29,10 @@ import com.jayway.jsonpath.JsonPath; import com.juick.*; import com.juick.server.*; import com.juick.server.api.activity.model.ActivityObject; -import com.juick.server.component.MessageEvent; -import com.juick.server.helpers.AnonymousUser; -import com.juick.server.helpers.CommandResult; -import com.juick.server.helpers.TagStats; +import com.juick.service.component.MessageEvent; +import com.juick.model.AnonymousUser; +import com.juick.model.CommandResult; +import com.juick.model.TagStats; import com.juick.server.util.HttpUtils; import com.juick.server.util.ImageUtils; import com.juick.server.www.Utils; -- cgit v1.2.3