This commit is contained in:
aisensiy
2017-08-18 12:09:07 +08:00
parent d6bf680a97
commit c3029aa636
16 changed files with 189 additions and 41 deletions

View File

@@ -28,7 +28,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import javax.xml.ws.Response;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -67,7 +66,7 @@ public class CommentsApi {
public ResponseEntity getComments(@PathVariable("slug") String slug,
@AuthenticationPrincipal User user) {
Article article = findArticle(slug);
List<CommentData> comments = commentQueryService.findByArticleSlug(article.getSlug(), user);
List<CommentData> comments = commentQueryService.findByArticleId(article.getId(), user);
return ResponseEntity.ok(new HashMap<String, Object>() {{
put("comments", comments);
}});

View File

@@ -1,6 +1,7 @@
package io.spring.api;
import com.fasterxml.jackson.annotation.JsonRootName;
import io.spring.api.exception.InvalidRequestException;
import io.spring.application.user.UserQueryService;
import io.spring.application.user.UserWithToken;
import io.spring.core.user.User;
@@ -22,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@RestController
@RequestMapping(path = "/user")
@@ -43,9 +45,13 @@ public class CurrentUserApi {
@PutMapping
public ResponseEntity updateProfile(@AuthenticationPrincipal User currentUser,
@RequestHeader(value = "Authorization") String authorization,
@Valid @RequestBody UpdateUserParam updateUserParam,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
throw new InvalidRequestException(bindingResult);
}
checkUniquenessOfUsernameAndEmail(currentUser, updateUserParam, bindingResult);
currentUser.update(
updateUserParam.getEmail(),
updateUserParam.getUsername(),
@@ -53,7 +59,27 @@ public class CurrentUserApi {
updateUserParam.getBio(),
updateUserParam.getImage());
userRepository.save(currentUser);
return ResponseEntity.ok(userResponse(userQueryService.fetchCurrentUser(currentUser.getUsername(), authorization.split(" ")[1])));
return ResponseEntity.ok(userResponse(userQueryService.fetchNewAuthenticatedUser(currentUser.getUsername())));
}
private void checkUniquenessOfUsernameAndEmail(User currentUser, UpdateUserParam updateUserParam, BindingResult bindingResult) {
if (!"".equals(updateUserParam.getUsername())) {
Optional<User> byUsername = userRepository.findByUsername(updateUserParam.getUsername());
if (byUsername.isPresent() && !byUsername.get().equals(currentUser)) {
bindingResult.rejectValue("username", "DUPLICATED", "username already exist");
}
}
if (!"".equals(updateUserParam.getEmail())) {
Optional<User> byEmail = userRepository.findByEmail(updateUserParam.getEmail());
if (byEmail.isPresent() && !byEmail.get().equals(currentUser)) {
bindingResult.rejectValue("email", "DUPLICATED", "email already exist");
}
}
if (bindingResult.hasErrors()) {
throw new InvalidRequestException(bindingResult);
}
}
private Map<String, Object> userResponse(UserWithToken userWithToken) {

View File

@@ -0,0 +1,25 @@
package io.spring.api.security;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CORSConfig {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
}

View File

@@ -30,16 +30,17 @@ public class JwtTokenFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
getTokenString(request.getHeader(header)).ifPresent(token -> {
jwtService.getSubFromToken(token).ifPresent(username -> {
jwtService.getSubFromToken(token).ifPresent(id -> {
if (SecurityContextHolder.getContext().getAuthentication() == null) {
User user = userRepository.findByUsername(username).get();
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
user,
null,
Collections.emptyList()
);
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
userRepository.findById(id).ifPresent(user -> {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
user,
null,
Collections.emptyList()
);
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
});
}
});
});

View File

@@ -25,9 +25,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers(HttpMethod.GET, "/articles/feed").authenticated()
.antMatchers(HttpMethod.POST, "/users", "/users/login").permitAll()
.antMatchers(HttpMethod.GET, "/articles/**", "/profiles/**").permitAll()
.antMatchers(HttpMethod.GET, "/articles/**", "/profiles/**", "/tags").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);

View File

@@ -4,9 +4,10 @@ import io.spring.application.profile.UserRelationshipQueryService;
import io.spring.core.user.User;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@Service
public class CommentQueryService {
@@ -31,7 +32,16 @@ public class CommentQueryService {
return Optional.ofNullable(commentData);
}
public List<CommentData> findByArticleSlug(String slug, User user) {
return new ArrayList<>();
public List<CommentData> findByArticleId(String articleId, User user) {
List<CommentData> comments = commentReadService.findByArticleId(articleId);
if (comments.size() > 0) {
Set<String> followingAuthors = userRelationshipQueryService.followingAuthors(user.getId(), comments.stream().map(commentData -> commentData.getProfileData().getId()).collect(Collectors.toList()));
comments.forEach(commentData -> {
if (followingAuthors.contains(commentData.getProfileData().getId())) {
commentData.getProfileData().setFollowing(true);
}
});
}
return comments;
}
}

View File

@@ -1,10 +1,15 @@
package io.spring.application.comment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Mapper
public interface CommentReadService {
CommentData findById(String id);
CommentData findById(@Param("id") String id);
List<CommentData> findByArticleId(@Param("articleId") String articleId);
}

View File

@@ -53,6 +53,7 @@ public class Article {
if (!"".equals(body)) {
this.body = body;
}
this.updatedAt = new DateTime();
}
private String toSlug(String title) {

View File

@@ -28,7 +28,7 @@ public class DefaultJwtService implements JwtService {
@Override
public String toToken(UserData userData) {
return Jwts.builder()
.setSubject(userData.getUsername())
.setSubject(userData.getId())
.setExpiration(expireTimeFromNow())
.signWith(SignatureAlgorithm.HS512, secret)
.compact();

View File

@@ -8,7 +8,7 @@
select count(1) from article_favorites where article_id = #{articleId}
</select>
<select id="articlesFavoriteCount" resultMap="favoriteCount">
select A.id, count(A.id) as favoriteCount from articles A
select A.id, count(AF.user_id) as favoriteCount from articles A
left join article_favorites AF on A.id = AF.article_id
where id in
<foreach collection="ids" item="item" separator="," open="(" close=")">

View File

@@ -1,17 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="io.spring.application.comment.CommentReadService">
<select id="findById" resultMap="commentData">
<sql id="selectCommentData">
SELECT
C.id commentId,
C.body commentBody,
C.created_at commentCreatedAt,
<include refid="io.spring.application.article.ArticleReadService.profileColumns"/>
C.id commentId,
C.body commentBody,
C.created_at commentCreatedAt,
<include refid="io.spring.application.article.ArticleReadService.profileColumns"/>
from comments C
left join users U
on C.user_id = U.id
</sql>
<select id="findById" resultMap="commentData">
<include refid="selectCommentData"/>
where C.id = #{id}
</select>
<select id="findByArticleId" resultMap="commentData">
<include refid="selectCommentData"/>
where C.article_id = #{articleId}
</select>
<resultMap id="commentData" type="io.spring.application.comment.CommentData">
<id column="commentId" property="id"/>