mirror of https://github.com/halo-dev/halo
Completed #208
parent
ec4932ef4a
commit
042e5af43d
|
@ -8,6 +8,7 @@ import run.halo.app.cache.lock.CacheLock;
|
||||||
import run.halo.app.model.dto.EnvironmentDTO;
|
import run.halo.app.model.dto.EnvironmentDTO;
|
||||||
import run.halo.app.model.dto.StatisticDTO;
|
import run.halo.app.model.dto.StatisticDTO;
|
||||||
import run.halo.app.model.params.LoginParam;
|
import run.halo.app.model.params.LoginParam;
|
||||||
|
import run.halo.app.model.params.ResetPasswordParam;
|
||||||
import run.halo.app.model.properties.PrimaryProperties;
|
import run.halo.app.model.properties.PrimaryProperties;
|
||||||
import run.halo.app.model.support.BaseResponse;
|
import run.halo.app.model.support.BaseResponse;
|
||||||
import run.halo.app.security.token.AuthToken;
|
import run.halo.app.security.token.AuthToken;
|
||||||
|
@ -57,6 +58,18 @@ public class AdminController {
|
||||||
adminService.clearToken();
|
adminService.clearToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("password/code")
|
||||||
|
@ApiOperation("Send reset password verify code.")
|
||||||
|
public void sendResetCode(@RequestBody @Valid ResetPasswordParam param) {
|
||||||
|
adminService.sendResetPasswordCode(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("password/reset")
|
||||||
|
@ApiOperation("Reset password by verify code.")
|
||||||
|
public void resetPassword(@RequestBody @Valid ResetPasswordParam param) {
|
||||||
|
adminService.resetPasswordByCode(param);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("refresh/{refreshToken}")
|
@PostMapping("refresh/{refreshToken}")
|
||||||
@ApiOperation("Refreshes token")
|
@ApiOperation("Refreshes token")
|
||||||
@CacheLock(autoDelete = false)
|
@CacheLock(autoDelete = false)
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class FreemarkerConfigAwareListener {
|
||||||
private void loadThemeConfig() throws TemplateModelException {
|
private void loadThemeConfig() throws TemplateModelException {
|
||||||
ThemeProperty activatedTheme = themeService.getActivatedTheme();
|
ThemeProperty activatedTheme = themeService.getActivatedTheme();
|
||||||
configuration.setSharedVariable("theme", activatedTheme);
|
configuration.setSharedVariable("theme", activatedTheme);
|
||||||
String baseUrl = optionService.getByProperty(OtherProperties.CDN_DOMAIN).orElse(optionService.getBlogBaseUrl()).toString();
|
String baseUrl = optionService.getByPropertyOrDefault(OtherProperties.CDN_DOMAIN, String.class, optionService.getBlogBaseUrl());
|
||||||
configuration.setSharedVariable("static", baseUrl + "/" + activatedTheme.getFolderName());
|
configuration.setSharedVariable("static", baseUrl + "/" + activatedTheme.getFolderName());
|
||||||
configuration.setSharedVariable("settings", themeSettingService.listAsMapBy(themeService.getActivatedThemeId()));
|
configuration.setSharedVariable("settings", themeSettingService.listAsMapBy(themeService.getActivatedThemeId()));
|
||||||
log.debug("Loaded theme and settings");
|
log.debug("Loaded theme and settings");
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package run.halo.app.model.params;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset password params.
|
||||||
|
*
|
||||||
|
* @author ryanwang
|
||||||
|
* @date 2019-09-05
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ResetPasswordParam {
|
||||||
|
|
||||||
|
@NotBlank(message = "用户名不能为空")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@NotBlank(message = "邮箱不能为空")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import org.springframework.lang.NonNull;
|
||||||
import run.halo.app.model.dto.EnvironmentDTO;
|
import run.halo.app.model.dto.EnvironmentDTO;
|
||||||
import run.halo.app.model.dto.StatisticDTO;
|
import run.halo.app.model.dto.StatisticDTO;
|
||||||
import run.halo.app.model.params.LoginParam;
|
import run.halo.app.model.params.LoginParam;
|
||||||
|
import run.halo.app.model.params.ResetPasswordParam;
|
||||||
import run.halo.app.security.token.AuthToken;
|
import run.halo.app.security.token.AuthToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,6 +43,20 @@ public interface AdminService {
|
||||||
*/
|
*/
|
||||||
void clearToken();
|
void clearToken();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send reset password code to administrator's email.
|
||||||
|
*
|
||||||
|
* @param param param must not be null
|
||||||
|
*/
|
||||||
|
void sendResetPasswordCode(@NonNull ResetPasswordParam param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset password by code.
|
||||||
|
*
|
||||||
|
* @param param param must not be null
|
||||||
|
*/
|
||||||
|
void resetPasswordByCode(@NonNull ResetPasswordParam param);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get system counts.
|
* Get system counts.
|
||||||
*
|
*
|
||||||
|
@ -74,6 +89,7 @@ public interface AdminService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get spring logs.
|
* Get spring logs.
|
||||||
|
*
|
||||||
* @return recently logs.
|
* @return recently logs.
|
||||||
*/
|
*/
|
||||||
String getSpringLogs();
|
String getSpringLogs();
|
||||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Optional;
|
||||||
* User service interface.
|
* User service interface.
|
||||||
*
|
*
|
||||||
* @author johnniang
|
* @author johnniang
|
||||||
|
* @author ryanwang
|
||||||
* @date 2019-03-14
|
* @date 2019-03-14
|
||||||
*/
|
*/
|
||||||
public interface UserService extends CrudService<User, Integer> {
|
public interface UserService extends CrudService<User, Integer> {
|
||||||
|
@ -125,9 +126,11 @@ public interface UserService extends CrudService<User, Integer> {
|
||||||
void setPassword(@NonNull User user, @NonNull String plainPassword);
|
void setPassword(@NonNull User user, @NonNull String plainPassword);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set user default avatar,use Gravatar(http://cn.gravatar.com)
|
* verify user's email and username
|
||||||
*
|
*
|
||||||
* @param user user must not be null
|
* @param username username must not be null
|
||||||
|
* @param password password must not be null
|
||||||
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
void setDefaultAvatar(@NonNull User user);
|
boolean verifyUser(@NonNull String username, @NonNull String password);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ package run.halo.app.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.io.file.FileReader;
|
import cn.hutool.core.io.file.FileReader;
|
||||||
import cn.hutool.core.lang.Validator;
|
import cn.hutool.core.lang.Validator;
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
@ -24,6 +26,8 @@ import run.halo.app.model.enums.LogType;
|
||||||
import run.halo.app.model.enums.Mode;
|
import run.halo.app.model.enums.Mode;
|
||||||
import run.halo.app.model.enums.PostStatus;
|
import run.halo.app.model.enums.PostStatus;
|
||||||
import run.halo.app.model.params.LoginParam;
|
import run.halo.app.model.params.LoginParam;
|
||||||
|
import run.halo.app.model.params.ResetPasswordParam;
|
||||||
|
import run.halo.app.model.properties.EmailProperties;
|
||||||
import run.halo.app.model.support.HaloConst;
|
import run.halo.app.model.support.HaloConst;
|
||||||
import run.halo.app.security.authentication.Authentication;
|
import run.halo.app.security.authentication.Authentication;
|
||||||
import run.halo.app.security.context.SecurityContextHolder;
|
import run.halo.app.security.context.SecurityContextHolder;
|
||||||
|
@ -36,7 +40,6 @@ import run.halo.app.utils.HaloUtils;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.management.RuntimeMXBean;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -75,6 +78,8 @@ public class AdminServiceImpl implements AdminService {
|
||||||
|
|
||||||
private final LinkService linkService;
|
private final LinkService linkService;
|
||||||
|
|
||||||
|
private final MailService mailService;
|
||||||
|
|
||||||
private final StringCacheStore cacheStore;
|
private final StringCacheStore cacheStore;
|
||||||
|
|
||||||
private final RestTemplate restTemplate;
|
private final RestTemplate restTemplate;
|
||||||
|
@ -96,6 +101,7 @@ public class AdminServiceImpl implements AdminService {
|
||||||
OptionService optionService,
|
OptionService optionService,
|
||||||
UserService userService,
|
UserService userService,
|
||||||
LinkService linkService,
|
LinkService linkService,
|
||||||
|
MailService mailService,
|
||||||
StringCacheStore cacheStore,
|
StringCacheStore cacheStore,
|
||||||
RestTemplate restTemplate,
|
RestTemplate restTemplate,
|
||||||
HaloProperties haloProperties,
|
HaloProperties haloProperties,
|
||||||
|
@ -111,6 +117,7 @@ public class AdminServiceImpl implements AdminService {
|
||||||
this.optionService = optionService;
|
this.optionService = optionService;
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.linkService = linkService;
|
this.linkService = linkService;
|
||||||
|
this.mailService = mailService;
|
||||||
this.cacheStore = cacheStore;
|
this.cacheStore = cacheStore;
|
||||||
this.restTemplate = restTemplate;
|
this.restTemplate = restTemplate;
|
||||||
this.haloProperties = haloProperties;
|
this.haloProperties = haloProperties;
|
||||||
|
@ -191,6 +198,65 @@ public class AdminServiceImpl implements AdminService {
|
||||||
log.info("You have been logged out, looking forward to your next visit!");
|
log.info("You have been logged out, looking forward to your next visit!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResetPasswordCode(ResetPasswordParam param) {
|
||||||
|
cacheStore.getAny("code", String.class).ifPresent(code -> {
|
||||||
|
throw new ServiceException("已经获取过验证码,不能重复获取");
|
||||||
|
});
|
||||||
|
|
||||||
|
Boolean emailEnabled = optionService.getByPropertyOrDefault(EmailProperties.ENABLED, Boolean.class, false);
|
||||||
|
|
||||||
|
if (!emailEnabled) {
|
||||||
|
throw new ServiceException("未启用 SMTP 服务");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userService.verifyUser(param.getUsername(), param.getEmail())) {
|
||||||
|
throw new ServiceException("用户名或者邮箱验证错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets random code.
|
||||||
|
String code = RandomUtil.randomNumbers(6);
|
||||||
|
|
||||||
|
// Send email to administrator.
|
||||||
|
String content = "您正在进行密码重置操作,如不是本人操作,请尽快做好相应措施。密码重置验证码如下(五分钟有效):\n" + code;
|
||||||
|
mailService.sendMail(param.getEmail(), "找回密码验证码", content);
|
||||||
|
|
||||||
|
// Cache code.
|
||||||
|
cacheStore.putAny("code", code, 5, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetPasswordByCode(ResetPasswordParam param) {
|
||||||
|
if (StringUtils.isEmpty(param.getCode())) {
|
||||||
|
throw new ServiceException("验证码不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(param.getPassword())) {
|
||||||
|
throw new ServiceException("密码不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userService.verifyUser(param.getUsername(), param.getEmail())) {
|
||||||
|
throw new ServiceException("用户名或者邮箱验证错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify code
|
||||||
|
String code = cacheStore.getAny("code", String.class).orElseThrow(() -> new ServiceException("未获取过验证码"));
|
||||||
|
if (!code.equals(param.getCode())) {
|
||||||
|
throw new ServiceException("验证码不正确");
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = userService.getCurrentUser().orElseThrow(() -> new ServiceException("找不到博主信息"));
|
||||||
|
|
||||||
|
// reset password
|
||||||
|
userService.setPassword(user, param.getPassword());
|
||||||
|
|
||||||
|
// Update this user
|
||||||
|
userService.update(user);
|
||||||
|
|
||||||
|
// clear code cache
|
||||||
|
cacheStore.delete("code");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StatisticDTO getCount() {
|
public StatisticDTO getCount() {
|
||||||
StatisticDTO statisticDTO = new StatisticDTO();
|
StatisticDTO statisticDTO = new StatisticDTO();
|
||||||
|
@ -221,8 +287,7 @@ public class AdminServiceImpl implements AdminService {
|
||||||
EnvironmentDTO environmentDTO = new EnvironmentDTO();
|
EnvironmentDTO environmentDTO = new EnvironmentDTO();
|
||||||
|
|
||||||
// Get application start time.
|
// Get application start time.
|
||||||
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
|
environmentDTO.setStartTime(ManagementFactory.getRuntimeMXBean().getStartTime());
|
||||||
environmentDTO.setStartTime(runtimeMXBean.getStartTime());
|
|
||||||
|
|
||||||
environmentDTO.setDatabase("org.h2.Driver".equals(driverClassName) ? "H2" : "MySQL");
|
environmentDTO.setDatabase("org.h2.Driver".equals(driverClassName) ? "H2" : "MySQL");
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class MailServiceImpl implements MailService {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.debug("Email properties: to username: [{}], from username: [{}], subject: [{}], content: [{}]",
|
log.debug("Email properties: to username: [{}], from username: [{}], subject: [{}], content: [{}]",
|
||||||
to, fromUsername, subject, content);
|
to, fromUsername, subject, content);
|
||||||
throw new EmailException("Failed to send email to " + to, e);
|
throw new EmailException("发送邮件到 " + to + " 失败,请检查 SMTP 服务配置是否正确", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ public class MailServiceImpl implements MailService {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.debug("Email properties: to username: [{}], from username: [{}], subject: [{}], template name: [{}], content: [{}]",
|
log.debug("Email properties: to username: [{}], from username: [{}], subject: [{}], template name: [{}], content: [{}]",
|
||||||
to, fromUsername, subject, templateName, content);
|
to, fromUsername, subject, templateName, content);
|
||||||
throw new EmailException("Failed to send template email to " + to, e).setErrorData(templateName);
|
throw new EmailException("发送模板邮件到 " + to + " 失败,请检查 SMTP 服务配置是否正确", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ public class MailServiceImpl implements MailService {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.debug("Email properties: to username: [{}], from username: [{}], subject: [{}], template name: [{}], attachment: [{}], content: [{}]",
|
log.debug("Email properties: to username: [{}], from username: [{}], subject: [{}], template name: [{}], attachment: [{}], content: [{}]",
|
||||||
to, fromUsername, subject, templateName, attachFilename, content);
|
to, fromUsername, subject, templateName, attachFilename, content);
|
||||||
throw new EmailException("Failed to send attachment email to " + to, e);
|
throw new EmailException("发送附件邮件到 " + to + " 失败,请检查 SMTP 服务配置是否正确", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package run.halo.app.service.impl;
|
package run.halo.app.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.text.StrBuilder;
|
|
||||||
import cn.hutool.crypto.SecureUtil;
|
|
||||||
import cn.hutool.crypto.digest.BCrypt;
|
import cn.hutool.crypto.digest.BCrypt;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
@ -16,6 +14,7 @@ import run.halo.app.event.user.UserUpdatedEvent;
|
||||||
import run.halo.app.exception.BadRequestException;
|
import run.halo.app.exception.BadRequestException;
|
||||||
import run.halo.app.exception.ForbiddenException;
|
import run.halo.app.exception.ForbiddenException;
|
||||||
import run.halo.app.exception.NotFoundException;
|
import run.halo.app.exception.NotFoundException;
|
||||||
|
import run.halo.app.exception.ServiceException;
|
||||||
import run.halo.app.model.entity.User;
|
import run.halo.app.model.entity.User;
|
||||||
import run.halo.app.model.enums.LogType;
|
import run.halo.app.model.enums.LogType;
|
||||||
import run.halo.app.model.params.UserParam;
|
import run.halo.app.model.params.UserParam;
|
||||||
|
@ -184,11 +183,8 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDefaultAvatar(User user) {
|
public boolean verifyUser(String username, String password) {
|
||||||
Assert.notNull(user, "User must not be null");
|
User user = getCurrentUser().orElseThrow(() -> new ServiceException("找不到博主信息"));
|
||||||
StrBuilder gravatar = new StrBuilder("//cn.gravatar.com/avatar/");
|
return user.getUsername().equals(username) && user.getEmail().equals(password);
|
||||||
gravatar.append(SecureUtil.md5(user.getEmail()));
|
|
||||||
gravatar.append("?s=256&d=mm");
|
|
||||||
user.setAvatar(gravatar.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue