mirror of https://github.com/halo-dev/halo
feat: add some APIs to separate theme-related Setting and ConfigMap permissions (#3135)
#### What type of PR is this? /kind feature /milestone 2.2.x /area core /kind api-change #### What this PR does / why we need it: 添加自定义 APIs 以分离主题对 Setting 和 ConfigMap 权限的依赖 ⚠️ 此 PR 新增了 APIs,需要 Console 对其进行适配,主题菜单下获取激活主题的 API 以及查询主题 Setting、ConfigMap 的 APIs 需要更改。 #### Which issue(s) this PR fixes: A part of #3069 Fixes https://github.com/halo-dev/halo/issues/3069 #### Special notes for your reviewer: how to test it? - 测试 `GET /themes/-/activation` 此 endpoint 是否能正确获取到激活主题信息 - 测试 `GET /themes/{name}/setting` 是否能正确获取到主题名称对应的主题的 Setting,如果 name 为 `-` 表示查询当前激活主题的 Setting - 测试 `GET /themes/{name}/config` 是否能正确获取到主题名称对应的主题的 ConfigMap, 如果 name 为 `-` 表示查询当前激活主题的 ConfigMap。 - 测试 `PUT themes/{name}/config` 是否能更新主题的 ConfigMap,如果名称不匹配则抛出异常。 切换用户为其分配主题的查看权限可以有权限调用以上描述的 GET 请求的 endpoints,管理权限可以调用 `PUT themes/{name}/config`。 - 测试 `PUT /themes/{name}/activation` 是否能设置激活主题。 /cc @halo-dev/sig-halo #### Does this PR introduce a user-facing change? ```release-note 添加自定义 APIs 以分离主题对 Setting 和 ConfigMap 权限的依赖 ```pull/3182/head^2
parent
536218d702
commit
7f4b3a1330
|
@ -11,7 +11,6 @@ import java.util.UUID;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.retry.support.RetryTemplate;
|
import org.springframework.retry.support.RetryTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.util.FileSystemUtils;
|
import org.springframework.util.FileSystemUtils;
|
||||||
import run.halo.app.core.extension.AnnotationSetting;
|
import run.halo.app.core.extension.AnnotationSetting;
|
||||||
import run.halo.app.core.extension.Setting;
|
import run.halo.app.core.extension.Setting;
|
||||||
|
@ -150,9 +149,7 @@ public class ThemeReconciler implements Reconciler<Request> {
|
||||||
client.fetch(Setting.class, theme.getSpec().getSettingName())
|
client.fetch(Setting.class, theme.getSpec().getSettingName())
|
||||||
.ifPresent(setting -> {
|
.ifPresent(setting -> {
|
||||||
var data = SettingUtils.settingDefinedDefaultValueMap(setting);
|
var data = SettingUtils.settingDefinedDefaultValueMap(setting);
|
||||||
if (CollectionUtils.isEmpty(data)) {
|
// Whether there is a default value or not
|
||||||
return;
|
|
||||||
}
|
|
||||||
ConfigMap configMap = new ConfigMap();
|
ConfigMap configMap = new ConfigMap();
|
||||||
configMap.setMetadata(new Metadata());
|
configMap.setMetadata(new Metadata());
|
||||||
configMap.getMetadata().setName(configMapNameToUse);
|
configMap.getMetadata().setName(configMapNameToUse);
|
||||||
|
|
|
@ -14,14 +14,19 @@ import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springdoc.webflux.core.fn.SpringdocRouteBuilder;
|
import org.springdoc.webflux.core.fn.SpringdocRouteBuilder;
|
||||||
|
import org.springframework.dao.OptimisticLockingFailureException;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.codec.multipart.FilePart;
|
import org.springframework.http.codec.multipart.FilePart;
|
||||||
import org.springframework.http.codec.multipart.Part;
|
import org.springframework.http.codec.multipart.Part;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.reactive.function.BodyExtractors;
|
import org.springframework.web.reactive.function.BodyExtractors;
|
||||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
|
@ -30,6 +35,8 @@ import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
import org.springframework.web.server.ServerWebInputException;
|
import org.springframework.web.server.ServerWebInputException;
|
||||||
import reactor.core.Exceptions;
|
import reactor.core.Exceptions;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import reactor.util.retry.Retry;
|
||||||
|
import run.halo.app.core.extension.Setting;
|
||||||
import run.halo.app.core.extension.Theme;
|
import run.halo.app.core.extension.Theme;
|
||||||
import run.halo.app.core.extension.endpoint.CustomEndpoint;
|
import run.halo.app.core.extension.endpoint.CustomEndpoint;
|
||||||
import run.halo.app.extension.ConfigMap;
|
import run.halo.app.extension.ConfigMap;
|
||||||
|
@ -37,7 +44,11 @@ import run.halo.app.extension.ListResult;
|
||||||
import run.halo.app.extension.ReactiveExtensionClient;
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
import run.halo.app.extension.router.IListRequest;
|
import run.halo.app.extension.router.IListRequest;
|
||||||
import run.halo.app.extension.router.QueryParamBuildUtil;
|
import run.halo.app.extension.router.QueryParamBuildUtil;
|
||||||
|
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
||||||
|
import run.halo.app.infra.SystemSetting;
|
||||||
import run.halo.app.infra.ThemeRootGetter;
|
import run.halo.app.infra.ThemeRootGetter;
|
||||||
|
import run.halo.app.infra.exception.NotFoundException;
|
||||||
|
import run.halo.app.infra.utils.JsonUtils;
|
||||||
import run.halo.app.theme.TemplateEngineManager;
|
import run.halo.app.theme.TemplateEngineManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,6 +59,7 @@ import run.halo.app.theme.TemplateEngineManager;
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
|
@AllArgsConstructor
|
||||||
public class ThemeEndpoint implements CustomEndpoint {
|
public class ThemeEndpoint implements CustomEndpoint {
|
||||||
|
|
||||||
private final ReactiveExtensionClient client;
|
private final ReactiveExtensionClient client;
|
||||||
|
@ -58,13 +70,7 @@ public class ThemeEndpoint implements CustomEndpoint {
|
||||||
|
|
||||||
private final TemplateEngineManager templateEngineManager;
|
private final TemplateEngineManager templateEngineManager;
|
||||||
|
|
||||||
public ThemeEndpoint(ReactiveExtensionClient client, ThemeRootGetter themeRoot,
|
private final SystemConfigurableEnvironmentFetcher systemEnvironmentFetcher;
|
||||||
ThemeService themeService, TemplateEngineManager templateEngineManager) {
|
|
||||||
this.client = client;
|
|
||||||
this.themeRoot = themeRoot;
|
|
||||||
this.themeService = themeService;
|
|
||||||
this.templateEngineManager = templateEngineManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouterFunction<ServerResponse> endpoint() {
|
public RouterFunction<ServerResponse> endpoint() {
|
||||||
|
@ -119,6 +125,36 @@ public class ThemeEndpoint implements CustomEndpoint {
|
||||||
.response(responseBuilder()
|
.response(responseBuilder()
|
||||||
.implementation(ConfigMap.class))
|
.implementation(ConfigMap.class))
|
||||||
)
|
)
|
||||||
|
.PUT("themes/{name}/config", this::updateThemeConfig,
|
||||||
|
builder -> builder.operationId("updateThemeConfig")
|
||||||
|
.description("Update the configMap of theme setting.")
|
||||||
|
.tag(tag)
|
||||||
|
.parameter(parameterBuilder()
|
||||||
|
.name("name")
|
||||||
|
.in(ParameterIn.PATH)
|
||||||
|
.required(true)
|
||||||
|
.implementation(String.class)
|
||||||
|
)
|
||||||
|
.requestBody(requestBodyBuilder()
|
||||||
|
.required(true)
|
||||||
|
.content(contentBuilder().mediaType(MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
.schema(schemaBuilder().implementation(ConfigMap.class))))
|
||||||
|
.response(responseBuilder()
|
||||||
|
.implementation(ConfigMap.class))
|
||||||
|
)
|
||||||
|
.PUT("themes/{name}/activation", this::activateTheme,
|
||||||
|
builder -> builder.operationId("activateTheme")
|
||||||
|
.description("Activate a theme by name.")
|
||||||
|
.tag(tag)
|
||||||
|
.parameter(parameterBuilder()
|
||||||
|
.name("name")
|
||||||
|
.in(ParameterIn.PATH)
|
||||||
|
.required(true)
|
||||||
|
.implementation(String.class)
|
||||||
|
)
|
||||||
|
.response(responseBuilder()
|
||||||
|
.implementation(Theme.class))
|
||||||
|
)
|
||||||
.GET("themes", this::listThemes,
|
.GET("themes", this::listThemes,
|
||||||
builder -> {
|
builder -> {
|
||||||
builder.operationId("ListThemes")
|
builder.operationId("ListThemes")
|
||||||
|
@ -129,9 +165,143 @@ public class ThemeEndpoint implements CustomEndpoint {
|
||||||
QueryParamBuildUtil.buildParametersFromType(builder, ThemeQuery.class);
|
QueryParamBuildUtil.buildParametersFromType(builder, ThemeQuery.class);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
.GET("themes/-/activation", this::fetchActivatedTheme,
|
||||||
|
builder -> builder.operationId("fetchActivatedTheme")
|
||||||
|
.description("Fetch the activated theme.")
|
||||||
|
.tag(tag)
|
||||||
|
.response(responseBuilder()
|
||||||
|
.implementation(Theme.class))
|
||||||
|
)
|
||||||
|
.GET("themes/{name}/setting", this::fetchThemeSetting,
|
||||||
|
builder -> builder.operationId("fetchThemeSetting")
|
||||||
|
.description("Fetch setting of theme.")
|
||||||
|
.tag(tag)
|
||||||
|
.parameter(parameterBuilder()
|
||||||
|
.name("name")
|
||||||
|
.in(ParameterIn.PATH)
|
||||||
|
.required(true)
|
||||||
|
.implementation(String.class)
|
||||||
|
)
|
||||||
|
.response(responseBuilder()
|
||||||
|
.implementation(Setting.class))
|
||||||
|
)
|
||||||
|
.GET("themes/{name}/config", this::fetchThemeConfig,
|
||||||
|
builder -> builder.operationId("fetchThemeConfig")
|
||||||
|
.description("Fetch configMap of theme by configured configMapName.")
|
||||||
|
.tag(tag)
|
||||||
|
.parameter(parameterBuilder()
|
||||||
|
.name("name")
|
||||||
|
.in(ParameterIn.PATH)
|
||||||
|
.required(true)
|
||||||
|
.implementation(String.class)
|
||||||
|
)
|
||||||
|
.response(responseBuilder()
|
||||||
|
.implementation(ConfigMap.class))
|
||||||
|
)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Mono<ServerResponse> activateTheme(ServerRequest request) {
|
||||||
|
final var activatedThemeName = request.pathVariable("name");
|
||||||
|
return client.fetch(Theme.class, activatedThemeName)
|
||||||
|
.switchIfEmpty(Mono.error(new NotFoundException("Theme not found.")))
|
||||||
|
.flatMap(theme -> systemEnvironmentFetcher.fetch(SystemSetting.Theme.GROUP,
|
||||||
|
SystemSetting.Theme.class)
|
||||||
|
.flatMap(themeSetting -> {
|
||||||
|
// update active theme config
|
||||||
|
themeSetting.setActive(activatedThemeName);
|
||||||
|
return systemEnvironmentFetcher.getConfigMap()
|
||||||
|
.filter(configMap -> configMap.getData() != null)
|
||||||
|
.map(configMap -> {
|
||||||
|
var themeConfigJson = JsonUtils.objectToJson(themeSetting);
|
||||||
|
configMap.getData()
|
||||||
|
.put(SystemSetting.Theme.GROUP, themeConfigJson);
|
||||||
|
return configMap;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.flatMap(client::update)
|
||||||
|
.retryWhen(Retry.backoff(5, Duration.ofMillis(300))
|
||||||
|
.filter(OptimisticLockingFailureException.class::isInstance)
|
||||||
|
)
|
||||||
|
.thenReturn(theme)
|
||||||
|
)
|
||||||
|
.flatMap(activatedTheme -> ServerResponse.ok().bodyValue(activatedTheme));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<ServerResponse> updateThemeConfig(ServerRequest request) {
|
||||||
|
final var themeName = request.pathVariable("name");
|
||||||
|
return client.fetch(Theme.class, themeName)
|
||||||
|
.doOnNext(theme -> {
|
||||||
|
String configMapName = theme.getSpec().getConfigMapName();
|
||||||
|
if (StringUtils.isBlank(configMapName)) {
|
||||||
|
throw new ServerWebInputException(
|
||||||
|
"Unable to complete the request because the theme configMapName is blank.");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.flatMap(theme -> {
|
||||||
|
final var configMapName = theme.getSpec().getConfigMapName();
|
||||||
|
return request.bodyToMono(ConfigMap.class)
|
||||||
|
.doOnNext(configMapToUpdate -> {
|
||||||
|
var configMapNameToUpdate = configMapToUpdate.getMetadata().getName();
|
||||||
|
if (!configMapName.equals(configMapNameToUpdate)) {
|
||||||
|
throw new ServerWebInputException(
|
||||||
|
"The name from the request body does not match the theme "
|
||||||
|
+ "configMapName name.");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.flatMap(configMapToUpdate -> client.fetch(ConfigMap.class, configMapName)
|
||||||
|
.map(persisted -> {
|
||||||
|
configMapToUpdate.getMetadata()
|
||||||
|
.setVersion(persisted.getMetadata().getVersion());
|
||||||
|
return configMapToUpdate;
|
||||||
|
})
|
||||||
|
.switchIfEmpty(client.create(configMapToUpdate))
|
||||||
|
)
|
||||||
|
.flatMap(client::update)
|
||||||
|
.retryWhen(Retry.backoff(5, Duration.ofMillis(300))
|
||||||
|
.filter(OptimisticLockingFailureException.class::isInstance)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.flatMap(configMap -> ServerResponse.ok().bodyValue(configMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<ServerResponse> fetchThemeConfig(ServerRequest request) {
|
||||||
|
return themeNameInPathVariableOrActivated(request)
|
||||||
|
.flatMap(themeName -> client.fetch(Theme.class, themeName))
|
||||||
|
.mapNotNull(theme -> theme.getSpec().getConfigMapName())
|
||||||
|
.flatMap(configMapName -> client.fetch(ConfigMap.class, configMapName))
|
||||||
|
.flatMap(configMap -> ServerResponse.ok().bodyValue(configMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<ServerResponse> fetchActivatedTheme(ServerRequest request) {
|
||||||
|
return systemEnvironmentFetcher.fetch(SystemSetting.Theme.GROUP, SystemSetting.Theme.class)
|
||||||
|
.map(SystemSetting.Theme::getActive)
|
||||||
|
.flatMap(activatedName -> client.fetch(Theme.class, activatedName))
|
||||||
|
.flatMap(theme -> ServerResponse.ok().bodyValue(theme));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<ServerResponse> fetchThemeSetting(ServerRequest request) {
|
||||||
|
return themeNameInPathVariableOrActivated(request)
|
||||||
|
.flatMap(name -> client.fetch(Theme.class, name))
|
||||||
|
.mapNotNull(theme -> theme.getSpec().getSettingName())
|
||||||
|
.flatMap(settingName -> client.fetch(Setting.class, settingName))
|
||||||
|
.flatMap(setting -> ServerResponse.ok().bodyValue(setting));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<String> themeNameInPathVariableOrActivated(ServerRequest request) {
|
||||||
|
Assert.notNull(request, "request must not be null.");
|
||||||
|
return Mono.fromSupplier(() -> request.pathVariable("name"))
|
||||||
|
.flatMap(name -> {
|
||||||
|
if ("-".equals(name)) {
|
||||||
|
return systemEnvironmentFetcher.fetch(SystemSetting.Theme.GROUP,
|
||||||
|
SystemSetting.Theme.class)
|
||||||
|
.mapNotNull(SystemSetting.Theme::getActive)
|
||||||
|
.defaultIfEmpty(name);
|
||||||
|
}
|
||||||
|
return Mono.just(name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static class ThemeQuery extends IListRequest.QueryListRequest {
|
public static class ThemeQuery extends IListRequest.QueryListRequest {
|
||||||
|
|
||||||
public ThemeQuery(MultiValueMap<String, String> queryParams) {
|
public ThemeQuery(MultiValueMap<String, String> queryParams) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ rules:
|
||||||
resources: [ "themes" ]
|
resources: [ "themes" ]
|
||||||
verbs: [ "*" ]
|
verbs: [ "*" ]
|
||||||
- apiGroups: [ "api.console.halo.run" ]
|
- apiGroups: [ "api.console.halo.run" ]
|
||||||
resources: [ "themes", "themes/reload", "themes/resetconfig" ]
|
resources: [ "themes", "themes/reload", "themes/resetconfig", "themes/config", "themes/activation" ]
|
||||||
verbs: [ "*" ]
|
verbs: [ "*" ]
|
||||||
- nonResourceURLs: [ "/apis/api.console.halo.run/themes/install" ]
|
- nonResourceURLs: [ "/apis/api.console.halo.run/themes/install" ]
|
||||||
verbs: [ "create" ]
|
verbs: [ "create" ]
|
||||||
|
@ -36,6 +36,6 @@ rules:
|
||||||
resources: [ "themes" ]
|
resources: [ "themes" ]
|
||||||
verbs: [ "get", "list" ]
|
verbs: [ "get", "list" ]
|
||||||
- apiGroups: [ "api.console.halo.run" ]
|
- apiGroups: [ "api.console.halo.run" ]
|
||||||
resources: [ "themes" ]
|
resources: [ "themes", "themes/activation", "themes/setting", "themes/config" ]
|
||||||
verbs: [ "get", "list" ]
|
verbs: [ "get", "list" ]
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,13 @@ import org.springframework.util.FileSystemUtils;
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
import org.springframework.web.server.ServerWebInputException;
|
import org.springframework.web.server.ServerWebInputException;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import run.halo.app.core.extension.Setting;
|
||||||
import run.halo.app.core.extension.Theme;
|
import run.halo.app.core.extension.Theme;
|
||||||
|
import run.halo.app.extension.ConfigMap;
|
||||||
import run.halo.app.extension.Metadata;
|
import run.halo.app.extension.Metadata;
|
||||||
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
|
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
||||||
|
import run.halo.app.infra.SystemSetting;
|
||||||
import run.halo.app.infra.ThemeRootGetter;
|
import run.halo.app.infra.ThemeRootGetter;
|
||||||
import run.halo.app.theme.TemplateEngineManager;
|
import run.halo.app.theme.TemplateEngineManager;
|
||||||
|
|
||||||
|
@ -53,6 +58,12 @@ class ThemeEndpointTest {
|
||||||
@Mock
|
@Mock
|
||||||
TemplateEngineManager templateEngineManager;
|
TemplateEngineManager templateEngineManager;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ReactiveExtensionClient client;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private SystemConfigurableEnvironmentFetcher environmentFetcher;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
ThemeEndpoint themeEndpoint;
|
ThemeEndpoint themeEndpoint;
|
||||||
|
|
||||||
|
@ -179,4 +190,126 @@ class ThemeEndpointTest {
|
||||||
.exchange()
|
.exchange()
|
||||||
.expectStatus().isOk();
|
.expectStatus().isOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class UpdateThemeConfigTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateWhenConfigMapNameIsNull() {
|
||||||
|
Theme theme = new Theme();
|
||||||
|
theme.setMetadata(new Metadata());
|
||||||
|
theme.setSpec(new Theme.ThemeSpec());
|
||||||
|
theme.getSpec().setConfigMapName(null);
|
||||||
|
|
||||||
|
when(client.fetch(eq(Theme.class), eq("fake-theme"))).thenReturn(Mono.just(theme));
|
||||||
|
webTestClient.put()
|
||||||
|
.uri("/themes/fake-theme/config")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isBadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateWhenConfigMapNameNotMatch() {
|
||||||
|
Theme theme = new Theme();
|
||||||
|
theme.setMetadata(new Metadata());
|
||||||
|
theme.setSpec(new Theme.ThemeSpec());
|
||||||
|
theme.getSpec().setConfigMapName("fake-config-map");
|
||||||
|
|
||||||
|
when(client.fetch(eq(Theme.class), eq("fake-theme"))).thenReturn(Mono.just(theme));
|
||||||
|
webTestClient.put()
|
||||||
|
.uri("/themes/fake-theme/config")
|
||||||
|
.body(Mono.fromSupplier(() -> {
|
||||||
|
ConfigMap configMap = new ConfigMap();
|
||||||
|
configMap.setMetadata(new Metadata());
|
||||||
|
configMap.getMetadata().setName("not-match");
|
||||||
|
return configMap;
|
||||||
|
}), ConfigMap.class)
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isBadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateWhenConfigMapNameMatch() {
|
||||||
|
Theme theme = new Theme();
|
||||||
|
theme.setMetadata(new Metadata());
|
||||||
|
theme.setSpec(new Theme.ThemeSpec());
|
||||||
|
theme.getSpec().setConfigMapName("fake-config-map");
|
||||||
|
|
||||||
|
when(client.fetch(eq(Theme.class), eq("fake-theme"))).thenReturn(Mono.just(theme));
|
||||||
|
when(client.fetch(eq(ConfigMap.class), eq("fake-config-map"))).thenReturn(Mono.empty());
|
||||||
|
when(client.create(any(ConfigMap.class))).thenReturn(Mono.empty());
|
||||||
|
|
||||||
|
webTestClient.put()
|
||||||
|
.uri("/themes/fake-theme/config")
|
||||||
|
.body(Mono.fromSupplier(() -> {
|
||||||
|
ConfigMap configMap = new ConfigMap();
|
||||||
|
configMap.setMetadata(new Metadata());
|
||||||
|
configMap.getMetadata().setName("fake-config-map");
|
||||||
|
return configMap;
|
||||||
|
}), ConfigMap.class)
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isOk();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void fetchActivatedTheme() {
|
||||||
|
when(environmentFetcher.fetch(eq(SystemSetting.Theme.GROUP), eq(SystemSetting.Theme.class)))
|
||||||
|
.thenReturn(Mono.fromSupplier(() -> {
|
||||||
|
SystemSetting.Theme theme = new SystemSetting.Theme();
|
||||||
|
theme.setActive("fake-activated");
|
||||||
|
return theme;
|
||||||
|
}));
|
||||||
|
|
||||||
|
when(client.fetch(eq(Theme.class), eq("fake-activated"))).thenReturn(Mono.empty());
|
||||||
|
webTestClient.get()
|
||||||
|
.uri("/themes/-/activation")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isOk();
|
||||||
|
|
||||||
|
verify(client).fetch(eq(Theme.class), eq("fake-activated"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void fetchThemeSetting() {
|
||||||
|
Theme theme = new Theme();
|
||||||
|
theme.setMetadata(new Metadata());
|
||||||
|
theme.getMetadata().setName("fake");
|
||||||
|
theme.setSpec(new Theme.ThemeSpec());
|
||||||
|
theme.getSpec().setSettingName("fake-setting");
|
||||||
|
|
||||||
|
when(client.fetch(eq(Setting.class), eq("fake-setting")))
|
||||||
|
.thenReturn(Mono.just(new Setting()));
|
||||||
|
|
||||||
|
when(client.fetch(eq(Theme.class), eq("fake"))).thenReturn(Mono.just(theme));
|
||||||
|
webTestClient.get()
|
||||||
|
.uri("/themes/fake/setting")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isOk();
|
||||||
|
|
||||||
|
verify(client).fetch(eq(Setting.class), eq("fake-setting"));
|
||||||
|
verify(client).fetch(eq(Theme.class), eq("fake"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void fetchThemeConfig() {
|
||||||
|
Theme theme = new Theme();
|
||||||
|
theme.setMetadata(new Metadata());
|
||||||
|
theme.getMetadata().setName("fake");
|
||||||
|
theme.setSpec(new Theme.ThemeSpec());
|
||||||
|
theme.getSpec().setConfigMapName("fake-config");
|
||||||
|
|
||||||
|
when(client.fetch(eq(ConfigMap.class), eq("fake-config")))
|
||||||
|
.thenReturn(Mono.just(new ConfigMap()));
|
||||||
|
|
||||||
|
when(client.fetch(eq(Theme.class), eq("fake"))).thenReturn(Mono.just(theme));
|
||||||
|
webTestClient.get()
|
||||||
|
.uri("/themes/fake/config")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isOk();
|
||||||
|
|
||||||
|
verify(client).fetch(eq(ConfigMap.class), eq("fake-config"));
|
||||||
|
verify(client).fetch(eq(Theme.class), eq("fake"));
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue