From 559ae343aa72db04e12b94acfa0bec30ed9a11f1 Mon Sep 17 00:00:00 2001
From: Vitaly Takmazov
Date: Fri, 9 Dec 2016 16:14:27 +0300
Subject: juick-spring-www: merge some work from develop branch, port some
templates to Thymeleaf
---
.../java/com/juick/api/controllers/Messages.java | 4 +-
.../com/juick/api/controllers/Notifications.java | 4 +-
.../java/com/juick/api/controllers/Others.java | 4 +-
.../main/java/com/juick/api/controllers/PM.java | 4 +-
.../main/java/com/juick/api/controllers/Post.java | 8 +-
.../com/juick/api/controllers/Subscriptions.java | 4 +-
.../main/java/com/juick/api/controllers/Users.java | 4 +-
.../juick/api/util/HttpBadRequestException.java | 12 --
.../com/juick/api/util/HttpForbiddenException.java | 12 --
.../com/juick/api/util/HttpNotFoundException.java | 12 --
.../main/java/com/juick/api/util/HttpUtils.java | 111 --------------
.../java/com/juick/api/tests/MessagesTests.java | 30 ++--
.../juick/server/util/HttpBadRequestException.java | 12 ++
.../juick/server/util/HttpForbiddenException.java | 12 ++
.../juick/server/util/HttpNotFoundException.java | 12 ++
.../main/java/com/juick/server/util/HttpUtils.java | 111 ++++++++++++++
.../main/java/com/juick/service/EmailService.java | 8 +
.../java/com/juick/service/EmailServiceImpl.java | 33 ++++
.../com/juick/www/controllers/HelpController.java | 58 ++++++-
.../com/juick/www/controllers/IndexController.java | 117 +++++++++++++--
.../juick/www/controllers/SettingsController.java | 66 +++++++-
.../com/juick/www/controllers/TagController.java | 86 ++++++++++-
.../java/com/juick/www/helpers/QueryString.java | 14 ++
.../com/juick/www/helpers/QueryStringResolver.java | 31 ++++
.../main/java/com/juick/www/util/EncodeUtils.java | 10 ++
.../WEB-INF/templates/layout/mainLayout.html | 48 +-----
.../webapp/WEB-INF/templates/layout/sponsors.html | 8 -
.../main/webapp/WEB-INF/templates/views/help.html | 18 +++
.../WEB-INF/templates/views/partial/footer.html | 34 +++++
.../templates/views/partial/homecolumn.html | 6 +
.../templates/views/partial/navigation.html | 37 +++++
.../templates/views/partial/settings_tabs.html | 5 +
.../WEB-INF/templates/views/partial/tags.html | 3 +
.../WEB-INF/templates/views/settings_about.html | 31 ++++
.../templates/views/settings_auth-email.html | 20 +++
.../WEB-INF/templates/views/settings_main.html | 167 +++++++++++++++++++++
.../WEB-INF/templates/views/settings_password.html | 26 ++++
.../WEB-INF/templates/views/settings_result.html | 18 +++
38 files changed, 954 insertions(+), 246 deletions(-)
delete mode 100644 juick-api/src/main/java/com/juick/api/util/HttpBadRequestException.java
delete mode 100644 juick-api/src/main/java/com/juick/api/util/HttpForbiddenException.java
delete mode 100644 juick-api/src/main/java/com/juick/api/util/HttpNotFoundException.java
delete mode 100644 juick-api/src/main/java/com/juick/api/util/HttpUtils.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/service/EmailService.java
create mode 100644 juick-server/src/main/java/com/juick/service/EmailServiceImpl.java
create mode 100644 juick-spring-www/src/main/java/com/juick/www/helpers/QueryString.java
create mode 100644 juick-spring-www/src/main/java/com/juick/www/helpers/QueryStringResolver.java
create mode 100644 juick-spring-www/src/main/java/com/juick/www/util/EncodeUtils.java
delete mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/layout/sponsors.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/help.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/partial/footer.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/partial/homecolumn.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/partial/navigation.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/partial/settings_tabs.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/partial/tags.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_about.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_auth-email.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_main.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_password.html
create mode 100644 juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_result.html
diff --git a/juick-api/src/main/java/com/juick/api/controllers/Messages.java b/juick-api/src/main/java/com/juick/api/controllers/Messages.java
index f30a7687..723d2f15 100644
--- a/juick-api/src/main/java/com/juick/api/controllers/Messages.java
+++ b/juick-api/src/main/java/com/juick/api/controllers/Messages.java
@@ -3,8 +3,8 @@ package com.juick.api.controllers;
import com.juick.Tag;
import com.juick.User;
import com.juick.api.ApiServer;
-import com.juick.api.util.HttpBadRequestException;
-import com.juick.api.util.HttpForbiddenException;
+import com.juick.server.util.HttpBadRequestException;
+import com.juick.server.util.HttpForbiddenException;
import com.juick.server.helpers.Status;
import com.juick.service.MessagesService;
import com.juick.service.TagService;
diff --git a/juick-api/src/main/java/com/juick/api/controllers/Notifications.java b/juick-api/src/main/java/com/juick/api/controllers/Notifications.java
index ff3679c0..cd31ad39 100644
--- a/juick-api/src/main/java/com/juick/api/controllers/Notifications.java
+++ b/juick-api/src/main/java/com/juick/api/controllers/Notifications.java
@@ -4,8 +4,8 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.juick.Message;
import com.juick.User;
-import com.juick.api.util.HttpBadRequestException;
-import com.juick.api.util.HttpForbiddenException;
+import com.juick.server.util.HttpBadRequestException;
+import com.juick.server.util.HttpForbiddenException;
import com.juick.server.helpers.Status;
import com.juick.server.helpers.TokensList;
import com.juick.service.MessagesService;
diff --git a/juick-api/src/main/java/com/juick/api/controllers/Others.java b/juick-api/src/main/java/com/juick/api/controllers/Others.java
index e2d802d8..852c03d6 100644
--- a/juick-api/src/main/java/com/juick/api/controllers/Others.java
+++ b/juick-api/src/main/java/com/juick/api/controllers/Others.java
@@ -1,8 +1,8 @@
package com.juick.api.controllers;
import com.juick.User;
-import com.juick.api.util.HttpForbiddenException;
-import com.juick.api.util.HttpNotFoundException;
+import com.juick.server.util.HttpForbiddenException;
+import com.juick.server.util.HttpNotFoundException;
import com.juick.server.helpers.PrivateChats;
import com.juick.service.PMQueriesService;
import com.juick.service.UserService;
diff --git a/juick-api/src/main/java/com/juick/api/controllers/PM.java b/juick-api/src/main/java/com/juick/api/controllers/PM.java
index c928a11e..ffbea4b5 100644
--- a/juick-api/src/main/java/com/juick/api/controllers/PM.java
+++ b/juick-api/src/main/java/com/juick/api/controllers/PM.java
@@ -2,8 +2,8 @@ package com.juick.api.controllers;
import com.juick.User;
import com.juick.api.ApiServer;
-import com.juick.api.util.HttpBadRequestException;
-import com.juick.api.util.HttpForbiddenException;
+import com.juick.server.util.HttpBadRequestException;
+import com.juick.server.util.HttpForbiddenException;
import com.juick.service.PMQueriesService;
import com.juick.service.UserService;
import com.juick.util.UserUtils;
diff --git a/juick-api/src/main/java/com/juick/api/controllers/Post.java b/juick-api/src/main/java/com/juick/api/controllers/Post.java
index 6d273f7a..53cfc3e5 100644
--- a/juick-api/src/main/java/com/juick/api/controllers/Post.java
+++ b/juick-api/src/main/java/com/juick/api/controllers/Post.java
@@ -2,10 +2,10 @@ package com.juick.api.controllers;
import com.juick.User;
import com.juick.api.ApiServer;
-import com.juick.api.util.HttpBadRequestException;
-import com.juick.api.util.HttpForbiddenException;
-import com.juick.api.util.HttpNotFoundException;
-import com.juick.api.util.HttpUtils;
+import com.juick.server.util.HttpBadRequestException;
+import com.juick.server.util.HttpForbiddenException;
+import com.juick.server.util.HttpNotFoundException;
+import com.juick.server.util.HttpUtils;
import com.juick.service.MessagesService;
import com.juick.service.SubscriptionService;
import com.juick.service.UserService;
diff --git a/juick-api/src/main/java/com/juick/api/controllers/Subscriptions.java b/juick-api/src/main/java/com/juick/api/controllers/Subscriptions.java
index 42be9903..b93ec1f3 100644
--- a/juick-api/src/main/java/com/juick/api/controllers/Subscriptions.java
+++ b/juick-api/src/main/java/com/juick/api/controllers/Subscriptions.java
@@ -2,8 +2,8 @@ package com.juick.api.controllers;
import com.juick.Message;
import com.juick.User;
-import com.juick.api.util.HttpBadRequestException;
-import com.juick.api.util.HttpForbiddenException;
+import com.juick.server.util.HttpBadRequestException;
+import com.juick.server.util.HttpForbiddenException;
import com.juick.service.MessagesService;
import com.juick.service.SubscriptionService;
import com.juick.service.UserService;
diff --git a/juick-api/src/main/java/com/juick/api/controllers/Users.java b/juick-api/src/main/java/com/juick/api/controllers/Users.java
index 396a716c..d6035cf2 100644
--- a/juick-api/src/main/java/com/juick/api/controllers/Users.java
+++ b/juick-api/src/main/java/com/juick/api/controllers/Users.java
@@ -1,8 +1,8 @@
package com.juick.api.controllers;
import com.juick.User;
-import com.juick.api.util.HttpForbiddenException;
-import com.juick.api.util.HttpNotFoundException;
+import com.juick.server.util.HttpForbiddenException;
+import com.juick.server.util.HttpNotFoundException;
import com.juick.service.UserService;
import com.juick.util.UserUtils;
import com.juick.util.WebUtils;
diff --git a/juick-api/src/main/java/com/juick/api/util/HttpBadRequestException.java b/juick-api/src/main/java/com/juick/api/util/HttpBadRequestException.java
deleted file mode 100644
index 3a42e999..00000000
--- a/juick-api/src/main/java/com/juick/api/util/HttpBadRequestException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.juick.api.util;
-
-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 {
-
-}
diff --git a/juick-api/src/main/java/com/juick/api/util/HttpForbiddenException.java b/juick-api/src/main/java/com/juick/api/util/HttpForbiddenException.java
deleted file mode 100644
index d8f4ddf3..00000000
--- a/juick-api/src/main/java/com/juick/api/util/HttpForbiddenException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.juick.api.util;
-
-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 {
-
-}
diff --git a/juick-api/src/main/java/com/juick/api/util/HttpNotFoundException.java b/juick-api/src/main/java/com/juick/api/util/HttpNotFoundException.java
deleted file mode 100644
index 14f34cf0..00000000
--- a/juick-api/src/main/java/com/juick/api/util/HttpNotFoundException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.juick.api.util;
-
-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 {
-
-}
diff --git a/juick-api/src/main/java/com/juick/api/util/HttpUtils.java b/juick-api/src/main/java/com/juick/api/util/HttpUtils.java
deleted file mode 100644
index ca75eae7..00000000
--- a/juick-api/src/main/java/com/juick/api/util/HttpUtils.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Juick
- * Copyright (C) 2008-2011, Ugnich Anton
- *
- * 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.api.util;
-
-import org.apache.commons.codec.digest.DigestUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.UUID;
-
-/**
- *
- * @author Ugnich Anton
- */
-public class HttpUtils {
- private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);
-
- public static String receiveMultiPartFile(MultipartFile attach, String tmpDir) {
- if (attach !=null && !attach.isEmpty()) {
- String partname = attach.getOriginalFilename();
- if (partname != null && partname.length() > 0) {
- String attachmentType = partname.substring(partname.length() - 3).toLowerCase();
- if (attachmentType.equals("jpg") || attachmentType.equals("peg") || attachmentType.equals("png")) {
- if (attachmentType.equals("peg")) {
- attachmentType = "jpg";
- }
- String attachmentFName = DigestUtils.md5Hex(UUID.randomUUID().toString()) + "." + attachmentType;
- try {
- Files.write(Paths.get(tmpDir, attachmentFName),
- attach.getBytes());
- return attachmentFName;
- } catch (IOException e) {
- logger.warn("file receive error", e);
- }
- }
- }
- }
- return "";
- }
- public static String downloadImage(URL url) throws Exception {
- String attachmentFName = null;
- Exception ex = null;
-
- InputStream is = null;
- FileOutputStream fos = null;
- try {
- URLConnection urlConn = url.openConnection();
- is = urlConn.getInputStream();
- String mime = urlConn.getContentType();
-
- String attachmentType;
- if (mime != null && mime.equals("image/jpeg")) {
- attachmentType = "jpg";
- } else if (mime != null && mime.equals("image/png")) {
- attachmentType = "png";
- } else {
- throw new Exception("Wrong file type");
- }
-
- attachmentFName = UUID.randomUUID().toString() + "." + attachmentType;
- fos = new FileOutputStream("/var/www/juick.com/i/tmp/" + attachmentFName);
- byte[] buffer = new byte[10240];
- int len;
- while ((len = is.read(buffer)) > 0) {
- fos.write(buffer, 0, len);
- }
- } catch (Exception e) {
- ex = e;
- attachmentFName = null;
- } finally {
- try {
- if (is != null) {
- is.close();
- }
- } finally {
- if (fos != null) {
- fos.close();
- }
- }
- }
-
- if (ex != null) {
- throw ex;
- } else {
- return attachmentFName;
- }
- }
-}
diff --git a/juick-api/src/test/java/com/juick/api/tests/MessagesTests.java b/juick-api/src/test/java/com/juick/api/tests/MessagesTests.java
index e0f9b840..9f74c00d 100644
--- a/juick-api/src/test/java/com/juick/api/tests/MessagesTests.java
+++ b/juick-api/src/test/java/com/juick/api/tests/MessagesTests.java
@@ -38,6 +38,7 @@ import static org.mockito.Mockito.when;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
/**
@@ -173,12 +174,10 @@ public class MessagesTests {
@Test
public void homeTestWithMessagesAndRememberMe() throws Exception {
- String ugnichName = "ugnich";
- String uginchPassword = "MyPassw0rd!";
String msgText = "Привет, я - Угнич";
String hash = "12345678";
- User user = getUser(1, ugnichName, uginchPassword);
+ User user = getUser(1, ugnichName, ugnichPassword);
Message msg = getMessage(user, msgText);
when(userService.getUIDbyName(ugnichName))
@@ -198,7 +197,7 @@ public class MessagesTests {
mockMvc.perform(
get("/home")
- .with(httpBasic(ugnichName, uginchPassword)))
+ .with(httpBasic(ugnichName, ugnichPassword)))
.andExpect(status().isOk())
.andReturn();
@@ -211,11 +210,8 @@ public class MessagesTests {
}
@Test
- public void homeTestWithMEssagesAndSimpleCors() throws Exception {
- String ugnichName = "ugnich";
- String uginchPassword = "MyPassw0rd!";
-
- User user = getUser(1, ugnichName, uginchPassword);
+ public void homeTestWithMessagesAndSimpleCors() throws Exception {
+ User user = getUser(1, ugnichName, ugnichPassword);
Message msg = getMessage(user, null);
when(userService.getFullyUserByName(ugnichName))
@@ -229,7 +225,7 @@ public class MessagesTests {
mockMvc.perform(
get("/home")
- .with(httpBasic(ugnichName, uginchPassword))
+ .with(httpBasic(ugnichName, ugnichPassword))
.header("Origin", "http://api.example.net"))
.andExpect(status().isOk())
.andExpect(header().string("Access-Control-Allow-Origin", "*"));
@@ -237,16 +233,13 @@ public class MessagesTests {
@Test
public void homeTestWithPreflightCors() throws Exception {
- String ugnichName = "ugnich";
- String uginchPassword = "MyPassw0rd!";
-
- User user = getUser(1, ugnichName, uginchPassword);
+ User user = getUser(1, ugnichName, ugnichPassword);
when(userService.getFullyUserByName(ugnichName))
.thenReturn(user);
mockMvc.perform(
options("/home")
- .with(httpBasic(ugnichName, uginchPassword))
+ .with(httpBasic(ugnichName, ugnichPassword))
.header("Origin", "http://api.example.net")
.header("Access-Control-Request-Method", "POST")
.header("Access-Control-Request-Headers", "X-PINGOTHER, Content-Type"))
@@ -291,4 +284,11 @@ public class MessagesTests {
.andExpect(jsonPath("$", hasSize(1)))
.andExpect(jsonPath("$[0].messages", is(5)));
}
+ @Test
+ public void postWithReferer() throws Exception {
+ mockMvc.perform(post("/post")
+ .param("body", "yo")
+ .with(httpBasic(ugnichName, ugnichPassword)))
+ .andExpect(status().isOk());
+ }
}
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..cd862830
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/server/util/HttpBadRequestException.java
@@ -0,0 +1,12 @@
+package com.juick.server.util;
+
+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 {
+
+}
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..7e85816e
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/server/util/HttpForbiddenException.java
@@ -0,0 +1,12 @@
+package com.juick.server.util;
+
+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 {
+
+}
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..378eadfc
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/server/util/HttpNotFoundException.java
@@ -0,0 +1,12 @@
+package com.juick.server.util;
+
+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 {
+
+}
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..fa0b2ec2
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/server/util/HttpUtils.java
@@ -0,0 +1,111 @@
+/*
+ * Juick
+ * Copyright (C) 2008-2011, Ugnich Anton
+ *
+ * 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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.UUID;
+
+/**
+ *
+ * @author Ugnich Anton
+ */
+public class HttpUtils {
+ private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);
+
+ public static String receiveMultiPartFile(MultipartFile attach, String tmpDir) {
+ if (attach !=null && !attach.isEmpty()) {
+ String partname = attach.getOriginalFilename();
+ if (partname != null && partname.length() > 0) {
+ String attachmentType = partname.substring(partname.length() - 3).toLowerCase();
+ if (attachmentType.equals("jpg") || attachmentType.equals("peg") || attachmentType.equals("png")) {
+ if (attachmentType.equals("peg")) {
+ attachmentType = "jpg";
+ }
+ String attachmentFName = DigestUtils.md5Hex(UUID.randomUUID().toString()) + "." + attachmentType;
+ try {
+ Files.write(Paths.get(tmpDir, attachmentFName),
+ attach.getBytes());
+ return attachmentFName;
+ } catch (IOException e) {
+ logger.warn("file receive error", e);
+ }
+ }
+ }
+ }
+ return "";
+ }
+ public static String downloadImage(URL url) throws Exception {
+ String attachmentFName = null;
+ Exception ex = null;
+
+ InputStream is = null;
+ FileOutputStream fos = null;
+ try {
+ URLConnection urlConn = url.openConnection();
+ is = urlConn.getInputStream();
+ String mime = urlConn.getContentType();
+
+ String attachmentType;
+ if (mime != null && mime.equals("image/jpeg")) {
+ attachmentType = "jpg";
+ } else if (mime != null && mime.equals("image/png")) {
+ attachmentType = "png";
+ } else {
+ throw new Exception("Wrong file type");
+ }
+
+ attachmentFName = UUID.randomUUID().toString() + "." + attachmentType;
+ fos = new FileOutputStream("/var/www/juick.com/i/tmp/" + attachmentFName);
+ byte[] buffer = new byte[10240];
+ int len;
+ while ((len = is.read(buffer)) > 0) {
+ fos.write(buffer, 0, len);
+ }
+ } catch (Exception e) {
+ ex = e;
+ attachmentFName = null;
+ } finally {
+ try {
+ if (is != null) {
+ is.close();
+ }
+ } finally {
+ if (fos != null) {
+ fos.close();
+ }
+ }
+ }
+
+ if (ex != null) {
+ throw ex;
+ } else {
+ return attachmentFName;
+ }
+ }
+}
diff --git a/juick-server/src/main/java/com/juick/service/EmailService.java b/juick-server/src/main/java/com/juick/service/EmailService.java
new file mode 100644
index 00000000..f62f4b32
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/service/EmailService.java
@@ -0,0 +1,8 @@
+package com.juick.service;
+
+/**
+ * Created by vitalyster on 09.12.2016.
+ */
+public interface EmailService {
+ boolean verifyAddressByCode(Integer userId, String code);
+}
diff --git a/juick-server/src/main/java/com/juick/service/EmailServiceImpl.java b/juick-server/src/main/java/com/juick/service/EmailServiceImpl.java
new file mode 100644
index 00000000..bdd78609
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/service/EmailServiceImpl.java
@@ -0,0 +1,33 @@
+package com.juick.service;
+
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.inject.Inject;
+
+/**
+ * Created by vitalyster on 09.12.2016.
+ */
+@Repository
+@Transactional
+public class EmailServiceImpl extends BaseJdbcService implements EmailService {
+ @Inject
+ public EmailServiceImpl(JdbcTemplate jdbcTemplate) {
+ super(jdbcTemplate, null);
+ }
+
+ @Override
+ public boolean verifyAddressByCode(Integer userId, String code) {
+ try {
+ String address = getJdbcTemplate().queryForObject("SELECT account FROM auth WHERE user_id=? AND protocol='email' AND authcode=?",
+ String.class, userId, code);
+ getJdbcTemplate().update("INSERT INTO emails(user_id,email) VALUES (?,?)", userId, address);
+ getJdbcTemplate().update("DELETE FROM auth WHERE user_id=? AND authcode=?", userId, code);
+ } catch (EmptyResultDataAccessException e) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/juick-spring-www/src/main/java/com/juick/www/controllers/HelpController.java b/juick-spring-www/src/main/java/com/juick/www/controllers/HelpController.java
index dad3ff9f..49e24c8c 100644
--- a/juick-spring-www/src/main/java/com/juick/www/controllers/HelpController.java
+++ b/juick-spring-www/src/main/java/com/juick/www/controllers/HelpController.java
@@ -1,12 +1,68 @@
package com.juick.www.controllers;
+import com.juick.User;
+import com.juick.server.util.HttpNotFoundException;
+import com.juick.service.UserService;
+import com.juick.util.UserUtils;
+import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
+import javax.inject.Inject;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.Principal;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
/**
* Created by aalexeev on 11/21/16.
*/
@Controller
-@RequestMapping("/help")
public class HelpController {
+ @Inject
+ UserService userService;
+
+ @RequestMapping({"/help", "/help/{lang}", "/help/{lang}/{page}"})
+ protected String doGetHelp(
+ Principal principal,
+ @PathVariable("lang") Optional lang,
+ @PathVariable("page") Optional page,
+ ModelMap model) throws IOException, URISyntaxException {
+ String name = UserUtils.getUsername(principal, null);
+ User visitor = userService.getUserByName(name);
+
+ lang.ifPresent(l -> {
+ if (l.length() != 2 || !l.matches("^[a-z]+$")) {
+ throw new HttpNotFoundException();
+ }
+ });
+ if (!lang.isPresent()) {
+ lang = Optional.of("ru");
+ }
+
+ page.ifPresent(p -> {
+ if (!p.matches("^[a-zA-Z0-9\\-]*$") || p.equals("navigation") || p.equals("index")) {
+ throw new HttpNotFoundException();
+ }
+ });
+ if (!page.isPresent()) {
+ page = Optional.of("index");
+ }
+
+ String filePath = "help/" + lang.get() + "/" + page.get();
+ String navigationPath = "help/" + lang.get() + "/navigation";
+
+ model.addAttribute("title", "Помощь");
+ model.addAttribute("visitor", visitor);
+ model.addAttribute("help_nav", Files.readAllLines(Paths.get(new ClassPathResource(navigationPath).getURI()))
+ .stream().collect(Collectors.joining()));
+ model.addAttribute("help_data", Files.readAllLines(Paths.get(new ClassPathResource(filePath).getURI()))
+ .stream().collect(Collectors.joining()));
+ return "views/help";
+ }
}
diff --git a/juick-spring-www/src/main/java/com/juick/www/controllers/IndexController.java b/juick-spring-www/src/main/java/com/juick/www/controllers/IndexController.java
index 2973bf30..91efd8aa 100644
--- a/juick-spring-www/src/main/java/com/juick/www/controllers/IndexController.java
+++ b/juick-spring-www/src/main/java/com/juick/www/controllers/IndexController.java
@@ -1,9 +1,26 @@
package com.juick.www.controllers;
+import com.juick.Message;
+import com.juick.User;
+import com.juick.service.MessagesService;
+import com.juick.service.TagService;
+import com.juick.service.UserService;
+import com.juick.util.UserUtils;
+import com.juick.www.util.EncodeUtils;
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.*;
+
+import javax.inject.Inject;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
/**
* Created by aalexeev on 11/21/16.
@@ -11,14 +28,94 @@ import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class IndexController {
- @RequestMapping("/")
- public String index(
- java.security.Principal userPrincipal,
- @RequestParam(required = false, defaultValue = "0") int before,
- Model model) {
+ @Inject
+ UserService userService;
+ @Inject
+ MessagesService messagesService;
+ @Inject
+ TagService tagService;
+
+ @RequestMapping(value = "/", method = RequestMethod.GET)
+ protected String doGet(
+ Principal principal,
+ @CookieValue("ref") Optional ref,
+ @RequestHeader("Referer") Optional referer,
+ @RequestParam("show") Optional paramShow,
+ @RequestParam("tag") Optional paramTagStr,
+ @RequestParam(value = "before", required = false) Integer paramBefore,
+ @RequestParam(value = "search", required = false) String paramSearch,
+ ModelMap model) throws IOException {
+
+ if (paramTagStr.isPresent()) {
+ return "redirect:/tag/" + URLEncoder.encode(paramTagStr.get(), "UTF-8");
+ }
+
+ if (StringUtils.isNotEmpty(paramSearch) && paramSearch.length() > 64) {
+ paramSearch = "";
+ }
+
+ String name = UserUtils.getUsername(principal, null);
+ User visitor = userService.getUserByName(name);
- model.addAttribute("currentUser", userPrincipal);
+ String title;
+ if (visitor.getUid() > 0) {
+ title = "Популярные";
+ } else {
+ title = "Микроблоги Juick: популярные записи";
+ }
+ List mids = new ArrayList<>();
- return "index";
+ if (StringUtils.isNotEmpty(paramSearch)) {
+ title = "Поиск: " + StringEscapeUtils.escapeHtml4(paramSearch);
+ mids = messagesService.getSearch(EncodeUtils.encodeSphinx(paramSearch),
+ paramBefore);
+ } else if (!paramShow.isPresent()) {
+ mids = messagesService.getPopular(visitor.getUid(), paramBefore);
+ } else if (paramShow.get().equals("top")) {
+ return "redirect:/";
+ } else if (paramShow.get().equals("my") && visitor.getUid() > 0) {
+ title = "Моя лента";
+ mids = messagesService.getMyFeed(visitor.getUid(), paramBefore);
+ } else if (paramShow.get().equals("private") && visitor.getUid() > 0) {
+ title = "Приватные";
+ mids = messagesService.getPrivate(visitor.getUid(), paramBefore);
+ } else if (paramShow.get().equals("discuss") && visitor.getUid() > 0) {
+ title = "Обсуждения";
+ mids = messagesService.getDiscussions(visitor.getUid(), paramBefore);
+ } else if (paramShow.get().equals("recommended") && visitor.getUid() > 0) {
+ title = "Рекомендации";
+ mids = messagesService.getRecommended(visitor.getUid(), paramBefore);
+ } else if (paramShow.get().equals("photos")) {
+ title = "Фотографии";
+ mids = messagesService.getPhotos(visitor.getUid(), paramBefore);
+ } else if (paramShow.get().equals("all")) {
+ title = "Все сообщения";
+ mids = messagesService.getAll(visitor.getUid(), paramBefore);
+ }
+ model.addAttribute("title", title);
+ model.addAttribute("visitor", visitor);
+ model.addAttribute("tags", tagService.getPopularTags());
+ model.addAttribute("showAdv", true);
+ List msgs = messagesService.getMessages(mids);
+ List blUIDs = userService.checkBL(visitor.getUid(),
+ msgs.stream().map(m -> m.getUser().getUid()).collect(Collectors.toList()));
+ model.addAttribute("msgs",
+ msgs.stream().map(msg -> {
+ msg.ReadOnly |= blUIDs.contains(msg.getUser().getUid());
+ return msg;
+ }).collect(Collectors.toList())
+ );
+ if (mids.size() >= 20) {
+ String nextpage = "?before=" + mids.get(mids.size() - 1);
+ if (paramShow.isPresent()) {
+ nextpage += "&show=" + paramShow.get();
+ }
+ if (StringUtils.isNotEmpty(paramSearch)) {
+ nextpage += "&search=" + paramSearch;
+ }
+ model.addAttribute("nextpage", nextpage);
+ }
+ //model.addAttribute("isModerator", userService.getModerators().contains(visitor.getUid()));
+ return "blog/index";
}
}
diff --git a/juick-spring-www/src/main/java/com/juick/www/controllers/SettingsController.java b/juick-spring-www/src/main/java/com/juick/www/controllers/SettingsController.java
index eef41c38..a038389f 100644
--- a/juick-spring-www/src/main/java/com/juick/www/controllers/SettingsController.java
+++ b/juick-spring-www/src/main/java/com/juick/www/controllers/SettingsController.java
@@ -1,16 +1,76 @@
package com.juick.www.controllers;
+import com.juick.User;
+import com.juick.service.*;
+import com.juick.util.UserUtils;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.inject.Inject;
+import javax.servlet.ServletException;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
/**
* Created by aalexeev on 11/21/16.
*/
@Controller
public class SettingsController {
+ @Inject
+ UserService userService;
+ @Inject
+ TagService tagService;
+ @Inject
+ CrosspostService crosspostService;
+ @Inject
+ SubscriptionService subscriptionService;
+ @Inject
+ EmailService emailService;
- @RequestMapping("/settings")
- public String showSettings() {
- return "index";
+ @RequestMapping("settings")
+ public String showSettings(
+ Principal principal,
+ @RequestParam(required = false) String page,
+ @RequestParam(required = false) String code,
+ ModelMap context
+ ) throws ServletException, IOException {
+ String name = UserUtils.getUsername(principal, null);
+ User visitor = userService.getUserByName(name);
+ if (visitor.getUid() == 0) {
+ return "redirect:/login";
+ }
+ List pages = Arrays.asList("main", "password", "about", "auth-email", "privacy");
+ if (StringUtils.isEmpty(page) || !pages.contains(page)) {
+ page = "main";
+ }
+ context.put("title", "Настройки");
+ context.put("visitor", visitor);
+ context.put("tags", tagService.getPopularTags());
+ context.put("auths", userService.getAuthCodes(visitor));
+ context.put("eopts", userService.getEmailOpts(visitor));
+ context.put("ehash", userService.getEmailHash(visitor));
+ context.put("emails", userService.getEmails(visitor));
+ context.put("jids", userService.getAllJIDs(visitor));
+ List hours = IntStream.rangeClosed(0, 23).boxed()
+ .map(i -> StringUtils.leftPad(String.format("%d", i), 2, "0")).collect(Collectors.toList());
+ context.put("hours", hours);
+ context.put("fbstatus", crosspostService.getFbCrossPostStatus(visitor.getUid()));
+ context.put("twitter_name", crosspostService.getTwitterName(visitor.getUid()));
+ context.put("telegram_name", crosspostService.getTelegramName(visitor.getUid()));
+ context.put("notify_options", subscriptionService.getNotifyOptions(visitor));
+ context.put("userinfo", userService.getUserInfo(visitor));
+ if (page.equals("auth-email")) {
+ String response = emailService.verifyAddressByCode(visitor.getUid(), code) ?
+ "OK!" : "Sorry, code unknown.";
+ context.put("result", response);
+ }
+ return String.format("views/settings_%s", page);
}
}
diff --git a/juick-spring-www/src/main/java/com/juick/www/controllers/TagController.java b/juick-spring-www/src/main/java/com/juick/www/controllers/TagController.java
index 5c3b6287..0961f683 100644
--- a/juick-spring-www/src/main/java/com/juick/www/controllers/TagController.java
+++ b/juick-spring-www/src/main/java/com/juick/www/controllers/TagController.java
@@ -1,14 +1,28 @@
package com.juick.www.controllers;
+import com.juick.Message;
+import com.juick.User;
+import com.juick.server.util.HttpNotFoundException;
+import com.juick.service.AdsService;
import com.juick.service.MessagesService;
import com.juick.service.TagService;
+import com.juick.service.UserService;
+import com.juick.util.UserUtils;
+import com.juick.www.helpers.QueryString;
+import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
+import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.inject.Inject;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.security.Principal;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
/**
* Created by aalexeev on 11/21/16.
@@ -19,15 +33,75 @@ public class TagController {
private TagService tagService;
@Inject
private MessagesService messagesService;
+ @Inject
+ private AdsService adsService;
+ @Inject
+ private UserService userService;
@RequestMapping("/tag/{tagName}")
- public String showTags(
- @PathVariable String tagName,
- @RequestParam(required = false, defaultValue = "0") int before,
- Model model) {
+ protected String doGet(
+ Principal principal,
+ @PathVariable("tagName") String paramTagStr,
+ @RequestParam(value = "before", required = false, defaultValue = "0") Integer paramBefore,
+ @QueryString Optional queryString,
+ ModelMap model) throws UnsupportedEncodingException {
+ String name = UserUtils.getUsername(principal, null);
+ User visitor = userService.getUserByName(name);
+
+ com.juick.Tag paramTag = tagService.getTag(paramTagStr, false);
+ if (paramTag == null) {
+ throw new HttpNotFoundException();
+ } else if (paramTag.SynonymID > 0 && paramTag.TID != paramTag.SynonymID) {
+ com.juick.Tag synTag = tagService.getTag(paramTag.SynonymID);
+ String url = "/tag/" + URLEncoder.encode(synTag.getName(), "UTF-8");
+ if (queryString.isPresent()) {
+ url += "?" + queryString.get();
+ }
+ return "redirect:" + url;
+ } else if (!paramTag.getName().equals(paramTagStr)) {
+ String url = "/tag/" + URLEncoder.encode(paramTag.getName(), "UTF-8");
+ if (queryString.isPresent()) {
+ url += "?" + queryString.get();
+ }
+ return "redirect:" + url;
+ }
+
+ int visitor_uid = visitor != null ? visitor.getUid() : 0;
- return "index";
+ String title = "*" + StringEscapeUtils.escapeHtml4(paramTag.getName());
+ List mids = messagesService.getTag(paramTag.TID, visitor_uid, paramBefore, (visitor == null) ? 40 : 20);
+ model.addAttribute("title", title);
+ if (tagService.getTagNoIndex(paramTag.TID)) {
+ model.addAttribute("headers", "");
+ } else if (paramBefore > 0 || mids.size() < 5) {
+ model.addAttribute("headers", "");
+ }
+ if (mids.size() > 0) {
+ int vuid = visitor != null ? visitor.getUid() : 0;
+ int ad_mid = adsService.getAdMid(vuid);
+ if (ad_mid > 0 && mids.indexOf(ad_mid) == -1) {
+ mids.add(0, ad_mid);
+ adsService.logAdMid(vuid, ad_mid);
+ } else {
+ ad_mid = 0;
+ }
+ }
+ model.addAttribute("visitor", visitor);
+ List msgs = messagesService.getMessages(mids);
+ List blUIDs = userService.checkBL(visitor_uid,
+ msgs.stream().map(m -> m.getUser().getUid()).collect(Collectors.toList()));
+ model.addAttribute("msgs",
+ msgs.stream().map(msg -> {
+ msg.ReadOnly |= blUIDs.contains(msg.getUser().getUid());
+ return msg;
+ }).collect(Collectors.toList())
+ );
+ if (mids.size() >= 20) {
+ String nextpage = "/tag/" + URLEncoder.encode(paramTag.getName(), "UTF-8") + "?before=" + mids.get(mids.size() - 1);
+ model.addAttribute("nextpage", nextpage);
+ }
+ return "blog/index";
}
@RequestMapping("/tag")
diff --git a/juick-spring-www/src/main/java/com/juick/www/helpers/QueryString.java b/juick-spring-www/src/main/java/com/juick/www/helpers/QueryString.java
new file mode 100644
index 00000000..0eb6c76f
--- /dev/null
+++ b/juick-spring-www/src/main/java/com/juick/www/helpers/QueryString.java
@@ -0,0 +1,14 @@
+package com.juick.www.helpers;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Created by vt on 22/03/16.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface QueryString {
+}
\ No newline at end of file
diff --git a/juick-spring-www/src/main/java/com/juick/www/helpers/QueryStringResolver.java b/juick-spring-www/src/main/java/com/juick/www/helpers/QueryStringResolver.java
new file mode 100644
index 00000000..812c4497
--- /dev/null
+++ b/juick-spring-www/src/main/java/com/juick/www/helpers/QueryStringResolver.java
@@ -0,0 +1,31 @@
+package com.juick.www.helpers;
+
+import org.springframework.core.MethodParameter;
+import org.springframework.web.bind.support.WebDataBinderFactory;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.method.support.ModelAndViewContainer;
+
+import javax.servlet.http.HttpServletRequest;
+import java.lang.annotation.Annotation;
+import java.util.Optional;
+
+public class QueryStringResolver implements HandlerMethodArgumentResolver {
+ @Override
+ public boolean supportsParameter(MethodParameter parameter) {
+ Annotation[] parameterAnnotations = parameter.getParameterAnnotations();
+ for (Annotation parameterAnnotation : parameterAnnotations) {
+ if (QueryString.class.isInstance(parameterAnnotation)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
+ HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
+ return Optional.ofNullable(request.getQueryString());
+ }
+}
\ No newline at end of file
diff --git a/juick-spring-www/src/main/java/com/juick/www/util/EncodeUtils.java b/juick-spring-www/src/main/java/com/juick/www/util/EncodeUtils.java
new file mode 100644
index 00000000..a444ec4d
--- /dev/null
+++ b/juick-spring-www/src/main/java/com/juick/www/util/EncodeUtils.java
@@ -0,0 +1,10 @@
+package com.juick.www.util;
+
+/**
+ * Created by vitalyster on 09.12.2016.
+ */
+public class EncodeUtils {
+ public static String encodeSphinx(String str) {
+ return str.replaceAll("@", "\\\\@");
+ }
+}
diff --git a/juick-spring-www/src/main/webapp/WEB-INF/templates/layout/mainLayout.html b/juick-spring-www/src/main/webapp/WEB-INF/templates/layout/mainLayout.html
index bbee7f6a..61062a3b 100644
--- a/juick-spring-www/src/main/webapp/WEB-INF/templates/layout/mainLayout.html
+++ b/juick-spring-www/src/main/webapp/WEB-INF/templates/layout/mainLayout.html
@@ -11,53 +11,21 @@
Juick.com
-
+
-
-
+Navigation block
+
+
-
+