Skip to content

Commit 8a39cce

Browse files
committed
admin can modify app information
1 parent f5373b1 commit 8a39cce

File tree

30 files changed

+716
-337
lines changed

30 files changed

+716
-337
lines changed

apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.springframework.web.bind.annotation.RestController;
2121

2222
import java.util.List;
23+
import java.util.Objects;
2324

2425
@RestController
2526
public class AppController {
@@ -47,7 +48,7 @@ public AppDTO create(@RequestBody AppDTO dto) {
4748
return dto;
4849
}
4950

50-
@RequestMapping(path = "/apps/{appId}", method = RequestMethod.DELETE)
51+
@RequestMapping(value = "/apps/{appId}", method = RequestMethod.DELETE)
5152
public void delete(@PathVariable("appId") String appId, @RequestParam String operator) {
5253
App entity = appService.findOne(appId);
5354
if (entity == null) {
@@ -56,6 +57,15 @@ public void delete(@PathVariable("appId") String appId, @RequestParam String ope
5657
appService.delete(entity.getId(), operator);
5758
}
5859

60+
@RequestMapping(value = "/apps/{appId}", method = RequestMethod.PUT)
61+
public void update(@PathVariable String appId, @RequestBody App app) {
62+
if (!Objects.equals(appId, app.getAppId())) {
63+
throw new BadRequestException("The App Id of path variable and request body is different");
64+
}
65+
66+
appService.update(app);
67+
}
68+
5969
@RequestMapping(value = "/apps", method = RequestMethod.GET)
6070
public List<AppDTO> find(@RequestParam(value = "name", required = false) String name,
6171
Pageable pageable) {

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppService.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.ctrip.framework.apollo.biz.entity.Audit;
44
import com.ctrip.framework.apollo.biz.repository.AppRepository;
55
import com.ctrip.framework.apollo.common.entity.App;
6+
import com.ctrip.framework.apollo.common.exception.BadRequestException;
67
import com.ctrip.framework.apollo.common.exception.ServiceException;
78
import com.ctrip.framework.apollo.common.utils.BeanUtils;
89

@@ -71,14 +72,25 @@ public App save(App entity) {
7172
}
7273

7374
@Transactional
74-
public App update(App app) {
75-
App managedApp = appRepository.findByAppId(app.getAppId());
76-
BeanUtils.copyEntityProperties(app, managedApp);
75+
public void update(App app) {
76+
String appId = app.getAppId();
77+
78+
App managedApp = appRepository.findByAppId(appId);
79+
if (managedApp == null) {
80+
throw new BadRequestException(String.format("App not exists. AppId = %s", appId));
81+
}
82+
83+
managedApp.setName(app.getName());
84+
managedApp.setOrgId(app.getOrgId());
85+
managedApp.setOrgName(app.getOrgName());
86+
managedApp.setOwnerName(app.getOwnerName());
87+
managedApp.setOwnerEmail(app.getOwnerEmail());
88+
managedApp.setDataChangeLastModifiedBy(app.getDataChangeLastModifiedBy());
89+
7790
managedApp = appRepository.save(managedApp);
7891

7992
auditService.audit(App.class.getSimpleName(), managedApp.getId(), Audit.OP.UPDATE,
8093
managedApp.getDataChangeLastModifiedBy());
8194

82-
return managedApp;
8395
}
8496
}

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ public AppDTO loadApp(Env env, String appId) {
5858
public AppDTO createApp(Env env, AppDTO app) {
5959
return restTemplate.post(env, "apps", app, AppDTO.class);
6060
}
61+
62+
public void updateApp(Env env, AppDTO app) {
63+
restTemplate.put(env, "apps/{appId}", app, app.getAppId());
64+
}
6165
}
6266

6367

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/PermissionValidator.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ public boolean hasCreateAppNamespacePermission(String appId, AppNamespace appNam
6565
}
6666
}
6767

68+
public boolean isAppAdmin(String appId) {
69+
return isSuperAdmin() || hasAssignRolePermission(appId);
70+
}
71+
6872
public boolean isSuperAdmin() {
6973
return rolePermissionService.isSuperAdmin(userInfoHolder.getUser().getUserId());
7074
}

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.ctrip.framework.apollo.portal.entity.model.AppModel;
1515
import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo;
1616
import com.ctrip.framework.apollo.portal.listener.AppCreationEvent;
17+
import com.ctrip.framework.apollo.portal.listener.AppInfoChangedEvent;
1718
import com.ctrip.framework.apollo.portal.service.AppService;
1819
import com.ctrip.framework.apollo.portal.service.RolePermissionService;
1920
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
@@ -24,6 +25,7 @@
2425
import org.springframework.data.domain.Pageable;
2526
import org.springframework.http.HttpStatus;
2627
import org.springframework.http.ResponseEntity;
28+
import org.springframework.security.access.prepost.PreAuthorize;
2729
import org.springframework.util.CollectionUtils;
2830
import org.springframework.util.StringUtils;
2931
import org.springframework.web.bind.annotation.PathVariable;
@@ -35,6 +37,7 @@
3537
import org.springframework.web.client.HttpClientErrorException;
3638

3739
import java.util.List;
40+
import java.util.Objects;
3841
import java.util.Set;
3942

4043

@@ -69,6 +72,38 @@ public List<App> findAppsByOwner(@RequestParam("owner") String owner, Pageable p
6972
return appService.findByOwnerName(owner, page);
7073
}
7174

75+
@RequestMapping(value = "", method = RequestMethod.POST)
76+
public App create(@RequestBody AppModel appModel) {
77+
78+
App app = transformToApp(appModel);
79+
80+
App createdApp = appService.createAppInLocal(app);
81+
82+
publisher.publishEvent(new AppCreationEvent(createdApp));
83+
84+
Set<String> admins = appModel.getAdmins();
85+
if (!CollectionUtils.isEmpty(admins)) {
86+
rolePermissionService.assignRoleToUsers(RoleUtils.buildAppMasterRoleName(createdApp.getAppId()),
87+
admins, userInfoHolder.getUser().getUserId());
88+
}
89+
90+
return createdApp;
91+
}
92+
93+
@PreAuthorize(value = "@permissionValidator.isAppAdmin(#appId)")
94+
@RequestMapping(value = "/{appId}", method = RequestMethod.PUT)
95+
public void update(@PathVariable String appId, @RequestBody AppModel appModel) {
96+
if (!Objects.equals(appId, appModel.getAppId())) {
97+
throw new BadRequestException("The App Id of path variable and request body is different");
98+
}
99+
100+
App app = transformToApp(appModel);
101+
102+
App updatedApp = appService.updateAppInLocal(app);
103+
104+
publisher.publishEvent(new AppInfoChangedEvent(updatedApp));
105+
}
106+
72107
@RequestMapping(value = "/{appId}/navtree", method = RequestMethod.GET)
73108
public MultiResponseEntity<EnvClusterInfo> nav(@PathVariable String appId) {
74109

@@ -86,41 +121,6 @@ public MultiResponseEntity<EnvClusterInfo> nav(@PathVariable String appId) {
86121
return response;
87122
}
88123

89-
@RequestMapping(value = "", method = RequestMethod.POST)
90-
public App create(@RequestBody AppModel appModel) {
91-
92-
String appId = appModel.getAppId();
93-
String appName = appModel.getName();
94-
String ownerName = appModel.getOwnerName();
95-
String orgId = appModel.getOrgId();
96-
String orgName = appModel.getOrgName();
97-
98-
RequestPrecondition.checkArgumentsNotEmpty(appId, appName, ownerName, orgId, orgName);
99-
100-
if (!InputValidator.isValidClusterNamespace(appModel.getAppId())) {
101-
throw new BadRequestException(String.format("AppId格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE));
102-
}
103-
104-
App app = new App();
105-
app.setAppId(appId);
106-
app.setName(appName);
107-
app.setOwnerName(ownerName);
108-
app.setOrgId(orgId);
109-
app.setOrgName(orgName);
110-
111-
App createdApp = appService.create(app);
112-
113-
publisher.publishEvent(new AppCreationEvent(createdApp));
114-
115-
Set<String> admins = appModel.getAdmins();
116-
if (!CollectionUtils.isEmpty(admins)) {
117-
rolePermissionService
118-
.assignRoleToUsers(RoleUtils.buildAppMasterRoleName(appId), admins, userInfoHolder.getUser().getUserId());
119-
}
120-
121-
return createdApp;
122-
}
123-
124124
@RequestMapping(value = "/envs/{env}", method = RequestMethod.POST, consumes = {
125125
"application/json"})
126126
public ResponseEntity<Void> create(@PathVariable String env, @RequestBody App app) {
@@ -131,7 +131,7 @@ public ResponseEntity<Void> create(@PathVariable String env, @RequestBody App ap
131131
throw new BadRequestException(InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE);
132132
}
133133

134-
appService.createApp(Env.valueOf(env), app);
134+
appService.createAppInRemote(Env.valueOf(env), app);
135135

136136
return ResponseEntity.ok().build();
137137
}
@@ -155,7 +155,8 @@ public MultiResponseEntity<Env> findMissEnvs(@PathVariable String appId) {
155155
response.addResponseEntity(RichResponseEntity.ok(env));
156156
} else {
157157
response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR,
158-
String.format("load appId:%s from env %s error.", appId,env)
158+
String.format("load appId:%s from env %s error.", appId,
159+
env)
159160
+ e.getMessage()));
160161
}
161162
}
@@ -164,4 +165,27 @@ public MultiResponseEntity<Env> findMissEnvs(@PathVariable String appId) {
164165
return response;
165166

166167
}
168+
169+
private App transformToApp(AppModel appModel) {
170+
String appId = appModel.getAppId();
171+
String appName = appModel.getName();
172+
String ownerName = appModel.getOwnerName();
173+
String orgId = appModel.getOrgId();
174+
String orgName = appModel.getOrgName();
175+
176+
RequestPrecondition.checkArgumentsNotEmpty(appId, appName, ownerName, orgId, orgName);
177+
178+
if (!InputValidator.isValidClusterNamespace(appModel.getAppId())) {
179+
throw new BadRequestException(String.format("AppId格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE));
180+
}
181+
182+
App app = new App();
183+
app.setAppId(appId);
184+
app.setName(appName);
185+
app.setOwnerName(ownerName);
186+
app.setOrgId(orgId);
187+
app.setOrgName(orgName);
188+
189+
return app;
190+
}
167191
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.ctrip.framework.apollo.portal.listener;
2+
3+
import com.google.common.base.Preconditions;
4+
5+
import com.ctrip.framework.apollo.common.entity.App;
6+
7+
import org.springframework.context.ApplicationEvent;
8+
9+
public class AppInfoChangedEvent extends ApplicationEvent{
10+
11+
public AppInfoChangedEvent(Object source) {
12+
super(source);
13+
}
14+
15+
public App getApp() {
16+
Preconditions.checkState(source != null);
17+
return (App) this.source;
18+
}
19+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.ctrip.framework.apollo.portal.listener;
2+
3+
import com.ctrip.framework.apollo.common.dto.AppDTO;
4+
import com.ctrip.framework.apollo.common.utils.BeanUtils;
5+
import com.ctrip.framework.apollo.core.enums.Env;
6+
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
7+
import com.ctrip.framework.apollo.portal.component.PortalSettings;
8+
import com.ctrip.framework.apollo.tracer.Tracer;
9+
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
12+
import org.springframework.beans.factory.annotation.Autowired;
13+
import org.springframework.context.event.EventListener;
14+
import org.springframework.stereotype.Component;
15+
16+
import java.util.List;
17+
18+
@Component
19+
public class AppInfoChangedListener {
20+
private static final Logger logger = LoggerFactory.getLogger(AppInfoChangedListener.class);
21+
22+
@Autowired
23+
private AdminServiceAPI.AppAPI appAPI;
24+
@Autowired
25+
private PortalSettings portalSettings;
26+
27+
28+
@EventListener
29+
public void onAppInfoChange(AppInfoChangedEvent event) {
30+
AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp());
31+
String appId = appDTO.getAppId();
32+
33+
List<Env> envs = portalSettings.getActiveEnvs();
34+
for (Env env : envs) {
35+
try {
36+
appAPI.updateApp(env, appDTO);
37+
} catch (Throwable e) {
38+
logger.error("Update app's info failed. Env = {}, AppId = {}", env, appId, e);
39+
Tracer.logError(String.format("Update app's info failed. Env = {}, AppId = {}", env, appId), e);
40+
}
41+
}
42+
43+
}
44+
45+
}

apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/CreationListener.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ public void onAppCreationEvent(AppCreationEvent event) {
3636
try {
3737
appAPI.createApp(env, appDTO);
3838
} catch (Throwable e) {
39-
logger.error("call appAPI.createApp error.(appId={appId}, env={env})", appDTO.getAppId(), env, e);
40-
Tracer.logError(String.format("call appAPI.createApp error. (appId=%s, env=%s)", appDTO.getAppId(), env), e);
39+
logger.error("Create app failed. appId = {}, env = {})", appDTO.getAppId(), env, e);
40+
Tracer.logError(String.format("Create app failed. appId = %s, env = %s", appDTO.getAppId(), env), e);
4141
}
4242
}
4343
}
@@ -50,8 +50,8 @@ public void onAppNamespaceCreationEvent(AppNamespaceCreationEvent event) {
5050
try {
5151
namespaceAPI.createAppNamespace(env, appNamespace);
5252
} catch (Throwable e) {
53-
logger.error("call appAPI.createApp error.(appId={appId}, env={env})", appNamespace.getAppId(), env, e);
54-
Tracer.logError(String.format("call appAPI.createApp error. (appId=%s, env=%s)", appNamespace.getAppId(), env), e);
53+
logger.error("Create appNamespace failed. appId = {}, env = {}", appNamespace.getAppId(), env, e);
54+
Tracer.logError(String.format("Create appNamespace failed. appId = %s, env = %s", appNamespace.getAppId(), env), e);
5555
}
5656
}
5757
}

0 commit comments

Comments
 (0)