Skip to content

Commit

Permalink
feat($auth-center): provide remote service: get user for api-portal
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnymillergh committed May 10, 2020
1 parent 9c64522 commit 71daf55
Show file tree
Hide file tree
Showing 19 changed files with 697 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package com.jmsoftware.apiportal.remoteapi.authcenter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.jmsoftware.apiportal.remoteapi.authcenter.user;

import com.jmsoftware.common.bean.ResponseBodyBean;
import com.jmsoftware.common.domain.authcenter.user.GetUserByLoginTokenPayload;
import com.jmsoftware.common.domain.authcenter.user.GetUserByLoginTokenResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

/**
* <h1>UserRemoteApi</h1>
* <p>
* Change description here.
*
* @author Johnny Miller (鍾俊), email: johnnysviva@outlook.com
* @date 5/10/20 4:50 PM
*/
@FeignClient(name = "auth-center")
public interface UserRemoteApi {
/**
* Gets user by login token.
*
* @param payload the payload
* @return the user by login token
*/
@PostMapping("/user/get-user-by-login-token")
ResponseBodyBean<GetUserByLoginTokenResponse> getUserByLoginToken(@RequestBody GetUserByLoginTokenPayload payload);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package com.jmsoftware.apiportal.remoteapi;
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.jmsoftware.apiportal.universal.aspect;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.jmsoftware.common.bean.ResponseBodyBean;
import com.jmsoftware.common.constant.HttpStatus;
import com.jmsoftware.common.exception.BaseException;
Expand Down Expand Up @@ -50,86 +49,81 @@ public class ExceptionControllerAdvice {
public ResponseBodyBean<Object> handleException(HttpServletRequest request,
HttpServletResponse response,
Exception exception) {
log.error("Exception occurred when [{}] requested access. URL: {}",
RequestUtil.getRequestIpAndPort(request),
log.error("Exception occurred when [{}] requested access. URL: {}", RequestUtil.getRequestIpAndPort(request),
request.getServletPath());

// FIXME: THIS IS NOT A PROBLEM
// ATTENTION: Use only ResponseBodyBean.ofStatus() in handleException() method and DON'T throw any exception
if (exception instanceof NoHandlerFoundException) {
log.error("[GlobalExceptionCapture] NoHandlerFoundException: Request URL = {}, HTTP method = {}",
log.error("NoHandlerFoundException: Request URL = {}, HTTP method = {}",
((NoHandlerFoundException) exception).getRequestURL(),
((NoHandlerFoundException) exception).getHttpMethod());
response.setStatus(HttpStatus.NOT_FOUND.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.NOT_FOUND);
} else if (exception instanceof HttpRequestMethodNotSupportedException) {
log.error("[GlobalExceptionCapture] HttpRequestMethodNotSupportedException: " +
log.error("Exception occurred when the request handler does not support a specific request method. " +
"Current method is {}, Support HTTP method = {}",
((HttpRequestMethodNotSupportedException) exception).getMethod(),
JSONUtil.toJsonStr(
((HttpRequestMethodNotSupportedException) exception).getSupportedHttpMethods()));
((HttpRequestMethodNotSupportedException) exception).getSupportedHttpMethods());
response.setStatus(HttpStatus.METHOD_NOT_ALLOWED.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.METHOD_NOT_ALLOWED);
} else if (exception instanceof MethodArgumentNotValidException) {
log.error("[GlobalExceptionCapture] MethodArgumentNotValidException: {}", exception.getMessage());
log.error("Exception occurred when validation on an argument annotated with fails. Exception message: {}",
exception.getMessage());
response.setStatus(HttpStatus.BAD_REQUEST.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.BAD_REQUEST.getCode(),
getFieldErrorMessageFromException((MethodArgumentNotValidException) exception),
null);
} else if (exception instanceof ConstraintViolationException) {
log.error("[GlobalExceptionCapture] ConstraintViolationException: {}", exception.getMessage());
log.error("Constraint violations exception occurred. Exception message: {}", exception.getMessage());
response.setStatus(HttpStatus.BAD_REQUEST.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.BAD_REQUEST.getCode(),
CollUtil.getFirst(((ConstraintViolationException) exception)
.getConstraintViolations())
.getMessage(), null);
CollUtil.getFirst(((ConstraintViolationException) exception).getConstraintViolations()).getMessage(),
null);
} else if (exception instanceof MethodArgumentTypeMismatchException) {
log.error("[GlobalExceptionCapture] MethodArgumentTypeMismatchException: " +
"Parameter name = {}, Exception information: {}",
log.error("MethodArgumentTypeMismatchException: Parameter name = {}, Exception message: {}",
((MethodArgumentTypeMismatchException) exception).getName(),
((MethodArgumentTypeMismatchException) exception).getMessage());
response.setStatus(HttpStatus.PARAM_NOT_MATCH.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.PARAM_NOT_MATCH);
} else if (exception instanceof HttpMessageNotReadableException) {
log.error("[GlobalExceptionCapture] HttpMessageNotReadableException: {}",
log.error("HttpMessageNotReadableException: {}",
((HttpMessageNotReadableException) exception).getMessage());
response.setStatus(HttpStatus.PARAM_NOT_NULL.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.PARAM_NOT_NULL);
} else if (exception instanceof BaseException) {
log.error("[GlobalExceptionCapture] BaseException: Status code: {}, message: {}, data: {}",
((BaseException) exception).getCode(),
exception.getMessage(),
((BaseException) exception).getData());
log.error("BaseException: Status code: {}, message: {}, data: {}", ((BaseException) exception).getCode(),
exception.getMessage(), ((BaseException) exception).getData());
response.setStatus(((BaseException) exception).getCode());
return ResponseBodyBean.ofStatus(((BaseException) exception).getCode(),
exception.getMessage(),
return ResponseBodyBean.ofStatus(((BaseException) exception).getCode(), exception.getMessage(),
((BaseException) exception).getData());
} else if (exception instanceof BindException) {
log.error("[GlobalExceptionCapture]: Exception information: {} ", exception.getMessage());
log.error("Exception message: {} ", exception.getMessage());
response.setStatus(HttpStatus.INVALID_PARAM.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.INVALID_PARAM);
} else if (exception instanceof IllegalArgumentException) {
log.error("[GlobalExceptionCapture]: Exception information: {} ", exception.getMessage());
log.error("Exception message: {} ", exception.getMessage());
response.setStatus(HttpStatus.BAD_REQUEST.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.BAD_REQUEST.getCode(), exception.getMessage(), null);
} else if (exception instanceof BadCredentialsException) {
// IMPORTANT: org.springframework.security.authentication.BadCredentialsException only exists in the project
// that depends on org.springframework.boot.spring-boot-starter-security
log.error("[GlobalExceptionCapture]: Exception information: {} ", exception.getMessage());
log.error("Exception message: {} ", exception.getMessage());
response.setStatus(HttpStatus.BAD_CREDENTIALS.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.BAD_CREDENTIALS.getCode(), exception.getMessage(), null);
} else if (exception instanceof InternalAuthenticationServiceException) {
log.error("[GlobalExceptionCapture]: Exception information: {} ", exception.getMessage());
log.error("An authentication request could not be processed due to a system problem that occurred " +
"internally. Exception message: {} ", exception.getMessage());
if (exception.getCause() instanceof BaseException) {
val exceptionCause = (BaseException) exception.getCause();
val code = exceptionCause.getCode();
response.setStatus(code);
return ResponseBodyBean.ofStatus(HttpStatus.fromCode(code));
}
response.setStatus(HttpStatus.ERROR.getCode());
response.setStatus(HttpStatus.BAD_CREDENTIALS.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.BAD_CREDENTIALS.getCode(), exception.getMessage(), null);
}
log.error("[GlobalExceptionCapture]: Exception information: {} ", exception.getMessage(), exception);
log.error("Internal system exception occurred! Exception message: {} ", exception.getMessage(), exception);
response.setStatus(HttpStatus.ERROR.getCode());
return ResponseBodyBean.ofStatus(HttpStatus.ERROR.getCode(), HttpStatus.ERROR.getMessage(), null);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package com.jmsoftware.apiportal.universal.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.jmsoftware.apiportal.remoteapi.authcenter.user.UserRemoteApi;
import com.jmsoftware.apiportal.universal.domain.PermissionPO;
import com.jmsoftware.apiportal.universal.domain.RolePO;
import com.jmsoftware.apiportal.universal.domain.UserPO;
import com.jmsoftware.apiportal.universal.domain.UserPrincipal;
import com.jmsoftware.apiportal.universal.mapper.PermissionMapper;
import com.jmsoftware.apiportal.universal.mapper.UserMapper;
import com.jmsoftware.apiportal.universal.service.RoleService;
import com.jmsoftware.common.constant.HttpStatus;
import com.jmsoftware.common.domain.authcenter.user.GetUserByLoginTokenPayload;
import com.jmsoftware.common.exception.SecurityException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
Expand All @@ -31,26 +35,31 @@
@Service
@RequiredArgsConstructor
public class CustomUserDetailsServiceImpl implements UserDetailsService {
private final UserMapper userMapper;
private final RoleService roleService;
private final PermissionMapper permissionMapper;
private final UserRemoteApi userRemoteApi;

@Override
public UserDetails loadUserByUsername(String credentials) throws UsernameNotFoundException {
UserPO user = userMapper.selectByUsernameOrEmailOrCellphone(credentials, credentials, credentials)
.orElseThrow(() -> {
String errorMessage = "User's account not found: " + credentials;
log.error(errorMessage);
return new UsernameNotFoundException(errorMessage);
});
List<RolePO> rolesByUserId = roleService.getRolesByUserId(user.getId());
val payload = new GetUserByLoginTokenPayload();
payload.setLoginToken(credentials);
var response = userRemoteApi.getUserByLoginToken(payload);
val data = response.getData();
if (ObjectUtil.isNull(data)) {
String errorMessage = "User's account not found: " + credentials;
log.error(errorMessage);
throw new UsernameNotFoundException(errorMessage);
}
List<RolePO> rolesByUserId = roleService.getRolesByUserId(data.getId());
if (CollUtil.isEmpty(rolesByUserId)) {
throw new SecurityException(HttpStatus.ROLE_NOT_FOUND);
}
List<Long> roleIds = rolesByUserId.stream()
.map(RolePO::getId)
.collect(Collectors.toList());
.map(RolePO::getId)
.collect(Collectors.toList());
List<PermissionPO> permissionList = permissionMapper.selectByRoleIdList(roleIds);
var user = new UserPO();
BeanUtil.copyProperties(data, user);
return UserPrincipal.create(user, rolesByUserId, permissionList);
}
}
1 change: 1 addition & 0 deletions api-portal/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ feign:
default:
connectTimeout: 5000
readTimeout: 10000
loggerLevel: basic

management:
endpoints:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public class UserPO {
*/
private String gender;
/**
* User avatar full path on SFTP server
* UserPersistence avatar full path on SFTP server
*/
private String avatar;
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jmsoftware.authcenter.universal.domain.UserPO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;
Expand All @@ -18,8 +16,8 @@
* @author Johnny Miller (鍾俊), email: johnnysviva@outlook.com
* @date 2019-03-02 17:32
**/
@Mapper
@Component
//@Mapper
//@Component
public interface UserMapper extends BaseMapper<UserPO> {
/**
* Find by username, email or cellphone.
Expand Down Expand Up @@ -62,7 +60,7 @@ Optional<UserPO> selectByUsernameOrEmailOrCellphone(@Param("username") String us
/**
* Register
*
* @param po User info
* @param po UserPersistence info
* @return Registered user ID
*/
Long register(UserPO po);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.jmsoftware.authcenter.user.controller;

import com.jmsoftware.authcenter.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* <h1>UserController</h1>
* <p>
* Controller implementation of UserPersistence.(UserPersistence)
*
* @author Johnny Miller (鍾俊)
* @date 2020-05-10 12:08:28
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
public class UserController {
private final UserService userService;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.jmsoftware.authcenter.user.entity;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
* <h1>UserPersistence</h1>
* <p>
* User Persistence object class
*
* @author Johnny Miller (鍾俊), e-mail: johnnysviva@outlook.com
* @date 5/10/20 12:12 PM
*/
@Data
public class UserPersistence implements Serializable {
private static final long serialVersionUID = -11418821727467072L;
/**
* Primary key of user
*/
private Long id;
/**
* Username
*/
private String username;
/**
* Email
*/
private String email;
/**
* Cellphone number
*/
private String cellphone;
/**
* Password
*/
private String password;
/**
* Full name
*/
private String fullName;
/**
* Birthday
*/
private Date birthday;
/**
* 26 gender options
*/
private String gender;
/**
* UserPersistence avatar full path on SFTP server
*/
private String avatar;
/**
* Status. 1 - enabled, 2 - disabled
*/
private Integer status;
/**
* Created time
*/
private Date createdTime;
/**
* Modified time
*/
private Date modifiedTime;
}
Loading

0 comments on commit 71daf55

Please sign in to comment.