Commit 7e418c8f authored by Van's avatar Van

Merge remote-tracking branch 'origin/3.2.0-dev' into 3.2.0-dev

parents 3e2d72a8 15009f3e
......@@ -6,7 +6,7 @@ ADD . /tmp
RUN cd /tmp && mvn install -DskipTests -Pci && mv target/solo/* /opt/b3log/solo/ \
&& mkdir -p /opt/b3log/backup/ && mkdir -p /opt/b3log/tmp/ \
&& rm -rf /opt/b3log/solo/WEB-INF/classes/local.properties /opt/b3log/solo/WEB-INF/classes/mail.properties /opt/b3log/solo/WEB-INF/classes/latke.properties \
&& rm -rf /opt/b3log/solo/WEB-INF/classes/local.properties /opt/b3log/solo/WEB-INF/classes/latke.properties \
&& rm -rf /tmp/* && rm -rf ~/.m2
ADD ./src/main/resources/docker/entrypoint.sh $WORKDIR
......
......@@ -11,10 +11,6 @@ services:
SERVER_SCHMEA: https
SERVER_NAME: <your host>
SERVER_PORT: 80
EMAIL_ADDRESS: <your address>
EMAIL_PASSWORD: <your smtp password>
SMTP_HOST: <your smtp host>
SMTP_PROT: <your smtp port>
volumes:
- database:/opt/b3log/backup
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
Description: Solo POM.
Version: 3.18.3.50, Mar 1, 2019
Version: 3.18.3.51, Mar 3, 2019
Author: <a href="http://88250.b3log.org">Liang Ding</a>
Author: <a href="http://www.annpeter.cn">Ann Peter</a>
Author: <a href="http://vanessa.b3log.org">Vanessa</a>
......@@ -74,11 +74,11 @@
</scm>
<properties>
<org.b3log.latke.version>2.4.44</org.b3log.latke.version>
<org.b3log.latke.version>2.4.45</org.b3log.latke.version>
<slf4j.version>1.7.5</slf4j.version>
<jsoup.version>1.9.1</jsoup.version>
<flexmark.version>0.40.0</flexmark.version>
<flexmark.version>0.40.20</flexmark.version>
<jetty.version>9.4.12.v20180830</jetty.version>
<commons-cli.version>1.3.1</commons-cli.version>
<commons-codec.version>1.10</commons-codec.version>
......@@ -89,7 +89,6 @@
<freemarker.version>2.3.28</freemarker.version>
<user-agent-utils.version>1.21</user-agent-utils.version>
<servlet.version>3.1.0</servlet.version>
<javax.mail.version>1.6.2</javax.mail.version>
<license-maven-plugin.version>3.0</license-maven-plugin.version>
<maven-surefire-plugin.version>2.22.1</maven-surefire-plugin.version>
......@@ -117,12 +116,6 @@
<version>${servlet.version}</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>${javax.mail.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
......
......@@ -34,7 +34,10 @@ import org.b3log.latke.servlet.DispatcherServlet;
import org.b3log.latke.util.Requests;
import org.b3log.latke.util.Stopwatchs;
import org.b3log.latke.util.Strings;
import org.b3log.solo.event.*;
import org.b3log.solo.event.B3ArticleSender;
import org.b3log.solo.event.B3ArticleUpdater;
import org.b3log.solo.event.B3CommentSender;
import org.b3log.solo.event.PluginRefresher;
import org.b3log.solo.model.Option;
import org.b3log.solo.model.Skin;
import org.b3log.solo.processor.InitCheckHandler;
......@@ -216,10 +219,6 @@ public final class SoloServletListener extends AbstractServletListener {
try {
final EventManager eventManager = beanManager.getReference(EventManager.class);
final ArticleCommentReplyNotifier articleCommentReplyNotifier = beanManager.getReference(ArticleCommentReplyNotifier.class);
eventManager.registerListener(articleCommentReplyNotifier);
final PageCommentReplyNotifier pageCommentReplyNotifier = beanManager.getReference(PageCommentReplyNotifier.class);
eventManager.registerListener(pageCommentReplyNotifier);
final PluginRefresher pluginRefresher = beanManager.getReference(PluginRefresher.class);
eventManager.registerListener(pluginRefresher);
eventManager.registerListener(new ViewLoadEventHandler());
......@@ -386,8 +385,6 @@ public final class SoloServletListener extends AbstractServletListener {
DispatcherServlet.post("/console/plugin/updateSetting", pluginConsole::updateSetting);
final PreferenceConsole preferenceConsole = beanManager.getReference(PreferenceConsole.class);
DispatcherServlet.get("/console/reply/notification/template", preferenceConsole::getReplyNotificationTemplate);
DispatcherServlet.put("/console/reply/notification/template", preferenceConsole::updateReplyNotificationTemplate);
DispatcherServlet.get("/console/signs/", preferenceConsole::getSigns);
DispatcherServlet.get("/console/preference/", preferenceConsole::getPreference);
DispatcherServlet.put("/console/preference/", preferenceConsole::updatePreference);
......
......@@ -20,7 +20,6 @@ package org.b3log.solo.cache;
import org.b3log.latke.Keys;
import org.b3log.latke.ioc.Singleton;
import org.b3log.latke.model.Role;
import org.b3log.latke.model.User;
import org.b3log.solo.util.Solos;
import org.json.JSONObject;
......@@ -31,7 +30,7 @@ import java.util.concurrent.ConcurrentHashMap;
* User cache.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.1.0.1, Sep 25, 2018
* @version 1.1.0.2, Mar 3, 2019
* @since 2.3.0
*/
@Singleton
......@@ -42,11 +41,6 @@ public class UserCache {
*/
private final Map<String, JSONObject> idCache = new ConcurrentHashMap<>();
/**
* Email, User.
*/
private final Map<String, JSONObject> emailCache = new ConcurrentHashMap<>();
/**
* Admin user.
*/
......@@ -85,21 +79,6 @@ public class UserCache {
return Solos.clone(user);
}
/**
* Gets a user by the specified user email.
*
* @param userEmail the specified user email
* @return user, returns {@code null} if not found
*/
public JSONObject getUserByEmail(final String userEmail) {
final JSONObject user = emailCache.get(userEmail);
if (null == user) {
return null;
}
return Solos.clone(user);
}
/**
* Adds or updates the specified user.
*
......@@ -107,7 +86,6 @@ public class UserCache {
*/
public void putUser(final JSONObject user) {
idCache.put(user.optString(Keys.OBJECT_ID), Solos.clone(user));
emailCache.put(user.optString(User.USER_EMAIL), Solos.clone(user));
}
/**
......@@ -122,9 +100,6 @@ public class UserCache {
}
idCache.remove(id);
final String email = user.optString(User.USER_EMAIL);
emailCache.remove(email);
}
/**
......@@ -132,7 +107,6 @@ public class UserCache {
*/
public void clear() {
idCache.clear();
emailCache.clear();
adminCache.clear();
}
}
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.event;
import org.apache.commons.lang.StringUtils;
import org.b3log.latke.Keys;
import org.b3log.latke.Latkes;
import org.b3log.latke.event.AbstractEventListener;
import org.b3log.latke.event.Event;
import org.b3log.latke.ioc.BeanManager;
import org.b3log.latke.ioc.Singleton;
import org.b3log.latke.logging.Level;
import org.b3log.latke.logging.Logger;
import org.b3log.latke.util.Strings;
import org.b3log.solo.mail.MailService;
import org.b3log.solo.mail.MailServiceFactory;
import org.b3log.solo.model.Article;
import org.b3log.solo.model.Comment;
import org.b3log.solo.model.Option;
import org.b3log.solo.repository.CommentRepository;
import org.b3log.solo.service.PreferenceQueryService;
import org.b3log.solo.util.Solos;
import org.json.JSONObject;
/**
* This listener is responsible for processing article comment reply.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @author <a href="http://www.wanglay.com">Lei Wang</a>
* @version 1.2.2.12, Oct 23, 2018
* @since 0.3.1
*/
@Singleton
public class ArticleCommentReplyNotifier extends AbstractEventListener<JSONObject> {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(ArticleCommentReplyNotifier.class);
/**
* Mail service.
*/
private MailService mailService = MailServiceFactory.getMailService();
@Override
public void action(final Event<JSONObject> event) {
final JSONObject eventData = event.getData();
final JSONObject comment = eventData.optJSONObject(Comment.COMMENT);
final JSONObject article = eventData.optJSONObject(Article.ARTICLE);
LOGGER.log(Level.DEBUG, "Processing an event [type={0}, data={1}] in listener [className={2}]",
event.getType(), eventData, ArticleCommentReplyNotifier.class.getName());
final String originalCommentId = comment.optString(Comment.COMMENT_ORIGINAL_COMMENT_ID);
if (StringUtils.isBlank(originalCommentId)) {
LOGGER.log(Level.DEBUG, "This comment[id={0}] is not a reply", comment.optString(Keys.OBJECT_ID));
return;
}
if (Latkes.getServePath().contains("localhost") || Strings.isIPv4(Latkes.getServePath())) {
LOGGER.log(Level.INFO, "Solo runs on local server, so should not send mail");
return;
}
if (!Solos.isMailConfigured()) {
return;
}
final BeanManager beanManager = BeanManager.getInstance();
final PreferenceQueryService preferenceQueryService = beanManager.getReference(PreferenceQueryService.class);
final CommentRepository commentRepository = beanManager.getReference(CommentRepository.class);
try {
final String commentEmail = comment.getString(Comment.COMMENT_EMAIL);
final JSONObject originalComment = commentRepository.get(originalCommentId);
final String originalCommentEmail = originalComment.getString(Comment.COMMENT_EMAIL);
if (originalCommentEmail.equalsIgnoreCase(commentEmail)) {
return;
}
if (!Strings.isEmail(originalCommentEmail)) {
return;
}
final JSONObject preference = preferenceQueryService.getPreference();
if (null == preference) {
throw new Exception("Not found preference");
}
final String blogTitle = preference.getString(Option.ID_C_BLOG_TITLE);
final String adminEmail = preference.getString(Option.ID_C_ADMIN_EMAIL);
final String commentContent = comment.getString(Comment.COMMENT_CONTENT);
final String commentSharpURL = comment.getString(Comment.COMMENT_SHARP_URL);
final MailService.Message message = new MailService.Message();
message.setFrom(adminEmail);
message.addRecipient(originalCommentEmail);
final JSONObject replyNotificationTemplate = preferenceQueryService.getReplyNotificationTemplate();
final String articleTitle = article.getString(Article.ARTICLE_TITLE);
final String articleLink = Latkes.getServePath() + article.getString(Article.ARTICLE_PERMALINK);
final String commentName = comment.getString(Comment.COMMENT_NAME);
final String commentURL = comment.getString(Comment.COMMENT_URL);
String commenter;
if (!"http://".equals(commentURL)) {
commenter = "<a target=\"_blank\" " + "href=\"" + commentURL + "\">" + commentName + "</a>";
} else {
commenter = commentName;
}
final String mailSubject = replyNotificationTemplate.getString(
"subject").replace("${postLink}", articleLink).
replace("${postTitle}", articleTitle).
replace("${replier}", commenter).
replace("${blogTitle}", blogTitle).
replace("${replyURL}", Latkes.getServePath() + commentSharpURL).
replace("${replyContent}", commentContent).
replace("${servePath}", Latkes.getServePath());
message.setSubject(mailSubject);
final String mailBody = replyNotificationTemplate.
getString("body").
replace("${postLink}", articleLink).
replace("${postTitle}", articleTitle).
replace("${replier}", commenter).
replace("${blogTitle}", blogTitle).
replace("${replyURL}", Latkes.getServePath() + commentSharpURL).
replace("${replyContent}", commentContent).
replace("${servePath}", Latkes.getServePath());
message.setHtmlBody(mailBody);
LOGGER.log(Level.DEBUG, "Sending a mail [mailSubject={0}, mailBody=[{1}] to [{2}]",
mailSubject, mailBody, originalCommentEmail);
mailService.send(message);
} catch (final Exception e) {
LOGGER.log(Level.ERROR, e.getMessage(), e);
}
}
/**
* Gets the event type {@linkplain EventTypes#ADD_COMMENT_TO_ARTICLE}.
*
* @return event type
*/
@Override
public String getEventType() {
return EventTypes.ADD_COMMENT_TO_ARTICLE;
}
}
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.event;
import org.apache.commons.lang.StringUtils;
import org.b3log.latke.Keys;
import org.b3log.latke.Latkes;
import org.b3log.latke.event.AbstractEventListener;
import org.b3log.latke.event.Event;
import org.b3log.latke.ioc.BeanManager;
import org.b3log.latke.ioc.Singleton;
import org.b3log.latke.logging.Level;
import org.b3log.latke.logging.Logger;
import org.b3log.latke.util.Strings;
import org.b3log.solo.mail.MailService;
import org.b3log.solo.mail.MailServiceFactory;
import org.b3log.solo.model.Comment;
import org.b3log.solo.model.Option;
import org.b3log.solo.model.Page;
import org.b3log.solo.repository.CommentRepository;
import org.b3log.solo.service.PreferenceQueryService;
import org.b3log.solo.util.Solos;
import org.json.JSONObject;
/**
* This listener is responsible for processing page comment reply.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.2.6, Sep 25, 2018
* @since 0.3.1
*/
@Singleton
public class PageCommentReplyNotifier extends AbstractEventListener<JSONObject> {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(PageCommentReplyNotifier.class);
/**
* Mail service.
*/
private MailService mailService = MailServiceFactory.getMailService();
@Override
public void action(final Event<JSONObject> event) {
final JSONObject eventData = event.getData();
final JSONObject comment = eventData.optJSONObject(Comment.COMMENT);
final JSONObject page = eventData.optJSONObject(Page.PAGE);
LOGGER.log(Level.DEBUG, "Processing an event [type={0}, data={1}] in listener [className={2}]",
event.getType(), eventData, PageCommentReplyNotifier.class.getName());
final String originalCommentId = comment.optString(Comment.COMMENT_ORIGINAL_COMMENT_ID);
if (StringUtils.isBlank(originalCommentId)) {
LOGGER.log(Level.DEBUG, "This comment[id={0}] is not a reply", comment.optString(Keys.OBJECT_ID));
return;
}
if (!Solos.isMailConfigured()) {
return;
}
final BeanManager beanManager = BeanManager.getInstance();
final PreferenceQueryService preferenceQueryService = beanManager.getReference(PreferenceQueryService.class);
final CommentRepository commentRepository = beanManager.getReference(CommentRepository.class);
try {
final String commentEmail = comment.getString(Comment.COMMENT_EMAIL);
final JSONObject originalComment = commentRepository.get(originalCommentId);
final String originalCommentEmail = originalComment.getString(Comment.COMMENT_EMAIL);
if (originalCommentEmail.equalsIgnoreCase(commentEmail)) {
return;
}
if (!Strings.isEmail(originalCommentEmail)) {
return;
}
final JSONObject preference = preferenceQueryService.getPreference();
if (null == preference) {
LOGGER.log(Level.ERROR, "Not found preference");
return;
}
final String blogTitle = preference.getString(Option.ID_C_BLOG_TITLE);
final String adminEmail = preference.getString(Option.ID_C_ADMIN_EMAIL);
final String commentContent = comment.getString(Comment.COMMENT_CONTENT);
final String commentSharpURL = comment.getString(Comment.COMMENT_SHARP_URL);
final MailService.Message message = new MailService.Message();
message.setFrom(adminEmail);
message.addRecipient(originalCommentEmail);
final JSONObject replyNotificationTemplate = preferenceQueryService.getReplyNotificationTemplate();
final String mailSubject = replyNotificationTemplate.getString("subject").replace("${blogTitle}", blogTitle);
message.setSubject(mailSubject);
final String pageTitle = page.getString(Page.PAGE_TITLE);
final String pageLink = Latkes.getServePath() + page.getString(Page.PAGE_PERMALINK);
final String commentName = comment.getString(Comment.COMMENT_NAME);
final String commentURL = comment.getString(Comment.COMMENT_URL);
String commenter;
if (!"http://".equals(commentURL)) {
commenter = "<a target=\"_blank\" " + "href=\"" + commentURL + "\">" + commentName + "</a>";
} else {
commenter = commentName;
}
final String mailBody = replyNotificationTemplate.getString("body").replace("${postLink}", pageLink).replace("${postTitle}", pageTitle).replace("${replier}", commenter).replace("${replyURL}", Latkes.getServePath() + commentSharpURL).replace(
"${replyContent}", commentContent);
message.setHtmlBody(mailBody);
LOGGER.log(Level.DEBUG, "Sending a mail[mailSubject={0}, mailBody=[{1}] to [{2}]",
mailSubject, mailBody, originalCommentEmail);
mailService.send(message);
} catch (final Exception e) {
LOGGER.log(Level.ERROR, e.getMessage(), e);
}
}
/**
* Gets the event type {@linkplain EventTypes#ADD_COMMENT_TO_PAGE}.
*
* @return event type
*/
@Override
public String getEventType() {
return EventTypes.ADD_COMMENT_TO_PAGE;
}
}
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.mail;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* Mail service.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.0, Aug 8, 2011
*/
public interface MailService {
/**
* Sends the specified message as a mail asynchronously.
*
* @param message the specified message
* @throws IOException if internal errors
*/
void send(final Message message) throws IOException;
/**
* Mail message.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.0, Aug 8, 2011
*/
class Message {
/**
* From.
*/
private String from;
/**
* Recipients.
*/
private Set<String> recipients = new HashSet<>();
/**
* HTML body.
*/
private String htmlBody;
/**
* Subject.
*/
private String subject;
/**
* Gets the recipients.
*
* @return recipients
*/
public Set<String> getRecipients() {
return Collections.unmodifiableSet(recipients);
}
/**
* Adds the specified recipient.
*
* @param recipient the specified recipient
*/
public void addRecipient(final String recipient) {
recipients.add(recipient);
}
/**
* Gets the HTML body.
*
* @return HTML body
*/
public String getHtmlBody() {
return htmlBody;
}
/**
* Sets the HTML body with the specified HTML body.
*
* @param htmlBody the specified HTML body
*/
public void setHtmlBody(final String htmlBody) {
this.htmlBody = htmlBody;
}
/**
* Gets the from.
*
* @return from
*/
public String getFrom() {
return from;
}
/**
* Sets the from with the specified from.
*
* @param from the specified from
*/
public void setFrom(final String from) {
this.from = from;
}
/**
* Gets the subject.
*
* @return subject
*/
public String getSubject() {
return subject;
}
/**
* Sets the subject with the specified subject.
*
* @param subject the specified subject
*/
public void setSubject(final String subject) {
this.subject = subject;
}
}
}
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.mail;
/**
* Mail service factory.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 2.0.1.3, Dec 3, 2018
*/
public final class MailServiceFactory {
/**
* Mail service.
*/
private static final MailService MAIL_SERVICE;
static {
try {
final Class<MailService> mailServiceClass = (Class<MailService>) Class.forName("org.b3log.solo.mail.local.LocalMailService");
MAIL_SERVICE = mailServiceClass.newInstance();
} catch (final Exception e) {
throw new RuntimeException("Can not initialize mail service!", e);
}
}
/**
* Private constructor.
*/
private MailServiceFactory() {
}
/**
* Gets mail service.
*
* @return mail service
*/
public static MailService getMailService() {
return MAIL_SERVICE;
}
}
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.mail.local;
import org.b3log.solo.mail.MailService;
/**
* JavaMail implementation of the {@link MailService} interface.
*
* @author <a href="https://hacpai.com/member/jiangzezhou">zezhou jiang</a>
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.5, Jan 18, 2019
*/
public final class LocalMailService implements MailService {
@Override
public void send(final Message message) {
new Thread(() -> new MailSender().sendMail(message)).start();
}
}
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.mail.local;
import org.apache.commons.lang.StringUtils;
import org.b3log.latke.logging.Level;
import org.b3log.latke.logging.Logger;
import org.b3log.solo.mail.MailService.Message;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import javax.mail.internet.MimeUtility;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
/**
* Email sender.
*
* @author <a href="https://hacpai.com/member/jiangzezhou">zezhou jiang</a>
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.2.5, Jan 18, 2019
*/
final class MailSender {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(MailSender.class);
/**
* Mail configurations.
*
* <ul>
* <li>mail.user</li>
* <li>mail.password</li>
* <li>mail.smtp.host</li>
* <li>mail.smtp.auth</li>
* <li>mail.smtp.port</li>
* <li>mail.smtp.starttls.enable</li>
* <li>mail.debug</li>
* <li>mail.smtp.socketFactory.class</li>
* <li>mail.smtp.socketFactory.fallback</li>
* <li>mail.smtp.socketFactory.port</li>
* </ul>
*/
private static final ResourceBundle mailProperties = ResourceBundle.getBundle("mail");
/**
* Create session based on the mail properties.
*
* @return session session from mail properties
*/
private Session getSession() {
final Properties props = new Properties();
props.setProperty("mail.smtp.host", mailProperties.getString("mail.smtp.host"));
String auth = "true";
if (mailProperties.containsKey("mail.smtp.auth")) {
auth = mailProperties.getString("mail.smtp.auth");
}
props.setProperty("mail.smtp.auth", auth);
props.setProperty("mail.smtp.port", mailProperties.getString("mail.smtp.port"));
String starttls = "true";
if (mailProperties.containsKey("mail.smtp.starttls.enable")) {
starttls = mailProperties.getString("mail.smtp.starttls.enable");
}
props.put("mail.smtp.starttls.enable", starttls);
props.put("mail.debug", mailProperties.getString("mail.debug"));
props.put("mail.smtp.socketFactory.class", mailProperties.getString("mail.smtp.socketFactory.class"));
props.put("mail.smtp.socketFactory.fallback", mailProperties.getString("mail.smtp.socketFactory.fallback"));
props.put("mail.smtp.socketFactory.port", mailProperties.getString("mail.smtp.socketFactory.port"));
return Session.getInstance(props, new SMTPAuthenticator());
}
/**
* Converts the specified message into a {@link javax.mail.Message javax.mail.Message}.
*
* @param message the specified message
* @return a {@link javax.mail.internet.MimeMessage}
* @throws Exception if converts error
*/
public javax.mail.Message convert2JavaMailMsg(final Message message) throws Exception {
if (null == message) {
return null;
}
if (StringUtils.isBlank(message.getFrom())) {
throw new MessagingException("Null from");
}
if (null == message.getRecipients() || message.getRecipients().isEmpty()) {
throw new MessagingException("Null recipients");
}
final MimeMessage ret = new MimeMessage(getSession());
ret.setFrom(new InternetAddress(message.getFrom()));
final String subject = message.getSubject();
ret.setSubject(MimeUtility.encodeText(subject != null ? subject : "", "UTF-8", "B"));
final String htmlBody = message.getHtmlBody();
ret.setContent(htmlBody != null ? htmlBody : "", "text/html;charset=UTF-8");
ret.addRecipients(RecipientType.TO, transformRecipients(message.getRecipients()));
return ret;
}
/**
* Transport recipients to InternetAddress array.
*
* @param recipients the set of all recipients
* @return InternetAddress array of all recipients internetAddress
* @throws MessagingException messagingException from javax.mail
*/
private InternetAddress[] transformRecipients(final Set<String> recipients) throws MessagingException {
if (recipients.isEmpty()) {
throw new MessagingException("recipients of mail should not be empty");
}
final InternetAddress[] ret = new InternetAddress[recipients.size()];
int i = 0;
for (String recipient : recipients) {
ret[i] = new InternetAddress(recipient);
i++;
}
return ret;
}
/**
* Sends email.
*
* @param message the specified message
* @throws Exception message exception
*/
void sendMail(final Message message) {
try {
final javax.mail.Message msg = convert2JavaMailMsg(message);
Transport.send(msg);
} catch (final Exception e) {
LOGGER.log(Level.ERROR, "Sends mail failed", e);
}
}
/**
* Inner class for Authenticator.
*/
private class SMTPAuthenticator extends Authenticator {
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(mailProperties.getString("mail.user"), mailProperties.getString("mail.password"));
}
}
}
/**
* Provides mail service (via <a href="http://www.oracle.com/technetwork/java/javamail/index.html">
* JavaMail</a>) on local (standard Servlet container).
*/
package org.b3log.solo.mail.local;
/**
* Main service.
*/
package org.b3log.solo.mail;
......@@ -138,11 +138,6 @@ public final class Article {
*/
public static final String ARTICLE_AUTHOR_ID = "articleAuthorId";
/**
* Key of author email.
*/
public static final String ARTICLE_T_AUTHOR_EMAIL = "articleAuthorEmail";
/**
* Key of had been published.
*/
......
......@@ -24,7 +24,7 @@ import org.json.JSONObject;
* This class defines all comment model relevant keys.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.2.0.0, Sep 21, 2018
* @version 1.2.0.1, Mar 3, 2019
* @since 0.3.1
*/
public final class Comment {
......@@ -49,11 +49,6 @@ public final class Comment {
*/
public static final String COMMENT_NAME = "commentName";
/**
* Key of comment email.
*/
public static final String COMMENT_EMAIL = "commentEmail";
/**
* Key of comment URL.
*/
......
......@@ -26,7 +26,7 @@ import org.json.JSONObject;
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @author <a href="https://github.com/hzchendou">hzchendou</a>
* @version 1.5.0.3, Feb 8, 2019
* @version 1.5.0.4, Mar 3, 2019
* @since 0.6.0
*/
public final class Option {
......@@ -117,11 +117,6 @@ public final class Option {
*/
public static final String ID_C_ARTICLE_LIST_PAGINATION_WINDOW_SIZE = "articleListPaginationWindowSize";
/**
* Key of administrator's email.
*/
public static final String ID_C_ADMIN_EMAIL = "adminEmail";
/**
* Key of locale string.
*/
......@@ -227,16 +222,6 @@ public final class Option {
*/
public static final String ID_C_SKIN_NAME = "skinName";
/**
* Key of reply notification template body.
*/
public static final String ID_C_REPLY_NOTI_TPL_BODY = "replyNotiTplBody";
/**
* Key of reply notification template subject.
*/
public static final String ID_C_REPLY_NOTI_TPL_SUBJECT = "replyNotiTplSubject";
/**
* Key of footer content.
*/
......@@ -426,16 +411,6 @@ public final class Option {
*/
public static final String DEFAULT_ARTICLE_LIST_STYLE = "titleAndAbstract";
/**
* Default key of solo.
*/
public static final String DEFAULT_KEY_OF_SOLO = "Your key";
/**
* Default reply notification template.
*/
public static final String DEFAULT_REPLY_NOTIFICATION_TEMPLATE;
/**
* Default feed output mode.
*/
......@@ -459,13 +434,6 @@ public final class Option {
// Sign(id=0) is the 'empty' sign, used for article user needn't a sign
DEFAULT_SIGNS = signs.toString();
final JSONObject replyNotificationTemplate = new JSONObject();
replyNotificationTemplate.put("subject", "${blogTitle}: New reply of your comment");
replyNotificationTemplate.put("body",
"Your comment on post[<a href='${postLink}'>" + "${postTitle}</a>] received an reply: <p>${replier}"
+ ": <span><a href='${replyURL}'>${replyContent}</a></span></p>");
DEFAULT_REPLY_NOTIFICATION_TEMPLATE = replyNotificationTemplate.toString();
}
/**
......
......@@ -148,7 +148,7 @@ public class ArticleProcessor {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@RequestProcessing(value = "/console/markdown/2html", method = HttpMethod.POST)
public void markdown2HTML(final RequestContext context) {
......@@ -741,12 +741,7 @@ public class ArticleProcessor {
article.put(Common.AUTHOR_ID, authorId);
article.put(Common.AUTHOR_ROLE, author.getString(User.USER_ROLE));
final String userAvatar = author.optString(UserExt.USER_AVATAR);
if (StringUtils.isNotBlank(userAvatar)) {
article.put(Common.AUTHOR_THUMBNAIL_URL, userAvatar);
} else {
final String thumbnailURL = Solos.getGravatarURL(author.optString(User.USER_EMAIL), "128");
article.put(Common.AUTHOR_THUMBNAIL_URL, thumbnailURL);
}
article.put(Common.AUTHOR_THUMBNAIL_URL, userAvatar);
dataModelService.fillCategory(article);
......@@ -836,12 +831,7 @@ public class ArticleProcessor {
dataModel.put(Common.AUTHOR_NAME, author.optString(User.USER_NAME));
final String userAvatar = author.optString(UserExt.USER_AVATAR);
if (StringUtils.isNotBlank(userAvatar)) {
dataModel.put(Common.AUTHOR_THUMBNAIL_URL, userAvatar);
} else {
final String thumbnailURL = Solos.getGravatarURL(author.optString(User.USER_EMAIL), "128");
dataModel.put(Common.AUTHOR_THUMBNAIL_URL, thumbnailURL);
}
dataModel.put(Common.AUTHOR_THUMBNAIL_URL, userAvatar);
dataModel.put(Pagination.PAGINATION_CURRENT_PAGE_NUM, currentPageNum);
}
......
......@@ -133,7 +133,7 @@ public class B3Receiver {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@RequestProcessing(value = "/apis/symphony/article", method = {HttpMethod.POST, HttpMethod.PUT})
public void postArticle(final RequestContext context) {
......@@ -235,7 +235,7 @@ public class B3Receiver {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@RequestProcessing(value = "/apis/symphony/comment", method = HttpMethod.PUT)
public void addComment(final RequestContext context) {
......@@ -290,7 +290,6 @@ public class B3Receiver {
final String commentId = Ids.genTimeMillisId();
comment.put(Keys.OBJECT_ID, commentId);
comment.put(Comment.COMMENT_NAME, commentName);
comment.put(Comment.COMMENT_EMAIL, "");
comment.put(Comment.COMMENT_URL, commentURL);
comment.put(Comment.COMMENT_THUMBNAIL_URL, commentThumbnailURL);
comment.put(Comment.COMMENT_CONTENT, commentContent);
......@@ -304,12 +303,7 @@ public class B3Receiver {
comment.put(Comment.COMMENT_SHARP_URL, commentSharpURL);
commentRepository.add(comment);
articleMgmtService.incArticleCommentCount(articleId);
try {
final JSONObject preference = preferenceQueryService.getPreference();
commentMgmtService.sendNotificationMail(article, comment, null, preference);
} catch (final Exception e) {
LOGGER.log(Level.WARN, "Send mail failed", e);
}
transaction.commit();
} catch (final Exception e) {
LOGGER.log(Level.ERROR, e.getMessage(), e);
......
......@@ -99,7 +99,6 @@ public class CommentProcessor {
* "captcha": "",
* "oId": pageId,
* "commentName": "",
* "commentEmail": "",
* "commentURL": "",
* "commentContent": "",
* "commentOriginalCommentId": "" // optional, if exists this key, the comment is an reply
......@@ -196,7 +195,6 @@ public class CommentProcessor {
* "captcha": "",
* "oId": articleId,
* "commentName": "",
* "commentEmail": "",
* "commentURL": "",
* "commentContent": "",
* "commentOriginalCommentId": "" // optional, if exists this key, the comment is an reply
......@@ -295,7 +293,6 @@ public class CommentProcessor {
}
requestJSONObject.put(Comment.COMMENT_NAME, currentUser.optString(User.USER_NAME));
requestJSONObject.put(Comment.COMMENT_EMAIL, currentUser.optString(User.USER_EMAIL));
requestJSONObject.put(Comment.COMMENT_URL, currentUser.optString(User.USER_URL));
}
}
......@@ -49,7 +49,7 @@ public class KanBanNiangProcessor {
/**
* Returns a random model.
*
* @param context the specified http request context
* @param context the specified request context
*/
@RequestProcessing(value = "/plugins/kanbanniang/assert/model", method = HttpMethod.GET)
public void randomModel(final RequestContext context) {
......
......@@ -54,7 +54,7 @@ import java.util.concurrent.ConcurrentHashMap;
* </ul>
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.5, Feb 27, 2019
* @version 1.0.0.6, Mar 2, 2019
* @since 2.9.5
*/
@RequestProcessor
......@@ -142,7 +142,7 @@ public class OAuthProcessor {
STATES.put(state, URLs.encode(state));
final String path = loginAuthURL + "?client_id=" + clientId + "&state=" + state
+ "&scope=public_repo,read:user,user:email,user:follow";
+ "&scope=public_repo,read:user,user:follow";
context.sendRedirect(path);
}
......@@ -157,7 +157,7 @@ public class OAuthProcessor {
final String state = context.param("state");
String referer = STATES.get(state);
if (StringUtils.isBlank(referer)) {
context.sendError(HttpServletResponse.SC_FORBIDDEN);
context.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
......@@ -166,6 +166,7 @@ public class OAuthProcessor {
final String accessToken = context.param("ak");
final JSONObject userInfo = GitHubs.getGitHubUserInfo(accessToken);
if (null == userInfo) {
LOGGER.log(Level.WARN, "Can't get user info with token [" + accessToken + "]");
context.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
......@@ -175,7 +176,6 @@ public class OAuthProcessor {
final HttpServletRequest request = context.getRequest();
final String openId = userInfo.optString("openId");
final String userName = userInfo.optString(User.USER_NAME);
final String userEmail = userInfo.optString(User.USER_EMAIL);
final String userAvatar = userInfo.optString(UserExt.USER_AVATAR);
JSONObject user = userQueryService.getUserByGitHubId(openId);
......@@ -183,20 +183,16 @@ public class OAuthProcessor {
if (!initService.isInited()) {
final JSONObject initReq = new JSONObject();
initReq.put(User.USER_NAME, userName);
initReq.put(User.USER_EMAIL, userEmail);
initReq.put(UserExt.USER_AVATAR, userAvatar);
initReq.put(UserExt.USER_B3_KEY, openId);
initReq.put(UserExt.USER_GITHUB_ID, openId);
try {
initService.init(initReq);
} catch (final Exception e) {
// ignored
}
initService.init(initReq);
} else {
user = userQueryService.getUserByEmailOrUserName(userName);
user = userQueryService.getUserByName(userName);
if (null == user) {
final JSONObject preference = preferenceQueryService.getPreference();
if (!preference.optBoolean(Option.ID_C_ALLOW_REGISTER)) {
LOGGER.log(Level.DEBUG, "Not allow register");
context.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
......@@ -204,7 +200,6 @@ public class OAuthProcessor {
final JSONObject addUserReq = new JSONObject();
addUserReq.put(User.USER_NAME, userName);
addUserReq.put(User.USER_EMAIL, userEmail);
addUserReq.put(UserExt.USER_AVATAR, userAvatar);
addUserReq.put(User.USER_ROLE, Role.VISITOR_ROLE);
addUserReq.put(UserExt.USER_GITHUB_ID, openId);
......@@ -213,7 +208,7 @@ public class OAuthProcessor {
userMgmtService.addUser(addUserReq);
} catch (final Exception e) {
LOGGER.log(Level.ERROR, "Register via oauth failed", e);
context.sendError(HttpServletResponse.SC_UNAUTHORIZED);
context.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
......@@ -221,8 +216,9 @@ public class OAuthProcessor {
}
}
user = userQueryService.getUserByEmailOrUserName(userName);
user = userQueryService.getUserByName(userName);
if (null == user) {
LOGGER.log(Level.WARN, "Can't get user by name [" + userName + "]");
context.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
......
......@@ -135,14 +135,8 @@ public class AdminConsole {
dataModel.put(User.USER_NAME, userName);
final String roleName = currentUser.optString(User.USER_ROLE);
dataModel.put(User.USER_ROLE, roleName);
final String email = currentUser.optString(User.USER_EMAIL);
final String userAvatar = currentUser.optString(UserExt.USER_AVATAR);
if (StringUtils.isNotBlank(userAvatar)) {
dataModel.put(Common.GRAVATAR, userAvatar);
} else {
final String gravatar = Solos.getGravatarURL(email, "128");
dataModel.put(Common.GRAVATAR, gravatar);
}
dataModel.put(Common.GRAVATAR, userAvatar);
try {
final JSONObject preference = preferenceQueryService.getPreference();
......@@ -238,7 +232,7 @@ public class AdminConsole {
/**
* Exports data as SQL zip file.
*
* @param context the specified HTTP request context
* @param context the specified request context
*/
public void exportSQL(final RequestContext context) {
final HttpServletResponse response = context.getResponse();
......@@ -351,7 +345,7 @@ public class AdminConsole {
/**
* Exports data as JSON zip file.
*
* @param context the specified HTTP request context
* @param context the specified request context
*/
public void exportJSON(final RequestContext context) {
final HttpServletResponse response = context.getResponse();
......@@ -401,7 +395,7 @@ public class AdminConsole {
/**
* Exports data as Hexo markdown zip file.
*
* @param context the specified HTTP request context
* @param context the specified request context
*/
public void exportHexo(final RequestContext context) {
final HttpServletResponse response = context.getResponse();
......
......@@ -114,7 +114,7 @@ public class ArticleConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getArticleThumbs(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -175,7 +175,7 @@ public class ArticleConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getArticle(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -224,7 +224,7 @@ public class ArticleConsole {
* </pre>, order by article update date and sticky(put top).
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getArticles(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -285,7 +285,7 @@ public class ArticleConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void removeArticle(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -329,7 +329,7 @@ public class ArticleConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void cancelPublishArticle(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -373,7 +373,7 @@ public class ArticleConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void cancelTopArticle(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -414,7 +414,7 @@ public class ArticleConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void putTopArticle(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -475,7 +475,7 @@ public class ArticleConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void updateArticle(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -540,7 +540,7 @@ public class ArticleConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void addArticle(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......
......@@ -108,7 +108,7 @@ public class CategoryConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
* @throws Exception exception
*/
public void changeOrder(final RequestContext context) {
......@@ -151,7 +151,7 @@ public class CategoryConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
* @throws Exception exception
*/
public void getCategory(final RequestContext context) {
......@@ -197,7 +197,7 @@ public class CategoryConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
* @throws Exception exception
*/
public void removeCategory(final RequestContext context) {
......@@ -243,7 +243,7 @@ public class CategoryConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void updateCategory(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -375,7 +375,7 @@ public class CategoryConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void addCategory(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -505,7 +505,7 @@ public class CategoryConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getCategories(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......
......@@ -81,7 +81,7 @@ public class CommentConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void removePageComment(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -123,7 +123,7 @@ public class CommentConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void removeArticleComment(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -173,7 +173,6 @@ public class CommentConsole {
* "oId": "",
* "commentTitle": "",
* "commentName": "",
* "commentEmail": "",
* "thumbnailUrl": "",
* "commentURL": "",
* "commentContent": "",
......@@ -184,7 +183,7 @@ public class CommentConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getComments(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -219,7 +218,6 @@ public class CommentConsole {
* "comments": [{
* "oId": "",
* "commentName": "",
* "commentEmail": "",
* "thumbnailUrl": "",
* "commentURL": "",
* "commentContent": "",
......@@ -231,7 +229,7 @@ public class CommentConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getArticleComments(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -264,7 +262,6 @@ public class CommentConsole {
* "comments": [{
* "oId": "",
* "commentName": "",
* "commentEmail": "",
* "thumbnailUrl": "",
* "commentURL": "",
* "commentContent": "",
......@@ -276,7 +273,7 @@ public class CommentConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getPageComments(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......
......@@ -82,7 +82,7 @@ public class LinkConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void removeLink(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -129,7 +129,7 @@ public class LinkConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void updateLink(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -173,7 +173,7 @@ public class LinkConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void changeOrder(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -223,7 +223,7 @@ public class LinkConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void addLink(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -273,7 +273,7 @@ public class LinkConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getLinks(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -320,7 +320,7 @@ public class LinkConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getLink(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......
......@@ -109,7 +109,7 @@ public class PageConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void updatePage(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -144,7 +144,7 @@ public class PageConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void removePage(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -196,7 +196,7 @@ public class PageConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void addPage(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -241,7 +241,7 @@ public class PageConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void changeOrder(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -288,7 +288,7 @@ public class PageConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getPage(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -338,7 +338,7 @@ public class PageConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getPages(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......
......@@ -82,7 +82,7 @@ public class PluginConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void setPluginStatus(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -122,7 +122,7 @@ public class PluginConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
* @throws Exception exception
*/
public void getPlugins(final RequestContext context) {
......@@ -149,7 +149,7 @@ public class PluginConsole {
/**
* get the info of the specified pluginoId,just fot the plugin-setting.
*
* @param context the specified http request context
* @param context the specified request context
*/
public void toSetting(final RequestContext context) {
final ConsoleRenderer renderer = new ConsoleRenderer(context, "admin-plugin-setting.ftl");
......@@ -175,7 +175,7 @@ public class PluginConsole {
/**
* update the setting of the plugin.
*
* @param context the specified http request context
* @param context the specified request context
*/
public void updateSetting(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......
......@@ -87,82 +87,6 @@ public class PreferenceConsole {
@Inject
private LangPropsService langPropsService;
/**
* Gets reply template.
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "replyNotificationTemplate": {
* "subject": "",
* "body": ""
* }
* }
* </pre>
* </p>
*
* @param context the specified http request context
*/
public void getReplyNotificationTemplate(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
context.setRenderer(renderer);
try {
final JSONObject replyNotificationTemplate = preferenceQueryService.getReplyNotificationTemplate();
final JSONObject ret = new JSONObject();
renderer.setJSONObject(ret);
ret.put("replyNotificationTemplate", replyNotificationTemplate);
ret.put(Keys.STATUS_CODE, true);
} catch (final Exception e) {
LOGGER.log(Level.ERROR, e.getMessage(), e);
final JSONObject jsonObject = new JSONObject().put(Keys.STATUS_CODE, false);
renderer.setJSONObject(jsonObject);
jsonObject.put(Keys.MSG, langPropsService.get("getFailLabel"));
}
}
/**
* Updates reply template.
* <p>
* <p>
* Request json:
* <pre>
* {
* "replyNotificationTemplate": {
* "subject": "",
* "body": ""
* }
* }
* </pre>
* </p>
*
* @param context the specified http request context
*/
public void updateReplyNotificationTemplate(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
context.setRenderer(renderer);
try {
final JSONObject requestJSONObject = context.requestJSON();
final JSONObject replyNotificationTemplate = requestJSONObject.getJSONObject("replyNotificationTemplate");
preferenceMgmtService.updateReplyNotificationTemplate(replyNotificationTemplate);
final JSONObject ret = new JSONObject();
ret.put(Keys.STATUS_CODE, true);
ret.put(Keys.MSG, langPropsService.get("updateSuccLabel"));
renderer.setJSONObject(ret);
} catch (final Exception e) {
LOGGER.log(Level.ERROR, e.getMessage(), e);
final JSONObject jsonObject = new JSONObject().put(Keys.STATUS_CODE, false);
renderer.setJSONObject(jsonObject);
jsonObject.put(Keys.MSG, langPropsService.get("updateFailLabel"));
}
}
/**
* Gets signs.
* <p>
......@@ -178,7 +102,7 @@ public class PreferenceConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getSigns(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -237,7 +161,6 @@ public class PreferenceConsole {
* "noticeBoard": "",
* "footerContent": "",
* "htmlHead": "",
* "adminEmail": "",
* "metaKeywords": "",
* "metaDescription": "",
* "enableArticleUpdateHint": boolean,
......@@ -258,7 +181,7 @@ public class PreferenceConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void getPreference(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......@@ -336,7 +259,7 @@ public class PreferenceConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
public void updatePreference(final RequestContext context) {
final JsonRenderer renderer = new JsonRenderer();
......
......@@ -24,8 +24,6 @@ import org.b3log.latke.servlet.RequestContext;
import org.b3log.latke.servlet.annotation.Before;
import org.b3log.latke.servlet.annotation.RequestProcessor;
import org.b3log.latke.servlet.renderer.TextHtmlRenderer;
import org.b3log.solo.mail.MailService;
import org.b3log.solo.mail.MailServiceFactory;
import org.b3log.solo.model.Option;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.solo.repository.TagArticleRepository;
......@@ -40,7 +38,7 @@ import org.json.JSONObject;
* Provides patches on some special issues.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.2.0.20, Jan 28, 2019
* @version 1.2.0.21, Mar 3, 2019
* @since 0.3.1
*/
@RequestProcessor
......@@ -52,11 +50,6 @@ public class RepairConsole {
*/
private static final Logger LOGGER = Logger.getLogger(RepairConsole.class);
/**
* Mail service.
*/
private static final MailService MAIL_SVC = MailServiceFactory.getMailService();
/**
* Preference query service.
*/
......
......@@ -83,7 +83,7 @@ public class TagConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@Before(ConsoleAuthAdvice.class)
public void getTags(final RequestContext context) {
......@@ -117,7 +117,7 @@ public class TagConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@Before(ConsoleAdminAuthAdvice.class)
public void getUnusedTags(final RequestContext context) {
......@@ -160,7 +160,7 @@ public class TagConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@Before(ConsoleAdminAuthAdvice.class)
public void removeUnusedTags(final RequestContext context) {
......
......@@ -86,7 +86,6 @@ public class UserConsole {
* {
* "oId": "",
* "userName": "",
* "userEmail": "",
* "userRole": "",
* "userURL": "",
* "userAvatar": "",
......@@ -104,7 +103,7 @@ public class UserConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@Before(ConsoleAdminAuthAdvice.class)
public void updateUser(final RequestContext context) {
......@@ -117,7 +116,7 @@ public class UserConsole {
userMgmtService.updateUser(requestJSONObject);
final String userName = requestJSONObject.optString(User.USER_NAME);
final JSONObject user = userQueryService.getUserByEmailOrUserName(userName);
final JSONObject user = userQueryService.getUserByName(userName);
Solos.login(user, context.getResponse());
ret.put(Keys.STATUS_CODE, true);
......@@ -144,7 +143,7 @@ public class UserConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@Before(ConsoleAdminAuthAdvice.class)
public void removeUser(final RequestContext context) {
......@@ -183,7 +182,6 @@ public class UserConsole {
* "users": [{
* "oId": "",
* "userName": "",
* "userEmail": "",
* "roleName": "",
* ....
* }, ....]
......@@ -192,7 +190,7 @@ public class UserConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@Before(ConsoleAdminAuthAdvice.class)
public void getUsers(final RequestContext context) {
......@@ -233,14 +231,13 @@ public class UserConsole {
* "user": {
* "oId": "",
* "userName": "",
* "userEmail": "",
* "userAvatar": ""
* }
* }
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@Before(ConsoleAdminAuthAdvice.class)
public void getUser(final RequestContext context) {
......@@ -273,7 +270,7 @@ public class UserConsole {
* </pre>
* </p>
*
* @param context the specified http request context
* @param context the specified request context
*/
@Before(ConsoleAdminAuthAdvice.class)
public void changeUserRole(final RequestContext context) {
......
......@@ -24,16 +24,13 @@ import org.b3log.latke.model.User;
import org.b3log.latke.repository.*;
import org.b3log.latke.repository.annotation.Repository;
import org.b3log.solo.cache.UserCache;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.List;
/**
* User repository.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.1.0.1, Sep 30, 2018
* @version 1.1.0.2, Mar 2, 2019
* @since 0.3.1
*/
@Repository
......@@ -96,41 +93,7 @@ public class UserRepository extends AbstractRepository {
* @throws RepositoryException repository exception
*/
public JSONObject getByUserName(final String userName) throws RepositoryException {
final Query query = new Query().setPageCount(1).
setFilter(new PropertyFilter(User.USER_NAME, FilterOperator.EQUAL, userName));
final List<JSONObject> users = getList(query);
if (users.isEmpty()) {
return null;
}
return users.get(0);
}
/**
* Gets a user by the specified email.
*
* @param email the specified email
* @return user, returns {@code null} if not found
* @throws RepositoryException repository exception
*/
public JSONObject getByEmail(final String email) throws RepositoryException {
JSONObject ret = userCache.getUserByEmail(email);
if (null != ret) {
return ret;
}
final Query query = new Query().setPageCount(1).
setFilter(new PropertyFilter(User.USER_EMAIL, FilterOperator.EQUAL, email.toLowerCase().trim()));
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
return null;
}
ret = array.optJSONObject(0);
userCache.putUser(ret);
return ret;
return getFirst(new Query().setFilter(new PropertyFilter(User.USER_NAME, FilterOperator.EQUAL, userName)));
}
/**
......@@ -145,14 +108,11 @@ public class UserRepository extends AbstractRepository {
return ret;
}
final Query query = new Query().setFilter(new PropertyFilter(User.USER_ROLE, FilterOperator.EQUAL, Role.ADMIN_ROLE)).setPageCount(1);
final JSONObject result = get(query);
final JSONArray array = result.optJSONArray(Keys.RESULTS);
if (0 == array.length()) {
ret = getFirst(new Query().setFilter(new PropertyFilter(User.USER_ROLE, FilterOperator.EQUAL, Role.ADMIN_ROLE)));
if (null == ret) {
return null;
}
ret = array.optJSONObject(0);
userCache.putAdmin(ret);
return ret;
......
......@@ -39,7 +39,6 @@ import org.b3log.solo.repository.CommentRepository;
import org.b3log.solo.repository.PageRepository;
import org.b3log.solo.util.Emotions;
import org.b3log.solo.util.Markdowns;
import org.b3log.solo.util.Solos;
import org.json.JSONArray;
import org.json.JSONObject;
import org.jsoup.Jsoup;
......@@ -145,7 +144,6 @@ public class CommentQueryService {
* "oId": "",
* "commentTitle": "",
* "commentName": "",
* "commentEmail": "",
* "thumbnailUrl": "",
* "commentURL": "",
* "commentContent": "",
......@@ -248,12 +246,6 @@ public class CommentQueryService {
comment.put(Comment.COMMENT_URL, url);
comment.put(Common.IS_REPLY, false); // Assumes this comment is not a reply
final String thumbnailURL = comment.optString(Comment.COMMENT_THUMBNAIL_URL);
if (StringUtils.isBlank(thumbnailURL)) {
final String email = comment.optString(Comment.COMMENT_EMAIL);
comment.put(Comment.COMMENT_THUMBNAIL_URL, Solos.getGravatarURL(email, "128"));
}
if (StringUtils.isNotBlank(comment.optString(Comment.COMMENT_ORIGINAL_COMMENT_ID))) {
// This comment is a reply
comment.put(Common.IS_REPLY, true);
......
......@@ -528,15 +528,8 @@ public class DataModelService {
comment.put(Comment.COMMENT_NAME, comment.getString(Comment.COMMENT_NAME));
comment.put(Comment.COMMENT_URL, comment.getString(Comment.COMMENT_URL));
comment.put(Common.IS_REPLY, false);
comment.remove(Comment.COMMENT_EMAIL); // Erases email for security reason
comment.put(Comment.COMMENT_T_DATE, new Date(comment.optLong(Comment.COMMENT_CREATED)));
comment.put("commentDate2", new Date(comment.optLong(Comment.COMMENT_CREATED)));
final String email = comment.optString(Comment.COMMENT_EMAIL);
final String thumbnailURL = comment.optString(Comment.COMMENT_THUMBNAIL_URL);
if (StringUtils.isBlank(thumbnailURL)) {
comment.put(Comment.COMMENT_THUMBNAIL_URL, Solos.getGravatarURL(email, "128"));
}
}
dataModel.put(Common.RECENT_COMMENTS, recentComments);
......@@ -615,14 +608,7 @@ public class DataModelService {
final JSONObject currentUser = Solos.getCurrentUser(context.getRequest(), context.getResponse());
if (null != currentUser) {
final String userAvatar = currentUser.optString(UserExt.USER_AVATAR);
if (StringUtils.isNotBlank(userAvatar)) {
dataModel.put(Common.GRAVATAR, userAvatar);
} else {
final String email = currentUser.optString(User.USER_EMAIL);
final String gravatar = Solos.getGravatarURL(email, "128");
dataModel.put(Common.GRAVATAR, gravatar);
}
dataModel.put(Common.GRAVATAR, userAvatar);
dataModel.put(User.USER_NAME, currentUser.optString(User.USER_NAME));
}
......@@ -909,12 +895,7 @@ public class DataModelService {
article.put(Article.ARTICLE_T_UPDATE_DATE, new Date(article.optLong(Article.ARTICLE_UPDATED)));
final String userAvatar = author.optString(UserExt.USER_AVATAR);
if (StringUtils.isNotBlank(userAvatar)) {
article.put(Common.AUTHOR_THUMBNAIL_URL, userAvatar);
} else {
final String thumbnailURL = Solos.getGravatarURL(author.optString(User.USER_EMAIL), "128");
article.put(Common.AUTHOR_THUMBNAIL_URL, thumbnailURL);
}
article.put(Common.AUTHOR_THUMBNAIL_URL, userAvatar);
if (preference.getBoolean(Option.ID_C_ENABLE_ARTICLE_UPDATE_HINT)) {
article.put(Common.HAS_UPDATED, articleQueryService.hasUpdated(article));
......
......@@ -17,7 +17,6 @@
*/
package org.b3log.solo.service;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.b3log.latke.Keys;
......@@ -34,7 +33,6 @@ import org.b3log.latke.repository.Transaction;
import org.b3log.latke.repository.jdbc.util.JdbcRepositories;
import org.b3log.latke.repository.jdbc.util.JdbcRepositories.CreateTableResult;
import org.b3log.latke.service.LangPropsService;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.service.annotation.Service;
import org.b3log.latke.util.Ids;
import org.b3log.solo.SoloServletListener;
......@@ -56,7 +54,7 @@ import java.util.Set;
* Solo initialization service.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.5.2.29, Feb 10, 2019
* @version 1.5.2.30, Mar 2, 2019
* @since 0.4.0
*/
@Service
......@@ -214,14 +212,12 @@ public class InitService {
* @param requestJSONObject the specified request json object, for example,
* {
* "userName": "",
* "userEmail": "",
* "userAvatar": "", // optional
* "userB3Key": "", // optional
* "userGitHubId": "" // optional
* }
* @throws ServiceException service exception
*/
public void init(final JSONObject requestJSONObject) throws ServiceException {
public void init(final JSONObject requestJSONObject) {
if (isInited()) {
return;
}
......@@ -230,15 +226,15 @@ public class InitService {
try {
initStatistic();
initPreference(requestJSONObject);
initReplyNotificationTemplate();
initAdmin(requestJSONObject);
initLink();
helloWorld();
transaction.commit();
} catch (final Exception e) {
} catch (final Throwable e) {
LOGGER.log(Level.ERROR, "Initializes Solo failed", e);
throw new ServiceException("Initializes Solo failed: " + e.getMessage());
System.exit(-1);
} finally {
if (transaction.isActive()) {
transaction.rollback();
......@@ -287,7 +283,6 @@ public class InitService {
final JSONObject comment = new JSONObject();
comment.put(Keys.OBJECT_ID, articleId);
comment.put(Comment.COMMENT_NAME, "88250");
comment.put(Comment.COMMENT_EMAIL, "d@b3log.org");
comment.put(Comment.COMMENT_URL, "https://hacpai.com/member/88250");
comment.put(Comment.COMMENT_CONTENT, langPropsService.get("helloWorld.comment.content"));
comment.put(Comment.COMMENT_ORIGINAL_COMMENT_ID, "");
......@@ -302,6 +297,8 @@ public class InitService {
comment.put(Comment.COMMENT_SHARP_URL, commentSharpURL);
commentRepository.add(comment);
LOGGER.info("Hello World!");
}
/**
......@@ -411,7 +408,6 @@ public class InitService {
* @param requestJSONObject the specified request json object, for example,
* {
* "userName": "",
* "userEmail": "",
* "userAvatar": "", // optional
* "userB3Key": "", // optional
* "userGitHubId": "" // optional
......@@ -423,19 +419,14 @@ public class InitService {
final JSONObject admin = new JSONObject();
admin.put(User.USER_NAME, requestJSONObject.getString(User.USER_NAME));
admin.put(User.USER_EMAIL, requestJSONObject.getString(User.USER_EMAIL));
admin.put(User.USER_URL, Latkes.getServePath());
admin.put(User.USER_ROLE, Role.ADMIN_ROLE);
String avatar = requestJSONObject.optString(UserExt.USER_AVATAR);
if (StringUtils.isBlank(avatar)) {
avatar = Solos.getGravatarURL(requestJSONObject.getString(User.USER_EMAIL), "128");
}
admin.put(UserExt.USER_AVATAR, avatar);
admin.put(UserExt.USER_AVATAR, requestJSONObject.optString(UserExt.USER_AVATAR));
admin.put(UserExt.USER_B3_KEY, requestJSONObject.optString(UserExt.USER_B3_KEY));
admin.put(UserExt.USER_GITHUB_ID, requestJSONObject.optString(UserExt.USER_GITHUB_ID));
userRepository.add(admin);
LOGGER.debug("Initialized admin");
LOGGER.info("Initialized admin");
}
/**
......@@ -444,6 +435,7 @@ public class InitService {
* @throws Exception exception
*/
private void initLink() throws Exception {
LOGGER.debug("Initializing link....");
final JSONObject link = new JSONObject();
link.put(Link.LINK_TITLE, "黑客派");
......@@ -451,7 +443,8 @@ public class InitService {
link.put(Link.LINK_DESCRIPTION, "黑客与画家的社区");
final int maxOrder = linkRepository.getMaxOrder();
link.put(Link.LINK_ORDER, maxOrder + 1);
final String ret = linkRepository.add(link);
linkRepository.add(link);
LOGGER.info("Initialized link");
}
/**
......@@ -469,33 +462,7 @@ public class InitService {
statisticBlogViewCountOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_STATISTIC);
optionRepository.add(statisticBlogViewCountOpt);
LOGGER.debug("Initialized statistic");
}
/**
* Initializes reply notification template.
*
* @throws Exception exception
*/
private void initReplyNotificationTemplate() throws Exception {
LOGGER.debug("Initializing reply notification template");
final JSONObject replyNotificationTemplate = new JSONObject(DefaultPreference.DEFAULT_REPLY_NOTIFICATION_TEMPLATE);
replyNotificationTemplate.put(Keys.OBJECT_ID, "replyNotificationTemplate");
final JSONObject subjectOpt = new JSONObject();
subjectOpt.put(Keys.OBJECT_ID, Option.ID_C_REPLY_NOTI_TPL_SUBJECT);
subjectOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
subjectOpt.put(Option.OPTION_VALUE, replyNotificationTemplate.optString("subject"));
optionRepository.add(subjectOpt);
final JSONObject bodyOpt = new JSONObject();
bodyOpt.put(Keys.OBJECT_ID, Option.ID_C_REPLY_NOTI_TPL_BODY);
bodyOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
bodyOpt.put(Option.OPTION_VALUE, replyNotificationTemplate.optString("body"));
optionRepository.add(bodyOpt);
LOGGER.debug("Initialized reply notification template");
LOGGER.info("Initialized statistic");
}
/**
......@@ -609,12 +576,6 @@ public class InitService {
blogSubtitleOpt.put(Option.OPTION_VALUE, DefaultPreference.DEFAULT_BLOG_SUBTITLE);
optionRepository.add(blogSubtitleOpt);
final JSONObject adminEmailOpt = new JSONObject();
adminEmailOpt.put(Keys.OBJECT_ID, Option.ID_C_ADMIN_EMAIL);
adminEmailOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
adminEmailOpt.put(Option.OPTION_VALUE, requestJSONObject.getString(User.USER_EMAIL));
optionRepository.add(adminEmailOpt);
final JSONObject localeStringOpt = new JSONObject();
localeStringOpt.put(Keys.OBJECT_ID, Option.ID_C_LOCALE_STRING);
localeStringOpt.put(Option.OPTION_CATEGORY, Option.CATEGORY_C_PREFERENCE);
......@@ -718,6 +679,6 @@ public class InitService {
skinsOpt.put(Option.OPTION_VALUE, skinArray.toString());
optionRepository.add(skinsOpt);
LOGGER.debug("Initialized preference");
LOGGER.info("Initialized preference");
}
}
......@@ -140,35 +140,6 @@ public class PreferenceMgmtService {
Stopwatchs.end();
}
/**
* Updates the reply notification template with the specified reply notification template.
*
* @param replyNotificationTemplate the specified reply notification template
* @throws ServiceException service exception
*/
public void updateReplyNotificationTemplate(final JSONObject replyNotificationTemplate) throws ServiceException {
final Transaction transaction = optionRepository.beginTransaction();
try {
final JSONObject bodyOpt = optionRepository.get(Option.ID_C_REPLY_NOTI_TPL_BODY);
bodyOpt.put(Option.OPTION_VALUE, replyNotificationTemplate.optString("body"));
optionRepository.update(Option.ID_C_REPLY_NOTI_TPL_BODY, bodyOpt);
final JSONObject subjectOpt = optionRepository.get(Option.ID_C_REPLY_NOTI_TPL_SUBJECT);
subjectOpt.put(Option.OPTION_VALUE, replyNotificationTemplate.optString("subject"));
optionRepository.update(Option.ID_C_REPLY_NOTI_TPL_SUBJECT, subjectOpt);
transaction.commit();
} catch (final Exception e) {
if (transaction.isActive()) {
transaction.rollback();
}
LOGGER.log(Level.ERROR, "Updates reply notification failed", e);
throw new ServiceException(e);
}
}
/**
* Updates the preference with the specified preference.
*
......@@ -209,20 +180,13 @@ public class PreferenceMgmtService {
preference.put(Option.ID_C_SIGNS, preference.get(Option.ID_C_SIGNS).toString());
final JSONObject oldPreference = preferenceQueryService.getPreference();
final String adminEmail = oldPreference.getString(Option.ID_C_ADMIN_EMAIL);
preference.put(Option.ID_C_ADMIN_EMAIL, adminEmail);
final String version = oldPreference.optString(Option.ID_C_VERSION);
preference.put(Option.ID_C_VERSION, version);
final String localeString = preference.getString(Option.ID_C_LOCALE_STRING);
LOGGER.log(Level.DEBUG, "Current locale[string={0}]", localeString);
Latkes.setLocale(new Locale(Locales.getLanguage(localeString), Locales.getCountry(localeString)));
final JSONObject adminEmailOpt = optionRepository.get(Option.ID_C_ADMIN_EMAIL);
adminEmailOpt.put(Option.OPTION_VALUE, adminEmail);
optionRepository.update(Option.ID_C_ADMIN_EMAIL, adminEmailOpt);
final JSONObject allowVisitDraftViaPermalinkOpt = optionRepository.get(Option.ID_C_ALLOW_VISIT_DRAFT_VIA_PERMALINK);
allowVisitDraftViaPermalinkOpt.put(Option.OPTION_VALUE, preference.optString(Option.ID_C_ALLOW_VISIT_DRAFT_VIA_PERMALINK));
optionRepository.update(Option.ID_C_ALLOW_VISIT_DRAFT_VIA_PERMALINK, allowVisitDraftViaPermalinkOpt);
......
......@@ -20,7 +20,6 @@ package org.b3log.solo.service;
import org.b3log.latke.ioc.Inject;
import org.b3log.latke.logging.Level;
import org.b3log.latke.logging.Logger;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.service.annotation.Service;
import org.b3log.solo.model.Option;
import org.b3log.solo.repository.OptionRepository;
......@@ -53,27 +52,6 @@ public class PreferenceQueryService {
@Inject
private OptionQueryService optionQueryService;
/**
* Gets the reply notification template.
*
* @return reply notification template, returns {@code null} if not found
* @throws ServiceException service exception
*/
public JSONObject getReplyNotificationTemplate() throws ServiceException {
try {
final JSONObject ret = new JSONObject();
final JSONObject preference = getPreference();
ret.put("subject", preference.optString(Option.ID_C_REPLY_NOTI_TPL_SUBJECT));
ret.put("body", preference.optString(Option.ID_C_REPLY_NOTI_TPL_BODY));
return ret;
} catch (final Exception e) {
LOGGER.log(Level.ERROR, "Updates reply notification template failed", e);
throw new ServiceException(e);
}
}
/**
* Gets the user preference.
*
......@@ -81,13 +59,10 @@ public class PreferenceQueryService {
*/
public JSONObject getPreference() {
try {
final JSONObject checkInit = optionRepository.get(Option.ID_C_ADMIN_EMAIL);
if (null == checkInit) {
return null;
}
return optionQueryService.getOptions(Option.CATEGORY_C_PREFERENCE);
} catch (final Exception e) {
LOGGER.log(Level.ERROR, "Gets preference failed", e);
return null;
}
}
......
......@@ -33,7 +33,6 @@ import org.b3log.latke.service.annotation.Service;
import org.b3log.latke.util.Strings;
import org.b3log.solo.model.UserExt;
import org.b3log.solo.repository.UserRepository;
import org.b3log.solo.util.Solos;
import org.json.JSONObject;
/**
......@@ -88,7 +87,6 @@ public class UserMgmtService {
* @param requestJSONObject the specified request json object, for example,
* "oId": "",
* "userName": "",
* "userEmail": "",
* "userRole": "",
* "userURL": "",
* "userB3Key": ""
......@@ -104,19 +102,12 @@ public class UserMgmtService {
throw new ServiceException(langPropsService.get("updateFailLabel"));
}
final String userNewEmail = requestJSONObject.optString(User.USER_EMAIL).toLowerCase().trim();
JSONObject mayBeAnother = userRepository.getByEmail(userNewEmail);
if (null != mayBeAnother && !mayBeAnother.optString(Keys.OBJECT_ID).equals(oldUserId)) {
throw new ServiceException(langPropsService.get("duplicatedEmailLabel"));
}
oldUser.put(User.USER_EMAIL, userNewEmail);
final String userName = requestJSONObject.optString(User.USER_NAME);
if (UserExt.invalidUserName(userName)) {
throw new ServiceException(langPropsService.get("userNameInvalidLabel"));
}
mayBeAnother = userRepository.getByUserName(userName);
JSONObject mayBeAnother = userRepository.getByUserName(userName);
if (null != mayBeAnother && !mayBeAnother.optString(Keys.OBJECT_ID).equals(oldUserId)) {
throw new ServiceException(langPropsService.get("duplicatedUserNameLabel"));
}
......@@ -189,7 +180,6 @@ public class UserMgmtService {
*
* @param requestJSONObject the specified request json object, for example,
* "userName": "",
* "userEmail": "",
* "userURL": "", // optional, uses 'servePath' instead if not specified
* "userRole": "", // optional, uses {@value Role#DEFAULT_ROLE} instead if not specified
* "userAvatar": "", // optional, users generated gravatar url instead if not specified
......@@ -202,28 +192,12 @@ public class UserMgmtService {
final Transaction transaction = userRepository.beginTransaction();
try {
final JSONObject user = new JSONObject();
final String userEmail = requestJSONObject.optString(User.USER_EMAIL).trim().toLowerCase();
if (!Strings.isEmail(userEmail)) {
throw new ServiceException(langPropsService.get("mailInvalidLabel"));
}
JSONObject duplicatedUser = userRepository.getByEmail(userEmail);
if (null != duplicatedUser) {
if (transaction.isActive()) {
transaction.rollback();
}
throw new ServiceException(langPropsService.get("duplicatedEmailLabel"));
}
user.put(User.USER_EMAIL, userEmail);
final String userName = requestJSONObject.optString(User.USER_NAME);
if (UserExt.invalidUserName(userName)) {
throw new ServiceException(langPropsService.get("userNameInvalidLabel"));
}
duplicatedUser = userRepository.getByUserName(userName);
JSONObject duplicatedUser = userRepository.getByUserName(userName);
if (null != duplicatedUser) {
if (transaction.isActive()) {
transaction.rollback();
......@@ -231,26 +205,22 @@ public class UserMgmtService {
throw new ServiceException(langPropsService.get("duplicatedUserNameLabel"));
}
final JSONObject user = new JSONObject();
user.put(User.USER_NAME, userName);
String userURL = requestJSONObject.optString(User.USER_URL);
if (StringUtils.isBlank(userURL)) {
userURL = Latkes.getServePath();
}
if (!Strings.isURL(userURL)) {
throw new ServiceException(langPropsService.get("urlInvalidLabel"));
}
user.put(User.USER_URL, userURL);
final String roleName = requestJSONObject.optString(User.USER_ROLE, Role.DEFAULT_ROLE);
user.put(User.USER_ROLE, roleName);
String userAvatar = requestJSONObject.optString(UserExt.USER_AVATAR);
if (StringUtils.isBlank(userAvatar)) {
userAvatar = Solos.getGravatarURL(userEmail, "128");
}
final String userAvatar = requestJSONObject.optString(UserExt.USER_AVATAR);
user.put(UserExt.USER_AVATAR, userAvatar);
final String userGitHubId = requestJSONObject.optString(UserExt.USER_GITHUB_ID);
......
......@@ -43,7 +43,7 @@ import java.util.List;
* User query service.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.7, Oct 5, 2018
* @version 1.1.0.0, Feb 3, 2019
* @since 0.4.0
*/
@Service
......@@ -98,21 +98,16 @@ public class UserQueryService {
}
/**
* Gets a user by the specified email or username.
* Gets a user by the specified user name.
*
* @param emailOrUserName the specified email or username
* @param userName the specified user name
* @return user, returns {@code null} if not found
*/
public JSONObject getUserByEmailOrUserName(final String emailOrUserName) {
public JSONObject getUserByName(final String userName) {
try {
JSONObject ret = userRepository.getByEmail(emailOrUserName);
if (null == ret) {
ret = userRepository.getByUserName(emailOrUserName);
}
return ret;
return userRepository.getByUserName(userName);
} catch (final RepositoryException e) {
LOGGER.log(Level.ERROR, "Gets a user by email or username [" + emailOrUserName + "] failed", e);
LOGGER.log(Level.ERROR, "Gets a user by username [" + userName + "] failed", e);
return null;
}
......@@ -135,7 +130,6 @@ public class UserQueryService {
* "users": [{
* "oId": "",
* "userName": "",
* "userEmail": "",
* "roleName": ""
* }, ....]
* }
......@@ -181,8 +175,7 @@ public class UserQueryService {
* {
* "user": {
* "oId": "",
* "userName": "",
* "userEmail": ""
* "userName": ""
* }
* }
* </pre>, returns {@code null} if not found
......
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.upgrade;
import org.b3log.latke.Latkes;
import org.b3log.latke.ioc.BeanManager;
import org.b3log.latke.logging.Level;
import org.b3log.latke.logging.Logger;
import org.b3log.latke.repository.Transaction;
import org.b3log.latke.repository.jdbc.util.Connections;
import org.b3log.solo.model.Option;
import org.b3log.solo.repository.ArticleRepository;
import org.b3log.solo.repository.OptionRepository;
import org.json.JSONObject;
import java.sql.Connection;
import java.sql.Statement;
/**
* Upgrade script from v3.1.0 to v3.2.0.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.0, Mar 3, 2019
* @since 3.2.0
*/
public final class V310_320 {
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(V310_320.class);
/**
* Performs upgrade from v3.1.0 to v3.2.0.
*
* @throws Exception upgrade fails
*/
public static void perform() throws Exception {
final String fromVer = "3.1.0";
final String toVer = "3.2.0";
LOGGER.log(Level.INFO, "Upgrading from version [" + fromVer + "] to version [" + fromVer + "]....");
final BeanManager beanManager = BeanManager.getInstance();
final OptionRepository optionRepository = beanManager.getReference(OptionRepository.class);
final ArticleRepository articleRepository = beanManager.getReference(ArticleRepository.class);
try {
Connection connection = Connections.getConnection();
Statement statement = connection.createStatement();
// 移除邮件相关功能 https://github.com/b3log/solo/issues/12690
final String tablePrefix = Latkes.getLocalProperty("jdbc.tablePrefix") + "_";
statement.executeUpdate("ALTER TABLE `" + tablePrefix + "article` DROP COLUMN `userEmail`");
statement.executeUpdate("ALTER TABLE `" + tablePrefix + "comment` DROP COLUMN `commentEmail`");
statement.close();
connection.commit();
connection.close();
optionRepository.remove("adminEmail");
optionRepository.remove("replyNotiTplBody");
optionRepository.remove("replyNotiTplSubject");
final Transaction transaction = optionRepository.beginTransaction();
final JSONObject versionOpt = optionRepository.get(Option.ID_C_VERSION);
versionOpt.put(Option.OPTION_VALUE, toVer);
optionRepository.update(Option.ID_C_VERSION, versionOpt);
transaction.commit();
LOGGER.log(Level.INFO, "Upgraded from version [" + fromVer + "] to version [" + toVer + "] successfully");
} catch (final Exception e) {
LOGGER.log(Level.ERROR, "Upgrade failed!", e);
throw new Exception("Upgrade failed from version [" + fromVer + "] to version [" + toVer + "]");
}
}
}
......@@ -82,7 +82,6 @@ public final class GitHubs {
* {
* "openId": "",
* "userName": "D",
* "userEmail": "d@b3log.org", // may be empty
* "userAvatar": "https://avatars3.githubusercontent.com/u/873584?v=4"
* }
* </pre>, returns {@code null} if not found QQ user info
......@@ -101,14 +100,12 @@ public final class GitHubs {
}
final JSONObject data = result.optJSONObject(Common.DATA);
final String userName = StringUtils.trim(data.optString("userName"));
final String email = data.optString("userEmail");
final String openId = data.optString("userId");
final String avatarUrl = data.optString("userAvatarURL");
final JSONObject ret = new JSONObject();
ret.put("openId", openId);
ret.put(User.USER_NAME, userName);
ret.put(User.USER_EMAIL, email);
ret.put(UserExt.USER_AVATAR, avatarUrl);
return ret;
......
......@@ -19,7 +19,6 @@ package org.b3log.solo.util;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.b3log.latke.Keys;
......@@ -55,7 +54,7 @@ import java.util.ResourceBundle;
* Solo utilities.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.7.0.0, Feb 7, 2019
* @version 1.7.0.1, Mar 3, 2019
* @since 2.8.0
*/
public final class Solos {
......@@ -65,11 +64,6 @@ public final class Solos {
*/
private static final Logger LOGGER = Logger.getLogger(Solos.class);
/**
* Mail configuration (mail.properties).
*/
private static final ResourceBundle mailConf = ResourceBundle.getBundle("mail");
/**
* Favicon API.
*/
......@@ -427,22 +421,6 @@ public final class Solos {
return !(null != currentUser && !Role.VISITOR_ROLE.equals(currentUser.optString(User.USER_ROLE)));
}
/**
* Whether user configures the mail.properties.
*
* @return {@code true} if user configured, returns {@code false} otherwise
*/
public static boolean isMailConfigured() {
try {
return StringUtils.isNotBlank(mailConf.getString("mail.user")) &&
StringUtils.isNotBlank(mailConf.getString("mail.password")) &&
StringUtils.isNotBlank(mailConf.getString("mail.smtp.host")) &&
StringUtils.isNotBlank(mailConf.getString("mail.smtp.port"));
} catch (final Exception e) {
return false;
}
}
/**
* Checks the specified request is made from a mobile device.
*
......@@ -474,14 +452,12 @@ public final class Solos {
}
/**
* Gets the Gravatar URL for the specified email with the specified size.
* Gets the default user avatar URL..
*
* @param email the specified email
* @param size the specified size
* @return the Gravatar URL
* @return default user avatar URL
*/
public static String getGravatarURL(final String email, final String size) {
return GRAVATAR + DigestUtils.md5Hex(email) + "?s=" + size;
public static String getDefaultAvatar() {
return Latkes.getStaticServePath() + "/images/default-user-thumbnail.png";
}
/**
......
......@@ -41,13 +41,6 @@ if [ ! -f "/opt/b3log/solo/WEB-INF/classes/local.properties" ]; then
-e "s|{{SERVER_PORT}}|${SERVER_PORT:-8080}|g" \
> /opt/b3log/solo/WEB-INF/classes/latke.properties
cat /opt/b3log/tmp/mail.properties | sed \
-e "s|{{EMAIL_ADDRESS}}|${EMAIL_ADDRESS}|g" \
-e "s|{{EMAIL_PASSWORD}}|${EMAIL_PASSWORD}|g" \
-e "s|{{SMTP_HOST}}|${SMTP_HOST:-smtp.gmail.com}|g" \
-e "s|{{SMTP_PROT}}|${SMTP_PROT:-587}|g" \
-e "s|{{SMTP_SOCKETFACTORY_PORT}}|${SMTP_SOCKETFACTORY_PORT:-465}|g" \
> /opt/b3log/solo/WEB-INF/classes/mail.properties
rm -rf /opt/b3log/tmp
fi
......
......@@ -24,7 +24,7 @@
# Author: Dongxu Wang
#
commentEmailLabel=Email
queryUserFailedLabel=Query user info failed
commentContentLabel=Content
cancelLabel=Cancel
langLabel=en_US
......@@ -89,15 +89,11 @@ type1Label=Type:
typeLabel=Type
onlineVisitor1Label=Online Visitors:
noDataLabel=Lazy guy, has nothing!
replayEmailExplanationLabel=<b>Variables Explanation</b><ul class="marginLeft12"><li><b>${blogTitle}:</b> Blog title</li><li><b>${postLink}:</b> Post link</li><li><b>${postTitle}:</b> Post title</li><li><b>${replier}:</b> Replier ( if has link address, this variable is change to link address ) </li><li><b>${replyURL}:</b> Replay URL ( include # ) </li><li><b>${replyContent}:</b> Reply content</li></ul>
emailSubject1Label=Email Subject:
emailContent1Label=Email Content:
linkDescriptionLabel=Link Description
linkDescription1Label=Description:
descriptionLabel=Description
addressInvalidLabel=start protocol, e.g.: http://
ToolLabel=Tool
replayEmailTemplateLabel=Email Template for Reply
titleAndContentLabel=Title+Content
titleAndAbstractLabel=Title+Abstract
titleOnlyLabel=Title only
......@@ -336,7 +332,6 @@ articleViewPwdLabel=View Password
articleViewPwd1Label=View Password:
####
forbiddenLabel=Forbidden Access!
sorryLabel=Sorry!
notFoundLabel=Not Found!
unPulbishSuccLabel=Un Publish Successfully
unPulbishFailLabel=Un Publish Fail
......@@ -355,7 +350,6 @@ updatePreferenceFailNeedMulUsersLabel=Update Fail, the selected skin need multip
setFailLabel=Set Fail
setSuccLabel=Set Successfully
getFailLabel=Get Fail
noSettingLabel=No Setting
getSuccLabel=Get Successfully
importSuccLabel=Import Successfully :-)
importFailLabel=Some Import Fail %>_<%
......@@ -364,16 +358,10 @@ captchaErrorLabel=Captcha Error
inputErrorLabel=Input Error!
gotoLabel=Go
nameEmptyLabel=Username is empty
passwordEmptyLabel=Password is empty
passwordNotMatchLabel=Password Not Match
userPasswordConfirm1Label=Input password again:
blogEmptyLabel=Blogging service is empty
blogArticleEmptyLabel=Please select articles
notAllowCommentLabel=Not allow comment!
nameTooLongLabel=Sorry, your username must be between 2 and 20 characters long.
categoryTooLongLabel=Sorry, category name must be between 2 and 32 characters long.
mailCannotEmptyLabel=Mail is empty
mailInvalidLabel=Mail is invalid
urlInvalidLabel=URL is invalid
nonNegativeIntegerOnlyLabel=Non-Negative integer only
commentContentCannotEmptyLabel=Sorry, your content must be between 2 and 500 characters long.
......@@ -389,7 +377,6 @@ noAuthorizationURLLabel=Can not retrieve authorization URL from Google, please \
make sure the <em>Consumer Secret</em> you typed in and then try again.
duplicatedPermalinkLabel=Duplicated permalink!
invalidPermalinkFormatLabel=Invalid permalink format!
duplicatedEmailLabel=Duplicated email!
duplicatedUserNameLabel=Duplicated username!
refreshAndRetryLabel=Please refresh and try again!
editorLeaveLabel=Content is not null, Do you leave?
......@@ -402,10 +389,6 @@ confirmRemoveLabel=Are You Remove
confirmInitLabel=Are You Sure?
###### Common ######
mobileLabel=Mobile Theme
# Send an email to the user who upgrades Solo with a discontinuous version #
skipVersionMailSubject=[no-reply]Better not to skip more than one version to upgrade Solo
skipVersionMailBody=Hey, sorry for any inconvenience caused. If your Solo is too old to upgrade, \
developers in <a href="https://b3log.org" target="_blank">B3log</a> are more than welcome to help, thank you.
helloWorld.title=\u4E16\u754C\uFF0C\u4F60\u597D\uFF01
helloWorld.content=Solo \u535A\u5BA2\u7CFB\u7EDF\u5DF2\u7ECF\u521D\u59CB\u5316\u5B8C\u6BD5\uFF0C\u53EF\u5728\u7BA1\u7406\u540E\u53F0 - \u5DE5\u5177 - \u504F\u597D\u8BBE\u5B9A\u4E2D\u8C03\u6574\u66F4\u591A\u7EC6\u8282\u8BBE\u7F6E\u3002\u5982\u679C\u9700\u8981\u5BFC\u5165\u5DF2\u6709\u535A\u5BA2\u6587\u7AE0\uFF0C\u8BF7\u53C2\u8003\u6587\u6863 [Hexo/Jekyll/Markdown \u6587\u4EF6\u5BFC\u5165](https://hacpai.com/article/1498490209748)\u3002\n\n\
\u53E6\u5916\uFF0C\u51FA\u4E8E\u5B89\u5168\u8003\u8651\u8BF7\u5C3D\u5FEB\u5B8C\u6210\u5982\u4E0B\u64CD\u4F5C\uFF1A\n\n\
......
......@@ -24,7 +24,7 @@
# Author: Dongxu Wang
#
commentEmailLabel=\u90AE\u7BB1
queryUserFailedLabel=\u67E5\u8BE2\u7528\u6237\u4FE1\u606F\u5931\u8D25
commentContentLabel=\u8BC4\u8BBA\u5185\u5BB9
cancelLabel=\u53D6\u6D88
langLabel=zh_CN
......@@ -89,15 +89,11 @@ type1Label=\u7C7B\u578B\uFF1A
typeLabel=\u7C7B\u578B
onlineVisitor1Label=\u5F53\u524D\u8BBF\u5BA2\uFF1A
noDataLabel=\u8BE5\u5217\u8868\u5F88\u61D2\uFF0C\u4EC0\u4E48\u90FD\u6CA1\u6709\u7559\u4E0B\u3002\u3002\u3002
replayEmailExplanationLabel=<b>\u53D8\u91CF\u8BF4\u660E</b><ul class="marginLeft12"><li><b>${blogTitle}:</b> \u535A\u5BA2\u6807\u9898</li><li><b>${postLink}:</b> \u539F\u6587\uFF08\u6587\u7AE0/\u81EA\u5B9A\u4E49\u9875\u9762\uFF09\u94FE\u63A5\u5730\u5740</li><li><b>${postTitle}:</b> \u539F\u6587\u6807\u9898</li><li><b>${replier}:</b> \u56DE\u590D\u4EBA\uFF08\u5982\u679C\u56DE\u590D\u4EBA\u586B\u5199\u4E86\u4ED6\u7684\u94FE\u63A5\u5730\u5740\uFF0C\u8FD9\u4E2A\u53D8\u91CF\u5C06\u5305\u542B\u94FE\u63A5\u5730\u5740\uFF09</li><li><b>${replyURL}:</b> \u56DE\u590D\u94FE\u63A5\uFF08\u5E26 # \u951A\u70B9\uFF09</li><li><b>${replyContent}:</b> \u56DE\u590D\u5185\u5BB9</li></ul>
emailSubject1Label=\u90AE\u4EF6\u4E3B\u9898\uFF1A
emailContent1Label=\u90AE\u4EF6\u5185\u5BB9\uFF1A
linkDescriptionLabel=\u94FE\u63A5\u63CF\u8FF0
linkDescription1Label=\u63CF\u8FF0\uFF1A
descriptionLabel=\u63CF\u8FF0
addressInvalidLabel=\u8BF7\u4EE5\u534F\u8BAE\u5F00\u5934\uFF0C\u5982: http://
ToolLabel=\u5DE5\u5177
replayEmailTemplateLabel=\u56DE\u590D\u63D0\u9192\u90AE\u4EF6\u6A21\u7248
titleAndContentLabel=\u6807\u9898+\u6B63\u6587
titleAndAbstractLabel=\u6807\u9898+\u6458\u8981
titleOnlyLabel=\u4EC5\u6807\u9898
......@@ -336,7 +332,6 @@ articleViewPwdLabel=\u8BBF\u95EE\u5BC6\u7801
articleViewPwd1Label=\u8BBF\u95EE\u5BC6\u7801\uFF1A
####
forbiddenLabel=\u64CD\u4F5C\u88AB\u7981\u6B62\uFF01
sorryLabel=\u5BF9\u4E0D\u8D77\uFF01
notFoundLabel=\u627E\u4E0D\u5230\uFF01
unPulbishSuccLabel=\u53D6\u6D88\u53D1\u5E03\u6210\u529F
unPulbishFailLabel=\u53D6\u6D88\u53D1\u5E03\u5931\u8D25
......@@ -355,7 +350,6 @@ updatePreferenceFailNeedMulUsersLabel=\u66F4\u65B0\u5931\u8D25\uFF0C\u9700\u8981
setFailLabel=\u8BBE\u7F6E\u5931\u8D25
setSuccLabel=\u8BBE\u7F6E\u6210\u529F
getFailLabel=\u83B7\u53D6\u5931\u8D25
noSettingLabel=\u8BE5\u535A\u5BA2\u65E0\u8D26\u53F7\uFF0C\u8BF7\u6DFB\u52A0
getSuccLabel=\u83B7\u53D6\u6210\u529F
importSuccLabel=\u5BFC\u5165\u6210\u529F :-)
importFailLabel=\u90E8\u5206\u5BFC\u5165\u5931\u8D25 %>_<%
......@@ -364,16 +358,10 @@ captchaErrorLabel=\u9A8C\u8BC1\u7801\u9519\u8BEF
inputErrorLabel=\u8F93\u5165\u9519\u8BEF\uFF01
gotoLabel=\u8DF3\u8F6C
nameEmptyLabel=\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A\uFF01
passwordEmptyLabel=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF01
passwordNotMatchLabel=\u5BC6\u7801\u4E0D\u5339\u914D\uFF01
userPasswordConfirm1Label=\u518D\u6B21\u8F93\u5165\u5BC6\u7801\uFF1A
blogEmptyLabel=\u8BF7\u9009\u62E9\u535A\u5BA2\u670D\u52A1\uFF01
blogArticleEmptyLabel=\u8BF7\u9009\u62E9\u9700\u8981\u5BFC\u5165\u7684\u6587\u7AE0
notAllowCommentLabel=\u4E0D\u5141\u8BB8\u8BC4\u8BBA\uFF01
nameTooLongLabel=\u59D3\u540D\u53EA\u80FD\u4E3A 2 \u5230 20 \u4E2A\u5B57\u7B26\uFF01
categoryTooLongLabel=\u5206\u7C7B\u540D\u79F0\u53EA\u80FD\u4E3A 2 \u5230 32 \u4E2A\u5B57\u7B26\uFF01
mailCannotEmptyLabel=\u90AE\u7BB1\u4E0D\u80FD\u4E3A\u7A7A\uFF01
mailInvalidLabel=\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E\uFF01
urlInvalidLabel=\u94FE\u63A5\u683C\u5F0F\u4E0D\u6B63\u786E\uFF01
nonNegativeIntegerOnlyLabel=\u53EA\u80FD\u4E3A\u975E\u8D1F\u6574\u6570\uFF01
commentContentCannotEmptyLabel=\u8BC4\u8BBA\u5185\u5BB9\u53EA\u80FD\u4E3A 2 \u5230 500 \u4E2A\u5B57\u7B26\uFF01
......@@ -389,7 +377,6 @@ noAuthorizationURLLabel=\u4ECE Google \u83B7\u53D6\u6388\u6743\u5730\u5740\u5931
<em>Consumer Secret</em> \u662F\u6B63\u786E\u7684\uFF0C\u7136\u540E\u8FDB\u884C\u91CD\u8BD5\u3002
duplicatedPermalinkLabel=\u94FE\u63A5\u91CD\u590D\uFF01
invalidPermalinkFormatLabel=\u975E\u6CD5\u7684\u94FE\u63A5\u683C\u5F0F\uFF01
duplicatedEmailLabel=\u90AE\u4EF6\u5730\u5740\u91CD\u590D\uFF01
duplicatedUserNameLabel=\u7528\u6237\u540D\u91CD\u590D\uFF01
refreshAndRetryLabel=\u8BF7\u5237\u65B0\u91CD\u8BD5\uFF01
editorLeaveLabel=\u7F16\u8F91\u5668\u4E2D\u8FD8\u6709\u5185\u5BB9\uFF0C\u662F\u5426\u79BB\u5F00\uFF1F
......@@ -402,10 +389,6 @@ confirmRemoveLabel=\u662F\u5426\u5220\u9664
confirmInitLabel=\u786E\u5B9A\u8FDB\u884C\u521D\u59CB\u5316\u5417\uFF1F
###### Common ######
mobileLabel=\u79FB\u52A8\u7248
# Send an email to the user who upgrades Solo with a discontinuous version #
skipVersionMailSubject=[\u65E0\u9700\u56DE\u590D]\u8DE8\u7248\u672C\u5347\u7EA7 Solo \u63D0\u9192
skipVersionMailBody=Hey, \u60A8\u597D\uFF01<p>\u975E\u5E38\u9AD8\u5174\u60A8\u51C6\u5907\u5347\u7EA7 Solo\uFF0C\u4E0D\u8FC7\u76EE\u524D\u8FD8\u4E0D\u652F\u6301\u8DE8\u7248\u672C\u5347\u7EA7\uFF0C\u8BF7\u6309\u7167\u5386\u53F2\u7248\u672C\u4F9D\u6B21\u8FDB\u884C\u5347\u7EA7\u3002</p>\
<p>\u5BF9\u6B64\u7ED9\u60A8\u5E26\u6765\u7684\u4E0D\u4FBF\u6211\u4EEC\u6DF1\u8868\u6B49\u610F\uFF0C\u8C22\u8C22\u60A8\u5BF9 <a href="https://b3log.org" target="_blank">B3log</a> \u7684\u652F\u6301\u3002</p>
helloWorld.title=\u4E16\u754C\uFF0C\u4F60\u597D\uFF01
helloWorld.content=Solo \u535A\u5BA2\u7CFB\u7EDF\u5DF2\u7ECF\u521D\u59CB\u5316\u5B8C\u6BD5\uFF0C\u53EF\u5728\u7BA1\u7406\u540E\u53F0 - \u5DE5\u5177 - \u504F\u597D\u8BBE\u5B9A\u4E2D\u8C03\u6574\u66F4\u591A\u7EC6\u8282\u8BBE\u7F6E\u3002\u5982\u679C\u9700\u8981\u5BFC\u5165\u5DF2\u6709\u535A\u5BA2\u6587\u7AE0\uFF0C\u8BF7\u53C2\u8003\u6587\u6863 [Hexo/Jekyll/Markdown \u6587\u4EF6\u5BFC\u5165](https://hacpai.com/article/1498490209748)\u3002\n\n\
\u53E6\u5916\uFF0C\u51FA\u4E8E\u5B89\u5168\u8003\u8651\u8BF7\u5C3D\u5FEB\u5B8C\u6210\u5982\u4E0B\u64CD\u4F5C\uFF1A\n\n\
......
......@@ -18,7 +18,7 @@
#
# Description: Solo local environment configurations.
# Version: 1.1.3.13, Feb 4, 2019
# Version: 1.1.3.14, Mar 3, 2019
# Author: Liang Ding
#
......@@ -40,8 +40,5 @@ jdbc.URL=jdbc:h2:~/solo_h2/db
jdbc.minConnCnt=5
jdbc.maxConnCnt=10
# Be care to change the transaction isolation
jdbc.transactionIsolation=REPEATABLE_READ
# The specific table name prefix
jdbc.tablePrefix=b3_solo
#
# Solo - A small and beautiful blogging system written in Java.
# Copyright (c) 2010-2019, b3log.org & hacpai.com
#
# 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 <https://www.gnu.org/licenses/>.
#
#
# Description: Solo mail configurations.
# Version: 1.0.0.6, Jan 18, 2019
# Author: Liang Ding
#
mail.user=
mail.password=
mail.debug=false
mail.smtp.host=smtp.qq.com
mail.smtp.port=465
mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
mail.smtp.socketFactory.fallback=false
mail.smtp.socketFactory.port=465
mail.smtp.auth=true
mail.smtp.starttls.enable=true
\ No newline at end of file
......@@ -132,12 +132,6 @@
"description": "评论时间戳",
"type": "long"
},
{
"name": "commentEmail",
"description": "评论人邮箱",
"type": "String",
"length": 255
},
{
"name": "commentName",
"description": "评论人名称",
......@@ -383,12 +377,6 @@
"type": "String",
"length": 19
},
{
"name": "userEmail",
"description": "用户邮箱",
"type": "String",
"length": 255
},
{
"name": "userName",
"description": "用户名",
......
......@@ -79,21 +79,13 @@
"statusLabel": "${statusLabel}",
"versionLabel": "${versionLabel}",
"userNameLabel": "${userNameLabel}",
"commentEmailLabel": "${commentEmailLabel}",
"roleLabel": "${roleLabel}",
"administratorLabel": "${administratorLabel}",
"duplicatedEmailLabel": "${duplicatedEmailLabel}",
"mailInvalidLabel": "${mailInvalidLabel}",
"mailCannotEmptyLabel": "${mailCannotEmptyLabel}",
"noSettingLabel": "${noSettingLabel}",
"blogEmptyLabel": "${blogEmptyLabel}",
"sumLabel": "${sumLabel}",
"countLabel": "${countLabel}",
"blogArticleEmptyLabel": "${blogArticleEmptyLabel}",
"importSuccLabel": "${importSuccLabel}",
"categoryLabel": "${categoryLabel}",
"importedLabel": "${importedLabel}",
"passwordEmptyLabel": "${passwordEmptyLabel}",
"tagsEmptyLabel": "${tagsEmptyLabel}",
"abstractEmptyLabel": "${abstractEmptyLabel}",
"commonUserLabel": "${commonUserLabel}",
......
......@@ -19,11 +19,6 @@
-->
<div id="tabOthers" class="sub-tabs">
<ul>
<li>
<div id="tabOthers_email">
<a class="tab-current" href="#tools/others/email">${replayEmailTemplateLabel}</a>
</div>
</li>
<li>
<div id="tabOthers_tag">
<a href="#tools/others/tag">${clearTagLabel}</a>
......@@ -37,17 +32,6 @@
</ul>
</div>
<div id="tabOthersPanel" class="sub-tabs-main">
<div id="tabOthersPanel_email" class="form form__no-table">
<label for="replayEmailTemplateTitle">${emailSubject1Label}</label>
<input id="replayEmailTemplateTitle" type="text"/>
<label for="replayEmailTemplateBody">${emailContent1Label}</label>
<textarea rows="9" id="replayEmailTemplateBody"></textarea><br><br>
<button onclick="admin.others.update()" class="fn__right">${updateLabel}</button>
<div class="fn__clear"></div>
<div class="content-reset">
${replayEmailExplanationLabel}
</div>
</div>
<div id="tabOthersPanel_tag" class="fn__none">
<button class="fn__margin12" onclick="admin.others.removeUnusedTags();">${removeUnusedTagsLabel}</button>
</div>
......
......@@ -26,8 +26,6 @@
<div id="userUpdate" class="fn__none form form__no-table">
<label for="userNameUpdate">${userName1Label}</label>
<input id="userNameUpdate" type="text"/>
<label for="userEmailUpdate">${commentEmailLabel}</label>
<input id="userEmailUpdate" type="text"/>
<label for="userURLUpdate">${userURL1Label}</label>
<input id="userURLUpdate" type="text"/>
<label for="userAvatarUpdate">${userAvatar1Label}</label>
......
This diff is collapsed.
......@@ -79,8 +79,7 @@ admin.comment = {
commentsHTML += "@" + comments[i].commentOriginalCommentName;
}
commentsHTML += "</span><span title='" + Label.removeLabel + "' class='fn__right deleteIcon' onclick=\"admin.comment.del('"
+ comments[i].oId + "', '" + fromId + "', '" + onId + "')\"></span><span class='fn__right'><a href='mailto:"
+ comments[i].commentEmail + "'>" + comments[i].commentEmail + "</a>&nbsp;&nbsp;"
+ comments[i].oId + "', '" + fromId + "', '" + onId + "')\"></span><span class='fn__right'>&nbsp;&nbsp;"
+ $.bowknot.getDate(comments[i].commentTime)
+ "&nbsp;</span><div class='fn__clear'></div></div><div class='fn__margin12'>"
+ contentHTML + "</div>";
......
......@@ -101,8 +101,7 @@ admin.commentList = {
"' target='_blank' class='no-underline'>" + comments[i].commentName +
"</a>";
}
commentsData[i].title += "<br/><a href='mailto:" + comments[i].commentEmail +
"'>" + comments[i].commentEmail + "</a>";
commentsData[i].title += "<br/>";
commentsData[i].date = $.bowknot.getDate(comments[i].commentTime);
}
......
......@@ -23,31 +23,13 @@
* @version 1.3.0.0, Nov 11, 2017
*/
/* oterhs 相关操作 */
/* others 相关操作 */
admin.others = {
/*
* @description 初始化
*/
init: function () {
$("#tabOthers").tabs();
$.ajax({
url: latkeConfig.servePath + "/console/reply/notification/template",
type: "GET",
cache: false,
success: function (result, textStatus) {
$("#tipMsg").text(result.msg);
if (!result.sc) {
$("#loadMsg").text("");
return;
}
$("#replayEmailTemplateTitle").val(result.replyNotificationTemplate.subject);
$("#replayEmailTemplateBody").val(result.replyNotificationTemplate.body);
$("#loadMsg").text("");
}
});
},
/*
* @description 移除未使用的标签
......@@ -149,31 +131,6 @@ admin.others = {
}
}
});
},
/*
* @description 跟新回复提醒邮件模版
*/
update: function () {
$("#loadMsg").text(Label.loadingLabel);
$("#tipMsg").text("");
var requestJSONObject = {
"replyNotificationTemplate": {
"subject": $("#replayEmailTemplateTitle").val(),
"body": $("#replayEmailTemplateBody").val()
}
};
$.ajax({
url: latkeConfig.servePath + "/console/reply/notification/template",
type: "PUT",
cache: false,
data: JSON.stringify(requestJSONObject),
success: function (result, textStatus) {
$("#tipMsg").text(result.msg);
$("#loadMsg").text("");
}
});
}
};
......
......@@ -20,7 +20,7 @@
*
* @author <a href="http://vanessa.b3log.org">Liyuan Li</a>
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.1.2.5, Feb 10, 2019
* @version 1.1.2.6, Mar 3, 2019
*/
/* user-list 相关操作 */
......@@ -45,11 +45,6 @@ admin.userList = {
text: Label.userNameLabel,
index: 'userName',
width: 230,
}, {
style: 'padding-left: 12px;',
text: Label.commentEmailLabel,
index: 'userEmail',
minWidth: 180,
}, {
style: 'padding-left: 12px;',
text: Label.roleLabel,
......@@ -79,7 +74,7 @@ admin.userList = {
$.ajax({
url: latkeConfig.servePath + '/console/users/' + pageNum + '/' +
Label.PAGE_SIZE + '/' + Label.WINDOW_SIZE,
Label.PAGE_SIZE + '/' + Label.WINDOW_SIZE,
type: 'GET',
cache: false,
success: function (result, textStatus) {
......@@ -103,7 +98,6 @@ admin.userList = {
for (var i = 0; i < users.length; i++) {
userData[i] = {}
userData[i].userName = users[i].userName
userData[i].userEmail = users[i].userEmail
if ('adminRole' === users[i].userRole) {
userData[i].isAdmin = '&nbsp;' + Label.administratorLabel
......@@ -121,8 +115,7 @@ admin.userList = {
users[i].oId + '\')">' + Label.changeRoleLabel + '</a>'
if ('defaultRole' === users[i].userRole) {
userData[i].isAdmin = Label.commonUserLabel
}
else {
} else {
userData[i].isAdmin = Label.visitorUserLabel
}
}
......@@ -155,12 +148,6 @@ admin.userList = {
return
}
var $userEmailUpdate = $('#userEmailUpdate')
$('#userNameUpdate').val(result.user.userName).data('userInfo', {
'oId': id,
'userRole': userRole,
})
$userEmailUpdate.val(result.user.userEmail)
$('#userURLUpdate').val(result.user.userURL)
$('#userAvatarUpdate').val(result.user.userAvatar)
$('#userB3KeyUpdate').val(result.user.userB3Key)
......@@ -181,7 +168,6 @@ admin.userList = {
var requestJSONObject = {
'userName': $('#userNameUpdate').val(),
'oId': userInfo.oId,
'userEmail': $('#userEmailUpdate').val(),
'userURL': $('#userURLUpdate').val(),
'userRole': userInfo.userRole,
'userAvatar': $('#userAvatarUpdate').val(),
......@@ -297,16 +283,10 @@ admin.userList = {
if (2 > userName.length || userName.length > 20) {
$('#tipMsg').text(Label.nameTooLongLabel)
$('#userName' + status).focus()
} else if ($('#userEmail' + status).val().replace(/\s/g, '') === '') {
$('#tipMsg').text(Label.mailCannotEmptyLabel)
$('#userEmail' + status).focus()
} else if (!/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(
$('#userEmail' + status).val())) {
$('#tipMsg').text(Label.mailInvalidLabel)
$('#userEmail' + status).focus()
} else {
return true
}
return false
},
}
......
Subproject commit e4e32efbc543f0133131addf383b9cc573d9ec56
Subproject commit 3991aa69213dc450b1ea2c0c36601367de7cb68b
......@@ -122,12 +122,11 @@ public abstract class AbstractTestCase {
public void init() throws Exception {
final InitService initService = getInitService();
final JSONObject requestJSONObject = new JSONObject();
requestJSONObject.put(User.USER_EMAIL, "test@gmail.com");
requestJSONObject.put(User.USER_NAME, "Solo");
requestJSONObject.put(UserExt.USER_B3_KEY, "pass");
initService.init(requestJSONObject);
final UserQueryService userQueryService = getUserQueryService();
Assert.assertNotNull(userQueryService.getUserByEmailOrUserName("test@gmail.com"));
Assert.assertNotNull(userQueryService.getUserByName("Solo"));
}
/**
......
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.mail;
import org.b3log.latke.Latkes;
import org.b3log.solo.mail.MailService.Message;
import org.testng.annotations.Test;
/**
* {@link MailService} test case.
*
* @author <a href="https://hacpai.com/member/jiangzezhou">zezhou jiang</a>
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.4, Dec 2, 2018
*/
public final class MailServiceTestCase {
static {
Latkes.init();
}
/**
* Tests mail sending.
*
* @throws Exception exception
*/
//@Test
public void testSendMail() throws Exception {
System.out.println("testSendMail");
final MailService mailService = MailServiceFactory.getMailService();
final Message message = new Message();
message.setFrom("b3log.solo@gmail.com");
message.setSubject("Latke Mail Service[local] Test");
message.setHtmlBody("<htmL><body>测试</body><html>");
message.addRecipient("d@b3log.org");
mailService.send(message);
Thread.sleep(10000); // Waiting for sending....
}
}
\ No newline at end of file
......@@ -49,51 +49,6 @@ public class PreferenceConsoleTestCase extends AbstractTestCase {
super.init();
}
/**
* getReplyNotificationTemplate.
*
* @throws Exception exception
*/
@Test(dependsOnMethods = "init")
public void getReplyNotificationTemplate() throws Exception {
final MockHttpServletRequest request = mockRequest();
request.setRequestURI("/console/reply/notification/template");
mockAdminLogin(request);
final MockHttpServletResponse response = mockResponse();
mockDispatcherServletService(request, response);
final String content = response.body();
Assert.assertTrue(StringUtils.contains(content, "sc\":true"));
}
/**
* updateReplyNotificationTemplate.
*
* @throws Exception exception
*/
@Test(dependsOnMethods = "getReplyNotificationTemplate")
public void updateReplyNotificationTemplate() throws Exception {
final JSONObject p = getPreferenceQueryService().getReplyNotificationTemplate();
final MockHttpServletRequest request = mockRequest();
request.setRequestURI("/console/reply/notification/template");
request.setMethod("PUT");
final JSONObject requestJSON = new JSONObject();
requestJSON.put("replyNotificationTemplate", p);
final BufferedReader reader = new BufferedReader(new StringReader(requestJSON.toString()));
request.setReader(reader);
mockAdminLogin(request);
final MockHttpServletResponse response = mockResponse();
mockDispatcherServletService(request, response);
final String content = response.body();
Assert.assertTrue(StringUtils.contains(content, "sc\":true"));
}
/**
* getSigns.
*
......
......@@ -49,7 +49,6 @@ public class CommentRepositoryImplTestCase extends AbstractTestCase {
comment.put(Comment.COMMENT_CONTENT, "comment1 content");
comment.put(Comment.COMMENT_CREATED, new Date().getTime());
comment.put(Comment.COMMENT_EMAIL, "test@gmail.com");
comment.put(Comment.COMMENT_NAME, "comment1 name");
comment.put(Comment.COMMENT_ON_ID, "comment1 on id");
comment.put(Comment.COMMENT_ON_TYPE, "comment1 on type");
......
......@@ -51,7 +51,6 @@ public final class UserRepositoryImplTestCase extends AbstractTestCase {
final JSONObject another = new JSONObject();
another.put(User.USER_NAME, "test1");
another.put(User.USER_EMAIL, "test1@gmail.com");
another.put(User.USER_URL, "https://b3log.org");
another.put(User.USER_ROLE, Role.DEFAULT_ROLE);
another.put(UserExt.USER_AVATAR, "");
......@@ -66,7 +65,6 @@ public final class UserRepositoryImplTestCase extends AbstractTestCase {
JSONObject admin = new JSONObject();
admin.put(User.USER_NAME, "test");
admin.put(User.USER_EMAIL, "test@gmail.com");
admin.put(User.USER_URL, "https://b3log.org");
admin.put(User.USER_ROLE, Role.ADMIN_ROLE);
admin.put(UserExt.USER_AVATAR, "");
......@@ -87,13 +85,13 @@ public final class UserRepositoryImplTestCase extends AbstractTestCase {
final JSONArray users = result.getJSONArray(Keys.RESULTS);
Assert.assertEquals(users.length(), 1);
Assert.assertEquals(users.getJSONObject(0).getString(User.USER_EMAIL), "test1@gmail.com");
Assert.assertEquals(users.getJSONObject(0).getString(User.USER_NAME), "test1");
final JSONObject notFound = userRepository.getByEmail("not.found@gmail.com");
final JSONObject notFound = userRepository.getByUserName("not.found");
Assert.assertNull(notFound);
final JSONObject found = userRepository.getByEmail("test1@gmail.com");
final JSONObject found = userRepository.getByUserName("test1");
Assert.assertNotNull(found);
Assert.assertEquals(found.getString(User.USER_EMAIL), "test1@gmail.com");
Assert.assertEquals(found.getString(User.USER_NAME), "test1");
}
}
......@@ -74,8 +74,7 @@ public class CommentMgmtServiceTestCase extends AbstractTestCase {
final String articleId = articles.get(0).getString(Keys.OBJECT_ID);
requestJSONObject.put(Keys.OBJECT_ID, articleId);
requestJSONObject.put(Comment.COMMENT_NAME, "comment name");
requestJSONObject.put(Comment.COMMENT_EMAIL, "comment email");
requestJSONObject.put(Comment.COMMENT_NAME, "Solo");
requestJSONObject.put(Comment.COMMENT_URL, "comment URL");
requestJSONObject.put(Comment.COMMENT_CONTENT, "comment content");
......@@ -123,8 +122,7 @@ public class CommentMgmtServiceTestCase extends AbstractTestCase {
final String pageId = pages.getJSONObject(0).getString(Keys.OBJECT_ID);
requestJSONObject.put(Keys.OBJECT_ID, pageId);
requestJSONObject.put(Comment.COMMENT_NAME, "comment name");
requestJSONObject.put(Comment.COMMENT_EMAIL, "comment email");
requestJSONObject.put(Comment.COMMENT_NAME, "Solo");
requestJSONObject.put(Comment.COMMENT_URL, "comment URL");
requestJSONObject.put(Comment.COMMENT_CONTENT, "comment content");
......
......@@ -61,24 +61,4 @@ public class PreferenceMgmtServiceTestCase extends AbstractTestCase {
preference = preferenceQueryService.getPreference();
Assert.assertEquals(preference.getString(Option.ID_C_BLOG_TITLE), "updated blog title");
}
/**
* Update Reply Notification Template.
*
* @throws Exception exception
*/
@Test(dependsOnMethods = "init")
public void updateReplyNotificationTemplate() throws Exception {
final PreferenceMgmtService preferenceMgmtService = getPreferenceMgmtService();
final PreferenceQueryService preferenceQueryService = getPreferenceQueryService();
JSONObject replyNotificationTemplate = preferenceQueryService.getReplyNotificationTemplate();
Assert.assertEquals(replyNotificationTemplate.toString(), Option.DefaultPreference.DEFAULT_REPLY_NOTIFICATION_TEMPLATE);
replyNotificationTemplate.put("subject", "updated subject");
preferenceMgmtService.updateReplyNotificationTemplate(replyNotificationTemplate);
replyNotificationTemplate = preferenceQueryService.getReplyNotificationTemplate();
Assert.assertEquals(replyNotificationTemplate.getString("subject"), "updated subject");
}
}
......@@ -54,17 +54,4 @@ public class PreferenceQueryServiceTestCase extends AbstractTestCase {
Assert.assertEquals(preference.getString(Option.ID_C_BLOG_TITLE), "Solo 的个人博客");
}
/**
* Get Reply Notification Template.
*
* @throws Exception exception
*/
@Test(dependsOnMethods = "init")
public void getReplyNotificationTemplate() throws Exception {
final PreferenceQueryService preferenceQueryService = getPreferenceQueryService();
final JSONObject replyNotificationTemplate = preferenceQueryService.getReplyNotificationTemplate();
Assert.assertEquals(replyNotificationTemplate.toString(), Option.DefaultPreference.DEFAULT_REPLY_NOTIFICATION_TEMPLATE);
}
}
......@@ -48,7 +48,6 @@ public class UserMgmtServiceTestCase extends AbstractTestCase {
final JSONObject requestJSONObject = new JSONObject();
requestJSONObject.put(User.USER_NAME, "user1name");
requestJSONObject.put(User.USER_EMAIL, "test1@gmail.com");
final String id = userMgmtService.addUser(requestJSONObject);
Assert.assertNotNull(id);
......@@ -65,7 +64,6 @@ public class UserMgmtServiceTestCase extends AbstractTestCase {
JSONObject requestJSONObject = new JSONObject();
requestJSONObject.put(User.USER_NAME, "user2name");
requestJSONObject.put(User.USER_EMAIL, "test2@gmail.com");
requestJSONObject.put(User.USER_ROLE, Role.ADMIN_ROLE);
final String id = userMgmtService.addUser(requestJSONObject);
......@@ -91,7 +89,6 @@ public class UserMgmtServiceTestCase extends AbstractTestCase {
final JSONObject requestJSONObject = new JSONObject();
requestJSONObject.put(User.USER_NAME, "user1 name");
requestJSONObject.put(User.USER_EMAIL, "test1@gmail.com");
try {
final String id = userMgmtService.addUser(requestJSONObject);
......@@ -110,8 +107,7 @@ public class UserMgmtServiceTestCase extends AbstractTestCase {
final UserMgmtService userMgmtService = getUserMgmtService();
final JSONObject requestJSONObject = new JSONObject();
requestJSONObject.put(User.USER_NAME, "username");
requestJSONObject.put(User.USER_EMAIL, "<script></script>");
requestJSONObject.put(User.USER_NAME, "<script></script>");
final String id = userMgmtService.addUser(requestJSONObject);
}
......@@ -125,11 +121,11 @@ public class UserMgmtServiceTestCase extends AbstractTestCase {
public void removeUser() throws Exception {
final UserMgmtService userMgmtService = getUserMgmtService();
final JSONObject user = getUserQueryService().getUserByEmailOrUserName("test1@gmail.com");
final JSONObject user = getUserQueryService().getUserByName("user1name");
Assert.assertNotNull(user);
userMgmtService.removeUser(user.getString(Keys.OBJECT_ID));
Assert.assertNull(getUserQueryService().getUserByEmailOrUserName("test1@gmail.com"));
Assert.assertNull(getUserQueryService().getUserByName("user1name"));
}
}
......@@ -47,7 +47,6 @@ public class UserQueryServiceTestCase extends AbstractTestCase {
final JSONObject requestJSONObject = new JSONObject();
requestJSONObject.put(User.USER_NAME, "user1name");
requestJSONObject.put(User.USER_EMAIL, "test1@gmail.com");
final String id = userMgmtService.addUser(requestJSONObject);
Assert.assertNotNull(id);
......@@ -58,25 +57,21 @@ public class UserQueryServiceTestCase extends AbstractTestCase {
/**
* Get User.
*
* @throws Exception exception
*/
@Test(dependsOnMethods = "addUser")
public void getUser() throws Exception {
public void getUser() {
final UserQueryService userQueryService = getUserQueryService();
Assert.assertNull(userQueryService.getUser("not found"));
}
/**
* Get User By Email.
*
* @throws Exception exception
* Get User By Name.
*/
@Test(dependsOnMethods = "addUser")
public void getUserByEmail() throws Exception {
public void getUserByName() {
final UserQueryService userQueryService = getUserQueryService();
final JSONObject user = userQueryService.getUserByEmailOrUserName("test1@gmail.com");
final JSONObject user = userQueryService.getUserByName("user1name");
Assert.assertNotNull(user);
}
......
/*
* Solo - A small and beautiful blogging system written in Java.
* Copyright (c) 2010-2019, b3log.org & hacpai.com
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.b3log.solo.util;
import org.b3log.latke.Latkes;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.Locale;
/**
* {@link org.b3log.solo.util.Solos} test case.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.1, Mar 11, 2018
* @since 0.6.1
*/
public final class SolosTestCase {
/**
* Test method for {@linkplain Solos#getGravatarURL(String, String)}.
*/
@Test
public void getGravatarURL() {
Latkes.init();
final String gravatarURL = Solos.getGravatarURL("test@b3log.org", "128");
Assert.assertEquals(gravatarURL, Solos.GRAVATAR + "bd7e4673cf7fa4b4777353008c86e093?s=128");
}
}
......@@ -17,16 +17,28 @@
#
#
# Description: Solo mail configurations.
# Version: 1.0.0.4, Jul 19, 2017
# Author: Liang Ding
# Description: Solo logging configurations for test.
# Version: 1.0.0.0, Mar 3, 2019
# Author: <a href="http://88250.b3log.org">Liang Ding</a>
#
mail.user={{EMAIL_ADDRESS}}
mail.password={{EMAIL_PASSWORD}}
mail.debug=false
mail.smtp.host={{SMTP_HOST}}
mail.smtp.port={{SMTP_PROT}}
mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
mail.smtp.socketFactory.fallback=false
mail.smtp.socketFactory.port={{SMTP_SOCKETFACTORY_PORT}}
log4j.rootLogger=INFO,stdout
log4j.logger.org.b3log.solo=INFO
log4j.logger.org.b3log.latke=WARN
log4j.logger.org.b3log.latke.util.freemarker.Templates=ERROR
log4j.logger.org.b3log.latke.repository.jdbc.util=WARN
log4j.logger.org.eclipse.jetty=WARN
log4j.logger.freemarker=WARN
log4j.logger.com.mchange=WARN
log4j.logger.com.alibaba=WARN
# Print only messages of level ERROR or above in the package noModule.
log4j.logger.noModule=ERROR
# Console appender
log4j.appender.stdout.Encoding=UTF-8
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%-5p]-[%d{yyyy-MM-dd HH:mm:ss}]-[%c:%L]: %m%n
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment