From 7fd5d5190b2469bca0846a75ecd451abe0025769 Mon Sep 17 00:00:00 2001 From: Anatol Sialitski Date: Wed, 13 Nov 2024 09:58:32 +0100 Subject: [PATCH] Migrate Admin Event API to Universal API #10762 --- modules/admin/admin-event/build.gradle | 2 +- .../xp/admin/event/impl/EventApiHandler.java | 58 +++++++++++++++++++ .../enonic/xp/lib/admin/AdminLibHelper.java | 45 +++++++++++++- .../src/main/resources/lib/xp/admin.ts | 11 ++++ .../universalapi/UniversalApiHandler.java | 6 ++ .../impl/api/DynamicUniversalApiHandler.java | 7 +++ .../websocket/WebSocketApiEndpointImpl.java | 6 ++ .../impl/websocket/WebSocketContextImpl.java | 18 ++++-- 8 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 modules/admin/admin-event/src/main/java/com/enonic/xp/admin/event/impl/EventApiHandler.java diff --git a/modules/admin/admin-event/build.gradle b/modules/admin/admin-event/build.gradle index 672a938265d..51f96c8764a 100644 --- a/modules/admin/admin-event/build.gradle +++ b/modules/admin/admin-event/build.gradle @@ -1,5 +1,5 @@ dependencies { - implementation project( ':web:web-api' ) + api project( ':portal:portal-api' ) implementation project( ':core:core-internal' ) testImplementation( testFixtures( project(":web:web-jetty") ) ) diff --git a/modules/admin/admin-event/src/main/java/com/enonic/xp/admin/event/impl/EventApiHandler.java b/modules/admin/admin-event/src/main/java/com/enonic/xp/admin/event/impl/EventApiHandler.java new file mode 100644 index 00000000000..db62620d7bd --- /dev/null +++ b/modules/admin/admin-event/src/main/java/com/enonic/xp/admin/event/impl/EventApiHandler.java @@ -0,0 +1,58 @@ +package com.enonic.xp.admin.event.impl; + +import java.util.List; + +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +import com.enonic.xp.portal.universalapi.UniversalApiHandler; +import com.enonic.xp.web.HttpStatus; +import com.enonic.xp.web.WebRequest; +import com.enonic.xp.web.WebResponse; +import com.enonic.xp.web.websocket.EndpointFactory; +import com.enonic.xp.web.websocket.WebSocketConfig; +import com.enonic.xp.web.websocket.WebSocketService; + +@Component(immediate = true, service = UniversalApiHandler.class, property = {"applicationKey=admin", "apiKey=event", + "displayName=Event API", "allowedPrincipals=role:system.admin.login", "mount=true"}) +public class EventApiHandler + implements UniversalApiHandler +{ + private final WebSocketService webSocketService; + + private final EndpointFactory endpointFactory; + + @Activate + public EventApiHandler( @Reference final WebSocketService webSocketService, + @Reference/*(service = EventEndpointFactory.class)*/ final EndpointFactory endpointFactory ) + { + this.webSocketService = webSocketService; + this.endpointFactory = endpointFactory; + } + + @Override + public WebResponse handle( final WebRequest request ) + { + final WebResponse.Builder responseBuilder = WebResponse.create(); + + if ( !webSocketService.isUpgradeRequest( request.getRawRequest(), null ) ) + { + responseBuilder.status( HttpStatus.FORBIDDEN ); + return responseBuilder.build(); + } + + final WebSocketConfig webSocketConfig = new WebSocketConfig(); + webSocketConfig.setSubProtocols( List.of( "text" ) ); + + responseBuilder.webSocket( webSocketConfig ); + + return responseBuilder.build(); + } + + @Override + public EndpointFactory getEndpointFactory() + { + return endpointFactory; + } +} diff --git a/modules/lib/lib-admin/src/main/java/com/enonic/xp/lib/admin/AdminLibHelper.java b/modules/lib/lib-admin/src/main/java/com/enonic/xp/lib/admin/AdminLibHelper.java index 8fe287e03e9..d724ffeb41e 100644 --- a/modules/lib/lib-admin/src/main/java/com/enonic/xp/lib/admin/AdminLibHelper.java +++ b/modules/lib/lib-admin/src/main/java/com/enonic/xp/lib/admin/AdminLibHelper.java @@ -4,6 +4,8 @@ import java.util.List; import java.util.Locale; import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; @@ -39,6 +41,41 @@ public String getBaseUri() return ServletRequestUrlHelper.createUri( ServletRequestHolder.getRequest(), ADMIN_URI_PREFIX ); } + private String subPath( final String requestURI, final String prefix ) + { + final int endpoint = requestURI.indexOf( "/_/" ); + final int endIndex = endpoint == -1 ? requestURI.length() : endpoint + 1; + return requestURI.substring( prefix.length(), endIndex ); + } + + public String getBaseUriNew() + { + final String requestURI = ServletRequestHolder.getRequest().getRequestURI(); + + String path = null; + if ( requestURI.equals( "/admin" ) ) + { + path = "/admin/com.enonic.xp.app.main/home"; + } + else + { + final Pattern TOOL_CXT_PATTERN = Pattern.compile( "^([^/]+)/([^/]+)" ); + final String subPath = subPath( requestURI, "/admin/" ); + final Matcher matcher = TOOL_CXT_PATTERN.matcher( subPath ); + if ( matcher.find() ) + { + path = "/admin/" + matcher.group( 0 ); + } + } + + if ( path == null ) + { + throw new IllegalArgumentException( String.format( "Invalid tool context: %s", requestURI ) ); + } + + return ServletRequestUrlHelper.createUri( ServletRequestHolder.getRequest(), path ); + } + public String getAssetsUri() { return ServletRequestUrlHelper.createUri( ServletRequestHolder.getRequest(), ADMIN_ASSETS_URI_PREFIX + this.version ); @@ -54,12 +91,14 @@ public String generateAdminToolUri( String application, String adminTool ) return this.adminToolDescriptorService.get().generateAdminToolUri( application, adminTool ); } - public String getHomeAppName() { + public String getHomeAppName() + { return ADMIN_APP_NAME; } - public String getLauncherToolUrl() { - return generateAdminToolUri(ADMIN_APP_NAME, "launcher"); + public String getLauncherToolUrl() + { + return generateAdminToolUri( ADMIN_APP_NAME, "launcher" ); } public String getLocale() diff --git a/modules/lib/lib-admin/src/main/resources/lib/xp/admin.ts b/modules/lib/lib-admin/src/main/resources/lib/xp/admin.ts index cb0ecbb7bb7..67733a25711 100644 --- a/modules/lib/lib-admin/src/main/resources/lib/xp/admin.ts +++ b/modules/lib/lib-admin/src/main/resources/lib/xp/admin.ts @@ -34,6 +34,8 @@ interface AdminLibHelper { getBaseUri(): string; + getBaseUriNew(): string; + getHomeToolUri(): string; getInstallation(): string; @@ -58,6 +60,15 @@ export function getBaseUri(): string { return helper.getBaseUri(); } +/** + * Returns the base uri. + * + * @returns {string} Admin base uri. + */ +export function getBaseUriNew(): string { + return helper.getBaseUriNew(); +} + /** * Returns the admin assets uri. * diff --git a/modules/portal/portal-api/src/main/java/com/enonic/xp/portal/universalapi/UniversalApiHandler.java b/modules/portal/portal-api/src/main/java/com/enonic/xp/portal/universalapi/UniversalApiHandler.java index 392d99a9ef9..0202d43bac0 100644 --- a/modules/portal/portal-api/src/main/java/com/enonic/xp/portal/universalapi/UniversalApiHandler.java +++ b/modules/portal/portal-api/src/main/java/com/enonic/xp/portal/universalapi/UniversalApiHandler.java @@ -2,6 +2,7 @@ import com.enonic.xp.web.WebRequest; import com.enonic.xp.web.WebResponse; +import com.enonic.xp.web.websocket.EndpointFactory; import com.enonic.xp.web.websocket.WebSocketEvent; public interface UniversalApiHandler @@ -11,4 +12,9 @@ public interface UniversalApiHandler default void onSocketEvent( WebSocketEvent event ) { } + + default EndpointFactory getEndpointFactory() + { + return null; + } } diff --git a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/api/DynamicUniversalApiHandler.java b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/api/DynamicUniversalApiHandler.java index 05b7f22cfc8..b5941e19f77 100644 --- a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/api/DynamicUniversalApiHandler.java +++ b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/api/DynamicUniversalApiHandler.java @@ -4,6 +4,7 @@ import com.enonic.xp.portal.universalapi.UniversalApiHandler; import com.enonic.xp.web.WebRequest; import com.enonic.xp.web.WebResponse; +import com.enonic.xp.web.websocket.EndpointFactory; import com.enonic.xp.web.websocket.WebSocketEvent; public final class DynamicUniversalApiHandler @@ -31,6 +32,12 @@ public void onSocketEvent( final WebSocketEvent event ) apiHandler.onSocketEvent( event ); } + @Override + public EndpointFactory getEndpointFactory() + { + return apiHandler.getEndpointFactory(); + } + public ApiDescriptor getApiDescriptor() { return apiDescriptor; diff --git a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/websocket/WebSocketApiEndpointImpl.java b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/websocket/WebSocketApiEndpointImpl.java index 57434ae88fe..fcdae1218da 100644 --- a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/websocket/WebSocketApiEndpointImpl.java +++ b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/websocket/WebSocketApiEndpointImpl.java @@ -3,6 +3,7 @@ import java.util.function.Supplier; import com.enonic.xp.portal.universalapi.UniversalApiHandler; +import com.enonic.xp.web.websocket.EndpointFactory; import com.enonic.xp.web.websocket.WebSocketConfig; import com.enonic.xp.web.websocket.WebSocketEndpoint; import com.enonic.xp.web.websocket.WebSocketEvent; @@ -31,4 +32,9 @@ public void onEvent( final WebSocketEvent event ) { this.apiHandlerSupplier.get().onSocketEvent( event ); } + + public EndpointFactory getEndpointFactory() + { + return this.apiHandlerSupplier.get().getEndpointFactory(); + } } diff --git a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/websocket/WebSocketContextImpl.java b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/websocket/WebSocketContextImpl.java index 5e927351cb6..8d8298ee398 100644 --- a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/websocket/WebSocketContextImpl.java +++ b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/websocket/WebSocketContextImpl.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import com.enonic.xp.web.websocket.EndpointFactory; import com.enonic.xp.web.websocket.WebSocketContext; import com.enonic.xp.web.websocket.WebSocketEndpoint; import com.enonic.xp.web.websocket.WebSocketService; @@ -24,10 +25,17 @@ final class WebSocketContextImpl public boolean apply( final WebSocketEndpoint endpoint ) throws IOException { - final EndpointFactoryImpl factory = new EndpointFactoryImpl(); - factory.registry = this.registry; - factory.endpoint = endpoint; - - return this.webSocketService.acceptWebSocket( this.request, this.response, factory ); + if ( endpoint instanceof WebSocketApiEndpointImpl ) + { + EndpointFactory factory = ( (WebSocketApiEndpointImpl) endpoint ).getEndpointFactory(); + return this.webSocketService.acceptWebSocket( this.request, this.response, factory ); + } + else + { + final EndpointFactoryImpl factory = new EndpointFactoryImpl(); + factory.registry = this.registry; + factory.endpoint = endpoint; + return this.webSocketService.acceptWebSocket( this.request, this.response, factory ); + } } }