Commit 7b7d753f authored by Jason Song's avatar Jason Song

add open api support

parent 872839c6
......@@ -67,7 +67,9 @@ public class NamespaceLockAspect {
@Before("@annotation(PreAcquireNamespaceLock) && args(itemId, operator, ..)")
public void requireLockAdvice(long itemId, String operator) {
Item item = itemService.findOne(itemId);
if (item == null){
throw new BadRequestException("item not exist.");
}
acquireLock(item.getNamespaceId(), operator);
}
......
......@@ -12,7 +12,6 @@ import org.springframework.context.ConfigurableApplicationContext;
import com.ctrip.framework.apollo.adminservice.AdminServiceApplication;
import com.ctrip.framework.apollo.configservice.ConfigServiceApplication;
import com.ctrip.framework.apollo.portal.PortalApplication;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class})
......
......@@ -12,7 +12,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import com.ctrip.framework.apollo.adminservice.AdminServiceApplication;
import com.ctrip.framework.apollo.configservice.ConfigServiceApplication;
import com.ctrip.framework.apollo.portal.PortalApplication;
import com.ctrip.framework.apollo.PortalApplication;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class})
......
......@@ -50,7 +50,7 @@ public class AppNamespaceService {
public List<AppNamespace> findPublicNamespacesByNames(Set<String> namespaceNames) {
if (namespaceNames == null || namespaceNames.isEmpty()) {
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
return appNamespaceRepository.findByNameInAndIsPublicTrue(namespaceNames);
......@@ -68,7 +68,7 @@ public class AppNamespaceService {
public List<AppNamespace> findByAppIdAndNamespaces(String appId, Set<String> namespaceNames) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(appId), "appId must not be null");
if (namespaceNames == null || namespaceNames.isEmpty()) {
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
return appNamespaceRepository.findByAppIdAndNameIn(appId, namespaceNames);
}
......
......@@ -32,7 +32,7 @@ public class ReleaseMessageService {
public List<ReleaseMessage> findLatestReleaseMessagesGroupByMessages(Collection<String> messages) {
if (CollectionUtils.isEmpty(messages)) {
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
List<Object[]> result =
releaseMessageRepository.findLatestReleaseMessagesGroupByMessages(messages);
......
......@@ -54,5 +54,9 @@
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
</dependencies>
</project>
package com.ctrip.framework.apollo.common.controller;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
......@@ -15,6 +18,7 @@ import org.springframework.web.client.HttpStatusCodeException;
import com.ctrip.framework.apollo.common.exception.AbstractApolloHttpException;
import com.dianping.cat.Cat;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
......@@ -24,70 +28,80 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import static org.springframework.http.MediaType.APPLICATION_JSON;
@ControllerAdvice
public class GlobalDefaultExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalDefaultExceptionHandler.class);
//处理系统内置的Exception
@ExceptionHandler(Throwable.class)
public ResponseEntity<Map<String, Object>> exception(HttpServletRequest request, Throwable ex) {
return handleError(request, INTERNAL_SERVER_ERROR, ex);
}
@ExceptionHandler({HttpRequestMethodNotSupportedException.class, HttpMediaTypeException.class})
public ResponseEntity<Map<String, Object>> badRequest(HttpServletRequest request,
ServletException ex) {
return handleError(request, BAD_REQUEST, ex);
}
@ExceptionHandler(HttpStatusCodeException.class)
public ResponseEntity<Map<String, Object>> restTemplateException(HttpServletRequest request,
HttpStatusCodeException ex) {
return handleError(request, ex.getStatusCode(), ex);
}
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<Map<String, Object>> accessDeny(HttpServletRequest request,
AccessDeniedException ex) {
return handleError(request, UNAUTHORIZED, ex);
}
//处理自定义Exception
@ExceptionHandler({AbstractApolloHttpException.class})
public ResponseEntity<Map<String, Object>> badRequest(HttpServletRequest request, AbstractApolloHttpException ex) {
return handleError(request, ex);
}
private ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request,
AbstractApolloHttpException ex) {
return handleError(request, ex.getHttpStatus(), ex);
}
private ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request,
HttpStatus status, Throwable ex) {
String message = ex.getMessage();
logger.error(message, ex);
Cat.logError(ex);
Map<String, Object> errorAttributes = new HashMap<>();
errorAttributes.put("status", status.value());
errorAttributes.put("message", message);
errorAttributes.put("timestamp",
LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
errorAttributes.put("exception", ex.getClass().getName());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(APPLICATION_JSON);
return new ResponseEntity<>(errorAttributes, headers, status);
}
private Gson gson = new Gson();
private static Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
private static final Logger logger = LoggerFactory.getLogger(GlobalDefaultExceptionHandler.class);
//处理系统内置的Exception
@ExceptionHandler(Throwable.class)
public ResponseEntity<Map<String, Object>> exception(HttpServletRequest request, Throwable ex) {
return handleError(request, INTERNAL_SERVER_ERROR, ex);
}
@ExceptionHandler({HttpRequestMethodNotSupportedException.class, HttpMediaTypeException.class})
public ResponseEntity<Map<String, Object>> badRequest(HttpServletRequest request,
ServletException ex) {
return handleError(request, BAD_REQUEST, ex);
}
@ExceptionHandler(HttpStatusCodeException.class)
public ResponseEntity<Map<String, Object>> restTemplateException(HttpServletRequest request,
HttpStatusCodeException ex) {
return handleError(request, ex.getStatusCode(), ex);
}
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<Map<String, Object>> accessDeny(HttpServletRequest request,
AccessDeniedException ex) {
return handleError(request, FORBIDDEN, ex);
}
//处理自定义Exception
@ExceptionHandler({AbstractApolloHttpException.class})
public ResponseEntity<Map<String, Object>> badRequest(HttpServletRequest request, AbstractApolloHttpException ex) {
return handleError(request, ex);
}
private ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request,
AbstractApolloHttpException ex) {
return handleError(request, ex.getHttpStatus(), ex);
}
private ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request,
HttpStatus status, Throwable ex) {
String message = ex.getMessage();
logger.error(message, ex);
Cat.logError(ex);
Map<String, Object> errorAttributes = new HashMap<>();
//如果是admin server引起的异常,则显示内部的异常信息
if (ex instanceof HttpStatusCodeException){
errorAttributes = gson.fromJson(((HttpStatusCodeException)ex).getResponseBodyAsString(), mapType);
status = ((HttpStatusCodeException)ex).getStatusCode();
} else {
errorAttributes.put("status", status.value());
errorAttributes.put("message", message);
errorAttributes.put("timestamp",
LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
errorAttributes.put("exception", ex.getClass().getName());
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(APPLICATION_JSON);
return new ResponseEntity<>(errorAttributes, headers, status);
}
}
......@@ -14,15 +14,15 @@ public class RequestPrecondition {
private static String ILLEGAL_NUMBER = "number should be positive";
public static void checkArgument(String... args) {
checkArgument(!StringUtils.isContainEmpty(args), CONTAIN_EMPTY_ARGUMENT);
public static void checkArgumentsNotEmpty(String... args) {
checkArguments(!StringUtils.isContainEmpty(args), CONTAIN_EMPTY_ARGUMENT);
}
public static void checkModel(boolean valid){
checkArgument(valid, ILLEGAL_MODEL);
checkArguments(valid, ILLEGAL_MODEL);
}
public static void checkArgument(boolean expression, Object errorMessage) {
public static void checkArguments(boolean expression, Object errorMessage) {
if (!expression) {
throw new BadRequestException(String.valueOf(errorMessage));
}
......@@ -36,6 +36,14 @@ public class RequestPrecondition {
}
}
public static void checkNumberPositive(long... args){
for (long num: args){
if (num <= 0){
throw new BadRequestException(ILLEGAL_NUMBER);
}
}
}
public static void checkNumberNotNegative(int... args){
for (int num: args){
if (num < 0){
......
package com.ctrip.framework.apollo.core.enums;
import com.google.common.base.Preconditions;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public enum Env{
LOCAL, DEV, FWS, FAT, UAT, LPT, PRO, TOOLS
LOCAL, DEV, FWS, FAT, UAT, LPT, PRO, TOOLS;
public static Env fromString(String env) {
Env environment = EnvUtils.transformEnv(env);
Preconditions.checkArgument(environment != null, String.format("Env %s is invalid", env));
return environment;
}
}
package com.ctrip.framework.apollo.portal;
package com.ctrip.framework.apollo;
import com.ctrip.framework.apollo.common.ApolloCommonConfig;
......@@ -16,8 +16,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableAutoConfiguration
@EnableTransactionManagement
@ComponentScan(basePackageClasses = {ApolloCommonConfig.class,
PortalApplication.class})
@ComponentScan(basePackageClasses = {ApolloCommonConfig.class, PortalApplication.class})
public class PortalApplication {
public static void main(String[] args) throws Exception {
......
package com.ctrip.framework.apollo.openapi.auth;
import com.ctrip.framework.apollo.openapi.service.ConsumerRolePermissionService;
import com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtil;
import com.ctrip.framework.apollo.portal.constant.PermissionType;
import com.ctrip.framework.apollo.portal.util.RoleUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class ConsumerPermissionValidator {
@Autowired
private ConsumerRolePermissionService permissionService;
@Autowired
private ConsumerAuthUtil consumerAuthUtil;
public boolean hasModifyNamespacePermission(HttpServletRequest request, String appId, String
namespaceName) {
return permissionService.consumerHasPermission(consumerAuthUtil.retrieveConsumerId(request),
PermissionType.MODIFY_NAMESPACE,
RoleUtils.buildNamespaceTargetId(appId, namespaceName));
}
public boolean hasReleaseNamespacePermission(HttpServletRequest request, String appId, String
namespaceName) {
return permissionService.consumerHasPermission(consumerAuthUtil.retrieveConsumerId(request),
PermissionType.RELEASE_NAMESPACE,
RoleUtils.buildNamespaceTargetId(appId, namespaceName));
}
}
package com.ctrip.framework.apollo.openapi.dto;
import com.ctrip.framework.apollo.common.dto.BaseDTO;
public class OpenItemDTO extends BaseDTO {
private long id;
private String key;
private String value;
private String comment;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}
package com.ctrip.framework.apollo.openapi.dto;
import com.ctrip.framework.apollo.common.dto.BaseDTO;
import java.util.List;
public class OpenNamespaceDTO extends BaseDTO {
private String appId;
private String clusterName;
private String namespaceName;
private String comment;
private String format;
private boolean isPublic;
private List<OpenItemDTO> items;
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public String getNamespaceName() {
return namespaceName;
}
public void setNamespaceName(String namespaceName) {
this.namespaceName = namespaceName;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public boolean isPublic() {
return isPublic;
}
public void setPublic(boolean aPublic) {
isPublic = aPublic;
}
public List<OpenItemDTO> getItems() {
return items;
}
public void setItems(List<OpenItemDTO> items) {
this.items = items;
}
}
package com.ctrip.framework.apollo.openapi.dto;
public class OpenNamespaceLockDTO {
private String namespaceName;
private boolean isLocked;
private String lockedBy;
public String getNamespaceName() {
return namespaceName;
}
public void setNamespaceName(String namespaceName) {
this.namespaceName = namespaceName;
}
public boolean isLocked() {
return isLocked;
}
public void setLocked(boolean locked) {
isLocked = locked;
}
public String getLockedBy() {
return lockedBy;
}
public void setLockedBy(String lockedBy) {
this.lockedBy = lockedBy;
}
}
package com.ctrip.framework.apollo.openapi.dto;
import com.ctrip.framework.apollo.common.dto.BaseDTO;
import java.util.Map;
public class OpenReleaseDTO extends BaseDTO {
private String appId;
private String clusterName;
private String namespaceName;
private String name;
private Map<String, String> configurations;
private String comment;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public String getNamespaceName() {
return namespaceName;
}
public void setNamespaceName(String namespaceName) {
this.namespaceName = namespaceName;
}
public Map<String, String> getConfigurations() {
return configurations;
}
public void setConfigurations(Map<String, String> configurations) {
this.configurations = configurations;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}
package com.ctrip.framework.apollo.openapi.entity;
import com.ctrip.framework.apollo.common.entity.BaseEntity;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "Consumer")
@SQLDelete(sql = "Update Consumer set isDeleted = 1 where id = ?")
@Where(clause = "isDeleted = 0")
public class Consumer extends BaseEntity {
@Column(name = "Name", nullable = false)
private String name;
@Column(name = "AppId", nullable = false)
private String appId;
@Column(name = "OrgId", nullable = false)
private String orgId;
@Column(name = "OrgName", nullable = false)
private String orgName;
@Column(name = "OwnerName", nullable = false)
private String ownerName;
@Column(name = "OwnerEmail", nullable = false)
private String ownerEmail;
public String getAppId() {
return appId;
}
public String getName() {
return name;
}
public String getOrgId() {
return orgId;
}
public String getOrgName() {
return orgName;
}
public String getOwnerEmail() {
return ownerEmail;
}
public String getOwnerName() {
return ownerName;
}
public void setAppId(String appId) {
this.appId = appId;
}
public void setName(String name) {
this.name = name;
}
public void setOrgId(String orgId) {
this.orgId = orgId;
}
public void setOrgName(String orgName) {
this.orgName = orgName;
}
public void setOwnerEmail(String ownerEmail) {
this.ownerEmail = ownerEmail;
}
public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
}
public String toString() {
return toStringHelper().add("name", name).add("appId", appId)
.add("orgId", orgId)
.add("orgName", orgName)
.add("ownerName", ownerName)
.add("ownerEmail", ownerEmail).toString();
}
}
package com.ctrip.framework.apollo.openapi.entity;
import com.ctrip.framework.apollo.common.entity.BaseEntity;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Entity
@Table(name = "ConsumerRole")
@SQLDelete(sql = "Update ConsumerRole set isDeleted = 1 where id = ?")
@Where(clause = "isDeleted = 0")
public class ConsumerRole extends BaseEntity {
@Column(name = "ConsumerId", nullable = false)
private long consumerId;
@Column(name = "RoleId", nullable = false)
private long roleId;
public long getConsumerId() {
return consumerId;
}
public void setConsumerId(long consumerId) {
this.consumerId = consumerId;
}
public long getRoleId() {
return roleId;
}
public void setRoleId(long roleId) {
this.roleId = roleId;
}
}
package com.ctrip.framework.apollo.openapi.entity;
import com.ctrip.framework.apollo.common.entity.BaseEntity;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Entity
@Table(name = "ConsumerToken")
@SQLDelete(sql = "Update ConsumerToken set isDeleted = 1 where id = ?")
@Where(clause = "isDeleted = 0")
public class ConsumerToken extends BaseEntity {
@Column(name = "ConsumerId", nullable = false)
private long consumerId;
@Column(name = "token", nullable = false)
private String token;
@Column(name = "Expires", nullable = false)
private Date expires;
public long getConsumerId() {
return consumerId;
}
public void setConsumerId(long consumerId) {
this.consumerId = consumerId;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public Date getExpires() {
return expires;
}
public void setExpires(Date expires) {
this.expires = expires;
}
}
package com.ctrip.framework.apollo.openapi.filter;
import com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtil;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class ConsumerAuthenticationFilter implements Filter {
private ConsumerAuthUtil consumerAuthUtil;
public ConsumerAuthenticationFilter(ConsumerAuthUtil consumerAuthUtil) {
this.consumerAuthUtil = consumerAuthUtil;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//nothing
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws
IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String token = request.getHeader("Authorization");
Long consumerId = consumerAuthUtil.getConsumerId(token);
if (consumerId == null) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
return;
}
consumerAuthUtil.storeConsumerId(request, consumerId);
chain.doFilter(req, resp);
}
@Override
public void destroy() {
//nothing
}
}
package com.ctrip.framework.apollo.openapi.repository;
import com.ctrip.framework.apollo.openapi.entity.Consumer;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public interface ConsumerRepository extends PagingAndSortingRepository<Consumer, Long> {
}
package com.ctrip.framework.apollo.openapi.repository;
import com.ctrip.framework.apollo.openapi.entity.ConsumerRole;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public interface ConsumerRoleRepository extends PagingAndSortingRepository<ConsumerRole, Long> {
/**
* find consumer roles by userId
*
* @param consumerId consumer id
*/
List<ConsumerRole> findByConsumerId(long consumerId);
/**
* find consumer roles by roleId
*/
List<ConsumerRole> findByRoleId(long roleId);
}
package com.ctrip.framework.apollo.openapi.repository;
import com.ctrip.framework.apollo.openapi.entity.ConsumerToken;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.Date;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public interface ConsumerTokenRepository extends PagingAndSortingRepository<ConsumerToken, Long> {
/**
* find consumer token by token
*
* @param token the token
* @param validDate the date when the token is valid
*/
ConsumerToken findTopByTokenAndExpiresAfter(String token, Date validDate);
}
package com.ctrip.framework.apollo.openapi.service;
import com.google.common.collect.FluentIterable;
import com.ctrip.framework.apollo.openapi.entity.ConsumerRole;
import com.ctrip.framework.apollo.openapi.repository.ConsumerRoleRepository;
import com.ctrip.framework.apollo.portal.entity.po.Permission;
import com.ctrip.framework.apollo.portal.entity.po.RolePermission;
import com.ctrip.framework.apollo.portal.repository.PermissionRepository;
import com.ctrip.framework.apollo.portal.repository.RolePermissionRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Set;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Service
public class ConsumerRolePermissionService {
@Autowired
private PermissionRepository permissionRepository;
@Autowired
private ConsumerRoleRepository consumerRoleRepository;
@Autowired
private RolePermissionRepository rolePermissionRepository;
/**
* Check whether user has the permission
*/
public boolean consumerHasPermission(long consumerId, String permissionType, String targetId) {
Permission permission =
permissionRepository.findTopByPermissionTypeAndTargetId(permissionType, targetId);
if (permission == null) {
return false;
}
List<ConsumerRole> consumerRoles = consumerRoleRepository.findByConsumerId(consumerId);
if (CollectionUtils.isEmpty(consumerRoles)) {
return false;
}
Set<Long> roleIds =
FluentIterable.from(consumerRoles).transform(consumerRole -> consumerRole.getRoleId())
.toSet();
List<RolePermission> rolePermissions = rolePermissionRepository.findByRoleIdIn(roleIds);
if (CollectionUtils.isEmpty(rolePermissions)) {
return false;
}
for (RolePermission rolePermission : rolePermissions) {
if (rolePermission.getPermissionId() == permission.getId()) {
return true;
}
}
return false;
}
}
package com.ctrip.framework.apollo.openapi.service;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.hash.Hashing;
import com.ctrip.framework.apollo.openapi.entity.Consumer;
import com.ctrip.framework.apollo.openapi.entity.ConsumerToken;
import com.ctrip.framework.apollo.openapi.repository.ConsumerRepository;
import com.ctrip.framework.apollo.openapi.repository.ConsumerTokenRepository;
import com.ctrip.framework.apollo.portal.service.ServerConfigService;
import org.apache.commons.lang.time.FastDateFormat;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Service
public class ConsumerService implements InitializingBean {
static final String TOKEN_SALT_KEY = "consumer.token.salt";
private static final FastDateFormat TIMESTAMP_FORMAT = FastDateFormat.getInstance
("yyyyMMddHHmmss");
private static final Joiner KEY_JOINER = Joiner.on("|");
@Autowired
private ConsumerTokenRepository consumerTokenRepository;
@Autowired
private ConsumerRepository consumerRepository;
@Autowired
private ServerConfigService serverConfigService;
private String consumerTokenSalt;
public Long getConsumerIdByToken(String token) {
if (Strings.isNullOrEmpty(token)) {
return null;
}
ConsumerToken consumerToken = consumerTokenRepository.findTopByTokenAndExpiresAfter(token,
new Date());
return consumerToken == null ? null : consumerToken.getConsumerId();
}
public Consumer getConsumerByConsumerId(long consumerId) {
return consumerRepository.findOne(consumerId);
}
public void generateAndEnrichConsumerToken(ConsumerToken consumerToken) {
Consumer consumer = getConsumerByConsumerId(consumerToken.getConsumerId());
Preconditions.checkState(consumer != null, String.format("Consumer with id: %d not found!",
consumerToken.getConsumerId()));
if (consumerToken.getDataChangeCreatedTime() == null) {
consumerToken.setDataChangeCreatedTime(new Date());
}
consumerToken.setToken(generateConsumerToken(consumer.getAppId(), consumerToken
.getDataChangeCreatedTime(), consumerTokenSalt));
}
@Transactional
public ConsumerToken createConsumerToken(ConsumerToken entity) {
entity.setId(0); //for protection
return consumerTokenRepository.save(entity);
}
String generateConsumerToken(String consumerAppId, Date generationTime, String
consumerTokenSalt) {
return Hashing.sha1().hashString(KEY_JOINER.join(consumerAppId, TIMESTAMP_FORMAT.format
(generationTime), consumerTokenSalt), Charsets.UTF_8).toString();
}
@Override
public void afterPropertiesSet() throws Exception {
consumerTokenSalt = serverConfigService.getValue(TOKEN_SALT_KEY, "apollo-portal");
}
}
package com.ctrip.framework.apollo.openapi.util;
import com.ctrip.framework.apollo.openapi.service.ConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Service
public class ConsumerAuthUtil {
static final String CONSUMER_ID = "ApolloConsumerId";
@Autowired
private ConsumerService consumerService;
public Long getConsumerId(String token) {
return consumerService.getConsumerIdByToken(token);
}
public void storeConsumerId(HttpServletRequest request, Long consumerId) {
request.setAttribute(CONSUMER_ID, consumerId);
}
public long retrieveConsumerId(HttpServletRequest request) {
Object value = request.getAttribute(CONSUMER_ID);
try {
return Long.parseLong(value.toString());
} catch (Throwable ex) {
throw new IllegalStateException("No consumer id!", ex);
}
}
}
package com.ctrip.framework.apollo.openapi.util;
import com.google.common.base.Preconditions;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.ctrip.framework.apollo.common.dto.ItemDTO;
import com.ctrip.framework.apollo.common.dto.NamespaceLockDTO;
import com.ctrip.framework.apollo.common.dto.ReleaseDTO;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class OpenApiBeanUtils {
private static Gson gson = new Gson();
private static Type type = new TypeToken<Map<String, String>>() {
}.getType();
public static OpenItemDTO transformFromItemDTO(ItemDTO item) {
Preconditions.checkArgument(item != null);
return BeanUtils.transfrom(OpenItemDTO.class, item);
}
public static ItemDTO transformToItemDTO(OpenItemDTO openItemDTO) {
Preconditions.checkArgument(openItemDTO != null);
return BeanUtils.transfrom(ItemDTO.class, openItemDTO);
}
public static OpenReleaseDTO transformFromReleaseDTO(ReleaseDTO release) {
Preconditions.checkArgument(release != null);
OpenReleaseDTO openReleaseDTO = BeanUtils.transfrom(OpenReleaseDTO.class, release);
Map<String, String> configs = gson.fromJson(release.getConfigurations(), type);
openReleaseDTO.setConfigurations(configs);
return openReleaseDTO;
}
public static OpenNamespaceDTO transformFromNamespaceVO(NamespaceVO namespaceVO) {
Preconditions.checkArgument(namespaceVO != null);
OpenNamespaceDTO openNamespaceDTO = BeanUtils.transfrom(OpenNamespaceDTO.class, namespaceVO
.getBaseInfo());
//app namespace info
openNamespaceDTO.setFormat(namespaceVO.getFormat());
openNamespaceDTO.setComment(namespaceVO.getComment());
openNamespaceDTO.setPublic(namespaceVO.isPublic());
//items
List<OpenItemDTO> items = new LinkedList<>();
List<NamespaceVO.ItemVO> itemVOs = namespaceVO.getItems();
if (!CollectionUtils.isEmpty(itemVOs)) {
items.addAll(itemVOs.stream().map(itemVO -> transformFromItemDTO(itemVO.getItem())).collect
(Collectors.toList()));
}
openNamespaceDTO.setItems(items);
return openNamespaceDTO;
}
public static List<OpenNamespaceDTO> batchTransformFromNamespaceVOs(List<NamespaceVO>
namespaceVOs) {
if (CollectionUtils.isEmpty(namespaceVOs)) {
return Collections.emptyList();
}
List<OpenNamespaceDTO> openNamespaceDTOs =
namespaceVOs.stream().map(OpenApiBeanUtils::transformFromNamespaceVO)
.collect(Collectors.toCollection(LinkedList::new));
return openNamespaceDTOs;
}
public static OpenNamespaceLockDTO transformFromNamespaceLockDTO(String namespaceName,
NamespaceLockDTO
namespaceLock) {
OpenNamespaceLockDTO lock = new OpenNamespaceLockDTO();
lock.setNamespaceName(namespaceName);
if (namespaceLock == null) {
lock.setLocked(false);
} else {
lock.setLocked(true);
lock.setLockedBy(namespaceLock.getDataChangeCreatedBy());
}
return lock;
}
}
package com.ctrip.framework.apollo.openapi.v1.controller;
import com.ctrip.framework.apollo.common.dto.ItemDTO;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;
import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils;
import com.ctrip.framework.apollo.portal.service.ItemService;
import com.ctrip.framework.apollo.portal.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController("openapiItemController")
@RequestMapping("/openapi/v1/envs/{env}")
public class ItemController {
@Autowired
private ItemService itemService;
@Autowired
private UserService userService;
@PreAuthorize(value = "@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.POST)
public OpenItemDTO createItem(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String
namespaceName,
@RequestBody OpenItemDTO item, HttpServletRequest request) {
RequestPrecondition.checkArguments(
!StringUtils.isContainEmpty(item.getKey(), item.getValue(), item.getDataChangeCreatedBy()),
"key,value,dataChangeCreatedBy 字段不能为空");
if (userService.findByUserId(item.getDataChangeCreatedBy()) == null) {
throw new BadRequestException("用户不存在.");
}
ItemDTO toCreate = OpenApiBeanUtils.transformToItemDTO(item);
//protect
toCreate.setLineNum(0);
toCreate.setId(0);
toCreate.setDataChangeLastModifiedBy(toCreate.getDataChangeCreatedBy());
ItemDTO createdItem = itemService.createItem(appId, Env.fromString(env),
clusterName, namespaceName, toCreate);
return OpenApiBeanUtils.transformFromItemDTO(createdItem);
}
@PreAuthorize(value = "@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}", method = RequestMethod.PUT)
public void updateItem(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName,
@PathVariable long itemId, @RequestBody OpenItemDTO item,
HttpServletRequest request) {
RequestPrecondition.checkArguments(item != null && item.getId() > 0 && itemId == item.getId(),
"item data error");
RequestPrecondition.checkArguments(
!StringUtils.isContainEmpty(item.getKey(), item.getValue(), item
.getDataChangeLastModifiedBy()),
"key,value,dataChangeLastModifiedBy 字段不能为空");
if (userService.findByUserId(item.getDataChangeLastModifiedBy()) == null) {
throw new BadRequestException("用户不存在.");
}
ItemDTO toUpdateItem = itemService.loadItem(Env.fromString(env), itemId);
if (toUpdateItem == null) {
throw new BadRequestException("item not exist");
}
//protect. only value,comment,lastModifiedBy can be modified
toUpdateItem.setComment(item.getComment());
toUpdateItem.setValue(item.getValue());
toUpdateItem.setDataChangeLastModifiedBy(item.getDataChangeLastModifiedBy());
itemService.updateItem(appId, Env.fromString(env), clusterName, namespaceName,
toUpdateItem);
}
@PreAuthorize(value = "@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}", method = RequestMethod.DELETE)
public void deleteItem(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName,
@PathVariable long itemId, @RequestParam String operator,
HttpServletRequest request) {
if (userService.findByUserId(operator) == null) {
throw new BadRequestException("用户不存在.");
}
itemService.deleteItem(Env.fromString(env), itemId, operator);
}
}
package com.ctrip.framework.apollo.openapi.v1.controller;
import com.ctrip.framework.apollo.common.dto.NamespaceDTO;
import com.ctrip.framework.apollo.common.dto.NamespaceLockDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO;
import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.service.NamespaceLockService;
import com.ctrip.framework.apollo.portal.service.NamespaceService;
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.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController("openapiNamespaceController")
@RequestMapping("/openapi/v1/envs/{env}")
public class NamespaceController {
@Autowired
private NamespaceLockService namespaceLockService;
@Autowired
private NamespaceService namespaceService;
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces", method = RequestMethod.GET)
public List<OpenNamespaceDTO> findNamespaces(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName) {
return OpenApiBeanUtils
.batchTransformFromNamespaceVOs(namespaceService.findNamespaces(appId, Env
.fromString(env), clusterName));
}
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName:.+}", method = RequestMethod.GET)
public OpenNamespaceDTO loadNamespace(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String
namespaceName) {
NamespaceVO namespaceVO = namespaceService.loadNamespace(appId, Env.fromString
(env), clusterName, namespaceName);
if (namespaceVO == null) {
return null;
}
return OpenApiBeanUtils.transformFromNamespaceVO(namespaceVO);
}
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock", method = RequestMethod.GET)
public OpenNamespaceLockDTO getNamespaceLock(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable
String namespaceName) {
NamespaceDTO namespace = namespaceService.loadNamespaceBaseInfo(appId, Env
.fromString(env), clusterName, namespaceName);
NamespaceLockDTO lockDTO = namespaceLockService.getNamespaceLock(appId, Env
.fromString(env), clusterName, namespaceName);
return OpenApiBeanUtils.transformFromNamespaceLockDTO(namespace.getNamespaceName(), lockDTO);
}
}
package com.ctrip.framework.apollo.openapi.v1.controller;
import com.ctrip.framework.apollo.common.dto.ReleaseDTO;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO;
import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.service.ReleaseService;
import com.ctrip.framework.apollo.portal.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;
@RestController("openapiReleaseController")
@RequestMapping("/openapi/v1/envs/{env}")
public class ReleaseController {
@Autowired
private ReleaseService releaseService;
@Autowired
private UserService userService;
@PreAuthorize(value = "@consumerPermissionValidator.hasReleaseNamespacePermission(#request, #appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases", method = RequestMethod.POST)
public OpenReleaseDTO createRelease(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String
namespaceName,
@RequestBody NamespaceReleaseModel model,
HttpServletRequest request) {
checkModel(model != null);
RequestPrecondition.checkArguments(!StringUtils.isContainEmpty(model.getReleaseBy(), model
.getReleaseTitle()),
"releaseTitle and releaseBy can not be empty");
if (userService.findByUserId(model.getReleaseBy()) == null) {
throw new BadRequestException("用户不存在.");
}
model.setAppId(appId);
model.setEnv(Env.fromString(env).toString());
model.setClusterName(clusterName);
model.setNamespaceName(namespaceName);
return OpenApiBeanUtils.transformFromReleaseDTO(releaseService.createRelease(model));
}
@RequestMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest", method = RequestMethod.GET)
public OpenReleaseDTO loadLatestActiveRelease(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable
String namespaceName) {
ReleaseDTO releaseDTO = releaseService.loadLatestRelease(appId, Env.fromString
(env), clusterName, namespaceName);
if (releaseDTO == null) {
return null;
}
return OpenApiBeanUtils.transformFromReleaseDTO(releaseDTO);
}
}
......@@ -90,6 +90,10 @@ public class AdminServiceAPI {
return Arrays.asList(itemDTOs);
}
public ItemDTO loadItem(Env env, long itemId) {
return restTemplate.get(env, "/items/{itemId}", ItemDTO.class, itemId);
}
public void updateItemsByChangeSet(String appId, Env env, String clusterName, String namespace,
ItemChangeSets changeSets) {
restTemplate.post(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/itemset",
......@@ -104,8 +108,7 @@ public class AdminServiceAPI {
public ItemDTO createItem(String appId, Env env, String clusterName, String namespace, ItemDTO item) {
return restTemplate.post(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items",
item, ItemDTO.class, appId, clusterName, namespace)
;
item, ItemDTO.class, appId, clusterName, namespace);
}
public void deleteItem(Env env, long itemId, String operator) {
......
......@@ -73,7 +73,7 @@ public class AdminServiceAddressLocator {
public List<ServiceDTO> getServiceList(Env env) {
List<ServiceDTO> services = cache.get(env);
if (CollectionUtils.isEmpty(services)) {
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
List<ServiceDTO> randomConfigServices = Lists.newArrayList(services);
Collections.shuffle(randomConfigServices);
......@@ -81,7 +81,7 @@ public class AdminServiceAddressLocator {
}
//Maintain admin server address
class RefreshAdminServerAddressTask implements Runnable {
private class RefreshAdminServerAddressTask implements Runnable {
@Override
public void run() {
......
......@@ -57,4 +57,8 @@ public class PermissionValidator {
return rolePermissionService.isSuperAdmin(userInfoHolder.getUser().getUserId());
}
}
public boolean isSuperAdmin() {
return rolePermissionService.isSuperAdmin(userInfoHolder.getUser().getUserId());
}
}
package com.ctrip.framework.apollo.portal.configuration;
import com.google.common.collect.Maps;
import com.ctrip.framework.apollo.openapi.filter.ConsumerAuthenticationFilter;
import com.ctrip.framework.apollo.openapi.service.ConsumerService;
import com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtil;
import com.ctrip.framework.apollo.portal.auth.LogoutHandler;
import com.ctrip.framework.apollo.portal.auth.SsoHeartbeatHandler;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.auth.ctrip.CtripLogoutHandler;
import com.ctrip.framework.apollo.portal.auth.ctrip.CtripSsoHeartbeatHandler;
import com.ctrip.framework.apollo.portal.auth.ctrip.CtripUserInfoHolder;
......@@ -8,9 +16,6 @@ import com.ctrip.framework.apollo.portal.auth.defaultimpl.DefaultLogoutHandler;
import com.ctrip.framework.apollo.portal.auth.defaultimpl.DefaultSsoHeartbeatHandler;
import com.ctrip.framework.apollo.portal.auth.defaultimpl.DefaultUserInfoHolder;
import com.ctrip.framework.apollo.portal.auth.defaultimpl.DefaultUserService;
import com.ctrip.framework.apollo.portal.auth.LogoutHandler;
import com.ctrip.framework.apollo.portal.auth.SsoHeartbeatHandler;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.service.ServerConfigService;
import com.ctrip.framework.apollo.portal.service.UserService;
......@@ -47,21 +52,21 @@ public class AuthConfiguration {
private ServerConfigService serverConfigService;
@Bean
public ServletListenerRegistrationBean redisAppSettingListner(){
public ServletListenerRegistrationBean redisAppSettingListner() {
ServletListenerRegistrationBean redisAppSettingListner = new ServletListenerRegistrationBean();
redisAppSettingListner.setListener(listener("org.jasig.cas.client.credis.CRedisAppSettingListner"));
return redisAppSettingListner;
}
@Bean
public ServletListenerRegistrationBean singleSignOutHttpSessionListener(){
public ServletListenerRegistrationBean singleSignOutHttpSessionListener() {
ServletListenerRegistrationBean singleSignOutHttpSessionListener = new ServletListenerRegistrationBean();
singleSignOutHttpSessionListener.setListener(listener("org.jasig.cas.client.session.SingleSignOutHttpSessionListener"));
return singleSignOutHttpSessionListener;
}
@Bean
public FilterRegistrationBean casFilter(){
public FilterRegistrationBean casFilter() {
FilterRegistrationBean singleSignOutFilter = new FilterRegistrationBean();
singleSignOutFilter.setFilter(filter("org.jasig.cas.client.session.SingleSignOutFilter"));
singleSignOutFilter.addUrlPatterns("/*");
......@@ -69,15 +74,16 @@ public class AuthConfiguration {
}
@Bean
public FilterRegistrationBean authenticationFilter(){
public FilterRegistrationBean authenticationFilter() {
FilterRegistrationBean casFilter = new FilterRegistrationBean();
Map<String, String> filterInitParam = new HashMap();
Map<String, String> filterInitParam = Maps.newHashMap();
filterInitParam.put("redisClusterName", "casClientPrincipal");
filterInitParam.put("serverName", serverConfigService.getValue("serverName"));
filterInitParam.put("casServerLoginUrl", serverConfigService.getValue("casServerLoginUrl"));
//we don't want to use session to store login information, since we will be deployed to a cluster, not a single instance
filterInitParam.put("useSession", "false");
filterInitParam.put("/openapi.*", "exclude");
casFilter.setInitParameters(filterInitParam);
casFilter.setFilter(filter("com.ctrip.framework.apollo.sso.filter.ApolloAuthenticationFilter"));
......@@ -87,9 +93,9 @@ public class AuthConfiguration {
}
@Bean
public FilterRegistrationBean casValidationFilter(){
public FilterRegistrationBean casValidationFilter() {
FilterRegistrationBean casValidationFilter = new FilterRegistrationBean();
Map<String, String> filterInitParam = new HashMap();
Map<String, String> filterInitParam = Maps.newHashMap();
filterInitParam.put("casServerUrlPrefix", serverConfigService.getValue("casServerUrlPrefix"));
filterInitParam.put("serverName", serverConfigService.getValue("serverName"));
filterInitParam.put("encoding", "UTF-8");
......@@ -107,11 +113,15 @@ public class AuthConfiguration {
}
@Bean
public FilterRegistrationBean assertionHolder(){
public FilterRegistrationBean assertionHolder() {
FilterRegistrationBean assertionHolderFilter = new FilterRegistrationBean();
Map<String, String> filterInitParam = Maps.newHashMap();
filterInitParam.put("/openapi.*", "exclude");
assertionHolderFilter.setInitParameters(filterInitParam);
assertionHolderFilter.setFilter(filter("com.ctrip.framework.apollo.sso.filter.ApolloAssertionThreadLocalFilter"));
assertionHolderFilter.addUrlPatterns("/*");
......@@ -119,16 +129,16 @@ public class AuthConfiguration {
}
@Bean
public CtripUserInfoHolder ctripUserInfoHolder(){
public CtripUserInfoHolder ctripUserInfoHolder() {
return new CtripUserInfoHolder();
}
@Bean
public CtripLogoutHandler logoutHandler(){
public CtripLogoutHandler logoutHandler() {
return new CtripLogoutHandler();
}
private Filter filter(String className){
private Filter filter(String className) {
Class clazz = null;
try {
clazz = Class.forName(className);
......@@ -140,7 +150,7 @@ public class AuthConfiguration {
}
private EventListener listener(String className){
private EventListener listener(String className) {
Class clazz = null;
try {
clazz = Class.forName(className);
......@@ -168,6 +178,16 @@ public class AuthConfiguration {
@Configuration
static class DefaultAuthAutoConfiguration {
@Bean
public FilterRegistrationBean openApiAuthenticationFilter(ConsumerAuthUtil consumerAuthUtil) {
FilterRegistrationBean openApiFilter = new FilterRegistrationBean();
openApiFilter.setFilter(new ConsumerAuthenticationFilter(consumerAuthUtil));
openApiFilter.addUrlPatterns("/openapi/*");
return openApiFilter;
}
@Bean
@ConditionalOnMissingBean(SsoHeartbeatHandler.class)
public SsoHeartbeatHandler defaultSsoHeartbeatHandler() {
......@@ -176,13 +196,13 @@ public class AuthConfiguration {
@Bean
@ConditionalOnMissingBean(UserInfoHolder.class)
public DefaultUserInfoHolder notCtripUserInfoHolder(){
public DefaultUserInfoHolder notCtripUserInfoHolder() {
return new DefaultUserInfoHolder();
}
@Bean
@ConditionalOnMissingBean(LogoutHandler.class)
public DefaultLogoutHandler logoutHandler(){
public DefaultLogoutHandler logoutHandler() {
return new DefaultLogoutHandler();
}
......
......@@ -5,6 +5,7 @@ import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.common.http.MultiResponseEntity;
import com.ctrip.framework.apollo.common.http.RichResponseEntity;
import com.ctrip.framework.apollo.common.utils.InputValidator;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.portal.PortalSettings;
......@@ -27,7 +28,6 @@ import org.springframework.web.client.HttpClientErrorException;
import java.util.List;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkArgument;
@RestController
@RequestMapping("/apps")
......@@ -75,8 +75,8 @@ public class AppController {
@RequestMapping(value = "", method = RequestMethod.POST)
public ResponseEntity<Void> create(@RequestBody App app) {
checkArgument(app.getName(), app.getAppId(), app.getOwnerName(),
app.getOrgId(), app.getOrgName());
RequestPrecondition.checkArgumentsNotEmpty(app.getName(), app.getAppId(), app.getOwnerName(),
app.getOrgId(), app.getOrgName());
if (!InputValidator.isValidClusterNamespace(app.getAppId())) {
throw new BadRequestException(String.format("AppId格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE));
}
......@@ -98,8 +98,8 @@ public class AppController {
"application/json"})
public ResponseEntity<Void> create(@PathVariable String env, @RequestBody App app) {
checkArgument(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName(),
app.getOrgId(), app.getOrgName());
RequestPrecondition.checkArgumentsNotEmpty(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName(),
app.getOrgId(), app.getOrgName());
if (!InputValidator.isValidClusterNamespace(app.getAppId())) {
throw new BadRequestException(InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE);
}
......
......@@ -2,6 +2,7 @@ package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.common.utils.InputValidator;
import com.ctrip.framework.apollo.common.dto.ClusterDTO;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
......@@ -15,7 +16,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkArgument;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;
@RestController
......@@ -32,7 +32,7 @@ public class ClusterController {
@RequestBody ClusterDTO cluster){
checkModel(cluster != null);
checkArgument(cluster.getAppId(), cluster.getName());
RequestPrecondition.checkArgumentsNotEmpty(cluster.getAppId(), cluster.getName());
if (!InputValidator.isValidClusterNamespace(cluster.getName())) {
throw new BadRequestException(String.format("Cluster格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE));
......
package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.openapi.entity.ConsumerToken;
import com.ctrip.framework.apollo.openapi.service.ConsumerService;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RestController
@RequestMapping("/consumers")
public class ConsumerController {
private static final Date DEFAULT_EXPIRES = new GregorianCalendar(2099, Calendar.JANUARY, 1)
.getTime();
@Autowired
private ConsumerService consumerService;
@Autowired
private UserInfoHolder userInfoHolder;
@PreAuthorize(value = "@permissionValidator.isSuperAdmin()")
@RequestMapping(value = "/{consumerId}/tokens", method = RequestMethod.POST)
public ConsumerToken createConsumerToken(@PathVariable long consumerId,
@RequestParam(value = "expires", required = false)
@DateTimeFormat(pattern = "yyyyMMddHHmmss") Date
expires) {
if (expires == null) {
expires = DEFAULT_EXPIRES;
}
ConsumerToken consumerToken = generateConsumerToken(consumerId, expires);
return consumerService.createConsumerToken(consumerToken);
}
private ConsumerToken generateConsumerToken(long consumerId, Date expires) {
String createdBy = userInfoHolder.getUser().getUserId();
Date createdTime = new Date();
ConsumerToken consumerToken = new ConsumerToken();
consumerToken.setConsumerId(consumerId);
consumerToken.setExpires(expires);
consumerToken.setDataChangeCreatedBy(createdBy);
consumerToken.setDataChangeCreatedTime(createdTime);
consumerToken.setDataChangeLastModifiedBy(createdBy);
consumerToken.setDataChangeLastModifiedTime(createdTime);
consumerService.generateAndEnrichConsumerToken(consumerToken);
return consumerToken;
}
}
......@@ -4,10 +4,11 @@ import com.ctrip.framework.apollo.common.dto.ItemDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceSyncModel;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceTextModel;
import com.ctrip.framework.apollo.portal.service.ConfigService;
import com.ctrip.framework.apollo.portal.service.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
......@@ -29,7 +30,9 @@ import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkM
public class ItemController {
@Autowired
private ConfigService configService;
private ItemService configService;
@Autowired
private UserInfoHolder userInfoHolder;
@PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.PUT, consumes = {
......@@ -77,7 +80,7 @@ public class ItemController {
if (itemId <= 0){
throw new BadRequestException("item id invalid");
}
configService.deleteItem(Env.valueOf(env), itemId);
configService.deleteItem(Env.valueOf(env), itemId, userInfoHolder.getUser().getUserId());
}
......
......@@ -4,6 +4,7 @@ import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.common.utils.InputValidator;
import com.ctrip.framework.apollo.common.dto.NamespaceDTO;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
......@@ -33,7 +34,6 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkArgument;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;
@RestController
......@@ -71,7 +71,8 @@ public class NamespaceController {
for (NamespaceCreationModel model : models) {
NamespaceDTO namespace = model.getNamespace();
checkArgument(model.getEnv(), namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName());
RequestPrecondition
.checkArgumentsNotEmpty(model.getEnv(), namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName());
try {
// TODO: 16/6/17 某些环境创建失败,统一处理这种场景
......@@ -89,7 +90,7 @@ public class NamespaceController {
@RequestMapping(value = "/apps/{appId}/appnamespaces", method = RequestMethod.POST)
public AppNamespace createAppNamespace(@PathVariable String appId, @RequestBody AppNamespace appNamespace) {
checkArgument(appNamespace.getAppId(), appNamespace.getName());
RequestPrecondition.checkArgumentsNotEmpty(appNamespace.getAppId(), appNamespace.getName());
if (!InputValidator.isValidAppNamespace(appNamespace.getName())) {
throw new BadRequestException(String.format("Namespace格式错误: %s",
InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE + " & "
......
......@@ -3,6 +3,7 @@ package com.ctrip.framework.apollo.portal.controller;
import com.google.common.collect.Sets;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.constant.RoleType;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
......@@ -26,7 +27,6 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.Set;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkArgument;
@RestController
......@@ -94,7 +94,7 @@ public class PermissionController {
public ResponseEntity<Void> assignNamespaceRoleToUser(@PathVariable String appId, @PathVariable String namespaceName,
@PathVariable String roleType, @RequestBody String user){
checkUserExists(user);
checkArgument(user);
RequestPrecondition.checkArgumentsNotEmpty(user);
if (!RoleType.isValidRoleType(roleType)){
throw new BadRequestException("role type is illegal");
......@@ -112,7 +112,7 @@ public class PermissionController {
@RequestMapping(value = "/apps/{appId}/namespaces/{namespaceName}/roles/{roleType}", method = RequestMethod.DELETE)
public ResponseEntity<Void> removeNamespaceRoleFromUser(@PathVariable String appId, @PathVariable String namespaceName,
@PathVariable String roleType, @RequestParam String user){
checkArgument(user);
RequestPrecondition.checkArgumentsNotEmpty(user);
if (!RoleType.isValidRoleType(roleType)){
throw new BadRequestException("role type is illegal");
......@@ -138,7 +138,7 @@ public class PermissionController {
public ResponseEntity<Void> assignAppRoleToUser(@PathVariable String appId, @PathVariable String roleType,
@RequestBody String user){
checkUserExists(user);
checkArgument(user);
RequestPrecondition.checkArgumentsNotEmpty(user);
if (!RoleType.isValidRoleType(roleType)){
throw new BadRequestException("role type is illegal");
......@@ -156,7 +156,7 @@ public class PermissionController {
@RequestMapping(value = "/apps/{appId}/roles/{roleType}", method = RequestMethod.DELETE)
public ResponseEntity<Void> removeAppRoleFromUser(@PathVariable String appId, @PathVariable String roleType,
@RequestParam String user){
checkArgument(user);
RequestPrecondition.checkArgumentsNotEmpty(user);
if (!RoleType.isValidRoleType(roleType)){
throw new BadRequestException("role type is illegal");
......
......@@ -28,7 +28,7 @@ public class ReleaseController {
private ReleaseService releaseService;
@PreAuthorize(value = "@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/release")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/release", method = RequestMethod.POST)
public ReleaseDTO createRelease(@PathVariable String appId,
@PathVariable String env, @PathVariable String clusterName,
@PathVariable String namespaceName, @RequestBody NamespaceReleaseModel model) {
......
......@@ -2,17 +2,18 @@ package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.po.ServerConfig;
import com.ctrip.framework.apollo.portal.repository.ServerConfigRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkArgument;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;
/**
......@@ -26,11 +27,12 @@ public class ServerConfigController {
@Autowired
private UserInfoHolder userInfoHolder;
@PreAuthorize(value = "@permissionValidator.isSuperAdmin()")
@RequestMapping(value = "/server/config", method = RequestMethod.POST)
public ServerConfig createOrUpdate(@RequestBody ServerConfig serverConfig) {
checkModel(serverConfig != null);
checkArgument(serverConfig.getKey(), serverConfig.getValue());
RequestPrecondition.checkArgumentsNotEmpty(serverConfig.getKey(), serverConfig.getValue());
String modifiedBy = userInfoHolder.getUser().getUserId();
......
......@@ -12,6 +12,7 @@ public class NamespaceReleaseModel implements Verifiable {
private String namespaceName;
private String releaseTitle;
private String releaseComment;
private String releaseBy;
@Override
public boolean isInvalid() {
......@@ -66,4 +67,11 @@ public class NamespaceReleaseModel implements Verifiable {
this.releaseComment = releaseComment;
}
public String getReleaseBy() {
return releaseBy;
}
public void setReleaseBy(String releaseBy) {
this.releaseBy = releaseBy;
}
}
package com.ctrip.framework.apollo.portal.entity.form;
import com.ctrip.framework.apollo.common.dto.ItemDTO;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifer;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifier;
import org.springframework.util.CollectionUtils;
......@@ -9,7 +9,7 @@ import java.util.List;
public class NamespaceSyncModel implements Verifiable {
private List<NamespaceIdentifer> syncToNamespaces;
private List<NamespaceIdentifier> syncToNamespaces;
private List<ItemDTO> syncItems;
@Override
......@@ -17,19 +17,19 @@ public class NamespaceSyncModel implements Verifiable {
if (CollectionUtils.isEmpty(syncToNamespaces) || CollectionUtils.isEmpty(syncItems)){
return true;
}
for (NamespaceIdentifer namespaceIdentifer: syncToNamespaces){
if (namespaceIdentifer.isInvalid()){
for (NamespaceIdentifier namespaceIdentifier : syncToNamespaces){
if (namespaceIdentifier.isInvalid()){
return true;
}
}
return false;
}
public List<NamespaceIdentifer> getSyncToNamespaces() {
public List<NamespaceIdentifier> getSyncToNamespaces() {
return syncToNamespaces;
}
public void setSyncToNamespaces(List<NamespaceIdentifer> syncToNamespaces) {
public void setSyncToNamespaces(List<NamespaceIdentifier> syncToNamespaces) {
this.syncToNamespaces = syncToNamespaces;
}
......
......@@ -3,18 +3,18 @@ package com.ctrip.framework.apollo.portal.entity.vo;
import com.ctrip.framework.apollo.common.dto.ItemChangeSets;
public class ItemDiffs {
private NamespaceIdentifer namespace;
private NamespaceIdentifier namespace;
private ItemChangeSets diffs;
private String extInfo;
public ItemDiffs(NamespaceIdentifer namespace){
public ItemDiffs(NamespaceIdentifier namespace){
this.namespace = namespace;
}
public NamespaceIdentifer getNamespace() {
public NamespaceIdentifier getNamespace() {
return namespace;
}
public void setNamespace(NamespaceIdentifer namespace) {
public void setNamespace(NamespaceIdentifier namespace) {
this.namespace = namespace;
}
......
......@@ -4,7 +4,7 @@ import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.entity.form.Verifiable;
public class NamespaceIdentifer implements Verifiable {
public class NamespaceIdentifier implements Verifiable {
private String appId;
private String env;
private String clusterName;
......
......@@ -49,7 +49,7 @@ public class AppService {
public List<App> findAll() {
Iterable<App> apps = appRepository.findAll();
if (apps == null) {
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
return Lists.newArrayList((apps));
}
......
......@@ -20,7 +20,7 @@ import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.constant.CatEventType;
import com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifer;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifier;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceTextModel;
import com.ctrip.framework.apollo.portal.service.txtresolver.ConfigTextResolver;
import com.dianping.cat.Cat;
......@@ -30,7 +30,7 @@ import java.util.List;
import java.util.Map;
@Service
public class ConfigService {
public class ItemService {
@Autowired
private UserInfoHolder userInfoHolder;
......@@ -38,8 +38,6 @@ public class ConfigService {
private AdminServiceAPI.NamespaceAPI namespaceAPI;
@Autowired
private AdminServiceAPI.ItemAPI itemAPI;
@Autowired
private AdminServiceAPI.ReleaseAPI releaseAPI;
@Autowired
@Qualifier("fileTextResolver")
......@@ -89,9 +87,11 @@ public class ConfigService {
}
item.setNamespaceId(namespace.getId());
String username = userInfoHolder.getUser().getUserId();
item.setDataChangeCreatedBy(username);
item.setDataChangeLastModifiedBy(username);
if (StringUtils.isEmpty(item.getDataChangeCreatedBy())){
String username = userInfoHolder.getUser().getUserId();
item.setDataChangeCreatedBy(username);
item.setDataChangeLastModifiedBy(username);
}
ItemDTO itemDTO = itemAPI.createItem(appId, env, clusterName, namespaceName, item);
Cat.logEvent(CatEventType.MODIFY_NAMESPACE, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName));
......@@ -99,30 +99,36 @@ public class ConfigService {
}
public void updateItem(String appId, Env env, String clusterName, String namespaceName, ItemDTO item) {
String username = userInfoHolder.getUser().getUserId();
item.setDataChangeLastModifiedBy(username);
if (StringUtils.isEmpty(item.getDataChangeLastModifiedBy())){
String username = userInfoHolder.getUser().getUserId();
item.setDataChangeLastModifiedBy(username);
}
itemAPI.updateItem(appId, env, clusterName, namespaceName, item.getId(), item);
}
public void deleteItem(Env env, long itemId) {
itemAPI.deleteItem(env, itemId, userInfoHolder.getUser().getUserId());
public void deleteItem(Env env, long itemId, String userId) {
itemAPI.deleteItem(env, itemId, userId);
}
public List<ItemDTO> findItems(String appId, Env env, String clusterName, String namespaceName) {
return itemAPI.findItems(appId, env, clusterName, namespaceName);
}
public void syncItems(List<NamespaceIdentifer> comparedNamespaces, List<ItemDTO> sourceItems) {
public ItemDTO loadItem(Env env, long itemId){
return itemAPI.loadItem(env, itemId);
}
public void syncItems(List<NamespaceIdentifier> comparedNamespaces, List<ItemDTO> sourceItems) {
List<ItemDiffs> itemDiffs = compare(comparedNamespaces, sourceItems);
for (ItemDiffs itemDiff : itemDiffs) {
NamespaceIdentifer namespaceIdentifer = itemDiff.getNamespace();
NamespaceIdentifier namespaceIdentifier = itemDiff.getNamespace();
ItemChangeSets changeSets = itemDiff.getDiffs();
changeSets.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId());
String appId = namespaceIdentifer.getAppId();
Env env = namespaceIdentifer.getEnv();
String clusterName = namespaceIdentifer.getClusterName();
String namespaceName = namespaceIdentifer.getNamespaceName();
String appId = namespaceIdentifier.getAppId();
Env env = namespaceIdentifier.getEnv();
String clusterName = namespaceIdentifier.getClusterName();
String namespaceName = namespaceIdentifier.getNamespaceName();
itemAPI.updateItemsByChangeSet(appId, env, clusterName, namespaceName, changeSets);
......@@ -130,11 +136,11 @@ public class ConfigService {
}
}
public List<ItemDiffs> compare(List<NamespaceIdentifer> comparedNamespaces, List<ItemDTO> sourceItems) {
public List<ItemDiffs> compare(List<NamespaceIdentifier> comparedNamespaces, List<ItemDTO> sourceItems) {
List<ItemDiffs> result = new LinkedList<>();
for (NamespaceIdentifer namespace : comparedNamespaces) {
for (NamespaceIdentifier namespace : comparedNamespaces) {
ItemDiffs itemDiffs = new ItemDiffs(namespace);
try {
......@@ -149,11 +155,11 @@ public class ConfigService {
return result;
}
private long getNamespaceId(NamespaceIdentifer namespaceIdentifer) {
String appId = namespaceIdentifer.getAppId();
String clusterName = namespaceIdentifer.getClusterName();
String namespaceName = namespaceIdentifer.getNamespaceName();
Env env = namespaceIdentifer.getEnv();
private long getNamespaceId(NamespaceIdentifier namespaceIdentifier) {
String appId = namespaceIdentifier.getAppId();
String clusterName = namespaceIdentifier.getClusterName();
String namespaceName = namespaceIdentifier.getNamespaceName();
Env env = namespaceIdentifier.getEnv();
NamespaceDTO namespaceDTO = null;
try {
namespaceDTO = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);
......@@ -167,7 +173,7 @@ public class ConfigService {
return namespaceDTO.getId();
}
private ItemChangeSets parseChangeSets(NamespaceIdentifer namespace, List<ItemDTO> sourceItems) {
private ItemChangeSets parseChangeSets(NamespaceIdentifier namespace, List<ItemDTO> sourceItems) {
ItemChangeSets changeSets = new ItemChangeSets();
List<ItemDTO>
targetItems =
......
......@@ -3,6 +3,7 @@ package com.ctrip.framework.apollo.portal.service;
import com.google.gson.Gson;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.common.dto.ItemDTO;
import com.ctrip.framework.apollo.common.dto.NamespaceDTO;
......@@ -21,7 +22,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
......@@ -36,9 +36,9 @@ public class NamespaceService {
@Autowired
private UserInfoHolder userInfoHolder;
@Autowired
private AdminServiceAPI.ItemAPI itemAPI;
private ItemService itemService;
@Autowired
private AdminServiceAPI.ReleaseAPI releaseAPI;
private ReleaseService releaseService;
@Autowired
private AdminServiceAPI.NamespaceAPI namespaceAPI;
@Autowired
......@@ -58,6 +58,13 @@ public class NamespaceService {
return createdNamespace;
}
public NamespaceDTO loadNamespaceBaseInfo(String appId, Env env, String clusterName, String namespaceName){
NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);
if (namespace == null){
throw new BadRequestException("namespaces not existed");
}
return namespace;
}
/**
* load cluster all namespace info with items
......@@ -66,7 +73,7 @@ public class NamespaceService {
List<NamespaceDTO> namespaces = namespaceAPI.findNamespaceByCluster(appId, env, clusterName);
if (namespaces == null || namespaces.size() == 0) {
return Collections.emptyList();
throw new BadRequestException("namespaces not existed");
}
List<NamespaceVO> namespaceVOs = new LinkedList<>();
......@@ -86,6 +93,14 @@ public class NamespaceService {
return namespaceVOs;
}
public NamespaceVO loadNamespace(String appId, Env env, String clusterName, String namespaceName){
NamespaceDTO namespace = namespaceAPI.loadNamespace(appId, env, clusterName, namespaceName);
if (namespace == null){
throw new BadRequestException("namespaces not existed");
}
return parseNamespace(appId, env, clusterName, namespace);
}
@SuppressWarnings("unchecked")
private NamespaceVO parseNamespace(String appId, Env env, String clusterName, NamespaceDTO namespace) {
NamespaceVO namespaceVO = new NamespaceVO();
......@@ -101,13 +116,13 @@ public class NamespaceService {
//latest Release
ReleaseDTO latestRelease = null;
Map<String, String> releaseItems = new HashMap<>();
latestRelease = releaseAPI.loadLatestRelease(appId, env, clusterName, namespaceName);
latestRelease = releaseService.loadLatestRelease(appId, env, clusterName, namespaceName);
if (latestRelease != null) {
releaseItems = gson.fromJson(latestRelease.getConfigurations(), Map.class);
}
//not Release config items
List<ItemDTO> items = itemAPI.findItems(appId, env, clusterName, namespaceName);
List<ItemDTO> items = itemService.findItems(appId, env, clusterName, namespaceName);
int modifiedItemCnt = 0;
for (ItemDTO itemDTO : items) {
......
......@@ -2,9 +2,11 @@ package com.ctrip.framework.apollo.portal.service;
import com.google.common.base.Objects;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ctrip.framework.apollo.common.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.constant.CatEventType;
......@@ -19,6 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
......@@ -28,99 +31,109 @@ import java.util.Set;
@Service
public class ReleaseService {
private static final Gson gson = new Gson();
@Autowired
private UserInfoHolder userInfoHolder;
@Autowired
private AdminServiceAPI.ReleaseAPI releaseAPI;
public ReleaseDTO createRelease(NamespaceReleaseModel model) {
String appId = model.getAppId();
Env env = model.getEnv();
String clusterName = model.getClusterName();
String namespaceName = model.getNamespaceName();
ReleaseDTO releaseDTO =
releaseAPI
.createRelease(appId, env, clusterName, namespaceName, model.getReleaseTitle(), model.getReleaseComment()
, userInfoHolder.getUser().getUserId());
Cat.logEvent(CatEventType.RELEASE_NAMESPACE, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName));
return releaseDTO;
}
public List<ReleaseVO> findAllReleases(String appId, Env env, String clusterName, String namespaceName, int page,
int size) {
List<ReleaseDTO> releaseDTOs = releaseAPI.findAllReleases(appId, env, clusterName, namespaceName, page, size);
if (CollectionUtils.isEmpty(releaseDTOs)) {
return Collections.EMPTY_LIST;
}
List<ReleaseVO> releases = new LinkedList<>();
for (ReleaseDTO releaseDTO : releaseDTOs) {
ReleaseVO release = new ReleaseVO();
release.setBaseInfo(releaseDTO);
Set<KVEntity> kvEntities = new LinkedHashSet<>();
Set<Map.Entry> entries = gson.fromJson(releaseDTO.getConfigurations(), Map.class).entrySet();
for (Map.Entry<String, String> entry : entries) {
kvEntities.add(new KVEntity(entry.getKey(), entry.getValue()));
}
release.setItems(kvEntities);
//为了减少数据量
releaseDTO.setConfigurations("");
releases.add(release);
}
return releases;
}
public List<ReleaseDTO> findActiveReleases(String appId, Env env, String clusterName, String namespaceName, int page,
int size) {
return releaseAPI.findActiveReleases(appId, env, clusterName, namespaceName, page, size);
}
public void rollback(Env env, long releaseId) {
releaseAPI.rollback(env, releaseId, userInfoHolder.getUser().getUserId());
}
public ReleaseCompareResult compare(Env env, long firstReleaseId, long secondReleaseId) {
ReleaseDTO firstRelease = releaseAPI.loadRelease(env, firstReleaseId);
ReleaseDTO secondRelease = releaseAPI.loadRelease(env, secondReleaseId);
Map<String, String> firstItems = gson.fromJson(firstRelease.getConfigurations(), Map.class);
Map<String, String> secondItems = gson.fromJson(secondRelease.getConfigurations(), Map.class);
ReleaseCompareResult compareResult = new ReleaseCompareResult();
//added and modified in firstRelease
for (Map.Entry<String, String> entry : firstItems.entrySet()) {
String key = entry.getKey();
String firstValue = entry.getValue();
String secondValue = secondItems.get(key);
//added
if (secondValue == null) {
compareResult.addEntityPair(ChangeType.DELETED, new KVEntity(key, firstValue),
new KVEntity(key, secondValue));
} else if (!Objects.equal(firstValue, secondValue)) {
compareResult.addEntityPair(ChangeType.MODIFIED, new KVEntity(key, firstValue),
new KVEntity(key, secondValue));
}
}
//deleted in firstRelease
for (Map.Entry<String, String> entry : secondItems.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (firstItems.get(key) == null) {
compareResult
.addEntityPair(ChangeType.ADDED, new KVEntity(key, ""), new KVEntity(key, value));
}
}
return compareResult;
}
private static final Gson gson = new Gson();
private static final Type configurationTypeReference =
new TypeToken<Map<String, String>>() {
}.getType();
@Autowired
private UserInfoHolder userInfoHolder;
@Autowired
private AdminServiceAPI.ReleaseAPI releaseAPI;
public ReleaseDTO createRelease(NamespaceReleaseModel model) {
String appId = model.getAppId();
Env env = model.getEnv();
String clusterName = model.getClusterName();
String namespaceName = model.getNamespaceName();
String releaseBy =
StringUtils.isEmpty(model.getReleaseBy()) ? userInfoHolder.getUser().getUserId() : model.getReleaseBy();
ReleaseDTO releaseDTO = releaseAPI
.createRelease(appId, env, clusterName, namespaceName, model.getReleaseTitle(), model.getReleaseComment()
, releaseBy);
Cat.logEvent(CatEventType.RELEASE_NAMESPACE, String.format("%s+%s+%s+%s", appId, env, clusterName, namespaceName));
return releaseDTO;
}
public List<ReleaseVO> findAllReleases(String appId, Env env, String clusterName, String namespaceName, int page,
int size) {
List<ReleaseDTO> releaseDTOs = releaseAPI.findAllReleases(appId, env, clusterName, namespaceName, page, size);
if (CollectionUtils.isEmpty(releaseDTOs)) {
return Collections.emptyList();
}
List<ReleaseVO> releases = new LinkedList<>();
for (ReleaseDTO releaseDTO : releaseDTOs) {
ReleaseVO release = new ReleaseVO();
release.setBaseInfo(releaseDTO);
Set<KVEntity> kvEntities = new LinkedHashSet<>();
Map<String, String> configurations = gson.fromJson(releaseDTO.getConfigurations(), configurationTypeReference);
Set<Map.Entry<String, String>> entries = configurations.entrySet();
for (Map.Entry<String, String> entry : entries) {
kvEntities.add(new KVEntity(entry.getKey(), entry.getValue()));
}
release.setItems(kvEntities);
//为了减少数据量
releaseDTO.setConfigurations("");
releases.add(release);
}
return releases;
}
public List<ReleaseDTO> findActiveReleases(String appId, Env env, String clusterName, String namespaceName, int page,
int size) {
return releaseAPI.findActiveReleases(appId, env, clusterName, namespaceName, page, size);
}
public ReleaseDTO loadLatestRelease(String appId, Env env, String clusterName, String namespaceName){
return releaseAPI.loadLatestRelease(appId, env, clusterName, namespaceName);
}
public void rollback(Env env, long releaseId) {
releaseAPI.rollback(env, releaseId, userInfoHolder.getUser().getUserId());
}
public ReleaseCompareResult compare(Env env, long firstReleaseId, long secondReleaseId) {
ReleaseDTO firstRelease = releaseAPI.loadRelease(env, firstReleaseId);
ReleaseDTO secondRelease = releaseAPI.loadRelease(env, secondReleaseId);
Map<String, String> firstItems = gson.fromJson(firstRelease.getConfigurations(), configurationTypeReference);
Map<String, String> secondItems = gson.fromJson(secondRelease.getConfigurations(), configurationTypeReference);
ReleaseCompareResult compareResult = new ReleaseCompareResult();
//added and modified in firstRelease
for (Map.Entry<String, String> entry : firstItems.entrySet()) {
String key = entry.getKey();
String firstValue = entry.getValue();
String secondValue = secondItems.get(key);
//added
if (secondValue == null) {
compareResult.addEntityPair(ChangeType.DELETED, new KVEntity(key, firstValue),
new KVEntity(key, secondValue));
} else if (!Objects.equal(firstValue, secondValue)) {
compareResult.addEntityPair(ChangeType.MODIFIED, new KVEntity(key, firstValue),
new KVEntity(key, secondValue));
}
}
//deleted in firstRelease
for (Map.Entry<String, String> entry : secondItems.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (firstItems.get(key) == null) {
compareResult
.addEntityPair(ChangeType.ADDED, new KVEntity(key, ""), new KVEntity(key, value));
}
}
return compareResult;
}
}
package com.ctrip.framework.apollo.openapi.filter;
import com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtil;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static org.junit.Assert.*;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConsumerAuthenticationFilterTest {
private ConsumerAuthenticationFilter authenticationFilter;
@Mock
private ConsumerAuthUtil consumerAuthUtil;
@Mock
private HttpServletRequest request;
@Mock
private HttpServletResponse response;
@Mock
private FilterChain filterChain;
@Before
public void setUp() throws Exception {
authenticationFilter = new ConsumerAuthenticationFilter(consumerAuthUtil);
}
@Test
public void testAuthSuccessfully() throws Exception {
String someToken = "someToken";
Long someConsumerId = 1L;
when(request.getHeader("Authorization")).thenReturn(someToken);
when(consumerAuthUtil.getConsumerId(someToken)).thenReturn(someConsumerId);
authenticationFilter.doFilter(request, response, filterChain);
verify(consumerAuthUtil, times(1)).storeConsumerId(request, someConsumerId);
verify(filterChain, times(1)).doFilter(request, response);
}
@Test
public void testAuthFailed() throws Exception {
String someInvalidToken = "someInvalidToken";
when(request.getHeader("Authorization")).thenReturn(someInvalidToken);
when(consumerAuthUtil.getConsumerId(someInvalidToken)).thenReturn(null);
authenticationFilter.doFilter(request, response, filterChain);
verify(response, times(1)).sendError(eq(HttpServletResponse.SC_UNAUTHORIZED), anyString());
verify(consumerAuthUtil, never()).storeConsumerId(eq(request), anyLong());
verify(filterChain, never()).doFilter(request, response);
}
}
\ No newline at end of file
package com.ctrip.framework.apollo.openapi.service;
import com.ctrip.framework.apollo.portal.AbstractIntegrationTest;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.jdbc.Sql;
import static org.junit.Assert.*;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class ConsumerRolePermissionServiceTest extends AbstractIntegrationTest {
@Autowired
private ConsumerRolePermissionService consumerRolePermissionService;
@Before
public void setUp() throws Exception {
}
@Test
@Sql(scripts = "/sql/permission/insert-test-roles.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/permission/insert-test-permissions.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/permission/insert-test-consumerroles.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/permission/insert-test-rolepermissions.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "/sql/cleanup.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void testConsumerHasPermission() throws Exception {
String someTargetId = "someTargetId";
String anotherTargetId = "anotherTargetId";
String somePermissionType = "somePermissionType";
String anotherPermissionType = "anotherPermissionType";
long someConsumerId = 1;
long anotherConsumerId = 2;
long someConsumerWithNoPermission = 3;
assertTrue(consumerRolePermissionService.consumerHasPermission(someConsumerId, somePermissionType, someTargetId));
assertTrue(consumerRolePermissionService.consumerHasPermission(someConsumerId, anotherPermissionType, anotherTargetId));
assertTrue(consumerRolePermissionService.consumerHasPermission(anotherConsumerId, somePermissionType, someTargetId));
assertTrue(consumerRolePermissionService.consumerHasPermission(anotherConsumerId, anotherPermissionType, anotherTargetId));
assertFalse(consumerRolePermissionService.consumerHasPermission(someConsumerWithNoPermission, somePermissionType, someTargetId));
assertFalse(consumerRolePermissionService.consumerHasPermission(someConsumerWithNoPermission, anotherPermissionType, anotherTargetId));
}
}
\ No newline at end of file
package com.ctrip.framework.apollo.openapi.service;
import com.ctrip.framework.apollo.openapi.entity.Consumer;
import com.ctrip.framework.apollo.openapi.entity.ConsumerToken;
import com.ctrip.framework.apollo.openapi.repository.ConsumerRepository;
import com.ctrip.framework.apollo.openapi.repository.ConsumerTokenRepository;
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.test.util.ReflectionTestUtils;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConsumerServiceTest {
private ConsumerService consumerService;
@Mock
private ConsumerTokenRepository consumerTokenRepository;
@Mock
private ConsumerRepository consumerRepository;
@Mock
private ServerConfigService serverConfigService;
private String someTokenSalt;
@Before
public void setUp() throws Exception {
consumerService = spy(new ConsumerService());
ReflectionTestUtils.setField(consumerService, "consumerTokenRepository",
consumerTokenRepository);
ReflectionTestUtils.setField(consumerService, "consumerRepository",
consumerRepository);
ReflectionTestUtils.setField(consumerService, "serverConfigService",
serverConfigService);
someTokenSalt = "someTokenSalt";
when(serverConfigService.getValue(eq(ConsumerService.TOKEN_SALT_KEY), anyString())).thenReturn(someTokenSalt);
consumerService.afterPropertiesSet();
}
@Test
public void testGetConsumerId() throws Exception {
String someToken = "someToken";
long someConsumerId = 1;
ConsumerToken someConsumerToken = new ConsumerToken();
someConsumerToken.setConsumerId(someConsumerId);
when(consumerTokenRepository.findTopByTokenAndExpiresAfter(eq(someToken), any(Date.class)))
.thenReturn(someConsumerToken);
assertEquals(someConsumerId, consumerService.getConsumerIdByToken(someToken).longValue());
}
@Test
public void testGetConsumerIdWithNullToken() throws Exception {
Long consumerId = consumerService.getConsumerIdByToken(null);
assertNull(consumerId);
verify(consumerTokenRepository, never()).findTopByTokenAndExpiresAfter(anyString(), any(Date
.class));
}
@Test
public void testGetConsumerByConsumerId() throws Exception {
long someConsumerId = 1;
Consumer someConsumer = mock(Consumer.class);
when(consumerRepository.findOne(someConsumerId)).thenReturn(someConsumer);
assertEquals(someConsumer, consumerService.getConsumerByConsumerId(someConsumerId));
verify(consumerRepository, times(1)).findOne(someConsumerId);
}
@Test
public void testCreateConsumerToken() throws Exception {
ConsumerToken someConsumerToken = mock(ConsumerToken.class);
ConsumerToken savedConsumerToken = mock(ConsumerToken.class);
when(consumerTokenRepository.save(someConsumerToken)).thenReturn(savedConsumerToken);
assertEquals(savedConsumerToken, consumerService.createConsumerToken(someConsumerToken));
}
@Test
public void testGenerateConsumerToken() throws Exception {
String someConsumerAppId = "100003171";
Date generationTime = new GregorianCalendar(2016, Calendar.AUGUST, 9, 12, 10, 50).getTime();
String tokenSalt = "apollo";
assertEquals("d0da35292dd5079eeb73cc3a5f7c0759afabd806", consumerService
.generateConsumerToken(someConsumerAppId, generationTime, tokenSalt));
}
@Test
public void testGenerateAndEnrichConsumerToken() throws Exception {
String someConsumerAppId = "someAppId";
long someConsumerId = 1;
String someToken = "someToken";
Date generationTime = new Date();
Consumer consumer = mock(Consumer.class);
when(consumerRepository.findOne(someConsumerId)).thenReturn(consumer);
when(consumer.getAppId()).thenReturn(someConsumerAppId);
when(consumerService.generateConsumerToken(someConsumerAppId, generationTime, someTokenSalt))
.thenReturn(someToken);
ConsumerToken consumerToken = new ConsumerToken();
consumerToken.setConsumerId(someConsumerId);
consumerToken.setDataChangeCreatedTime(generationTime);
consumerService.generateAndEnrichConsumerToken(consumerToken);
assertEquals(someToken, consumerToken.getToken());
}
@Test(expected = IllegalStateException.class)
public void testGenerateAndEnrichConsumerTokenWithConsumerNotFound() throws Exception {
long someConsumerIdNotExist = 1;
ConsumerToken consumerToken = new ConsumerToken();
consumerToken.setConsumerId(someConsumerIdNotExist);
when(consumerRepository.findOne(someConsumerIdNotExist)).thenReturn(null);
consumerService.generateAndEnrichConsumerToken(consumerToken);
}
}
\ No newline at end of file
package com.ctrip.framework.apollo.openapi.util;
import com.ctrip.framework.apollo.openapi.service.ConsumerService;
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.test.util.ReflectionTestUtils;
import javax.servlet.http.HttpServletRequest;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConsumerAuthUtilTest {
private ConsumerAuthUtil consumerAuthUtil;
@Mock
private ConsumerService consumerService;
@Mock
private HttpServletRequest request;
@Before
public void setUp() throws Exception {
consumerAuthUtil = new ConsumerAuthUtil();
ReflectionTestUtils.setField(consumerAuthUtil, "consumerService", consumerService);
}
@Test
public void testGetConsumerId() throws Exception {
String someToken = "someToken";
Long someConsumerId = 1L;
when(consumerService.getConsumerIdByToken(someToken)).thenReturn(someConsumerId);
assertEquals(someConsumerId, consumerAuthUtil.getConsumerId(someToken));
verify(consumerService, times(1)).getConsumerIdByToken(someToken);
}
@Test
public void testStoreConsumerId() throws Exception {
long someConsumerId = 1L;
consumerAuthUtil.storeConsumerId(request, someConsumerId);
verify(request, times(1)).setAttribute(ConsumerAuthUtil.CONSUMER_ID, someConsumerId);
}
@Test
public void testRetrieveConsumerId() throws Exception {
long someConsumerId = 1;
when(request.getAttribute(ConsumerAuthUtil.CONSUMER_ID)).thenReturn(someConsumerId);
assertEquals(someConsumerId, consumerAuthUtil.retrieveConsumerId(request));
verify(request, times(1)).getAttribute(ConsumerAuthUtil.CONSUMER_ID);
}
@Test(expected = IllegalStateException.class)
public void testRetrieveConsumerIdWithConsumerIdNotSet() throws Exception {
consumerAuthUtil.retrieveConsumerId(request);
}
@Test(expected = IllegalStateException.class)
public void testRetrieveConsumerIdWithConsumerIdInvalid() throws Exception {
String someInvalidConsumerId = "abc";
when(request.getAttribute(ConsumerAuthUtil.CONSUMER_ID)).thenReturn(someInvalidConsumerId);
consumerAuthUtil.retrieveConsumerId(request);
}
}
\ No newline at end of file
package com.ctrip.framework.apollo.portal;
import com.ctrip.framework.apollo.PortalApplication;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.SpringApplicationConfiguration;
......
package com.ctrip.framework.apollo.portal;
import com.ctrip.framework.apollo.openapi.filter.ConsumerAuthenticationFilterTest;
import com.ctrip.framework.apollo.openapi.service.ConsumerRolePermissionServiceTest;
import com.ctrip.framework.apollo.openapi.service.ConsumerServiceTest;
import com.ctrip.framework.apollo.openapi.util.ConsumerAuthUtilTest;
import com.ctrip.framework.apollo.portal.controller.ConsumerControllerTest;
import com.ctrip.framework.apollo.portal.service.AppNamespaceServiceTest;
import com.ctrip.framework.apollo.portal.service.ConfigServiceTest;
import com.ctrip.framework.apollo.portal.service.NamespaceServiceTest;
......@@ -18,7 +23,9 @@ import org.junit.runners.Suite.SuiteClasses;
ConfigServiceTest.class, PropertyResolverTest.class,
NamespaceServiceTest.class, ServiceExceptionTest.class, RolePermissionServiceTest.class,
AppNamespaceServiceTest.class, RoleInitializationServiceTest.class, FileTextResolverTest.class,
RetryableRestTemplateTest.class
RetryableRestTemplateTest.class, ConsumerRolePermissionServiceTest.class,
ConsumerAuthenticationFilterTest.class, ConsumerAuthUtilTest.class, ConsumerServiceTest.class,
ConsumerControllerTest.class
})
public class AllTests {
......
......@@ -11,77 +11,68 @@ import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.HttpStatusCodeException;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.common.utils.ExceptionUtils;
import com.ctrip.framework.apollo.common.dto.AppDTO;
import com.ctrip.framework.apollo.common.exception.ServiceException;
import com.ctrip.framework.apollo.portal.controller.AppController;
import com.ctrip.framework.apollo.portal.service.UserService;
import com.google.gson.Gson;
public class ServiceExceptionTest extends AbstractIntegrationTest {
public class ServiceExceptionTest extends AbstractUnitTest {
@Autowired
private AppController appController;
@Mock
private UserService userService;
@InjectMocks
private AppController appController;
@Mock
private UserService userService;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ReflectionTestUtils.setField(appController, "userService", userService);
}
private String getBaseAppUrl() {
return "http://localhost:" + port + "/apps";
}
@Test
public void testAdminServiceException() {
String errorMsg = "No available admin service";
String errorCode = "errorCode";
String status = "500";
@Test
public void testAdminServiceException() {
Map<String, Object> errorAttributes = new LinkedHashMap<>();
errorAttributes.put("status", 500);
errorAttributes.put("message", "No available admin service");
errorAttributes.put("timestamp",
LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
errorAttributes.put("exception", ServiceException.class.getName());
errorAttributes.put("errorCode", "8848");
Map<String, Object> errorAttributes = new LinkedHashMap<>();
errorAttributes.put("status", status);
errorAttributes.put("message", errorMsg);
errorAttributes.put("timestamp",
LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
errorAttributes.put("exception", ServiceException.class.getName());
errorAttributes.put("errorCode", errorCode);
HttpStatusCodeException adminException =
new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "admin server error",
new Gson().toJson(errorAttributes).getBytes(), Charset.defaultCharset());
HttpStatusCodeException adminException =
new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "admin server error",
new Gson().toJson(errorAttributes).getBytes(), Charset.defaultCharset());
when(userService.findByUserId(any(String.class))).thenThrow(adminException);
when(userService.findByUserId(any(String.class))).thenThrow(adminException);
App app = generateSampleApp();
try {
restTemplate.postForEntity(getBaseAppUrl(), app, AppDTO.class);
} catch (HttpStatusCodeException e) {
@SuppressWarnings("unchecked")
Map<String, String> attr = new Gson().fromJson(e.getResponseBodyAsString(), Map.class);
Assert.assertEquals("500 admin server error", attr.get("message"));
Assert.assertEquals(500.0, attr.get("status"));
}
}
App app = generateSampleApp();
try {
appController.create(app);
} catch (HttpStatusCodeException e) {
@SuppressWarnings("unchecked")
Map<String, String> attr = new Gson().fromJson(e.getResponseBodyAsString(), Map.class);
Assert.assertEquals(errorMsg, attr.get("message"));
Assert.assertEquals(errorCode, attr.get("errorCode"));
Assert.assertEquals(status, attr.get("status"));
}
}
private App generateSampleApp() {
App app = new App();
app.setAppId("someAppId");
app.setName("someName");
app.setOrgId("someOrgId");
app.setOrgName("someOrgNam");
app.setOwnerName("someOwner");
app.setOwnerEmail("someOwner@ctrip.com");
return app;
}
private App generateSampleApp() {
App app = new App();
app.setAppId("someAppId");
app.setName("someName");
app.setOrgId("someOrgId");
app.setOrgName("someOrgNam");
app.setOwnerName("someOwner");
app.setOwnerEmail("someOwner@ctrip.com");
return app;
}
}
package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.openapi.entity.ConsumerToken;
import com.ctrip.framework.apollo.openapi.service.ConsumerService;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
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.test.util.ReflectionTestUtils;
import java.util.Date;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConsumerControllerTest {
private ConsumerController consumerController;
@Mock
private ConsumerService consumerService;
@Mock
private UserInfoHolder userInfoHolder;
@Before
public void setUp() throws Exception {
consumerController = new ConsumerController();
ReflectionTestUtils.setField(consumerController, "consumerService", consumerService);
ReflectionTestUtils.setField(consumerController, "userInfoHolder", userInfoHolder);
}
@Test
public void testCreateConsumerToken() throws Exception {
UserInfo userInfo = mock(UserInfo.class);
String someUserId = "someUser";
ConsumerToken consumerToken = mock(ConsumerToken.class);
long someConsumerId = 1;
Date someDateExpires = new Date();
when(userInfo.getUserId()).thenReturn(someUserId);
when(userInfoHolder.getUser()).thenReturn(userInfo);
when(consumerService.createConsumerToken(any(ConsumerToken.class))).thenReturn(consumerToken);
assertEquals(consumerToken, consumerController.createConsumerToken(someConsumerId, someDateExpires));
verify(consumerService, times(1)).generateAndEnrichConsumerToken(any(ConsumerToken.class));
verify(consumerService, times(1)).createConsumerToken(any(ConsumerToken.class));
}
}
\ No newline at end of file
......@@ -10,7 +10,7 @@ import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
import com.ctrip.framework.apollo.portal.entity.vo.ItemDiffs;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifer;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceIdentifier;
import com.ctrip.framework.apollo.portal.entity.form.NamespaceTextModel;
import com.ctrip.framework.apollo.portal.service.txtresolver.PropertyResolver;
......@@ -44,7 +44,7 @@ public class ConfigServiceTest {
private UserInfoHolder userInfoHolder;
@InjectMocks
private ConfigService configService;
private ItemService configService;
@Before
public void setup() {
......@@ -100,7 +100,7 @@ public class ConfigServiceTest {
String appId = "6666", env = "LOCAL", clusterName = ConfigConsts.CLUSTER_NAME_DEFAULT,
namespaceName = ConfigConsts.NAMESPACE_APPLICATION;
List<NamespaceIdentifer> namespaceIdentifers = generateNamespaceIdentifer(appId, env, clusterName, namespaceName);
List<NamespaceIdentifier> namespaceIdentifiers = generateNamespaceIdentifer(appId, env, clusterName, namespaceName);
NamespaceDTO namespaceDTO = generateNamespaceDTO(appId, clusterName, namespaceName);
when(namespaceAPI.loadNamespace(appId, Env.valueOf(env), clusterName, namespaceName)).thenReturn(namespaceDTO);
......@@ -110,7 +110,7 @@ public class ConfigServiceTest {
userInfo.setUserId("test");
when(userInfoHolder.getUser()).thenReturn(userInfo);
List<ItemDiffs> itemDiffses = configService.compare(namespaceIdentifers, sourceItems);
List<ItemDiffs> itemDiffses = configService.compare(namespaceIdentifiers, sourceItems);
assertEquals(1,itemDiffses.size());
ItemDiffs itemDiffs = itemDiffses.get(0);
......@@ -141,7 +141,7 @@ public class ConfigServiceTest {
String appId = "6666", env = "LOCAL", clusterName = ConfigConsts.CLUSTER_NAME_DEFAULT,
namespaceName = ConfigConsts.NAMESPACE_APPLICATION;
List<NamespaceIdentifer> namespaceIdentifers = generateNamespaceIdentifer(appId, env, clusterName, namespaceName);
List<NamespaceIdentifier> namespaceIdentifiers = generateNamespaceIdentifer(appId, env, clusterName, namespaceName);
NamespaceDTO namespaceDTO = generateNamespaceDTO(appId, clusterName, namespaceName);
when(namespaceAPI.loadNamespace(appId, Env.valueOf(env), clusterName, namespaceName)).thenReturn(namespaceDTO);
......@@ -151,7 +151,7 @@ public class ConfigServiceTest {
userInfo.setUserId("test");
when(userInfoHolder.getUser()).thenReturn(userInfo);
List<ItemDiffs> itemDiffses = configService.compare(namespaceIdentifers, sourceItems);
List<ItemDiffs> itemDiffses = configService.compare(namespaceIdentifiers, sourceItems);
assertEquals(1, itemDiffses.size());
ItemDiffs itemDiffs = itemDiffses.get(0);
......@@ -161,11 +161,11 @@ public class ConfigServiceTest {
assertEquals(2, changeSets.getUpdateItems().size());
assertEquals(1, changeSets.getCreateItems().size());
NamespaceIdentifer namespaceIdentifer = itemDiffs.getNamespace();
assertEquals(appId, namespaceIdentifer.getAppId());
assertEquals(Env.valueOf("LOCAL"), namespaceIdentifer.getEnv());
assertEquals(clusterName, namespaceIdentifer.getClusterName());
assertEquals(namespaceName, namespaceIdentifer.getNamespaceName());
NamespaceIdentifier namespaceIdentifier = itemDiffs.getNamespace();
assertEquals(appId, namespaceIdentifier.getAppId());
assertEquals(Env.valueOf("LOCAL"), namespaceIdentifier.getEnv());
assertEquals(clusterName, namespaceIdentifier.getClusterName());
assertEquals(namespaceName, namespaceIdentifier.getNamespaceName());
ItemDTO createdItem = changeSets.getCreateItems().get(0);
assertEquals("newKey", createdItem.getKey());
......@@ -198,8 +198,8 @@ public class ConfigServiceTest {
return namespaceDTO;
}
private List<NamespaceIdentifer> generateNamespaceIdentifer(String appId, String env, String clusterName, String namespaceName){
NamespaceIdentifer targetNamespace = new NamespaceIdentifer();
private List<NamespaceIdentifier> generateNamespaceIdentifer(String appId, String env, String clusterName, String namespaceName){
NamespaceIdentifier targetNamespace = new NamespaceIdentifier();
targetNamespace.setAppId(appId);
targetNamespace.setEnv(env);
targetNamespace.setClusterName(clusterName);
......
......@@ -30,9 +30,9 @@ public class NamespaceServiceTest {
@Mock
private AdminServiceAPI.NamespaceAPI namespaceAPI;
@Mock
private AdminServiceAPI.ReleaseAPI releaseAPI;
private ReleaseService releaseService;
@Mock
private AdminServiceAPI.ItemAPI itemAPI;
private ItemService itemService;
@Mock
private PropertyResolver resolver;
@Mock
......@@ -82,9 +82,9 @@ public class NamespaceServiceTest {
.thenReturn(applicationAppNamespace);
when(appNamespaceService.findPublicAppNamespace("hermes")).thenReturn(hermesAppNamespace);
when(namespaceAPI.findNamespaceByCluster(appId, Env.DEV, clusterName)).thenReturn(namespaces);
when(releaseAPI.loadLatestRelease(appId, Env.DEV, clusterName, namespaceName)).thenReturn(someRelease);
when(releaseAPI.loadLatestRelease(appId, Env.DEV, clusterName, "hermes")).thenReturn(someRelease);
when(itemAPI.findItems(appId, Env.DEV, clusterName, namespaceName)).thenReturn(someItems);
when(releaseService.loadLatestRelease(appId, Env.DEV, clusterName, namespaceName)).thenReturn(someRelease);
when(releaseService.loadLatestRelease(appId, Env.DEV, clusterName, "hermes")).thenReturn(someRelease);
when(itemService.findItems(appId, Env.DEV, clusterName, namespaceName)).thenReturn(someItems);
List<NamespaceVO> namespaceVOs = namespaceService.findNamespaces(appId, Env.DEV, clusterName);
assertEquals(2, namespaceVOs.size());
......
......@@ -17,6 +17,7 @@ import org.mockito.Mock;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anySet;
import static org.mockito.Matchers.anySetOf;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
......@@ -46,7 +47,7 @@ public class RoleInitializationServiceTest extends AbstractUnitTest {
roleInitializationService.initAppRoles(mockApp());
verify(rolePermissionService, times(1)).findRoleByRoleName(RoleUtils.buildAppMasterRoleName(APP_ID));
verify(rolePermissionService, times(0)).assignRoleToUsers(anyString(), anySet(), anyString());
verify(rolePermissionService, times(0)).assignRoleToUsers(anyString(), anySetOf(String.class), anyString());
}
@Test
......@@ -62,7 +63,7 @@ public class RoleInitializationServiceTest extends AbstractUnitTest {
verify(rolePermissionService, times(1)).assignRoleToUsers(
RoleUtils.buildAppMasterRoleName(APP_ID), Sets.newHashSet(CURRENT_USER), CURRENT_USER);
verify(rolePermissionService, times(2)).createPermission(any());
verify(rolePermissionService, times(3)).createRoleWithPermissions(any(), anySet());
verify(rolePermissionService, times(3)).createRoleWithPermissions(any(), anySetOf(Long.class));
}
@Test
......@@ -80,7 +81,7 @@ public class RoleInitializationServiceTest extends AbstractUnitTest {
verify(rolePermissionService, times(2)).findRoleByRoleName(anyString());
verify(rolePermissionService, times(0)).createPermission(any());
verify(rolePermissionService, times(0)).createRoleWithPermissions(any(), anySet());
verify(rolePermissionService, times(0)).createRoleWithPermissions(any(), anySetOf(Long.class));
}
@Test
......@@ -101,7 +102,7 @@ public class RoleInitializationServiceTest extends AbstractUnitTest {
verify(rolePermissionService, times(2)).findRoleByRoleName(anyString());
verify(rolePermissionService, times(2)).createPermission(any());
verify(rolePermissionService, times(2)).createRoleWithPermissions(any(), anySet());
verify(rolePermissionService, times(2)).createRoleWithPermissions(any(), anySetOf(Long.class));
}
@Test
......@@ -122,7 +123,7 @@ public class RoleInitializationServiceTest extends AbstractUnitTest {
verify(rolePermissionService, times(2)).findRoleByRoleName(anyString());
verify(rolePermissionService, times(1)).createPermission(any());
verify(rolePermissionService, times(1)).createRoleWithPermissions(any(), anySet());
verify(rolePermissionService, times(1)).createRoleWithPermissions(any(), anySetOf(Long.class));
}
private App mockApp(){
......
INSERT INTO `consumerrole` (`Id`, `ConsumerId`, `RoleId`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)
VALUES (890, 1, 990, 'someOperator', 'someOperator');
INSERT INTO `consumerrole` (`Id`, `ConsumerId`, `RoleId`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)
VALUES (891, 2, 990, 'someOperator', 'someOperator');
......@@ -179,7 +179,7 @@
<dependency>
<groupId>com.ctrip.framework.apollo-sso</groupId>
<artifactId>apollo-sso-ctrip</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
</dependency>
<!--third party -->
<dependency>
......
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