Commit 4db23ba8 authored by lepdou's avatar lepdou

权限管理 & bugfix

parent 67ecbe8e
......@@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.biz.service.AdminService;
import com.ctrip.framework.apollo.biz.service.AppService;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
......
......@@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.ctrip.framework.apollo.biz.entity.AppNamespace;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.biz.service.AppNamespaceService;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.core.dto.AppNamespaceDTO;
......
......@@ -9,7 +9,7 @@ import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
import org.springframework.web.client.HttpClientErrorException;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.biz.repository.AppRepository;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.core.dto.AppDTO;
......
package com.ctrip.framework.apollo.adminservice.controller;
import com.ctrip.framework.apollo.biz.entity.AppNamespace;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.biz.repository.AppNamespaceRepository;
import com.ctrip.framework.apollo.core.dto.AppNamespaceDTO;
......
......@@ -14,12 +14,9 @@ import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.test.util.ReflectionTestUtils;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.biz.service.AdminService;
import com.ctrip.framework.apollo.biz.service.AppService;
import com.ctrip.framework.apollo.core.dto.AppDTO;
......
......@@ -16,7 +16,7 @@ import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.HttpStatusCodeException;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.biz.service.AdminService;
import com.ctrip.framework.apollo.biz.service.AppService;
import com.ctrip.framework.apollo.core.dto.AppDTO;
......
......@@ -2,7 +2,7 @@ package com.ctrip.framework.apollo.biz.repository;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.ctrip.framework.apollo.biz.entity.AppNamespace;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import java.util.List;
......
......@@ -6,7 +6,7 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
public interface AppRepository extends PagingAndSortingRepository<App, Long> {
......
......@@ -4,7 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
@Service
public class AdminService {
......
......@@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ctrip.framework.apollo.biz.entity.AppNamespace;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.biz.entity.Audit;
import com.ctrip.framework.apollo.biz.repository.AppNamespaceRepository;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
......
......@@ -9,7 +9,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.biz.entity.Audit;
import com.ctrip.framework.apollo.biz.repository.AppRepository;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
......
package com.ctrip.framework.apollo.biz.repository;
import com.ctrip.framework.apollo.biz.BizTestConfiguration;
import com.ctrip.framework.apollo.biz.entity.AppNamespace;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.core.ConfigConsts;
import org.junit.Assert;
......
......@@ -10,7 +10,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import com.ctrip.framework.apollo.biz.BizTestConfiguration;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = BizTestConfiguration.class)
......
......@@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import com.ctrip.framework.apollo.biz.BizTestConfiguration;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.biz.entity.Audit;
import com.ctrip.framework.apollo.biz.entity.Cluster;
import com.ctrip.framework.apollo.biz.entity.Namespace;
......
......@@ -17,7 +17,7 @@ import org.springframework.test.context.transaction.BeforeTransaction;
import org.springframework.transaction.annotation.Transactional;
import com.ctrip.framework.apollo.biz.BizTestConfiguration;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.biz.repository.AppNamespaceRepository;
import com.ctrip.framework.apollo.biz.repository.AppRepository;
import com.ctrip.framework.apollo.biz.repository.ClusterRepository;
......
......@@ -11,7 +11,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import com.ctrip.framework.apollo.biz.BizTestConfiguration;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.core.exception.ServiceException;
@RunWith(SpringJUnit4ClassRunner.class)
......
......@@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import com.ctrip.framework.apollo.biz.BizTestConfiguration;
import com.ctrip.framework.apollo.biz.entity.App;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.biz.entity.Cluster;
import com.ctrip.framework.apollo.biz.entity.Namespace;
import com.ctrip.framework.apollo.biz.entity.Privilege;
......
......@@ -3,12 +3,14 @@ package com.ctrip.framework.apollo.common.auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
......
......@@ -3,6 +3,7 @@ package com.ctrip.framework.apollo.common.controller;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.HttpMediaTypeException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
......@@ -28,6 +29,7 @@ import javax.servlet.http.HttpServletRequest;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import static org.springframework.http.MediaType.APPLICATION_JSON;
@ControllerAdvice
......@@ -42,25 +44,52 @@ public class GlobalDefaultExceptionHandler {
return handleError(request, INTERNAL_SERVER_ERROR, ex);
}
@ExceptionHandler({HttpRequestMethodNotSupportedException.class, HttpMediaTypeException.class, BadRequestException.class})
public ResponseEntity<Map<String, Object>> badRequest(HttpServletRequest request,
ServletException ex) {
return handleError(request, BAD_REQUEST, ex);
}
@ExceptionHandler(NotFoundException.class)
public ResponseEntity<Map<String, Object>> notFound(HttpServletRequest request,
NotFoundException ex) {
return handleError(request, NOT_FOUND, ex);
}
@ExceptionHandler(HttpStatusCodeException.class)
public ResponseEntity<Map<String, Object>> restTemplateException(HttpServletRequest request,
HttpStatusCodeException ex) {
Map<String, Object> errorAttributes = gson.fromJson(ex.getResponseBodyAsString(), mapType);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(APPLICATION_JSON);
return new ResponseEntity<>(errorAttributes, headers, ex.getStatusCode());
}
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<Map<String, Object>> accessDeny(HttpServletRequest request,
AccessDeniedException ex) {
return handleError(request, UNAUTHORIZED, ex);
}
private ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request,
HttpStatus status, Throwable ex) {
HttpStatus status, Throwable ex) {
return handleError(request, status, ex, ex.getMessage());
}
private ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request,
HttpStatus status, Throwable ex, String message) {
HttpStatus status, Throwable ex, String message) {
ex = resolveError(ex);
if (ex.getCause() instanceof HttpStatusCodeException) {
return restTemplateException(request, (HttpStatusCodeException) ex.getCause());
}
Cat.logError(ex);
Map<String, Object> errorAttributes = new LinkedHashMap<>();
errorAttributes.put("status", status.value());
errorAttributes.put("message", message);
errorAttributes.put("timestamp",
LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
errorAttributes.put("exception", resolveError(ex).getClass().getName());
// errorAttributes.put("stackTrace", ex.getStackTrace());
if (ex instanceof AbstractBaseException) {
......@@ -71,33 +100,6 @@ public class GlobalDefaultExceptionHandler {
return new ResponseEntity<>(errorAttributes, headers, status);
}
@ExceptionHandler({HttpRequestMethodNotSupportedException.class, HttpMediaTypeException.class})
public ResponseEntity<Map<String, Object>> methodNotSupportedException(HttpServletRequest request,
ServletException ex) {
return handleError(request, BAD_REQUEST, ex);
}
@ExceptionHandler(NotFoundException.class)
public ResponseEntity<Map<String, Object>> notFound(HttpServletRequest request,
NotFoundException ex) {
return handleError(request, NOT_FOUND, ex);
}
@ExceptionHandler(BadRequestException.class)
public ResponseEntity<Map<String, Object>> badRequest(HttpServletRequest request,
BadRequestException ex) {
return handleError(request, BAD_REQUEST, ex);
}
@ExceptionHandler(HttpStatusCodeException.class)
public ResponseEntity<Map<String, Object>> restTemplateException(HttpServletRequest request,
HttpStatusCodeException ex) {
Map<String, Object> errorAttributes = gson.fromJson(ex.getResponseBodyAsString(), mapType);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(APPLICATION_JSON);
return new ResponseEntity<>(errorAttributes, headers, ex.getStatusCode());
}
private Throwable resolveError(Throwable ex) {
while (ex instanceof ServletException && ex.getCause() != null) {
ex = ((ServletException) ex).getCause();
......
package com.ctrip.framework.apollo.biz.entity;
package com.ctrip.framework.apollo.common.entity;
import com.ctrip.framework.apollo.common.entity.BaseEntity;
......
package com.ctrip.framework.apollo.biz.entity;
package com.ctrip.framework.apollo.common.entity;
import com.ctrip.framework.apollo.common.entity.BaseEntity;
import javax.persistence.Column;
import javax.persistence.Entity;
......
......@@ -8,7 +8,7 @@ import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ctrip.framework.apollo.biz.entity.AppNamespace;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.biz.entity.Release;
import com.ctrip.framework.apollo.biz.service.AppNamespaceService;
import com.ctrip.framework.apollo.biz.service.ConfigService;
......
......@@ -9,7 +9,7 @@ import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Sets;
import com.ctrip.framework.apollo.biz.entity.AppNamespace;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.biz.entity.ReleaseMessage;
import com.ctrip.framework.apollo.biz.message.ReleaseMessageListener;
import com.ctrip.framework.apollo.biz.message.Topics;
......
......@@ -6,7 +6,7 @@ import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.ctrip.framework.apollo.biz.entity.AppNamespace;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.biz.entity.Release;
import com.ctrip.framework.apollo.biz.service.AppNamespaceService;
import com.ctrip.framework.apollo.biz.service.ConfigService;
......
......@@ -4,7 +4,7 @@ import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.ctrip.framework.apollo.biz.entity.AppNamespace;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.biz.entity.ReleaseMessage;
import com.ctrip.framework.apollo.biz.message.Topics;
import com.ctrip.framework.apollo.biz.service.AppNamespaceService;
......
......@@ -28,6 +28,11 @@
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
......
package com.ctrip.framework.apollo.portal.auth;
import com.ctrip.framework.apollo.portal.constant.PermissionType;
import com.ctrip.framework.apollo.portal.service.RolePermissionService;
import com.ctrip.framework.apollo.portal.util.RoleUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("permissionValidator")
public class PermissionValidator {
@Autowired
private UserInfoHolder userInfoHolder;
@Autowired
private RolePermissionService rolePermissionService;
public boolean hasModifyNamespacePermission(String appId, String namespaceName){
return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(),
PermissionType.MODIFY_NAMESPACE,
RoleUtils.buildNamespaceTargetId(appId, namespaceName));
}
public boolean hasReleaseNamespacePermission(String appId, String namespaceName){
return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(),
PermissionType.RELEASE_NAMESPACE,
RoleUtils.buildNamespaceTargetId(appId, namespaceName));
}
public boolean hasAssignRolePermission(String appId){
return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(),
PermissionType.ASSIGN_ROLE,
appId);
}
public boolean hasCreateNamespacePermission(String appId){
return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(),
PermissionType.CREATE_NAMESPACE,
appId);
}
public boolean hasCreateClusterPermission(String appId){
return rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(),
PermissionType.CREATE_CLUSTER,
appId);
}
}
package com.ctrip.framework.apollo.portal.constant;
public interface PermissionType {
/** APP level permission */
String CREATE_NAMESPACE = "CreateNamespace";
String CREATE_CLUSTER = "CreateCluster";
/**
* 分配用户权限的权限
*/
String ASSIGN_ROLE = "AssignRole";
/** namespace level permission*/
String MODIFY_NAMESPACE = "ModifyNamespace";
String RELEASE_NAMESPACE = "ReleaseNamespace";
}
package com.ctrip.framework.apollo.portal.constant;
public class RoleType {
public static final String MASTER = "Master";
public static final String MODIFY_NAMESPACE = "ModifyNamespace";
public static final String RELEASE_NAMESPACE = "ReleaseNamespace";
public static boolean isValidRoleType(String roleType) {
return MASTER.equals(roleType) || MODIFY_NAMESPACE.equals(roleType) || RELEASE_NAMESPACE.equals(roleType);
}
}
package com.ctrip.framework.apollo.portal.constants;
public interface PortalConstants {
long LASTEST_VERSION_ID = -1;
}
package com.ctrip.framework.apollo.portal.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
......@@ -10,43 +11,36 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpClientErrorException;
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.core.dto.AppDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.exception.BadRequestException;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.PortalSettings;
import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo;
import com.ctrip.framework.apollo.portal.service.PortalAppService;
import com.ctrip.framework.apollo.portal.service.AppService;
import java.util.List;
import static com.ctrip.framework.apollo.portal.util.RequestPrecondition.checkArgument;
@RestController
@RequestMapping("/apps")
public class PortalAppController {
public class AppController {
@Autowired
private PortalAppService appService;
private AppService appService;
@Autowired
private PortalSettings portalSettings;
@RequestMapping("/envs/{env}")
public List<AppDTO> findAllApp(@PathVariable String env){
if (StringUtils.isEmpty(env)){
throw new BadRequestException("env can not be empty");
}
return appService.findAll(Env.valueOf(env));
@RequestMapping("")
public List<App> findAllApp() {
return appService.findAll();
}
@RequestMapping("/{appId}/navtree")
public MultiResponseEntity<EnvClusterInfo> nav(@PathVariable String appId) {
if (StringUtils.isEmpty(appId)) {
throw new BadRequestException("app id can not be empty.");
}
MultiResponseEntity<EnvClusterInfo> response = MultiResponseEntity.ok();
List<Env> envs = portalSettings.getActiveEnvs();
for (Env env : envs) {
......@@ -61,42 +55,46 @@ public class PortalAppController {
return response;
}
@RequestMapping(value = "", method = RequestMethod.POST)
public ResponseEntity<Void> create(@RequestBody App app) {
checkArgument(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName());
appService.createApp(app);
return ResponseEntity.ok().build();
}
@RequestMapping(value = "/envs/{env}", method = RequestMethod.POST, consumes = {"application/json"})
public ResponseEntity<Void> create(@PathVariable String env, @RequestBody AppDTO app) {
if (isInvalidApp(app)){
throw new BadRequestException("request payload contains empty");
}
if ("ALL".equals(env)){
appService.createAppInAllEnvs(app);
} else {
appService.createApp(Env.valueOf(env), app);
}
public ResponseEntity<Void> create(@PathVariable String env, @RequestBody App app) {
checkArgument(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName());
appService.createApp(Env.valueOf(env), app);
return ResponseEntity.ok().build();
}
@RequestMapping(value = "/{appId}", method = RequestMethod.GET)
public AppDTO load(@PathVariable String appId){
if (StringUtils.isEmpty(appId)){
throw new BadRequestException("app id can not be empty.");
}
public App load(@PathVariable String appId) {
return appService.load(appId);
}
@RequestMapping(value = "/{appId}/miss_envs")
public MultiResponseEntity<Env> findMissEnvs(@PathVariable String appId) {
MultiResponseEntity<Env> response = MultiResponseEntity.ok();
for (Env env : portalSettings.getActiveEnvs()) {
try {
appService.load(env, appId);
} catch (Exception e) {
if (e instanceof HttpClientErrorException &&
((HttpClientErrorException)e).getStatusCode() == HttpStatus.NOT_FOUND){
((HttpClientErrorException) e).getStatusCode() == HttpStatus.NOT_FOUND) {
response.addResponseEntity(RichResponseEntity.ok(env));
} else {
response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR,
String
.format("load appId:%s from env %s error.", appId,
env)
String.format("load appId:%s from env %s error.", appId, env)
+ e.getMessage()));
}
}
......@@ -107,8 +105,4 @@ public class PortalAppController {
}
private boolean isInvalidApp(AppDTO app) {
return StringUtils.isContainEmpty(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName());
}
}
package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.core.dto.ItemDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
......@@ -10,11 +11,12 @@ 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.entity.form.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.service.PortalConfigService;
import com.ctrip.framework.apollo.portal.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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;
......@@ -23,85 +25,78 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static com.ctrip.framework.apollo.portal.util.RequestPrecondition.checkModel;
@RestController
@RequestMapping("")
public class PortalConfigController {
public class ConfigController {
@Autowired
private PortalConfigService configService;
private ConfigService configService;
@PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items", method = RequestMethod.PUT, consumes = {
"application/json"})
public void modifyItems(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName,
@RequestBody NamespaceTextModel model) {
if (model == null) {
throw new BadRequestException("request payload should not be null");
}
checkModel(model != null);
model.setAppId(appId);
model.setClusterName(clusterName);
model.setEnv(env);
model.setNamespaceName(namespaceName);
if (model.isInvalid()) {
throw new BadRequestException("request model is invalid");
}
configService.updateConfigItemByText(model);
}
@PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item", method = RequestMethod.POST)
public ItemDTO createItem(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName,
@RequestBody ItemDTO item){
if (StringUtils.isContainEmpty(appId, env, clusterName, namespaceName)){
throw new BadRequestException("request payload should not be contain empty.");
}
if (!isValidItem(item) && item.getNamespaceId() <= 0){
throw new BadRequestException("request model is invalid");
}
checkModel(isValidItem(item));
return configService.createOrUpdateItem(appId, Env.valueOf(env), clusterName, namespaceName, item);
}
@PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item", method = RequestMethod.PUT)
public ItemDTO updateItem(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName,
@RequestBody ItemDTO item){
if (StringUtils.isContainEmpty(appId, env, clusterName, namespaceName)){
throw new BadRequestException("request payload should not be contain empty.");
}
if (!isValidItem(item)){
throw new BadRequestException("request model is invalid");
}
checkModel(isValidItem(item));
return configService.createOrUpdateItem(appId, Env.valueOf(env), clusterName, namespaceName, item);
}
@RequestMapping(value = "/envs/{env}/items/{itemId}", method = RequestMethod.DELETE)
public void deleteItem(@PathVariable String env, @PathVariable long itemId){
@PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/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){
if (itemId <= 0){
throw new BadRequestException("item id invalid");
}
configService.deleteItem(Env.valueOf(env), itemId);
}
@PreAuthorize(value = "@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/release", method = RequestMethod.POST, consumes = {
"application/json"})
public ReleaseDTO createRelease(@PathVariable String appId,
@PathVariable String env, @PathVariable String clusterName,
@PathVariable String namespaceName, @RequestBody NamespaceReleaseModel model) {
if (model == null) {
throw new BadRequestException("request payload should not be null");
}
checkModel(model != null);
model.setAppId(appId);
model.setClusterName(clusterName);
model.setEnv(env);
model.setClusterName(clusterName);
model.setNamespaceName(namespaceName);
if (model.isInvalid()) {
throw new BadRequestException("request model is invalid");
}
return configService.createRelease(model);
}
......@@ -110,35 +105,24 @@ public class PortalConfigController {
public List<ItemDTO> findItems(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName){
if (StringUtils.isContainEmpty(appId, env, clusterName, namespaceName)){
throw new BadRequestException("appid,env,cluster name,namespace name can not be empty");
}
return configService.findItems(appId, Env.valueOf(env), clusterName, namespaceName);
}
@RequestMapping(value = "/namespaces/{namespaceName}/diff", method = RequestMethod.POST, consumes = {
"application/json"})
public List<ItemDiffs> diff(@RequestBody NamespaceSyncModel model){
if (model == null){
throw new BadRequestException("request payload should not be null");
}
if (model.isInvalid()) {
throw new BadRequestException("request model is invalid");
}
checkModel(model != null && !model.isInvalid());
return configService.compare(model.getSyncToNamespaces(), model.getSyncItems());
}
@RequestMapping(value = "/namespaces/{namespaceName}/items", method = RequestMethod.PUT, consumes = {
@PreAuthorize(value = "@permissionValidator.hasModifyNamespacePermission(#appId, #namespaceName)")
@RequestMapping(value = "/apps/{appId}/namespaces/{namespaceName}/items", method = RequestMethod.PUT, consumes = {
"application/json"})
public ResponseEntity<Void> update(@RequestBody NamespaceSyncModel model){
if (model == null){
throw new BadRequestException("request payload should not be null");
}
if (model.isInvalid()) {
throw new BadRequestException("request model is invalid");
}
public ResponseEntity<Void> update(@PathVariable String appId, @PathVariable String namespaceName,
@RequestBody NamespaceSyncModel model){
checkModel(model != null && !model.isInvalid());
configService.syncItems(model.getSyncToNamespaces(), model.getSyncItems());
return ResponseEntity.status(HttpStatus.OK).build();
}
......
......@@ -12,7 +12,7 @@ import java.util.List;
@RestController
@RequestMapping("/envs")
public class PortalEnvController {
public class EnvController {
@Autowired
private PortalSettings portalSettings;
......
......@@ -3,12 +3,11 @@ package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.core.dto.AppNamespaceDTO;
import com.ctrip.framework.apollo.core.dto.NamespaceDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.exception.BadRequestException;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.service.PortalNamespaceService;
import com.ctrip.framework.apollo.portal.service.NamespaceService;
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;
......@@ -17,40 +16,39 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static com.ctrip.framework.apollo.portal.util.RequestPrecondition.checkArgument;
@RestController
public class PortalNamespaceController {
public class NamespaceController {
@Autowired
private PortalNamespaceService namespaceService;
private NamespaceService namespaceService;
@RequestMapping("/appnamespaces/public")
public List<AppNamespaceDTO> findPublicAppNamespaces(){
public List<AppNamespaceDTO> findPublicAppNamespaces() {
return namespaceService.findPublicAppNamespaces();
}
@PreAuthorize(value = "@permissionValidator.hasCreateNamespacePermission(#appId)")
@RequestMapping(value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces", method = RequestMethod.POST)
public NamespaceDTO createNamespace(@PathVariable String env, @RequestBody NamespaceDTO namespace){
if (StringUtils.isContainEmpty(env, namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName())){
throw new BadRequestException("request payload contains empty");
}
public NamespaceDTO createNamespace(@PathVariable String env, @RequestBody NamespaceDTO namespace) {
checkArgument(namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName());
return namespaceService.createNamespace(Env.valueOf(env), namespace);
}
@RequestMapping(value = "/apps/{appId}/appnamespaces", method = RequestMethod.POST)
public void createAppNamespace(@PathVariable String appId, @RequestBody AppNamespaceDTO appNamespace){
if (StringUtils.isContainEmpty(appId, appNamespace.getAppId(), appNamespace.getName())){
throw new BadRequestException("request payload contains empty");
}
public void createAppNamespace(@PathVariable String appId, @RequestBody AppNamespaceDTO appNamespace) {
checkArgument(appNamespace.getAppId(), appNamespace.getName());
namespaceService.createAppNamespace(appNamespace);
namespaceService.createRemoteAppNamespace(appNamespace);
}
@RequestMapping("/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces")
public List<NamespaceVO> findNamespaces(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName) {
if (StringUtils.isContainEmpty(appId, env, clusterName)) {
throw new BadRequestException("app id and cluster name can not be empty");
}
return namespaceService.findNampspaces(appId, Env.valueOf(env), clusterName);
}
......
package com.ctrip.framework.apollo.portal.controller;
import com.google.common.collect.Sets;
import com.ctrip.framework.apollo.core.exception.BadRequestException;
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;
import com.ctrip.framework.apollo.portal.entity.vo.AppRolesAssignedUsers;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceRolesAssignedUsers;
import com.ctrip.framework.apollo.portal.entity.vo.PermissionCondition;
import com.ctrip.framework.apollo.portal.service.RolePermissionService;
import com.ctrip.framework.apollo.portal.util.RoleUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
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 java.util.Set;
import static com.ctrip.framework.apollo.portal.util.RequestPrecondition.checkArgument;
@RestController
public class PermissionController {
@Autowired
private UserInfoHolder userInfoHolder;
@Autowired
private RolePermissionService rolePermissionService;
@RequestMapping("/apps/{appId}/permissions/{permissionType}")
public ResponseEntity<PermissionCondition> isHasPermission(@PathVariable String appId, @PathVariable String permissionType) {
PermissionCondition permissionCondition = new PermissionCondition();
permissionCondition.setHasPermission(
rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), permissionType, appId));
return ResponseEntity.ok().body(permissionCondition);
}
@RequestMapping("/apps/{appId}/namespaces/{namespaceName}/permissions/{permissionType}")
public ResponseEntity<PermissionCondition> isHasPermission(@PathVariable String appId, @PathVariable String namespaceName,
@PathVariable String permissionType) {
PermissionCondition permissionCondition = new PermissionCondition();
permissionCondition.setHasPermission(
rolePermissionService.userHasPermission(userInfoHolder.getUser().getUserId(), permissionType,
RoleUtils.buildNamespaceTargetId(appId, namespaceName)));
return ResponseEntity.ok().body(permissionCondition);
}
@RequestMapping("/apps/{appId}/namespaces/{namespaceName}/role_users")
public NamespaceRolesAssignedUsers getNamespaceRoles(@PathVariable String appId, @PathVariable String namespaceName){
NamespaceRolesAssignedUsers assignedUsers = new NamespaceRolesAssignedUsers();
assignedUsers.setNamespaceName(namespaceName);
assignedUsers.setAppId(appId);
Set<UserInfo> releaseNamespaceUsers =
rolePermissionService.queryUsersWithRole(RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName));
assignedUsers.setReleaseRoleUsers(releaseNamespaceUsers);
Set<UserInfo> modifyNamespaceUsers =
rolePermissionService.queryUsersWithRole(RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName));
assignedUsers.setModifyRoleUsers(modifyNamespaceUsers);
return assignedUsers;
}
@PreAuthorize(value = "@permissionValidator.hasAssignRolePermission(#appId)")
@RequestMapping(value = "/apps/{appId}/namespaces/{namespaceName}/roles/{roleType}", method = RequestMethod.POST)
public ResponseEntity<Void> assignNamespaceRoleToUser(@PathVariable String appId, @PathVariable String namespaceName,
@PathVariable String roleType, @RequestBody String user){
checkArgument(user);
if (!RoleType.isValidRoleType(roleType)){
throw new BadRequestException("role type is illegal");
}
rolePermissionService.assignRoleToUsers(RoleUtils.buildNamespaceRoleName(appId, namespaceName, roleType),
Sets.newHashSet(user), userInfoHolder.getUser().getUserId());
return ResponseEntity.ok().build();
}
@PreAuthorize(value = "@permissionValidator.hasAssignRolePermission(#appId)")
@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);
if (!RoleType.isValidRoleType(roleType)){
throw new BadRequestException("role type is illegal");
}
rolePermissionService.removeRoleFromUsers(RoleUtils.buildNamespaceRoleName(appId, namespaceName, roleType),
Sets.newHashSet(user), userInfoHolder.getUser().getUserId());
return ResponseEntity.ok().build();
}
@RequestMapping(value = "/apps/{appId}/role_users")
public AppRolesAssignedUsers getAppRoles(@PathVariable String appId){
AppRolesAssignedUsers users = new AppRolesAssignedUsers();
users.setAppId(appId);
Set<UserInfo> masterUsers = rolePermissionService.queryUsersWithRole(RoleUtils.buildAppMasterRoleName(appId));
users.setMasterUsers(masterUsers);
return users;
}
@PreAuthorize(value = "@permissionValidator.hasAssignRolePermission(#appId)")
@RequestMapping(value = "/apps/{appId}/roles/{roleType}", method = RequestMethod.POST)
public ResponseEntity<Void> assignAppRoleToUser(@PathVariable String appId, @PathVariable String roleType,
@RequestBody String user){
checkArgument(user);
if (!RoleType.isValidRoleType(roleType)){
throw new BadRequestException("role type is illegal");
}
rolePermissionService.assignRoleToUsers(RoleUtils.buildAppRoleName(appId, roleType),
Sets.newHashSet(user), userInfoHolder.getUser().getUserId());
return ResponseEntity.ok().build();
}
@PreAuthorize(value = "@permissionValidator.hasAssignRolePermission(#appId)")
@RequestMapping(value = "/apps/{appId}/roles/{roleType}", method = RequestMethod.DELETE)
public ResponseEntity<Void> removeAppRoleFromUser(@PathVariable String appId, @PathVariable String roleType,
@RequestParam String user){
checkArgument(user);
if (!RoleType.isValidRoleType(roleType)){
throw new BadRequestException("role type is illegal");
}
rolePermissionService.removeRoleFromUsers(RoleUtils.buildAppRoleName(appId, roleType),
Sets.newHashSet(user), userInfoHolder.getUser().getUserId());
return ResponseEntity.ok().build();
}
}
......@@ -2,8 +2,6 @@ package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.core.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.po.ServerConfig;
import com.ctrip.framework.apollo.portal.repository.ServerConfigRepository;
......@@ -14,11 +12,14 @@ 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.portal.util.RequestPrecondition.checkArgument;
import static com.ctrip.framework.apollo.portal.util.RequestPrecondition.checkModel;
/**
* 配置中心本身需要一些配置,这些配置放在数据库里面
*/
@RestController
public class PortalServerConfigController {
public class ServerConfigController {
@Autowired
private ServerConfigRepository serverConfigRepository;
......@@ -28,9 +29,8 @@ public class PortalServerConfigController {
@RequestMapping(value = "/server/config", method = RequestMethod.POST)
public ServerConfig createOrUpdate(@RequestBody ServerConfig serverConfig) {
if (serverConfig == null || StringUtils.isContainEmpty(serverConfig.getKey(), serverConfig.getValue())) {
throw new BadRequestException("request payload contains empty");
}
checkModel(serverConfig != null);
checkArgument(serverConfig.getKey(), serverConfig.getValue());
String modifiedBy = userInfoHolder.getUser().getUserId();
......@@ -46,7 +46,6 @@ public class PortalServerConfigController {
return serverConfigRepository.save(storedConfig);
}
}
......
......@@ -14,7 +14,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
public class PortalUserInfoController {
public class UserInfoController {
@Autowired
private UserInfoHolder userInfoHolder;
......
package com.ctrip.framework.apollo.portal.entity.vo;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
import java.util.Set;
public class AppRolesAssignedUsers {
private String appId;
private Set<UserInfo> masterUsers;
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public Set<UserInfo> getMasterUsers() {
return masterUsers;
}
public void setMasterUsers(Set<UserInfo> masterUsers) {
this.masterUsers = masterUsers;
}
}
package com.ctrip.framework.apollo.portal.entity.vo;
import com.ctrip.framework.apollo.portal.entity.po.UserInfo;
import java.util.Set;
public class NamespaceRolesAssignedUsers {
private String appId;
private String namespaceName;
private Set<UserInfo> modifyRoleUsers;
private Set<UserInfo> releaseRoleUsers;
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getNamespaceName() {
return namespaceName;
}
public void setNamespaceName(String namespaceName) {
this.namespaceName = namespaceName;
}
public Set<UserInfo> getModifyRoleUsers() {
return modifyRoleUsers;
}
public void setModifyRoleUsers(
Set<UserInfo> modifyRoleUsers) {
this.modifyRoleUsers = modifyRoleUsers;
}
public Set<UserInfo> getReleaseRoleUsers() {
return releaseRoleUsers;
}
public void setReleaseRoleUsers(
Set<UserInfo> releaseRoleUsers) {
this.releaseRoleUsers = releaseRoleUsers;
}
}
package com.ctrip.framework.apollo.portal.entity.vo;
public class PermissionCondition {
private boolean hasPermission;
public boolean isHasPermission() {
return hasPermission;
}
public void setHasPermission(boolean hasPermission) {
this.hasPermission = hasPermission;
}
}
package com.ctrip.framework.apollo.portal.listener;
import com.google.common.base.Preconditions;
import com.ctrip.framework.apollo.common.entity.App;
import org.springframework.context.ApplicationEvent;
public class AppCreationEvent extends ApplicationEvent {
/**
* Create a new ApplicationEvent.
*
* @param source the object on which the event initially occurred (never {@code null})
*/
public AppCreationEvent(Object source) {
super(source);
}
public App getApp() {
Preconditions.checkState(source != null);
return (App) this.source;
}
}
package com.ctrip.framework.apollo.portal.listener;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.common.utils.ExceptionUtils;
import com.ctrip.framework.apollo.core.dto.AppDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.PortalSettings;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpStatusCodeException;
import java.util.List;
@Component
public class CreationListener {
private static Logger logger = LoggerFactory.getLogger(CreationListener.class);
@Autowired
private PortalSettings portalSettings;
@Autowired
private AdminServiceAPI.AppAPI appAPI;
@EventListener
public void onAppCreationEvent(AppCreationEvent event) {
AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp());
List<Env> envs = portalSettings.getActiveEnvs();
for (Env env : envs) {
try {
appAPI.createApp(env, appDTO);
} catch (HttpStatusCodeException e) {
logger.error(ExceptionUtils.toString(e));
}
}
}
}
package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNamespace, Long>{
AppNamespace findByAppIdAndName(String appId, String namespaceName);
AppNamespace findByName(String namespaceName);
List<AppNamespace> findByNameNot(String namespaceName);
}
package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.common.entity.App;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface AppRepository extends PagingAndSortingRepository<App, Long> {
@Query("SELECT a from App a WHERE a.name LIKE %:name%")
List<App> findByName(@Param("name") String name);
App findByAppId(String appId);
}
package com.ctrip.framework.apollo.portal.service;
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.HttpStatusCodeException;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.common.utils.ExceptionUtils;
import com.ctrip.framework.apollo.core.dto.AppDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.exception.BadRequestException;
import com.ctrip.framework.apollo.core.exception.ServiceException;
import com.ctrip.framework.apollo.portal.PortalSettings;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo;
import com.ctrip.framework.apollo.portal.listener.AppCreationEvent;
import com.ctrip.framework.apollo.portal.repository.AppRepository;
@Service
public class PortalAppService {
public class AppService {
private Logger logger = LoggerFactory.getLogger(PortalAppService.class);
private Logger logger = LoggerFactory.getLogger(AppService.class);
@Autowired
private UserInfoHolder userInfoHolder;
@Autowired
private ClusterService clusterService;
@Autowired
private NamespaceService namespaceService;
@Autowired
private RoleInitializationService roleInitializationService;
@Autowired
private PortalClusterService clusterService;
private AdminServiceAPI.AppAPI appAPI;
@Autowired
private PortalSettings portalSettings;
private AppRepository appRepository;
@Autowired
private AdminServiceAPI.AppAPI appAPI;
private ApplicationEventPublisher publisher;
public List<AppDTO> findAll(Env env) {
return appAPI.findApps(env);
public List<App> findAll() {
Iterable<App> apps = appRepository.findAll();
if (apps == null) {
return Collections.EMPTY_LIST;
}
return Lists.newArrayList((apps));
}
public AppDTO load(String appId) {
//轮询环境直到能找到此app的信息
AppDTO app = null;
boolean isCallAdminServiceError = false;
for (Env env : portalSettings.getActiveEnvs()) {
try {
app = appAPI.loadApp(env, appId);
break;
} catch (HttpClientErrorException e) {
//not exist maybe because create app fail.
if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
logger.warn("app:{} in {} not exist", appId, env);
} else {
isCallAdminServiceError = true;
logger.error("load app info({}) from env:{} error.", appId, env);
}
}
}
if (app == null) {
if (isCallAdminServiceError){
throw new ServiceException("call admin service error");
}else {
throw new BadRequestException(String.format("invalid app id %s", appId));
}
public App load(String appId) {
App app = appRepository.findByAppId(appId);
if (app == null){
throw new BadRequestException(String.format("app %s cant found.", appId));
}
return app;
}
public AppDTO load(Env env, String appId){
public AppDTO load(Env env, String appId) {
return appAPI.loadApp(env, appId);
}
public void createAppInAllEnvs(AppDTO app) {
/**
* 创建App流程: 1.先在portal db中创建 2.再保存到各个环境的apollo db中
*
* 只要第一步成功,就算这次创建app是成功操作,如果某个环境的apollo db创建失败,可通过portal db中的app信息再次创建.
*/
public void createApp(App app) {
enrichUserInfo(app);
List<Env> envs = portalSettings.getActiveEnvs();
for (Env env : envs) {
try {
appAPI.createApp(env, app);
} catch (HttpStatusCodeException e) {
logger.error(ExceptionUtils.toString(e));
throw e;
}
}
App localApp = createOrUpdateAppInLocal(app);
publisher.publishEvent(new AppCreationEvent(localApp));
}
public void createApp(Env env, AppDTO app) {
public void createApp(Env env, App app) {
enrichUserInfo(app);
try {
appAPI.createApp(env, app);
AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, app);
appAPI.createApp(env, appDTO);
} catch (HttpStatusCodeException e) {
logger.error(ExceptionUtils.toString(e));
throw e;
}
}
private void enrichUserInfo(AppDTO app){
private void enrichUserInfo(App app) {
String username = userInfoHolder.getUser().getUserId();
app.setDataChangeCreatedBy(username);
app.setDataChangeLastModifiedBy(username);
}
public EnvClusterInfo createEnvNavNode(Env env, String appId){
@Transactional
private App createOrUpdateAppInLocal(App app) {
String appId = app.getAppId();
App managedApp = appRepository.findByAppId(appId);
if (managedApp != null) {
BeanUtils.copyEntityProperties(app, managedApp);
return appRepository.save(managedApp);
} else {
App createdApp = appRepository.save(app);
namespaceService.createDefaultAppNamespace(appId);
//role
roleInitializationService.initAppRoles(createdApp);
return createdApp;
}
}
public EnvClusterInfo createEnvNavNode(Env env, String appId) {
EnvClusterInfo node = new EnvClusterInfo(env);
node.setClusters(clusterService.findClusters(env, appId));
return node;
......
......@@ -10,7 +10,7 @@ import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class PortalClusterService {
public class ClusterService {
@Autowired
private AdminServiceAPI.ClusterAPI clusterAPI;
......
......@@ -31,9 +31,9 @@ import java.util.List;
import java.util.Map;
@Service
public class PortalConfigService {
public class ConfigService {
private Logger logger = LoggerFactory.getLogger(PortalConfigService.class);
private Logger logger = LoggerFactory.getLogger(ConfigService.class);
@Autowired
private UserInfoHolder userInfoHolder;
......
......@@ -2,24 +2,29 @@ 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.utils.BeanUtils;
import com.ctrip.framework.apollo.common.utils.ExceptionUtils;
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.core.dto.AppNamespaceDTO;
import com.ctrip.framework.apollo.core.dto.ItemDTO;
import com.ctrip.framework.apollo.core.dto.NamespaceDTO;
import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.exception.ServiceException;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.PortalSettings;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.repository.AppNamespaceRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpStatusCodeException;
......@@ -28,11 +33,12 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Service
public class PortalNamespaceService {
public class NamespaceService {
private Logger logger = LoggerFactory.getLogger(PortalNamespaceService.class);
private Logger logger = LoggerFactory.getLogger(NamespaceService.class);
@Autowired
private UserInfoHolder userInfoHolder;
......@@ -44,6 +50,10 @@ public class PortalNamespaceService {
private AdminServiceAPI.NamespaceAPI namespaceAPI;
@Autowired
private PortalSettings portalSettings;
@Autowired
private AppNamespaceRepository appNamespaceRepository;
@Autowired
private RoleInitializationService roleInitializationService;
private Gson gson = new Gson();
......@@ -53,16 +63,41 @@ public class PortalNamespaceService {
}
public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) {
if (StringUtils.isEmpty(namespace.getDataChangeCreatedBy())){
if (StringUtils.isEmpty(namespace.getDataChangeCreatedBy())) {
namespace.setDataChangeCreatedBy(userInfoHolder.getUser().getUserId());
}
namespace.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId());
return namespaceAPI.createNamespace(env, namespace);
NamespaceDTO createdNamespace = namespaceAPI.createNamespace(env, namespace);
roleInitializationService.initNamespaceRoles(namespace.getAppId(), namespace.getNamespaceName());
return createdNamespace;
}
@Transactional
public void createDefaultAppNamespace(String appId) {
if (!isAppNamespaceNameUnique(appId, appId)) {
throw new ServiceException("appnamespace not unique");
}
AppNamespace appNs = new AppNamespace();
appNs.setAppId(appId);
appNs.setName(ConfigConsts.NAMESPACE_APPLICATION);
appNs.setComment("default app namespace");
String userId = userInfoHolder.getUser().getUserId();
appNs.setDataChangeCreatedBy(userId);
appNs.setDataChangeLastModifiedBy(userId);
appNamespaceRepository.save(appNs);
}
public boolean isAppNamespaceNameUnique(String appId, String namespaceName) {
Objects.requireNonNull(appId, "AppId must not be null");
Objects.requireNonNull(namespaceName, "Namespace must not be null");
return Objects.isNull(appNamespaceRepository.findByAppIdAndName(appId, namespaceName));
}
public void createAppNamespace(AppNamespaceDTO appNamespace) {
public void createRemoteAppNamespace(AppNamespaceDTO appNamespace) {
String operator = userInfoHolder.getUser().getUserId();
if (StringUtils.isEmpty(appNamespace.getDataChangeCreatedBy())){
if (StringUtils.isEmpty(appNamespace.getDataChangeCreatedBy())) {
appNamespace.setDataChangeCreatedBy(operator);
}
appNamespace.setDataChangeLastModifiedBy(operator);
......@@ -155,9 +190,9 @@ public class PortalNamespaceService {
Map<String, ItemDTO> newItemMap = BeanUtils.mapByKey("key", newItems);
List<NamespaceVO.ItemVO> deletedItems = new LinkedList<>();
for (Map.Entry<String, String> entry: releaseItems.entrySet()){
for (Map.Entry<String, String> entry : releaseItems.entrySet()) {
String key = entry.getKey();
if (newItemMap.get(key) == null){
if (newItemMap.get(key) == null) {
NamespaceVO.ItemVO deletedItem = new NamespaceVO.ItemVO();
ItemDTO deletedItemDto = new ItemDTO();
......
package com.ctrip.framework.apollo.portal.service;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.constant.PermissionType;
import com.ctrip.framework.apollo.portal.entity.po.Permission;
import com.ctrip.framework.apollo.portal.entity.po.Role;
import com.ctrip.framework.apollo.portal.util.RoleUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Set;
@Service
public class RoleInitializationService {
@Autowired
private UserInfoHolder userInfoHolder;
@Autowired
private RolePermissionService rolePermissionService;
@Transactional
public void initAppRoles(App app) {
String appId = app.getAppId();
String appMasterRoleName = RoleUtils.buildAppMasterRoleName(appId);
//has created before
if (rolePermissionService.findRoleByRoleName(appMasterRoleName) != null){
return;
}
String operaterUserId = userInfoHolder.getUser().getUserId();
//create app permissions
createAppMasterRole(appId);
//assign master role to user
rolePermissionService
.assignRoleToUsers(RoleUtils.buildAppMasterRoleName(appId), Sets.newHashSet(app.getOwnerName()),
operaterUserId);
initNamespaceRoles(appId, ConfigConsts.NAMESPACE_APPLICATION);
}
@Transactional
public void initNamespaceRoles(String appId, String namespaceName) {
String modifyNamespaceRoleName = RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName);
if (rolePermissionService.findRoleByRoleName(modifyNamespaceRoleName) == null) {
createDefaultNamespaceRole(appId, namespaceName, PermissionType.MODIFY_NAMESPACE,
RoleUtils.buildModifyNamespaceRoleName(appId, namespaceName));
}
String releaseNamespaceRoleName = RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName);
if (rolePermissionService.findRoleByRoleName(releaseNamespaceRoleName) == null) {
createDefaultNamespaceRole(appId, namespaceName, PermissionType.RELEASE_NAMESPACE,
RoleUtils.buildReleaseNamespaceRoleName(appId, namespaceName));
}
}
private void createAppMasterRole(String appId) {
Set<Permission> appPermissions =
FluentIterable.from(Lists.newArrayList(
PermissionType.CREATE_CLUSTER, PermissionType.CREATE_NAMESPACE, PermissionType.ASSIGN_ROLE))
.transform(permissionType -> createPermisson(appId, permissionType)).toSet();
Set<Permission> createdAppPermissions = rolePermissionService.createPermissions(appPermissions);
Set<Long>
appPermissionIds =
FluentIterable.from(createdAppPermissions).transform(permission -> permission.getId()).toSet();
//create app master role
Role appMasterRole = createRole(RoleUtils.buildAppMasterRoleName(appId));
rolePermissionService.createRoleWithPermissions(appMasterRole, appPermissionIds);
}
private Permission createPermisson(String targetId, String permisson) {
Permission permission = new Permission();
permission.setPermissionType(permisson);
permission.setTargetId(targetId);
String userId = userInfoHolder.getUser().getUserId();
permission.setDataChangeCreatedBy(userId);
permission.setDataChangeLastModifiedBy(userId);
return permission;
}
private Role createRole(String roleName) {
Role role = new Role();
role.setRoleName(roleName);
String operaterUserId = userInfoHolder.getUser().getUserId();
role.setDataChangeCreatedBy(operaterUserId);
role.setDataChangeLastModifiedBy(operaterUserId);
return role;
}
private void createDefaultNamespaceRole(String appId, String namespaceName, String permissionType, String roleName) {
Permission
modifyDefaultNsPermission =
createPermisson(RoleUtils.buildNamespaceTargetId(appId, namespaceName), permissionType);
Permission createdModifyDefaultNsPermission = rolePermissionService.createPermission(modifyDefaultNsPermission);
Role role = createRole(roleName);
rolePermissionService
.createRoleWithPermissions(role, Sets.newHashSet(createdModifyDefaultNsPermission.getId()));
}
}
package com.ctrip.framework.apollo.portal.util;
import com.ctrip.framework.apollo.core.exception.BadRequestException;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.sun.istack.internal.Nullable;
public class RequestPrecondition {
private static String CONTAIN_EMPTY_ARGUMENT = "request payload should not be contain empty.";
private static String ILLEGAL_MODEL = "request model is invalid";
public static void checkArgument(String... args) {
checkArgument(!StringUtils.isContainEmpty(args), CONTAIN_EMPTY_ARGUMENT);
}
public static void checkModel(boolean valid){
checkArgument(valid, ILLEGAL_MODEL);
}
public static void checkArgument(boolean expression, @Nullable Object errorMessage) {
if (!expression) {
throw new BadRequestException(String.valueOf(errorMessage));
}
}
}
package com.ctrip.framework.apollo.portal.util;
import com.google.common.base.Joiner;
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.portal.constant.RoleType;
public class RoleUtils {
private static final Joiner STRING_JOINER = Joiner.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR);
public static String buildAppMasterRoleName(String appId){
return STRING_JOINER.join(RoleType.MASTER, appId);
}
public static String buildAppRoleName(String appId, String roleType){
return STRING_JOINER.join(roleType, appId);
}
public static String buildModifyNamespaceRoleName(String appId, String namespaceName){
return STRING_JOINER.join(RoleType.MODIFY_NAMESPACE, appId, namespaceName);
}
public static String buildModifyDefaultNamespaceRoleName(String appId){
return STRING_JOINER.join(RoleType.MODIFY_NAMESPACE, appId, ConfigConsts.NAMESPACE_APPLICATION);
}
public static String buildReleaseNamespaceRoleName(String appId, String namespaceName){
return STRING_JOINER.join(RoleType.RELEASE_NAMESPACE, appId, namespaceName);
}
public static String buildNamespaceRoleName(String appId, String namespaceName, String roleType){
return STRING_JOINER.join(roleType, appId, namespaceName);
}
public static String buildReleaseDefaultNamespaceRoleName(String appId){
return STRING_JOINER.join(RoleType.RELEASE_NAMESPACE, appId, ConfigConsts.NAMESPACE_APPLICATION);
}
public static String buildNamespaceTargetId(String appId, String namespaceName){
return STRING_JOINER.join(appId, namespaceName);
}
public static String buildDefaultNamespaceTargetId(String appId){
return STRING_JOINER.join(appId, ConfigConsts.NAMESPACE_APPLICATION);
}
}
......@@ -16,7 +16,6 @@ logging:
endpoints:
health:
sensitive: false
management:
security:
enabled: false
......
<!doctype html>
<html ng-app="role">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- styles -->
<link rel="stylesheet" type="text/css" href="../vendor/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="../vendor/angular/angular-toastr-1.4.1.min.css">
<link rel="stylesheet" type="text/css" media='all' href="../vendor/angular/loading-bar.min.css">
<link rel="stylesheet" type="text/css" href="../styles/common-style.css">
<title>权限管理</title>
</head>
<body>
<apollonav></apollonav>
<div class="container-fluid apollo-container">
<section class="panel col-md-offset-1 col-md-10" ng-controller="AppRoleController">
<header class="panel-heading">
<div class="row">
<div class="col-md-7">
<h4 class="modal-title">权限管理<small>(AppId:<label ng-bind="pageContext.appId"></label> )</small>
</h4>
</div>
<div class="col-md-5 text-right">
<a type="button" class="btn btn-success" data-dismiss="modal"
href="/config.html?#appid={{pageContext.appId}}">返回
</a>
</div>
</div>
</header>
<div class="panel-body" ng-show="hasAssignUserPermission">
<div class="row">
<div class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">管理员<br><small>(可以创建Namspace<br>可以创建集群<br>可以分配用户权限)</small></label>
<div class="col-sm-8">
<form class="form-inline" ng-submit="assignMasterRoleToUser()">
<div class="form-group">
<input type="text" class="form-control" placeholder="域账号" required ng-model="toAssignMasterRoleUser">
</div>
<button type="submit" class="btn btn-default">添加</button>
</form>
<!-- Split button -->
<div class="user-container">
<div class="btn-group user-info" ng-repeat="user in appRoleUsers.masterUsers">
<button type="button" class="btn btn-default" ng-bind="user.userId"></button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false" ng-click="removeMasterRoleFromUser(user.userId)">
<span class="glyphicon glyphicon-remove"></span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel-body text-center" ng-show="!hasAssignUserPermission">
<h2>您没有权限哟!</h2>
</div>
<apolloconfirmdialog apollo-dialog-id="'warning'" apollo-title="'删除管理员'"
apollo-detail="'不能删除所有的管理员'" apollo-confirm=""
apollo-show-cancel-btn="false"></apolloconfirmdialog>
</section>
</div>
<div ng-include="'../views/common/footer.html'"></div>
<!-- jquery.js -->
<script src="../vendor/jquery.min.js" type="text/javascript"></script>
<!--angular-->
<script src="../vendor/angular/angular.min.js"></script>
<script src="../vendor/angular/angular-route.min.js"></script>
<script src="../vendor/angular/angular-resource.min.js"></script>
<script src="../vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="../vendor/angular/loading-bar.min.js"></script>
<!-- bootstrap.js -->
<script src="../vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<!--nicescroll-->
<script src="../vendor/jquery.nicescroll.min.js"></script>
<!--biz-->
<!--must import-->
<script type="application/javascript" src="../scripts/app.js"></script>
<script type="application/javascript" src="../scripts/services/AppService.js"></script>
<script type="application/javascript" src="../scripts/services/EnvService.js"></script>
<script type="application/javascript" src="../scripts/services/UserService.js"></script>
<script type="application/javascript" src="../scripts/services/PermissionService.js"></script>
<script type="application/javascript" src="../scripts/AppUtils.js"></script>
<script type="application/javascript" src="../scripts/PageCommon.js"></script>
<script type="application/javascript" src="../scripts/directive.js"></script>
<script type="application/javascript" src="../scripts/controller/role/AppRoleController.js"></script>
</body>
</html>
......@@ -61,12 +61,11 @@
</div>
</section>
<a class="list-group-item" data-toggle="modal" data-target="#createEnvModal"
ng-show="missEnvs.length > 0">
<a class="list-group-item" ng-show="missEnvs.length > 0" ng-click="createAppInMissEnv()">
<div class="row">
<div class="col-md-2"><img src="img/plus.png" class="i-20"></div>
<div class="col-md-7 hidden-xs">
<p class="btn-title">添加环境</p>
<p class="btn-title">补缺环境</p>
</div>
</div>
</a>
......@@ -79,7 +78,8 @@
</div>
</a>
<a class="list-group-item" href="namespace.html?#/appid={{pageContext.appId}}&type=link">
<a class="list-group-item" href="namespace.html?#/appid={{pageContext.appId}}&type=link"
ng-show="hasCreateNamespacePermission">
<div class="row">
<div class="col-md-2"><img src="img/plus.png" class="i-20"></div>
<div class="col-md-7 hidden-xs">
......@@ -87,39 +87,19 @@
</div>
</div>
</a>
<a class="list-group-item" href="/app/role.html?#/appid={{pageContext.appId}}"
ng-show="hasAssignUserPermission">
<div class="row">
<div class="col-md-2"><img src="img/user_manage.png" class="i-20"></div>
<div class="col-md-7 hidden-xs">
<p class="btn-title">项目管理员</p>
</div>
</div>
</a>
</section>
<!--create env modal-->
<div class="modal fade" id="createEnvModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header panel-primary">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title">添加环境</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label>请选择环境:</label>
<div class="checkbox" ng-repeat="env in missEnvs">
<label>
<input type="checkbox" name="selectedEnvs[]" value="{{env}}"
ng-checked="selectedEnvs.indexOf(env) > -1"
ng-click="toggleSelection(env)"><span ng-bind="env"></span>
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" data-dismiss="modal"
ng-click="createEnvs()">添加
</button>
</div>
</div>
</div>
</div>
</div>
<!--namespaces-->
......@@ -137,23 +117,27 @@
<div class="col-md-4">
<div class="btn-toolbar" role="toolbar" aria-label="...">
<div class="btn-group" role="group" aria-label="...">
<button type="button" data-toggle="modal" data-target="#releaseModal"
<button type="button"
class="btn btn-default btn-sm J_tableview_btn"
ng-disabled="namespace.isTextEditing"
ng-click="prepareReleaseNamespace(namespace)">发布
<!--ng-show="namespace.hasReleasePermission"-->
</button>
<button type="button"
class="btn btn-default btn-sm J_tableview_btn" disabled>回滚
class="btn btn-default btn-sm J_tableview_btn" disabled
ng-show="namespace.hasReleasePermission">回滚
</button>
<button type="button"
class="btn btn-default btn-sm J_historyview_btn" disabled>查看历史版本
</button>
<button type="button"
class="btn btn-default btn-sm J_tableview_btn" disabled>授权
</button>
<a type="button" class="btn btn-default btn-sm J_tableview_btn"
href="/namespace/role.html?#/appid={{pageContext.appId}}&namespaceName={{namespace.namespace.namespaceName}}"
ng-show="hasAssignUserPermission">授权
</a>
<a type="button"
href="config/sync.html?#/appid={{pageContext.appId}}&env={{pageContext.env}}&clusterName={{pageContext.clusterName}}&namespaceName={{namespace.namespace.namespaceName}}"
class="btn btn-default btn-sm J_tableview_btn">同步
class="btn btn-default btn-sm J_tableview_btn"
ng-show="namespace.hasModifyPermission">同步
</a>
</div>
</div>
......@@ -185,7 +169,7 @@
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</a>
<a data-tooltip="tooltip" data-placement="bottom" title="修改配置"
ng-show="!namespace.isTextEditing && namespace.viewType == 'text'"
ng-show="!namespace.isTextEditing && namespace.viewType == 'text' && namespace.hasModifyPermission"
ng-click="toggleTextEditStatus(namespace)">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
</a>
......@@ -198,7 +182,7 @@
</a>
<a data-tooltip="tooltip" data-placement="bottom" title="添加配置"
ng-show="namespace.viewType == 'table'"
ng-show="namespace.viewType == 'table' && namespace.hasModifyPermission"
data-toggle="modal" data-target="#itemModal"
ng-click="createItem(namespace)">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
......@@ -279,13 +263,15 @@
<span class="glyphicon glyphicon-edit" aria-hidden="true"
data-tooltip="tooltip" data-placement="bottom" title="修改"
data-toggle="modal" data-target="#itemModal"
ng-click="editItem(namespace, config.item)">
ng-click="editItem(namespace, config.item)"
ng-show="namespace.hasModifyPermission">
</span>
&nbsp;
<span class="glyphicon glyphicon-remove" aria-hidden="true"
data-toggle="modal" data-target="#deleteModal"
data-toggle="modal" data-target="#deleteConfirmDialog"
data-tooltip="tooltip" data-placement="bottom" title="删除"
ng-click="preDeleteItem(config.item.id)">
ng-click="preDeleteItem(namespace, config.item.id)"
ng-show="namespace.hasModifyPermission">
</span>
</td>
......@@ -367,27 +353,12 @@
</div>
<!-- delete modal-->
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header panel-primary">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title">删除配置</h4>
</div>
<div class="modal-body">
确定要删除配置吗?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-danger" data-dismiss="modal"
ng-click="deleteItem()">
确定
</button>
</div>
</div>
</div>
</div>
<apolloconfirmdialog apollo-dialog-id="'deleteConfirmDialog'" apollo-title="'删除配置'"
apollo-detail="'确定要删除配置吗?'" apollo-confirm="deleteItem"></apolloconfirmdialog>
<apolloconfirmdialog apollo-dialog-id="'releaseNoPermissionDialog'" apollo-title="'发布'"
apollo-detail="'您没有发布权限哦~'"
apollo-show-cancel-btn="false"></apolloconfirmdialog>
<!--create release modal-->
<form class="modal fade form-horizontal" id="releaseModal" tabindex="-1" role="dialog"
......@@ -556,7 +527,7 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="switchToEdit()"
ng-show="tableViewOperType == 'retrieve'">修改
ng-show="tableViewOperType == 'retrieve' && hasModifyPermission">修改
</button>
<button type="button" class="btn btn-default" data-dismiss="modal">关闭
</button>
......@@ -606,6 +577,7 @@
<script type="application/javascript" src="scripts/services/EnvService.js"></script>
<script type="application/javascript" src="scripts/services/UserService.js"></script>
<script type="application/javascript" src="scripts/services/ConfigService.js"></script>
<script type="application/javascript" src="scripts/services/PermissionService.js"></script>
<script type="application/javascript" src="scripts/AppUtils.js"></script>
......
......@@ -14,10 +14,8 @@
<body ng-controller="IndexController">
<div class="site-notice">当前站点支持
&nbsp;<a ng-repeat="env in envs" ng-class="{selected:selectedEnv == env}" ng-click="switchEnv(env)"><em ng-bind="env">
</em>&nbsp;</a>
环境点击切换
<div class="site-notice"><label>当前站点支持</label><label ng-repeat="env in envs" ng-bind="env" style="margin-left: 5px;"></label>
环境
</div>
<header class="site-header jumbotron">
......
<!doctype html>
<html ng-app="role">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- styles -->
<link rel="stylesheet" type="text/css" href="../vendor/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="../vendor/angular/angular-toastr-1.4.1.min.css">
<link rel="stylesheet" type="text/css" media='all' href="../vendor/angular/loading-bar.min.css">
<link rel="stylesheet" type="text/css" href="../styles/common-style.css">
<title>权限管理</title>
</head>
<body>
<apollonav></apollonav>
<div class="container-fluid apollo-container">
<section class="panel col-md-offset-1 col-md-10" ng-controller="NamespaceRoleController">
<header class="panel-heading">
<div class="row">
<div class="col-md-7">
<h4 class="modal-title">权限管理<small>(AppId:<label ng-bind="pageContext.appId"></label> Namespace:<label ng-bind="pageContext.namespaceName"></label>)</small>
</h4>
</div>
<div class="col-md-5 text-right">
<a type="button" class="btn btn-success" data-dismiss="modal"
href="/config.html?#appid={{pageContext.appId}}">返回
</a>
</div>
</div>
</header>
<div class="panel-body" ng-show="hasAssignUserPermission">
<div class="row">
<div class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">修改权<br><small>(可以修改配置)</small></label>
<div class="col-sm-8">
<form class="form-inline" ng-submit="assignRoleToUser('ModifyNamespace')">
<div class="form-group">
<input type="text" class="form-control" placeholder="域账号" required ng-model="toAssignModifyNamespaceRoleUser">
</div>
<button type="submit" class="btn btn-default">添加</button>
</form>
<!-- Split button -->
<div class="user-container">
<div class="btn-group user-info" ng-repeat="user in rolesAssignedUsers.modifyRoleUsers">
<button type="button" class="btn btn-default" ng-bind="user.userId"></button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false" ng-click="removeUserRole('ModifyNamespace', user.userId)">
<span class="glyphicon glyphicon-remove"></span>
</button>
</div>
</div>
</div>
</div>
</div>
<hr>
<div class="row" style="margin-top: 10px;">
<div class="form-horizontal">
<div class="col-sm-2 text-right">
<label class="control-label">发布权<br><small>(可以发布配置)</small></label>
</div>
<div class="col-sm-8">
<form class="form-inline" ng-submit="assignRoleToUser('ReleaseNamespace')">
<div class="form-group">
<input type="text" class="form-control" placeholder="域账号" required ng-model="toAssignReleaseNamespaceRoleUser">
</div>
<button type="submit" class="btn btn-default">添加</button>
</form>
<!-- Split button -->
<div style="margin-top: 15px;">
<div class="btn-group" ng-repeat="user in rolesAssignedUsers.releaseRoleUsers">
<button type="button" class="btn btn-default" ng-bind="user.userId"></button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false" ng-click="removeUserRole('ReleaseNamespace', user.userId)">
<span class="glyphicon glyphicon-remove"></span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel-body text-center" ng-show="!hasAssignUserPermission">
<h2>您没有权限哟!</h2>
</div>
</section>
</div>
<div ng-include="'../views/common/footer.html'"></div>
<!-- jquery.js -->
<script src="../vendor/jquery.min.js" type="text/javascript"></script>
<!--angular-->
<script src="../vendor/angular/angular.min.js"></script>
<script src="../vendor/angular/angular-route.min.js"></script>
<script src="../vendor/angular/angular-resource.min.js"></script>
<script src="../vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="../vendor/angular/loading-bar.min.js"></script>
<!-- bootstrap.js -->
<script src="../vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<!--nicescroll-->
<script src="../vendor/jquery.nicescroll.min.js"></script>
<!--biz-->
<!--must import-->
<script type="application/javascript" src="../scripts/app.js"></script>
<script type="application/javascript" src="../scripts/services/AppService.js"></script>
<script type="application/javascript" src="../scripts/services/EnvService.js"></script>
<script type="application/javascript" src="../scripts/services/UserService.js"></script>
<script type="application/javascript" src="../scripts/services/PermissionService.js"></script>
<script type="application/javascript" src="../scripts/AppUtils.js"></script>
<script type="application/javascript" src="../scripts/PageCommon.js"></script>
<script type="application/javascript" src="../scripts/directive.js"></script>
<script type="application/javascript" src="../scripts/controller/role/NamespaceRoleController.js"></script>
</body>
</html>
......@@ -20,6 +20,8 @@ var sync_item_module = angular.module('sync_item', ['app.service', 'apollo.direc
var namespace_module = angular.module('namespace', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
//server config
var server_config_module = angular.module('server_config', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
// namespace role
var role_module = angular.module('role', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
......
......@@ -2,7 +2,7 @@ create_app_module.controller('CreateAppController', ['$scope', '$window', 'toast
function ($scope, $window, toastr, AppService, AppUtil) {
$scope.create = function () {
AppService.create('ALL', $scope.app).then(function (result) {
AppService.create($scope.app).then(function (result) {
toastr.success('添加成功!');
setInterval(function () {
$window.location.href = '/config.html?#appid=' + result.appId;
......
application_module.controller("ConfigBaseInfoController",
['$rootScope', '$scope', '$location', 'toastr', 'AppService', 'AppUtil',
function ($rootScope, $scope, $location, toastr, AppService, AppUtil) {
['$rootScope', '$scope', '$location', 'toastr', 'AppService', 'PermissionService',
'AppUtil',
function ($rootScope, $scope, $location, toastr, AppService, PermissionService,
AppUtil) {
var appId = AppUtil.parseParams($location.$$url).appid;
var pageContext = {
......@@ -18,26 +19,44 @@ application_module.controller("ConfigBaseInfoController",
var navTree = [];
var nodes = AppUtil.collectData(result);
nodes.forEach(function (item) {
if (!item.clusters || item.clusters.length == 0){
return;
if (!nodes || nodes.length == 0){
toastr.error("加载导航信息出错");
return;
}
//默认显示第一个环境的default集群的
pageContext.env = nodes[0].env;
$rootScope.refreshNamespaces();
nodes.forEach(function (env, envIdx) {
if (!env.clusters || env.clusters.length == 0) {
return;
}
var node = {};
//first nav
node.text = item.env;
node.text = env.env;
var clusterNodes = [];
//如果env下面只有一个default集群则不显示集群列表
if (item.clusters && item.clusters.length == 1 && item.clusters[0].name == 'default'){
if (env.clusters && env.clusters.length == 1 && env.clusters[0].name
== 'default') {
if (envIdx == 0){
node.state = {};
node.state.selected = true;
}
node.selectable = true;
}else {
} else {
node.selectable = false;
//second nav
item.clusters.forEach(function (item) {
env.clusters.forEach(function (cluster, clusterIdx) {
var clusterNode = {},
parentNode = [];
clusterNode.text = item.name;
if (envIdx == 0 && clusterIdx == 0){
clusterNode.state = {};
clusterNode.state.selected = true;
}
clusterNode.text = cluster.name;
parentNode.push(node.text);
clusterNode.tags = parentNode;
clusterNodes.push(clusterNode);
......@@ -55,12 +74,14 @@ application_module.controller("ConfigBaseInfoController",
expandIcon: '',
collapseIcon: '',
onNodeSelected: function (event, data) {
if (!data.tags){//first nav node
if (!data.tags) {//first nav node
$rootScope.pageContext.env = data.text;
$rootScope.pageContext.clusterName = 'default';
}else {//second cluster node
$rootScope.pageContext.clusterName =
'default';
} else {//second cluster node
$rootScope.pageContext.env = data.tags[0];
$rootScope.pageContext.clusterName = data.text;
$rootScope.pageContext.clusterName =
data.text;
}
$rootScope.refreshNamespaces();
}
......@@ -71,55 +92,51 @@ application_module.controller("ConfigBaseInfoController",
});
////// app info //////
AppService.load($rootScope.pageContext.appId).then(function (result) {
$scope.appBaseInfo = result;
},function (result) {
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "加载App信息出错");
});
////// 补缺失的环境 //////
$scope.missEnvs = [];
AppService.find_miss_envs($rootScope.pageContext.appId).then(function (result) {
$scope.missEnvs = AppUtil.collectData(result);
},function (result) {
}, function (result) {
console.log(AppUtil.errorMsg(result));
});
$scope.selectedEnvs = [];
$scope.toggleSelection = function toggleSelection(env) {
var idx = $scope.selectedEnvs.indexOf(env);
// is currently selected
if (idx > -1) {
$scope.selectedEnvs.splice(idx, 1);
}
// is newly selected
else {
$scope.selectedEnvs.push(env);
}
};
$scope.createEnvs = function () {
$scope.createAppInMissEnv = function () {
var count = 0;
$scope.selectedEnvs.forEach(function (env) {
AppService.create(env, $scope.appBaseInfo).then(function (result) {
$scope.missEnvs.forEach(function (env) {
AppService.create_remote(env, $scope.appBaseInfo).then(function (result) {
toastr.success(env, '创建成功');
count ++;
if (count == $scope.selectedEnvs.length){
count++;
if (count == $scope.missEnvs.length) {
location.reload(true);
}
}, function (result) {
toastr.error(AppUtil.errorMsg(result), '创建失败:' + env);
count ++;
if (count == $scope.selectedEnvs){
$route.reload();
count++;
if (count == $scope.missEnvs.length) {
location.reload(true);
}
});
});
};
//permission
PermissionService.has_create_namespace_permission(appId).then(function (result) {
$scope.hasCreateNamespacePermission = result.hasPermission;
}, function (result) {
});
PermissionService.has_assign_user_permission(appId).then(function (result) {
$scope.hasAssignUserPermission = result.hasPermission;
}, function (result) {
});
}]);
application_module.controller("ConfigNamespaceController",
['$rootScope', '$scope', '$location', 'toastr', 'AppUtil', 'ConfigService',
function ($rootScope, $scope, $location, toastr, AppUtil, ConfigService) {
['$rootScope', '$scope', '$location', 'toastr', 'AppUtil', 'ConfigService', 'PermissionService',
function ($rootScope, $scope, $location, toastr, AppUtil, ConfigService, PermissionService) {
var namespace_view_type = {
TEXT: 'text',
......@@ -30,6 +30,21 @@ application_module.controller("ConfigNamespaceController",
}
namespace.isTextEditing = false;
//permission
PermissionService.has_modify_namespace_permission($rootScope.pageContext.appId, namespace.namespace.namespaceName)
.then(function (result) {
namespace.hasModifyPermission = result.hasPermission;
}, function (result) {
});
PermissionService.has_release_namespace_permission($rootScope.pageContext.appId, namespace.namespace.namespaceName)
.then(function (result) {
namespace.hasReleasePermission = result.hasPermission;
}, function (result) {
});
});
}
setInterval(function () {
......@@ -71,6 +86,10 @@ application_module.controller("ConfigNamespaceController",
var result = "";
var itemCnt = 0;
namespace.items.forEach(function (item) {
//deleted key
if (!item.item.lastModifiedBy){
return;
}
if (item.item.key) {
//use string \n to display as new line
var itemValue = item.item.value.replace(/\n/g,"\\n");
......@@ -136,6 +155,12 @@ application_module.controller("ConfigNamespaceController",
$scope.toReleaseNamespace = {};
$scope.prepareReleaseNamespace = function (namespace) {
if (!namespace.hasReleasePermission){
$('#releaseNoPermissionDialog').modal('show');
return;
}else {
$('#releaseModal').modal('show');
}
$scope.releaseTitle = new Date().Format("yyyy-MM-dd hh:mm:ss");
$scope.toReleaseNamespace = namespace;
};
......@@ -175,15 +200,21 @@ application_module.controller("ConfigNamespaceController",
$scope.item = item;
$scope.item.oldValue = oldValue;
toOperationNamespaceName = namespace.namespace.namespaceName;
$scope.hasModifyPermission = namespace.hasModifyPermission;
};
var toDeleteItemId = 0;
$scope.preDeleteItem = function (itemId) {
var toDeleteItemId = 0, toDeleteNamespace = {};
$scope.preDeleteItem = function (namespace, itemId) {
toDeleteNamespace = namespace;
toDeleteItemId = itemId;
};
$scope.deleteItem = function () {
ConfigService.delete_item($rootScope.pageContext.env, toDeleteItemId).then(
ConfigService.delete_item($rootScope.pageContext.appId,
$rootScope.pageContext.env,
$rootScope.pageContext.clusterName,
toDeleteNamespace.namespace.namespaceName,
toDeleteItemId).then(
function (result) {
toastr.success("删除成功!");
$rootScope.refreshNamespaces();
......@@ -263,6 +294,14 @@ application_module.controller("ConfigNamespaceController",
}
};
//permission
PermissionService.has_assign_user_permission($rootScope.pageContext.appId)
.then(function (result) {
$scope.hasAssignUserPermission = result.hasPermission;
}, function (result) {
});
$('.config-item-container').removeClass('hide');
}]);
......
......@@ -53,7 +53,7 @@ sync_item_module.controller("SyncItemController",
};
$scope.syncItems = function () {
ConfigService.sync_items($scope.pageContext.namespaceName, parseSyncSourceData()).then(function (result) {
ConfigService.sync_items($scope.pageContext.appId, $scope.pageContext.namespaceName, parseSyncSourceData()).then(function (result) {
$scope.syncItemStep += 1;
$scope.syncSuccess = true;
}, function (result) {
......
role_module.controller('AppRoleController', ['$scope', '$location', '$window', 'toastr', 'AppService', 'AppUtil', 'PermissionService',
function ($scope, $location, $window, toastr, AppService, AppUtil, PermissionService) {
var params = AppUtil.parseParams($location.$$url);
$scope.pageContext = {
appId: params.appid
};
PermissionService.has_assign_user_permission($scope.pageContext.appId)
.then(function (result) {
$scope.hasAssignUserPermission = result.hasPermission;
}, function (reslt) {
});
PermissionService.get_app_role_users($scope.pageContext.appId)
.then(function (result) {
$scope.appRoleUsers = result;
}, function (result) {
});
$scope.toAssignMasterRoleUser = '';
$scope.assignMasterRoleToUser = function () {
PermissionService.assign_master_role($scope.pageContext.appId,
$scope.toAssignMasterRoleUser)
.then(function (result) {
toastr.success("添加成功");
reloadPage();
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "添加失败");
});
};
$scope.removeMasterRoleFromUser = function (user) {
if ($scope.appRoleUsers.masterUsers.length <= 1){
$('#warning').modal('show');
return;
}
PermissionService.remove_master_role($scope.pageContext.appId, user)
.then(function (result) {
toastr.success("删除成功");
reloadPage();
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "删除失败");
});
};
function reloadPage() {
setInterval(function () {
location.reload(true);
}, 1000);
}
}]);
role_module.controller('NamespaceRoleController', ['$scope', '$location', '$window', 'toastr', 'AppService', 'AppUtil', 'PermissionService',
function ($scope, $location, $window, toastr, AppService, AppUtil, PermissionService) {
var params = AppUtil.parseParams($location.$$url);
$scope.pageContext = {
appId: params.appid,
namespaceName: params.namespaceName
};
PermissionService.has_assign_user_permission($scope.pageContext.appId)
.then(function (result) {
$scope.hasAssignUserPermission = result.hasPermission;
}, function (reslt) {
});
PermissionService.get_namespace_role_users($scope.pageContext.appId,
$scope.pageContext.namespaceName)
.then(function (result) {
$scope.rolesAssignedUsers = result;
console.log(result);
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "加载授权用户出错");
});
$scope.toAssignReleaseNamespaceRoleUser = '', $scope.toAssignModifyNamespaceRoleUser = '';
$scope.assignRoleToUser = function (roleType) {
if ('ReleaseNamespace' == roleType) {
PermissionService.assign_release_namespace_role($scope.pageContext.appId,
$scope.pageContext.namespaceName,
$scope.toAssignReleaseNamespaceRoleUser)
.then(function (result) {
toastr.success("添加成功");
reloadPage();
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "添加失败");
});
} else {
PermissionService.assign_modify_namespace_role($scope.pageContext.appId,
$scope.pageContext.namespaceName,
$scope.toAssignModifyNamespaceRoleUser)
.then(function (result) {
toastr.success("添加成功");
reloadPage();
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "添加失败");
});
}
};
$scope.removeUserRole = function (roleType, user) {
if ('ReleaseNamespace' == roleType) {
PermissionService.remove_release_namespace_role($scope.pageContext.appId,
$scope.pageContext.namespaceName,
user)
.then(function (result) {
toastr.success("删除成功");
reloadPage();
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "删除失败");
});
} else {
PermissionService.remove_modify_namespace_role($scope.pageContext.appId,
$scope.pageContext.namespaceName,
user)
.then(function (result) {
toastr.success("删除成功");
reloadPage();
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "删除失败");
});
}
};
function reloadPage() {
setInterval(function () {
location.reload(true);
}, 1000);
}
}]);
......@@ -10,19 +10,14 @@ directive_module.directive('apollonav', function ($compile, $window, toastr, App
scope.sourceApps = [];
scope.copyedApps = [];
EnvService.find_all_envs().then(function (result) {
//default select first env
AppService.find_all_app(result[0]).then(function (result) {
result.forEach(function (app) {
app.selected = false;
scope.sourceApps.push(app);
});
scope.copyedApps = angular.copy(scope.sourceApps);
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "load apps error");
AppService.find_all_app().then(function (result) {
result.forEach(function (app) {
app.selected = false;
scope.sourceApps.push(app);
});
scope.copyedApps = angular.copy(scope.sourceApps);
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "load env error");
toastr.error(AppUtil.errorMsg(result), "load apps error");
});
scope.searchKey = '';
......@@ -112,7 +107,7 @@ directive_module.directive('apollonav', function ($compile, $window, toastr, App
}
UserService.load_user().then(function (result) {
scope.userName = result.username;
scope.userName = result.userId;
}, function (result) {
});
......@@ -209,5 +204,29 @@ directive_module.directive('apollorequiredfiled', function ($compile, $window) {
transclude: true,
replace: true
}
});
directive_module.directive('apolloconfirmdialog', function ($compile, $window) {
return {
restrict: 'E',
templateUrl: '../views/component/confirm-dialog.html',
transclude: true,
replace: true,
scope: {
dialogId: '=apolloDialogId',
title: '=apolloTitle',
detail: '=apolloDetail',
showCancelBtn: '=apolloShowCancelBtn',
doConfirm: '=apolloConfirm'
},
link: function (scope, element, attrs) {
scope.confirm = function () {
if (scope.doConfirm){
scope.doConfirm();
}
}
}
}
});
......@@ -3,7 +3,7 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
find_all_app:{
method: 'GET',
isArray: true,
url:'/apps/envs/:env'
url:'/apps'
},
load_navtree:{
methode: 'GET',
......@@ -15,6 +15,10 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
isArray: false
},
create_app: {
method: 'POST',
url: '/apps'
},
create_app_remote: {
method: 'POST',
url: '/apps/envs/:env'
},
......@@ -24,10 +28,10 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
}
});
return {
find_all_app: function (env) {
find_all_app: function () {
var d = $q.defer();
app_resource.find_all_app({
env: env
}, function (result) {
d.resolve(result);
}, function (result) {
......@@ -46,9 +50,18 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) {
});
return d.promise;
},
create: function (env, app) {
create: function (app) {
var d = $q.defer();
app_resource.create_app({}, app, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
create_remote: function (env, app) {
var d = $q.defer();
app_resource.create_app({env:env}, app, function (result) {
app_resource.create_app_remote({env:env}, app, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
......
......@@ -25,7 +25,7 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
},
sync_item: {
method: 'PUT',
url: '/namespaces/:namespaceName/items',
url: '/apps/:appId/namespaces/:namespaceName/items',
isArray: false
},
create_item: {
......@@ -38,7 +38,7 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
},
delete_item: {
method: 'DELETE',
url: '/envs/:env/items/:itemId'
url: '/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName/items/:itemId'
}
});
......@@ -123,9 +123,10 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
return d.promise;
},
sync_items: function (namespaceName, sourceData) {
sync_items: function (appId, namespaceName, sourceData) {
var d = $q.defer();
config_source.sync_item({
appId: appId,
namespaceName: namespaceName
}, sourceData, function (result) {
d.resolve(result);
......@@ -165,10 +166,13 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
return d.promise;
},
delete_item: function (env, itemId) {
delete_item: function (appId, env, clusterName, namespaceName, itemId) {
var d = $q.defer();
config_source.delete_item({
appId: appId,
env: env,
clusterName: clusterName,
namespaceName: namespaceName,
itemId: itemId
}, function (result) {
d.resolve(result);
......
appService.service('PermissionService', ['$resource', '$q', function ($resource, $q) {
var permission_resource = $resource('', {}, {
has_app_permission: {
method: 'GET',
url: '/apps/:appId/permissions/:permissionType'
},
has_namespace_permission: {
method: 'GET',
url: '/apps/:appId/namespaces/:namespaceName/permissions/:permissionType'
},
get_namespace_role_users: {
method: 'GET',
url: '/apps/:appId/namespaces/:namespaceName/role_users'
},
assign_namespace_role_to_user: {
method: 'POST',
url: '/apps/:appId/namespaces/:namespaceName/roles/:roleType'
},
remove_namespace_role_from_user: {
method: 'DELETE',
url: '/apps/:appId/namespaces/:namespaceName/roles/:roleType?user=:user'
},
get_app_role_users: {
method: 'GET',
url: '/apps/:appId/role_users'
},
assign_app_role_to_user: {
method: 'POST',
url: '/apps/:appId/roles/:roleType'
},
remove_app_role_from_user: {
method: 'DELETE',
url: '/apps/:appId/roles/:roleType?user=:user'
}
});
function hasAppPermission(appId, permissionType) {
var d = $q.defer();
permission_resource.has_app_permission({
appId: appId,
permissionType: permissionType
},
function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
function hasNamespacePermission(appId, namespaceName, permissionType) {
var d = $q.defer();
permission_resource.has_namespace_permission({
appId: appId,
namespaceName: namespaceName,
permissionType: permissionType
},
function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
function assignNamespaceRoleToUser(appId, namespaceName, roleType, user) {
var d = $q.defer();
permission_resource.assign_namespace_role_to_user({
appId: appId,
namespaceName: namespaceName,
roleType: roleType
}, user,
function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
function removeRoleFromUser(appId, namespaceName, roleType, user) {
var d = $q.defer();
permission_resource.remove_namespace_role_from_user({
appId: appId,
namespaceName: namespaceName,
roleType: roleType,
user: user
},
function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
return {
has_create_namespace_permission: function (appId) {
return hasAppPermission(appId, 'CreateNamespace');
},
has_create_cluster_permission: function (appId) {
return hasAppPermission(appId, 'CreateCluster');
},
has_assign_user_permission: function (appId) {
return hasAppPermission(appId, 'AssignRole');
},
has_modify_namespace_permission: function (appId, namespaceName) {
return hasNamespacePermission(appId, namespaceName, 'ModifyNamespace');
},
has_release_namespace_permission: function (appId, namespaceName) {
return hasNamespacePermission(appId, namespaceName, 'ReleaseNamespace');
},
assign_modify_namespace_role: function (appId, namespaceName, user) {
return assignNamespaceRoleToUser(appId, namespaceName, 'ModifyNamespace', user);
},
assign_release_namespace_role: function (appId, namespaceName, user) {
return assignNamespaceRoleToUser(appId, namespaceName, 'ReleaseNamespace', user);
},
remove_modify_namespace_role: function (appId, namespaceName, user) {
return removeRoleFromUser(appId, namespaceName, 'ModifyNamespace', user);
},
remove_release_namespace_role: function (appId, namespaceName, user) {
return removeRoleFromUser(appId, namespaceName, 'ReleaseNamespace', user);
},
get_namespace_role_users: function (appId, namespaceName) {
var d = $q.defer();
permission_resource.get_namespace_role_users({
appId: appId,
namespaceName: namespaceName,
},
function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
get_app_role_users: function (appId) {
var d = $q.defer();
permission_resource.get_app_role_users({
appId: appId
},
function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
assign_master_role: function (appId, user) {
var d = $q.defer();
permission_resource.assign_app_role_to_user({
appId: appId,
roleType: 'Master'
}, user,
function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
remove_master_role: function (appId, user) {
var d = $q.defer();
permission_resource.remove_app_role_from_user({
appId: appId,
roleType: 'Master',
user: user
},
function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
}
}]);
......@@ -334,3 +334,12 @@ table th {
background: #c3c3c3;
}
.user-container {
margin-top: 15px;
padding: 20px 15px
}
.user-container .user-info{
margin-left: 5px;
}
......@@ -11,7 +11,7 @@
<ul class="nav navbar-nav navbar-right">
<li><a href="http://conf.ctripcorp.com/pages/viewpage.action?pageId=98435462" target="_blank">
help</span>
Help</span>
</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
......
<div class="modal fade" id="{{dialogId}}" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header panel-primary">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title">{{title}}</h4>
</div>
<div class="modal-body">
{{detail}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" ng-show="showCancelBtn">取消</button>
<button type="button" class="btn btn-danger" data-dismiss="modal"
ng-click="confirm()">
确定
</button>
</div>
</div>
</div>
</div>
......@@ -11,7 +11,7 @@ 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.form.NamespaceTextModel;
import com.ctrip.framework.apollo.portal.service.PortalConfigService;
import com.ctrip.framework.apollo.portal.service.ConfigService;
import com.ctrip.framework.apollo.portal.service.txtresolver.PropertyResolver;
import org.junit.Assert;
......@@ -43,7 +43,7 @@ public class ConfigServiceTest {
private UserInfoHolder userInfoHolder;
@InjectMocks
private PortalConfigService configService;
private ConfigService configService;
@Before
public void setup() {
......
......@@ -6,7 +6,7 @@ import com.ctrip.framework.apollo.core.dto.ReleaseDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO;
import com.ctrip.framework.apollo.portal.service.PortalNamespaceService;
import com.ctrip.framework.apollo.portal.service.NamespaceService;
import com.ctrip.framework.apollo.portal.service.txtresolver.PropertyResolver;
import org.junit.Before;
......@@ -35,7 +35,7 @@ public class NamespaceServiceTest {
private PropertyResolver resolver;
@InjectMocks
private PortalNamespaceService namespaceService;
private NamespaceService namespaceService;
@Before
public void setup() {
......
......@@ -26,14 +26,14 @@ import com.ctrip.framework.apollo.core.dto.AppDTO;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.exception.ServiceException;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.service.PortalAppService;
import com.ctrip.framework.apollo.portal.service.AppService;
import com.google.gson.Gson;
public class ServiceExceptionTest extends AbstractPortalTest {
@Autowired
private PortalAppService appService;
private AppService appService;
@Mock
private AdminServiceAPI.AppAPI appAPI;
......
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