Commit 568db2b0 by 张乐 Committed by GitHub

Merge pull request #287 from nobodyiam/user-service-merge

Add user service and user validation when assigning roles
parents d4ed153f 566b6fb9
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>apollo-biz</artifactId> <artifactId>apollo-biz</artifactId>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
......
...@@ -161,7 +161,13 @@ public class RemoteConfigRepository extends AbstractConfigRepository { ...@@ -161,7 +161,13 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
} }
private ApolloConfig loadApolloConfig() { private ApolloConfig loadApolloConfig() {
m_loadConfigRateLimiter.tryAcquire(5, TimeUnit.SECONDS);//wait at most 5 seconds if (!m_loadConfigRateLimiter.tryAcquire(5, TimeUnit.SECONDS)) {
//wait at most 5 seconds
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
}
}
String appId = m_configUtil.getAppId(); String appId = m_configUtil.getAppId();
String cluster = m_configUtil.getCluster(); String cluster = m_configUtil.getCluster();
String dataCenter = m_configUtil.getDataCenter(); String dataCenter = m_configUtil.getDataCenter();
...@@ -285,7 +291,13 @@ public class RemoteConfigRepository extends AbstractConfigRepository { ...@@ -285,7 +291,13 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
final Random random = new Random(); final Random random = new Random();
ServiceDTO lastServiceDto = null; ServiceDTO lastServiceDto = null;
while (!m_longPollingStopped.get() && !Thread.currentThread().isInterrupted()) { while (!m_longPollingStopped.get() && !Thread.currentThread().isInterrupted()) {
m_longPollRateLimiter.tryAcquire(5, TimeUnit.SECONDS);//wait at most 5 seconds if (!m_longPollRateLimiter.tryAcquire(5, TimeUnit.SECONDS)) {
//wait at most 5 seconds
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
}
}
Transaction transaction = Cat.newTransaction("Apollo.ConfigService", "pollNotification"); Transaction transaction = Cat.newTransaction("Apollo.ConfigService", "pollNotification");
try { try {
if (lastServiceDto == null) { if (lastServiceDto == null) {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>apollo-demo</artifactId> <artifactId>apollo-demo</artifactId>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
......
package com.ctrip.framework.apollo.portal.auth;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
import com.ctrip.framework.apollo.portal.service.ServerConfigService;
import com.ctrip.framework.apollo.portal.service.UserService;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class CtripUserService implements UserService {
private ServerConfigService serverConfigService;
private RestTemplate restTemplate;
private List<String> searchUserMatchFields;
private ParameterizedTypeReference<Map<String, List<UserServiceResponse>>> responseType;
public CtripUserService(ServerConfigService serverConfigService) {
this.serverConfigService = serverConfigService;
this.restTemplate = new RestTemplate();
this.searchUserMatchFields =
Lists.newArrayList("empcode", "empaccount", "displayname", "c_name", "pinyin");
this.responseType = new ParameterizedTypeReference<Map<String, List<UserServiceResponse>>>() {
};
}
@Override
public List<UserInfo> searchUsers(String keyword, int offset, int limit) {
UserServiceRequest request = assembleSearchUserRequest(keyword, offset, limit);
HttpEntity<UserServiceRequest> entity = new HttpEntity<>(request);
ResponseEntity<Map<String, List<UserServiceResponse>>> response =
restTemplate.exchange(getUserServiceUrl(), HttpMethod.POST, entity, responseType);
if (!response.getBody().containsKey("result")) {
return Collections.emptyList();
}
List<UserInfo> result = Lists.newArrayList();
result.addAll(
response.getBody().get("result").stream().map(this::transformUserServiceResponseToUserInfo)
.collect(Collectors.toList()));
return result;
}
@Override
public UserInfo findByUserId(String userId) {
List<UserInfo> userInfoList = this.findByUserIds(Lists.newArrayList(userId));
if (CollectionUtils.isEmpty(userInfoList)) {
return null;
}
return userInfoList.get(0);
}
public List<UserInfo> findByUserIds(List<String> userIds) {
UserServiceRequest request = assembleFindUserRequest(Lists.newArrayList(userIds));
HttpEntity<UserServiceRequest> entity = new HttpEntity<>(request);
ResponseEntity<Map<String, List<UserServiceResponse>>> response =
restTemplate.exchange(getUserServiceUrl(), HttpMethod.POST, entity, responseType);
if (!response.getBody().containsKey("result")) {
return Collections.emptyList();
}
List<UserInfo> result = Lists.newArrayList();
result.addAll(
response.getBody().get("result").stream().map(this::transformUserServiceResponseToUserInfo)
.collect(Collectors.toList()));
return result;
}
private UserInfo transformUserServiceResponseToUserInfo(UserServiceResponse userServiceResponse) {
UserInfo userInfo = new UserInfo();
userInfo.setUserId(userServiceResponse.getEmpaccount());
userInfo.setName(userServiceResponse.getDisplayname());
userInfo.setEmail(userServiceResponse.getEmail());
return userInfo;
}
UserServiceRequest assembleSearchUserRequest(String keyword, int offset, int limit) {
Map<String, Object> query = Maps.newHashMap();
Map<String, Object> multiMatchMap = Maps.newHashMap();
multiMatchMap.put("fields", searchUserMatchFields);
multiMatchMap.put("operator", "and");
multiMatchMap.put("query", keyword);
multiMatchMap.put("type", "best_fields");
query.put("multi_match", multiMatchMap);
return assembleUserServiceRequest(query, offset, limit);
}
UserServiceRequest assembleFindUserRequest(List<String> userIds) {
Map<String, Object>
query =
ImmutableMap.of("filtered", ImmutableMap
.of("filter", ImmutableMap.of("terms", ImmutableMap.of("empaccount", userIds))));
return assembleUserServiceRequest(query, 0, userIds.size());
}
private UserServiceRequest assembleUserServiceRequest(Map<String, Object> query, int offset,
int limit) {
UserServiceRequest request = new UserServiceRequest();
request.setAccess_token(getUserServiceAccessToken());
request.setType("emloyee");
UserServiceRequestBody requestBody = new UserServiceRequestBody();
requestBody.setIndexAlias("itdb_emloyee");
request.setRequest_body(requestBody);
Map<String, Object> queryJson = Maps.newHashMap();
requestBody.setQueryJson(queryJson);
queryJson.put("query", query);
queryJson.put("from", offset);
queryJson.put("size", limit);
return request;
}
private String getUserServiceUrl() {
return serverConfigService.getValue("userService.url");
}
private String getUserServiceAccessToken() {
return serverConfigService.getValue("userService.accessToken");
}
static class UserServiceRequest {
private String access_token;
private String type;
private UserServiceRequestBody request_body;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public UserServiceRequestBody getRequest_body() {
return request_body;
}
public void setRequest_body(
UserServiceRequestBody request_body) {
this.request_body = request_body;
}
}
static class UserServiceRequestBody {
private String indexAlias;
private Map<String, Object> queryJson;
public String getIndexAlias() {
return indexAlias;
}
public void setIndexAlias(String indexAlias) {
this.indexAlias = indexAlias;
}
public Map<String, Object> getQueryJson() {
return queryJson;
}
public void setQueryJson(Map<String, Object> queryJson) {
this.queryJson = queryJson;
}
}
static class UserServiceResponse {
private String empaccount;
private String displayname;
private String email;
public String getEmpaccount() {
return empaccount;
}
public void setEmpaccount(String empaccount) {
this.empaccount = empaccount;
}
public String getDisplayname() {
return displayname;
}
public void setDisplayname(String displayname) {
this.displayname = displayname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
}
package com.ctrip.framework.apollo.portal.auth;
import com.google.common.collect.Lists;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
import com.ctrip.framework.apollo.portal.service.UserService;
import java.util.Collections;
import java.util.List;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class DefaultUserService implements UserService {
@Override
public List<UserInfo> searchUsers(String keyword, int offset, int limit) {
return Collections.emptyList();
}
@Override
public UserInfo findByUserId(String userId) {
if (userId.equals("apollo")) {
return assembleDefaultUser();
}
return null;
}
@Override
public List<UserInfo> findByUserIds(List<String> userIds) {
if (userIds.contains("apollo")) {
return Lists.newArrayList(assembleDefaultUser());
}
return null;
}
private UserInfo assembleDefaultUser() {
UserInfo defaultUser = new UserInfo();
defaultUser.setUserId("apollo");
defaultUser.setName("apollo");
defaultUser.setEmail("apollo@acme.com");
return defaultUser;
}
}
...@@ -2,11 +2,14 @@ package com.ctrip.framework.apollo.portal.configutation; ...@@ -2,11 +2,14 @@ package com.ctrip.framework.apollo.portal.configutation;
import com.ctrip.framework.apollo.portal.auth.CtripLogoutHandler; import com.ctrip.framework.apollo.portal.auth.CtripLogoutHandler;
import com.ctrip.framework.apollo.portal.auth.CtripUserInfoHolder; import com.ctrip.framework.apollo.portal.auth.CtripUserInfoHolder;
import com.ctrip.framework.apollo.portal.auth.CtripUserService;
import com.ctrip.framework.apollo.portal.auth.DefaultLogoutHandler; import com.ctrip.framework.apollo.portal.auth.DefaultLogoutHandler;
import com.ctrip.framework.apollo.portal.auth.DefaultUserInfoHolder; import com.ctrip.framework.apollo.portal.auth.DefaultUserInfoHolder;
import com.ctrip.framework.apollo.portal.auth.DefaultUserService;
import com.ctrip.framework.apollo.portal.auth.LogoutHandler; import com.ctrip.framework.apollo.portal.auth.LogoutHandler;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder; import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.service.ServerConfigService; import com.ctrip.framework.apollo.portal.service.ServerConfigService;
import com.ctrip.framework.apollo.portal.service.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
...@@ -29,7 +32,6 @@ import javax.servlet.Filter; ...@@ -29,7 +32,6 @@ import javax.servlet.Filter;
@Configuration @Configuration
public class AuthConfiguration { public class AuthConfiguration {
/** /**
* 在ctrip内部运行时,会指定 spring.profiles.active = ctrip. * 在ctrip内部运行时,会指定 spring.profiles.active = ctrip.
* ctrip sso是通过cas实现的,所以需要加载相关的filter和listener. * ctrip sso是通过cas实现的,所以需要加载相关的filter和listener.
...@@ -141,6 +143,11 @@ public class AuthConfiguration { ...@@ -141,6 +143,11 @@ public class AuthConfiguration {
throw new RuntimeException("instance listener fail", e); throw new RuntimeException("instance listener fail", e);
} }
} }
@Bean
public UserService ctripUserService(ServerConfigService serverConfigService) {
return new CtripUserService(serverConfigService);
}
} }
/** /**
...@@ -160,6 +167,12 @@ public class AuthConfiguration { ...@@ -160,6 +167,12 @@ public class AuthConfiguration {
public DefaultLogoutHandler logoutHandler(){ public DefaultLogoutHandler logoutHandler(){
return new DefaultLogoutHandler(); return new DefaultLogoutHandler();
} }
@Bean
@ConditionalOnMissingBean(UserService.class)
public UserService defaultUserService() {
return new DefaultUserService();
}
} }
......
...@@ -10,6 +10,7 @@ import com.ctrip.framework.apollo.portal.entity.vo.AppRolesAssignedUsers; ...@@ -10,6 +10,7 @@ import com.ctrip.framework.apollo.portal.entity.vo.AppRolesAssignedUsers;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceRolesAssignedUsers; import com.ctrip.framework.apollo.portal.entity.vo.NamespaceRolesAssignedUsers;
import com.ctrip.framework.apollo.portal.entity.vo.PermissionCondition; import com.ctrip.framework.apollo.portal.entity.vo.PermissionCondition;
import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.service.RolePermissionService;
import com.ctrip.framework.apollo.portal.service.UserService;
import com.ctrip.framework.apollo.portal.util.RoleUtils; import com.ctrip.framework.apollo.portal.util.RoleUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -34,6 +35,8 @@ public class PermissionController { ...@@ -34,6 +35,8 @@ public class PermissionController {
private UserInfoHolder userInfoHolder; private UserInfoHolder userInfoHolder;
@Autowired @Autowired
private RolePermissionService rolePermissionService; private RolePermissionService rolePermissionService;
@Autowired
private UserService userService;
@RequestMapping("/apps/{appId}/permissions/{permissionType}") @RequestMapping("/apps/{appId}/permissions/{permissionType}")
public ResponseEntity<PermissionCondition> hasPermission(@PathVariable String appId, @PathVariable String permissionType) { public ResponseEntity<PermissionCondition> hasPermission(@PathVariable String appId, @PathVariable String permissionType) {
...@@ -80,7 +83,7 @@ public class PermissionController { ...@@ -80,7 +83,7 @@ public class PermissionController {
@RequestMapping(value = "/apps/{appId}/namespaces/{namespaceName}/roles/{roleType}", method = RequestMethod.POST) @RequestMapping(value = "/apps/{appId}/namespaces/{namespaceName}/roles/{roleType}", method = RequestMethod.POST)
public ResponseEntity<Void> assignNamespaceRoleToUser(@PathVariable String appId, @PathVariable String namespaceName, public ResponseEntity<Void> assignNamespaceRoleToUser(@PathVariable String appId, @PathVariable String namespaceName,
@PathVariable String roleType, @RequestBody String user){ @PathVariable String roleType, @RequestBody String user){
checkUserExists(user);
checkArgument(user); checkArgument(user);
if (!RoleType.isValidRoleType(roleType)){ if (!RoleType.isValidRoleType(roleType)){
...@@ -121,7 +124,7 @@ public class PermissionController { ...@@ -121,7 +124,7 @@ public class PermissionController {
@RequestMapping(value = "/apps/{appId}/roles/{roleType}", method = RequestMethod.POST) @RequestMapping(value = "/apps/{appId}/roles/{roleType}", method = RequestMethod.POST)
public ResponseEntity<Void> assignAppRoleToUser(@PathVariable String appId, @PathVariable String roleType, public ResponseEntity<Void> assignAppRoleToUser(@PathVariable String appId, @PathVariable String roleType,
@RequestBody String user){ @RequestBody String user){
checkUserExists(user);
checkArgument(user); checkArgument(user);
if (!RoleType.isValidRoleType(roleType)){ if (!RoleType.isValidRoleType(roleType)){
...@@ -147,5 +150,10 @@ public class PermissionController { ...@@ -147,5 +150,10 @@ public class PermissionController {
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
private void checkUserExists(String userId) {
if (userService.findByUserId(userId) == null) {
throw new BadRequestException(String.format("User %s does not exist!", userId));
}
}
} }
...@@ -3,12 +3,16 @@ package com.ctrip.framework.apollo.portal.controller; ...@@ -3,12 +3,16 @@ package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.portal.auth.LogoutHandler; import com.ctrip.framework.apollo.portal.auth.LogoutHandler;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder; import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo; import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
import com.ctrip.framework.apollo.portal.service.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
...@@ -21,6 +25,9 @@ public class UserInfoController { ...@@ -21,6 +25,9 @@ public class UserInfoController {
@Autowired @Autowired
private LogoutHandler logoutHandler; private LogoutHandler logoutHandler;
@Autowired
private UserService userService;
@RequestMapping("/user") @RequestMapping("/user")
public UserInfo getCurrentUserName() { public UserInfo getCurrentUserName() {
return userInfoHolder.getUser(); return userInfoHolder.getUser();
...@@ -30,4 +37,16 @@ public class UserInfoController { ...@@ -30,4 +37,16 @@ public class UserInfoController {
public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException { public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException {
logoutHandler.logout(request, response); logoutHandler.logout(request, response);
} }
@RequestMapping("/users")
public List<UserInfo> searchUsersByKeyword(@RequestParam(value = "keyword") String keyword,
@RequestParam(value = "offset", defaultValue = "0") int offset,
@RequestParam(value = "limit", defaultValue = "10") int limit) {
return userService.searchUsers(keyword, offset, limit);
}
@RequestMapping("/users/{userId}")
public UserInfo getUserByUserId(@PathVariable String userId) {
return userService.findByUserId(userId);
}
} }
...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.portal.entity.po; ...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.portal.entity.po;
public class UserInfo { public class UserInfo {
private String userId; private String userId;
private String name;
private String email;
public String getUserId() { public String getUserId() {
return userId; return userId;
...@@ -10,4 +12,20 @@ public class UserInfo { ...@@ -10,4 +12,20 @@ public class UserInfo {
public void setUserId(String userId) { public void setUserId(String userId) {
this.userId = userId; this.userId = userId;
} }
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
} }
package com.ctrip.framework.apollo.portal.service;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
import java.util.List;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public interface UserService {
List<UserInfo> searchUsers(String keyword, int offset, int limit);
UserInfo findByUserId(String userId);
List<UserInfo> findByUserIds(List<String> userIds);
}
package com.ctrip.framework.apollo.portal.auth;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
import com.ctrip.framework.apollo.portal.service.ServerConfigService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class CtripUserServiceTest {
private CtripUserService ctripUserService;
private String someUserServiceUrl;
private String someUserServiceToken;
private ParameterizedTypeReference<Map<String, List<CtripUserService.UserServiceResponse>>>
someResponseType;
@Mock
private ServerConfigService serverConfigService;
@Mock
private RestTemplate restTemplate;
@Before
public void setUp() throws Exception {
ctripUserService = new CtripUserService(serverConfigService);
ReflectionTestUtils.setField(ctripUserService, "restTemplate", restTemplate);
someResponseType =
(ParameterizedTypeReference<Map<String, List<CtripUserService.UserServiceResponse>>>) ReflectionTestUtils
.getField(ctripUserService, "responseType");
someUserServiceUrl = "http://someurl";
someUserServiceToken = "someToken";
when(serverConfigService.getValue("userService.url")).thenReturn(someUserServiceUrl);
when(serverConfigService.getValue("userService.accessToken")).thenReturn(someUserServiceToken);
}
@Test
public void testAssembleSearchUserRequest() throws Exception {
String someKeyword = "someKeyword";
int someOffset = 0;
int someLimit = 10;
CtripUserService.UserServiceRequest request =
ctripUserService.assembleSearchUserRequest(someKeyword, someOffset, someLimit);
assertEquals(someUserServiceToken, request.getAccess_token());
assertEquals("emloyee", request.getType());
CtripUserService.UserServiceRequestBody requestBody = request.getRequest_body();
assertEquals("itdb_emloyee", requestBody.getIndexAlias());
Map<String, Object> queryJson = requestBody.getQueryJson();
assertEquals(someOffset, queryJson.get("from"));
assertEquals(someLimit, queryJson.get("size"));
Map<String, Object> query = (Map<String, Object>) queryJson.get("query");
Map<String, Object> multiMatchMap = (Map<String, Object>) query.get("multi_match");
assertEquals(someKeyword, multiMatchMap.get("query"));
}
@Test
public void testAssembleFindUserRequest() throws Exception {
String someUserId = "someUser";
String anotherUserId = "anotherUser";
List<String> userIds = Lists.newArrayList(someUserId, anotherUserId);
CtripUserService.UserServiceRequest request = ctripUserService.assembleFindUserRequest(userIds);
assertEquals(someUserServiceToken, request.getAccess_token());
assertEquals("emloyee", request.getType());
CtripUserService.UserServiceRequestBody requestBody = request.getRequest_body();
assertEquals("itdb_emloyee", requestBody.getIndexAlias());
Map<String, Object> queryJson = requestBody.getQueryJson();
assertEquals(0, queryJson.get("from"));
assertEquals(2, queryJson.get("size"));
Map<String, Object> query = (Map<String, Object>) queryJson.get("query");
Map<String, Object> terms =
getMapFromMap(getMapFromMap(getMapFromMap(query, "filtered"), "filter"), "terms");
List<String> userIdTerms = (List<String>) terms.get("empaccount");
assertTrue(userIdTerms.containsAll(userIds));
}
private Map<String, Object> getMapFromMap(Map<String, Object> map, String key) {
return (Map<String, Object>) map.get(key);
}
@Test
public void testSearchUsers() throws Exception {
String someUserId = "someUserId";
String someName = "someName";
String someEmail = "someEmail";
String anotherUserId = "anotherUserId";
String anotherName = "anotherName";
String anotherEmail = "anotherEmail";
String someKeyword = "someKeyword";
int someOffset = 0;
int someLimit = 10;
CtripUserService.UserServiceResponse someUserResponse =
assembleUserServiceResponse(someUserId, someName, someEmail);
CtripUserService.UserServiceResponse anotherUserResponse =
assembleUserServiceResponse(anotherUserId, anotherName, anotherEmail);
Map<String, List<CtripUserService.UserServiceResponse>> resultMap =
ImmutableMap.of("result", Lists.newArrayList(someUserResponse, anotherUserResponse));
ResponseEntity<Map<String, List<CtripUserService.UserServiceResponse>>> someResponse
= new ResponseEntity<>(resultMap, HttpStatus.OK);
when(restTemplate.exchange(eq(someUserServiceUrl), eq(HttpMethod.POST), any(HttpEntity.class),
eq(someResponseType))).thenReturn(someResponse);
List<UserInfo> users = ctripUserService.searchUsers(someKeyword, someOffset, someLimit);
assertEquals(2, users.size());
compareUserInfoAndUserServiceResponse(someUserResponse, users.get(0));
compareUserInfoAndUserServiceResponse(anotherUserResponse, users.get(1));
}
@Test(expected = HttpClientErrorException.class)
public void testSearchUsersWithError() throws Exception {
when(restTemplate.exchange(eq(someUserServiceUrl), eq(HttpMethod.POST), any(HttpEntity.class),
eq(someResponseType)))
.thenThrow(new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR));
String someKeyword = "someKeyword";
int someOffset = 0;
int someLimit = 10;
ctripUserService.searchUsers(someKeyword, someOffset, someLimit);
}
@Test
public void testFindByUserId() throws Exception {
String someUserId = "someUserId";
String someName = "someName";
String someEmail = "someEmail";
CtripUserService.UserServiceResponse someUserResponse =
assembleUserServiceResponse(someUserId, someName, someEmail);
Map<String, List<CtripUserService.UserServiceResponse>> resultMap =
ImmutableMap.of("result", Lists.newArrayList(someUserResponse));
ResponseEntity<Map<String, List<CtripUserService.UserServiceResponse>>> someResponse
= new ResponseEntity<>(resultMap, HttpStatus.OK);
when(restTemplate.exchange(eq(someUserServiceUrl), eq(HttpMethod.POST), any(HttpEntity.class),
eq(someResponseType))).thenReturn(someResponse);
UserInfo user = ctripUserService.findByUserId(someUserId);
compareUserInfoAndUserServiceResponse(someUserResponse, user);
}
@Test
public void testFindByUserIds() throws Exception {
String someUserId = "someUserId";
String someName = "someName";
String someEmail = "someEmail";
String anotherUserId = "anotherUserId";
String anotherName = "anotherName";
String anotherEmail = "anotherEmail";
String someKeyword = "someKeyword";
CtripUserService.UserServiceResponse someUserResponse =
assembleUserServiceResponse(someUserId, someName, someEmail);
CtripUserService.UserServiceResponse anotherUserResponse =
assembleUserServiceResponse(anotherUserId, anotherName, anotherEmail);
Map<String, List<CtripUserService.UserServiceResponse>> resultMap =
ImmutableMap.of("result", Lists.newArrayList(someUserResponse, anotherUserResponse));
ResponseEntity<Map<String, List<CtripUserService.UserServiceResponse>>> someResponse
= new ResponseEntity<>(resultMap, HttpStatus.OK);
when(restTemplate.exchange(eq(someUserServiceUrl), eq(HttpMethod.POST), any(HttpEntity.class),
eq(someResponseType))).thenReturn(someResponse);
List<UserInfo> users =
ctripUserService.findByUserIds(Lists.newArrayList(someUserId, anotherUserId));
assertEquals(2, users.size());
compareUserInfoAndUserServiceResponse(someUserResponse, users.get(0));
compareUserInfoAndUserServiceResponse(anotherUserResponse, users.get(1));
}
private void compareUserInfoAndUserServiceResponse(
CtripUserService.UserServiceResponse userServiceReponse, UserInfo userInfo) {
assertEquals(userServiceReponse.getEmpaccount(), userInfo.getUserId());
assertEquals(userServiceReponse.getDisplayname(), userInfo.getName());
assertEquals(userServiceReponse.getEmail(), userInfo.getEmail());
}
private CtripUserService.UserServiceResponse assembleUserServiceResponse(String userId,
String name,
String email) {
CtripUserService.UserServiceResponse response = new CtripUserService.UserServiceResponse();
response.setEmpaccount(userId);
response.setDisplayname(name);
response.setEmail(email);
return response;
}
}
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.ctrip.framework.apollo</groupId> <groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo</artifactId> <artifactId>apollo</artifactId>
<version>0.0.2</version> <version>0.0.3-SNAPSHOT</version>
<name>Apollo</name> <name>Apollo</name>
<packaging>pom</packaging> <packaging>pom</packaging>
<description>Ctrip Configuration Center</description> <description>Ctrip Configuration Center</description>
......
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