Complete password update api and refactor user create api

pull/137/head
johnniang 2019-03-26 11:08:04 +08:00
parent e8a9498ea4
commit 157689b0c2
11 changed files with 117 additions and 55 deletions

View File

@ -1,9 +1,10 @@
package cc.ryanc.halo.model.params;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
/**
* Install parameters.
@ -11,8 +12,9 @@ import javax.validation.constraints.NotBlank;
* @author johnniang
* @date 3/19/19
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class InstallParam {
public class InstallParam extends UserParam {
/**
* Blog locale.
@ -32,28 +34,10 @@ public class InstallParam {
@NotBlank(message = "Blog url must not be blank")
private String url;
/**
* Username.
*/
@NotBlank(message = "Username must not be blank")
private String username;
/**
* Nickname.
*/
@NotBlank(message = "Nickname must not be blank")
private String nickname;
/**
* Email.
*/
@NotBlank(message = "Email must not be blank")
@Email(message = "It is not an email format")
private String email;
/**
* Password.
*/
@NotBlank(message = "Password must not be blank")
@Size(max = 100, message = "Length of password must not be more than {max}")
private String password;
}

View File

@ -0,0 +1,25 @@
package cc.ryanc.halo.model.params;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
/**
* User password param.
*
* @author johnniang
* @date 3/26/19
*/
@Data
public class PasswordParam {
@NotBlank(message = "Old password must not be blank")
@Size(max = 100, message = "Length of password must not be more than {max}")
private String oldPassword;
@NotBlank(message = "New password must not be blank")
@Size(max = 100, message = "Length of password must not be more than {max}")
private String newPassword;
}

View File

@ -3,7 +3,7 @@ package cc.ryanc.halo.model.params;
import cc.ryanc.halo.model.dto.base.InputConverter;
import cc.ryanc.halo.model.entity.Tag;
import cc.ryanc.halo.utils.HaloUtils;
import cn.hutool.core.util.URLUtil;
import cc.ryanc.halo.utils.SlugUtils;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
@ -30,7 +30,7 @@ public class TagParam implements InputConverter<Tag> {
public Tag convertTo() {
if (StringUtils.isBlank(slugName)) {
// Handle slug name
slugName = URLUtil.normalize(name);
slugName = SlugUtils.slugify(name);
}
slugName = HaloUtils.initializeUrlIfBlank(slugName);

View File

@ -15,13 +15,6 @@ import java.util.List;
*/
public interface TagService extends CrudService<Tag, Integer> {
/**
* Remove tag and relationship
*
* @param id id
*/
void remove(Integer id);
/**
* Get tag by slug name
*

View File

@ -2,6 +2,7 @@ package cc.ryanc.halo.service;
import cc.ryanc.halo.exception.NotFoundException;
import cc.ryanc.halo.model.entity.User;
import cc.ryanc.halo.model.params.UserParam;
import cc.ryanc.halo.service.base.CrudService;
import org.springframework.lang.NonNull;
@ -73,4 +74,25 @@ public interface UserService extends CrudService<User, Integer> {
*/
@NonNull
User login(@NonNull String key, @NonNull String password);
/**
* Updates user password.
*
* @param oldPassword old password must not be blank
* @param newPassword new password must not be blank
* @param userId user id must not be null
* @return updated user detail
*/
@NonNull
User updatePassword(@NonNull String oldPassword, @NonNull String newPassword, @NonNull Integer userId);
/**
* Creates an user.
*
* @param userParam user param must not be null.
* @param password password must not be blank
* @return created user
*/
@NonNull
User createBy(@NonNull UserParam userParam, @NonNull String password);
}

View File

@ -192,7 +192,7 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer> impl
@Override
public int getPostPageSize() {
try {
return getByProperty(BlogProperties.INDEX_POSTS).map(Integer::valueOf).orElse(DEFAULT_POST_PAGE_SIZE);
return getByProperty(BlogProperties.INDEX_POSTS, Integer.class, DEFAULT_COMMENT_PAGE_SIZE);
} catch (NumberFormatException e) {
log.error(BlogProperties.INDEX_POSTS + " option is not a number format", e);
return DEFAULT_POST_PAGE_SIZE;
@ -202,7 +202,7 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer> impl
@Override
public int getCommentPageSize() {
try {
return getByProperty(BlogProperties.INDEX_COMMENTS).map(Integer::valueOf).orElse(DEFAULT_COMMENT_PAGE_SIZE);
return getByProperty(BlogProperties.INDEX_COMMENTS, Integer.class, DEFAULT_COMMENT_PAGE_SIZE);
} catch (NumberFormatException e) {
log.error(BlogProperties.INDEX_COMMENTS + " option is not a number format", e);
return DEFAULT_COMMENT_PAGE_SIZE;
@ -212,7 +212,7 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer> impl
@Override
public int getRssPageSize() {
try {
return getByProperty(BlogProperties.RSS_POSTS).map(Integer::valueOf).orElse(DEFAULT_RSS_PAGE_SIZE);
return getByProperty(BlogProperties.RSS_POSTS, Integer.class, DEFAULT_COMMENT_PAGE_SIZE);
} catch (NumberFormatException e) {
log.error(BlogProperties.RSS_POSTS + " setting is not a number format", e);
return DEFAULT_RSS_PAGE_SIZE;

View File

@ -32,16 +32,6 @@ public class TagServiceImpl extends AbstractCrudService<Tag, Integer> implements
this.tagRepository = tagRepository;
}
/**
* Remove tag and relationship
*
* @param id id
*/
@Override
public void remove(Integer id) {
// TODO 删除标签,以及对应的文章关系
}
@Override
public Tag create(Tag tag) {
// Check if the tag is exist
@ -73,6 +63,8 @@ public class TagServiceImpl extends AbstractCrudService<Tag, Integer> implements
public List<TagOutputDTO> convertTo(List<Tag> tags) {
return CollectionUtils.isEmpty(tags) ?
Collections.emptyList() :
tags.stream().map(tag -> (TagOutputDTO) new TagOutputDTO().convertFrom(tag)).collect(Collectors.toList());
tags.stream()
.map(tag -> (TagOutputDTO) new TagOutputDTO().convertFrom(tag))
.collect(Collectors.toList());
}
}

View File

@ -4,12 +4,14 @@ import cc.ryanc.halo.cache.StringCacheStore;
import cc.ryanc.halo.exception.BadRequestException;
import cc.ryanc.halo.exception.NotFoundException;
import cc.ryanc.halo.model.entity.User;
import cc.ryanc.halo.model.params.UserParam;
import cc.ryanc.halo.repository.UserRepository;
import cc.ryanc.halo.service.UserService;
import cc.ryanc.halo.service.base.AbstractCrudService;
import cc.ryanc.halo.utils.DateUtils;
import cn.hutool.core.lang.Validator;
import cn.hutool.crypto.digest.BCrypt;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
@ -87,7 +89,7 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
if (!BCrypt.checkpw(password, user.getPassword())) {
// If the password is mismatched
// Add login failure count
Integer loginFailureCount = stringCacheStore.get(LOGIN_FAILURE_COUNT_KEY).map(countString -> Integer.valueOf(countString)).orElse(0);
Integer loginFailureCount = stringCacheStore.get(LOGIN_FAILURE_COUNT_KEY).map(Integer::valueOf).orElse(0);
if (loginFailureCount >= MAX_LOGIN_TRY) {
// Set expiration
@ -103,9 +105,53 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
throw new BadRequestException("账号或者密码错误,您还有" + (MAX_LOGIN_TRY - loginFailureCount) + "次机会");
}
// TODO Set session
// TODO Set session or cache token
return user;
}
@Override
public User updatePassword(String oldPassword, String newPassword, Integer userId) {
Assert.hasText(oldPassword, "Old password must not be blank");
Assert.hasText(newPassword, "New password must not be blank");
Assert.notNull(userId, "User id must not be blank");
if (oldPassword.equals(newPassword)) {
throw new BadRequestException("There is nothing changed because new password is equal to old password");
}
// Get the user
User user = getById(userId);
// Check the user old password
if (!BCrypt.checkpw(oldPassword, user.getPassword())) {
throw new BadRequestException("Old password is mismatch").setErrorData(oldPassword);
}
// Set new password
setPassword(newPassword, user);
// Update this user
return update(user);
}
@Override
public User createBy(UserParam userParam, String password) {
Assert.notNull(userParam, "User param must not be null");
Assert.hasText(password, "Password must not be blank");
User user = userParam.convertTo();
setPassword(password, user);
return create(user);
}
private void setPassword(@NonNull String plainPassword, @NonNull User user) {
Assert.hasText(plainPassword, "Plain password must not be blank");
Assert.notNull(user, "User must not be null");
user.setPassword(BCrypt.hashpw(plainPassword, BCrypt.gensalt()));
}
}

View File

@ -89,7 +89,9 @@ public class TagController {
@DeleteMapping("{tagId:\\d+}")
@ApiOperation("Delete tag by id")
public void deletePermanently(@PathVariable("tagId") Integer tagId) {
// Remove the tag
tagService.removeById(tagId);
// Remove the post tag relationship
postTagService.removeByTagId(tagId);
}
}

View File

@ -2,6 +2,7 @@ package cc.ryanc.halo.web.controller.admin.api;
import cc.ryanc.halo.model.dto.UserOutputDTO;
import cc.ryanc.halo.model.entity.User;
import cc.ryanc.halo.model.params.PasswordParam;
import cc.ryanc.halo.model.params.UserParam;
import cc.ryanc.halo.service.UserService;
import org.springframework.web.bind.annotation.*;
@ -35,4 +36,9 @@ public class UserController {
// Update user and convert to dto
return new UserOutputDTO().convertFrom(userService.update(user));
}
@PutMapping("profile/password")
public void updatePassword(@Valid @RequestBody PasswordParam passwordParam, User user) {
userService.updatePassword(passwordParam.getOldPassword(), passwordParam.getNewPassword(), user.getId());
}
}

View File

@ -9,7 +9,6 @@ import cc.ryanc.halo.model.support.BaseResponse;
import cc.ryanc.halo.service.*;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import freemarker.template.Configuration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
@ -158,14 +157,7 @@ public class InstallController {
}
private User createDefaultUser(InstallParam installParam) {
User user = new User();
user.setUsername(installParam.getUsername());
user.setNickname(installParam.getNickname());
user.setEmail(installParam.getEmail());
// Hash password with BCrypt
user.setPassword(BCrypt.hashpw(installParam.getPassword(), BCrypt.gensalt()));
return userService.create(user);
return userService.createBy(installParam, installParam.getPassword());
}
private void initSettings(InstallParam installParam) {