Skip to content

Commit

Permalink
first working REST-ish endpoint, very simple one
Browse files Browse the repository at this point in the history
  • Loading branch information
virgo47 committed Jan 24, 2020
1 parent 03248de commit a91205d
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 14 deletions.
5 changes: 5 additions & 0 deletions gui/admin-gui/pom.xml
Expand Up @@ -423,6 +423,11 @@
<artifactId>system-init</artifactId>
<version>4.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.evolveum.midpoint.model</groupId>
<artifactId>rest-impl</artifactId>
<version>4.1-SNAPSHOT</version>
</dependency>
<!-- MIDPOINT RUNTIME DEPENDENCIES -->
<dependency>
<groupId>com.evolveum.midpoint.repo</groupId>
Expand Down
Expand Up @@ -4,25 +4,21 @@
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.web.boot;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory;
import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry;
import com.evolveum.midpoint.gui.impl.factory.LockoutStatusPanelFactory;
import com.evolveum.midpoint.gui.impl.factory.TextAreaPanelFactory;
import com.evolveum.midpoint.gui.impl.registry.GuiComponentRegistryImpl;
import com.evolveum.midpoint.web.application.AsyncWebProcessManager;
import com.evolveum.midpoint.web.application.AsyncWebProcessManagerImpl;
import com.evolveum.midpoint.web.security.MidPointApplication;
import com.evolveum.midpoint.web.util.validation.MidpointFormValidatorRegistry;
import org.springframework.http.CacheControl;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

Expand All @@ -32,6 +28,8 @@
* Created by Viliam Repan (lazyman).
*/
@Configuration
@ComponentScan(basePackages = "com.evolveum.midpoint.rest.impl")
@EnableWebMvc
public class WebConfig {

@Bean
Expand All @@ -44,7 +42,6 @@ public MidpointFormValidatorRegistry midpointFormValidatorRegistry() {
return new MidpointFormValidatorRegistry();
}


@Bean
public AsyncWebProcessManager asyncWebProcessManager() {
return new AsyncWebProcessManagerImpl();
Expand All @@ -55,6 +52,7 @@ public static class StaticResourceConfiguration implements WebMvcConfigurer {

@Autowired
private ResourceProperties resourceProperties;

@Value("${midpoint.home}")
private String midpointHome;

Expand Down
Expand Up @@ -16,10 +16,10 @@
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.security.factory.channel.AuthChannelRegistryImpl;
import com.evolveum.midpoint.web.security.factory.module.AuthModuleRegistryImpl;
import com.evolveum.midpoint.web.security.filter.MidpointAnonymousAuthenticationFilter;
import com.evolveum.midpoint.web.security.filter.MidpointRequestAttributeAuthenticationFilter;
import com.evolveum.midpoint.web.security.filter.configurers.AuthFilterConfigurer;
import com.evolveum.midpoint.web.security.factory.module.AuthModuleRegistryImpl;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -58,7 +58,6 @@
/**
* @author skublik
*/

@Order(SecurityProperties.BASIC_AUTH_ORDER - 1)
@Configuration
@EnableWebSecurity
Expand Down Expand Up @@ -96,15 +95,12 @@ public class BasicWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${auth.logout.url:/}")
private String authLogoutUrl;

private ObjectPostProcessor<Object> objectObjectPostProcessor;

public BasicWebSecurityConfig(){
public BasicWebSecurityConfig() {
super(true);
}

@Override
public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
this.objectObjectPostProcessor = objectPostProcessor;
super.setObjectPostProcessor(objectPostProcessor);
}

Expand Down Expand Up @@ -171,6 +167,9 @@ public boolean matches(HttpServletRequest httpServletRequest) {
if (mather.match("/ws/**", httpServletRequest.getRequestURI().substring(httpServletRequest.getContextPath().length()))) {
return true;
}
if (mather.match("/rest2/**", httpServletRequest.getRequestURI().substring(httpServletRequest.getContextPath().length()))) {
return true;
}
return false;
}
});
Expand Down Expand Up @@ -211,7 +210,6 @@ protected void configure(HttpSecurity http) throws Exception {
.securityContext();
http.apply(new AuthFilterConfigurer());


http.sessionManagement()
.maximumSessions(-1)
.sessionRegistry(sessionRegistry)
Expand Down
Expand Up @@ -94,6 +94,10 @@ public enum PageUrlMapping {
REST("/ws/rest/**", new DisplayableValue[]{
new AuthorizationActionValue(AUTZ_REST_ALL_URL,
"RestEndpoint.authRest.all.label", "RestEndpoint.authRest.all.description")
}),
REST2("/rest2/**", new DisplayableValue[]{
new AuthorizationActionValue(AUTZ_REST_ALL_URL,
"RestEndpoint.authRest.all.label", "RestEndpoint.authRest.all.description")
});

private String url;
Expand Down
2 changes: 2 additions & 0 deletions model/pom.xml
Expand Up @@ -51,6 +51,8 @@
<module>report-impl</module>
<module>certification-api</module>
<module>certification-impl</module>
<!-- TODO separate rest-api after PoC is finished -->
<module>rest-impl</module>
</modules>
<build>
<plugins>
Expand Down
28 changes: 28 additions & 0 deletions model/rest-impl/pom.xml
@@ -0,0 +1,28 @@
<?xml version="1.0"?>
<!--
~ Copyright (c) 2010-2019 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>model</artifactId>
<groupId>com.evolveum.midpoint</groupId>
<version>4.1-SNAPSHOT</version>
</parent>

<name>midPoint REST-ish service implementation</name>
<groupId>com.evolveum.midpoint.model</groupId>
<artifactId>rest-impl</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,118 @@
package com.evolveum.midpoint.rest.impl;

import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.MediaTypeExpression;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

/**
* Support for simple index page with REST API endpoints (HTML and JSON).
*/
@RestController
@RequestMapping("/rest2")
public class RestApiIndex {

private final RequestMappingHandlerMapping handlerMapping;
private final List<OperationInfo> uiRestInfo;

public RestApiIndex(RequestMappingHandlerMapping handlerMapping) {
this.handlerMapping = handlerMapping;
uiRestInfo = operationInfoStream()
.filter(info -> info.handler.getBeanType()
.getPackageName().startsWith("com.evolveum.midpoint.rest."))
.collect(Collectors.toList());
}

@GetMapping()
public List<OperationJson> index() {
return uiRestInfo.stream()
.flatMap(OperationInfo::operationJsonStream)
.sorted(Comparator.comparing(json -> json.urlPattern))
.collect(Collectors.toList());
}

@GetMapping(value = "/x", produces = "text/html")
public String indexHtml() {
StringBuilder html = new StringBuilder("<!DOCTYPE html><html>"
+ "<head><meta charset='UTF-8'><title>REST-ish API</title>"
+ "<style>body {font-family: sans-serif;} form,li,p,h1 {margin: 0.4em;}"
+ " input,select {margin: 0 1em 0 0;} input {width:5em;}"
+ " #result {padding: 1em; border: solid thin red;}</style>"
+ "</head>"
+ "<body><h1>REST operations</h1>This is NOT Swagger! Click at your own risk!<ul>");
for (OperationJson operationJson : index()) {
html.append("<li>")
.append(Arrays.toString(operationJson.methods))
.append(" <a href=\"")
.append(operationJson.urlPattern)
.append("\">")
.append(operationJson.urlPattern)
.append("</a></li>");
}
return html.append("</ul></body>")
.toString();
}

private Stream<OperationInfo> operationInfoStream() {
return handlerMapping.getHandlerMethods().entrySet().stream()
.map(entry -> new OperationInfo(entry.getKey(), entry.getValue()));
}

private static class OperationInfo {
final RequestMappingInfo mappingInfo;
final HandlerMethod handler;

OperationInfo(RequestMappingInfo mappingInfo, HandlerMethod handler) {
this.mappingInfo = mappingInfo;
this.handler = handler;
}

Stream<OperationJson> operationJsonStream() {
return mappingInfo.getPatternsCondition().getPatterns().stream()
.map(pattern -> new OperationJson(pattern,
mappingInfo.getMethodsCondition().getMethods(),
mappingInfo.getConsumesCondition().getConsumableMediaTypes(),
mappingInfo.getProducesCondition().getExpressions()));
}
}

@SuppressWarnings("WeakerAccess")
public static class OperationJson {
public final String urlPattern;
public final String[] methods;
public final String[] accepts;
public final String[] produces;

public OperationJson(String urlPattern,
Set<RequestMethod> methods,
Set<MediaType> accepts,
Set<MediaTypeExpression> produces)
{
this.urlPattern = urlPattern;
this.methods = toStringArray(methods);
this.accepts = toStringArray(accepts);
this.produces = toStringArray(produces);
}

private String[] toStringArray(Collection<?> collection) {
return collection.isEmpty()
? null
: collection.stream()
.map(Object::toString)
.toArray(String[]::new);
}
}
}

0 comments on commit a91205d

Please sign in to comment.