Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ void setup()
@Test
void testHandle()
{
WebRequest request = mock( WebRequest.class );
when( request.getRawRequest() ).thenReturn( mock( HttpServletRequest.class ) );
when( request.isWebSocket() ).thenReturn( true );
final WebRequest request = new WebRequest();
request.setRawRequest( mock( HttpServletRequest.class ) );
request.setWebSocketContext( mock( com.enonic.xp.web.websocket.WebSocketContext.class ) );

WebResponse response = instance.handle( request );

Expand All @@ -56,9 +56,8 @@ void testHandle()
@Test
void testHandleBadRequest()
{
WebRequest request = mock( WebRequest.class );
when( request.getRawRequest() ).thenReturn( mock( HttpServletRequest.class ) );
when( request.isWebSocket() ).thenReturn( false );
final WebRequest request = new WebRequest();
request.setRawRequest( mock( HttpServletRequest.class ) );

WebResponse response = instance.handle( request );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@
import com.enonic.xp.project.ProjectName;
import com.enonic.xp.project.ProjectService;
import com.enonic.xp.repository.RepositoryId;
import com.enonic.xp.repository.RepositoryUtils;
import com.enonic.xp.security.PrincipalKey;
import com.enonic.xp.security.RoleKeys;
import com.enonic.xp.security.auth.AuthenticationInfo;
import com.enonic.xp.site.Site;
import com.enonic.xp.web.HttpStatus;
import com.enonic.xp.web.WebException;
import com.enonic.xp.web.WebRequest;
import com.enonic.xp.web.WebResponse;
Expand All @@ -48,9 +47,10 @@
public class AdminSiteHandler
extends BasePortalHandler
{
private static final String ADMIN_SITE_PREFIX = "/admin/site/";
public static final String ADMIN_SITE_PREFIX = "/admin/site/";

private static final Pattern BASE_URI_PATTERN = Pattern.compile( "^/admin/site/(edit|preview|admin|inline)" );
private static final Pattern ADMIN_SITE_PATH_PATTERN =
Pattern.compile( "^(?<base>/admin/site/(?<mode>edit|preview|admin|inline))/(?<project>[^/]+)/(?<branch>[^/]+)(?<path>.*)" );

private final ContentService contentService;

Expand Down Expand Up @@ -78,29 +78,45 @@ public void activate( final AdminConfig config )
@Override
protected boolean canHandle( final WebRequest webRequest )
{
return webRequest.getRawPath().startsWith( ADMIN_SITE_PREFIX );
return webRequest.getBasePath().startsWith( ADMIN_SITE_PREFIX );
}

@Override
protected PortalRequest createPortalRequest( final WebRequest webRequest, final WebResponse webResponse )
{
final Matcher matcher = BASE_URI_PATTERN.matcher( webRequest.getRawPath() );
if ( !matcher.find() )
final Matcher matcher = ADMIN_SITE_PATH_PATTERN.matcher( webRequest.getBasePath() );
if ( !matcher.matches() )
{
throw WebException.notFound( "Mode must be specified" );
throw WebException.notFound( "Invalid admin site URL" );
}
final String baseUri = matcher.group( 0 );
final RenderMode mode = RenderMode.from( matcher.group( 1 ) );
final String baseSubPath = webRequest.getRawPath().substring( baseUri.length() + 1 );
final PortalRequest portalRequest = new PortalRequest( webRequest );

final PortalRequest portalRequest = doCreatePortalRequest( webRequest, baseUri, baseSubPath, mode );
final ProjectName projectName;
final Branch branch;
final RenderMode mode;
final ContentPath contentPath;
try
{
mode = RenderMode.from( matcher.group( "mode" ) );
projectName = ProjectName.from( matcher.group( "project" ) );
branch = Branch.from( matcher.group( "branch" ) );
contentPath = ContentPath.from( matcher.group( "path" ) );
}
catch ( IllegalArgumentException e )
{
throw new WebException( HttpStatus.NOT_FOUND, "Invalid admin site URL", e );
}
final RepositoryId repositoryId = projectName.getRepoId();

final Project project = callInContext( portalRequest.getRepositoryId(), portalRequest.getBranch(), RoleKeys.ADMIN,
() -> projectService.get( ProjectName.from( portalRequest.getRepositoryId() ) ) );
portalRequest.setBaseUri( matcher.group( "base" ) );
portalRequest.setRepositoryId( repositoryId );
portalRequest.setBranch( branch );
portalRequest.setMode( mode );
portalRequest.setContentPath( contentPath );

final Project project = callAsContentAdmin( repositoryId, branch, () -> projectService.get( projectName ) );
portalRequest.setProject( project );

final ContentPath contentPath = portalRequest.getContentPath();
if ( contentPath.isRoot() )
{
return portalRequest;
Expand All @@ -110,36 +126,33 @@ protected PortalRequest createPortalRequest( final WebRequest webRequest, final
{
final ContentId contentId = tryConvertToContentId( contentPath.toString() );

final Content contentById = contentId != null ? callAsContentAdmin( portalRequest.getRepositoryId(), portalRequest.getBranch(),
() -> getContentById( contentId ) ) : null;
final Content contentById =
contentId != null ? callAsContentAdmin( repositoryId, branch, () -> getContentById( contentId ) ) : null;

final Content content = contentById != null
? contentById
: callAsContentAdmin( portalRequest.getRepositoryId(), portalRequest.getBranch(),
() -> this.getContentByPath( contentPath ) );
final Content content =
contentById != null ? contentById : callAsContentAdmin( repositoryId, branch, () -> this.getContentByPath( contentPath ) );

if ( content != null && !content.getPath().isRoot() )
{
portalRequest.setContent( content );
portalRequest.setContentPath( content.getPath() );
portalRequest.setSite( content.isSite()
? (Site) content
: callAsContentAdmin( portalRequest.getRepositoryId(), portalRequest.getBranch(),
: callAsContentAdmin( repositoryId, branch,
() -> this.contentService.getNearestSite( content.getId() ) ) );
}
}
else
{
final Content content =
callAsContentAdmin( portalRequest.getRepositoryId(), portalRequest.getBranch(), () -> getContentByPath( contentPath ) );
final Content content = callAsContentAdmin( repositoryId, branch, () -> getContentByPath( contentPath ) );

if ( content != null )
{
portalRequest.setContent( content );
portalRequest.setContentPath( content.getPath() );
portalRequest.setSite( content.isSite()
? (Site) content
: callAsContentAdmin( portalRequest.getRepositoryId(), portalRequest.getBranch(),
: callAsContentAdmin( repositoryId, branch,
() -> this.contentService.findNearestSiteByPath( contentPath ) ) );
}
}
Expand All @@ -155,7 +168,7 @@ protected WebResponse doHandle( final WebRequest webRequest, final WebResponse w

final RenderMode mode = request.getMode();

if ( mode == RenderMode.LIVE || request.getEndpointPath() != null )
if ( mode == RenderMode.LIVE || mode == null || request.getEndpointPath() != null )
{
return response;
}
Expand Down Expand Up @@ -215,106 +228,13 @@ private Content getContentByPath( final ContentPath contentPath )
}
}

private static RepositoryId findRepository( final String baseSubPath )
{
final int index = baseSubPath.indexOf( '/' );
final String result = baseSubPath.substring( 0, index > 0 ? index : baseSubPath.length() );
if ( result.isEmpty() )
{
throw WebException.notFound( "Repository must be specified" );
}

try
{
return toRepositoryId( result );
}
catch ( IllegalArgumentException e )
{
throw WebException.notFound( String.format( "Repository name is invalid [%s]", result ) );
}
}

private static RepositoryId toRepositoryId( String result )
{
final RepositoryId repositoryId = RepositoryUtils.fromContentRepoName( result );
if ( repositoryId == null )
{
throw new IllegalArgumentException();
}
return repositoryId;
}

private static Branch findBranch( final String baseSubPath )
{
final String branchSubPath = findPathAfterRepository( baseSubPath );
final int index = branchSubPath.indexOf( '/' );
final String result = branchSubPath.substring( 0, index > 0 ? index : branchSubPath.length() );
if ( result.isEmpty() )
{
throw WebException.notFound( "Branch must be specified" );
}
try
{
return Branch.from( result );
}
catch ( IllegalArgumentException e )
{
throw WebException.notFound( String.format( "Branch name is invalid [%s]", result ) );
}
}

private static ContentPath findContentPath( final String baseSubPath )
{
final String branchSubPath = findPathAfterBranch( baseSubPath );
final int underscore = branchSubPath.indexOf( "/_/" );
final String result = branchSubPath.substring( 0, underscore > -1 ? underscore : branchSubPath.length() );
return ContentPath.from( result );
}

private static String findPathAfterRepository( final String baseSubPath )
{
final int index = baseSubPath.indexOf( '/' );
return baseSubPath.substring( index > 0 && index < baseSubPath.length() ? index + 1 : baseSubPath.length() );
}

private static String findPathAfterBranch( final String baseSubPath )
{
final String repoSubPath = findPathAfterRepository( baseSubPath );
final int index = repoSubPath.indexOf( '/' );

return index >= 0 ? repoSubPath.substring( index ) : "";
}

protected PortalRequest doCreatePortalRequest( final WebRequest webRequest, final String baseUri, final String baseSubPath,
final RenderMode renderMode )
{
final RepositoryId repositoryId = findRepository( baseSubPath );
final Branch branch = findBranch( baseSubPath );
final ContentPath contentPath = findContentPath( baseSubPath );

final PortalRequest portalRequest = new PortalRequest( webRequest );
portalRequest.setBaseUri( baseUri );
portalRequest.setRepositoryId( repositoryId );
portalRequest.setBranch( branch );
portalRequest.setContentPath( contentPath );
portalRequest.setMode( renderMode );

return portalRequest;
}

private static <T> T callAsContentAdmin( final RepositoryId repositoryId, final Branch branch, final Callable<T> callable )
{
return callInContext( repositoryId, branch, RoleKeys.CONTENT_MANAGER_ADMIN, callable );
}

private static <T> T callInContext( final RepositoryId repositoryId, final Branch branch, final PrincipalKey principalKey,
final Callable<T> callable )
{
final Context context = ContextAccessor.current();
return ContextBuilder.from( context )
.repositoryId( repositoryId )
.branch( branch )
.authInfo( AuthenticationInfo.copyOf( context.getAuthInfo() ).principals( principalKey ).build() )
.authInfo( AuthenticationInfo.copyOf( context.getAuthInfo() ).principals( RoleKeys.CONTENT_MANAGER_ADMIN ).build() )
.build()
.callWith( callable );
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.enonic.xp.admin.impl.portal;

import java.util.regex.Pattern;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

Expand All @@ -25,8 +23,6 @@
public final class AdminToolHandler
extends BaseWebHandler
{
private static final Pattern TOOL_CXT_PATTERN = Pattern.compile( "^/admin/([^/]+)/([^/]+)" );

private AdminToolDescriptorService adminToolDescriptorService;

private ControllerScriptFactory controllerScriptFactory;
Expand All @@ -39,31 +35,29 @@ public AdminToolHandler()
@Override
protected boolean canHandle( final WebRequest webRequest )
{
return !webRequest.getRawPath().startsWith( "/admin/site/" ) &&
( webRequest.getRawPath().equals( AdminToolPortalHandler.ADMIN_TOOL_BASE ) ||
webRequest.getRawPath().startsWith( AdminToolPortalHandler.ADMIN_TOOL_PREFIX ) );
return webRequest instanceof PortalRequest portalRequest &&
( AdminToolPortalHandler.ADMIN_TOOL_BASE.equals( portalRequest.getBaseUri() ) ||
portalRequest.getBaseUri().startsWith( AdminToolPortalHandler.ADMIN_TOOL_PREFIX ) );
}

@Override
protected WebResponse doHandle( final WebRequest webRequest, final WebResponse webResponse, final WebHandlerChain webHandlerChain )
throws Exception
{
final String rawPath = webRequest.getRawPath();
if ( !rawPath.equals( "/admin" ) && !TOOL_CXT_PATTERN.matcher( rawPath ).find() )
WebHandlerHelper.checkAdminLoginRole( webRequest );

final DescriptorKey descriptorKey = AdminToolPortalHandler.getDescriptorKey( webRequest.getBasePath() );
if ( descriptorKey == null )
{
throw WebException.notFound( "Invalid admin tool mount" );
}

WebHandlerHelper.checkAdminAccess( webRequest );

PortalRequest portalRequest = (PortalRequest) webRequest;
portalRequest.setContextPath( portalRequest.getBaseUri() );

final AdminToolHandlerWorker worker = new AdminToolHandlerWorker( portalRequest );
worker.controllerScriptFactory = this.controllerScriptFactory;
worker.adminToolDescriptorService = adminToolDescriptorService;
final DescriptorKey descriptorKey = AdminToolPortalHandler.getDescriptorKey( webRequest.getRawPath() );
worker.descriptorKey = descriptorKey == null ? AdminToolPortalHandler.DEFAULT_DESCRIPTOR_KEY : descriptorKey;
worker.descriptorKey = descriptorKey;

final Trace trace = Tracer.newTrace( "portalRequest" );
if ( trace == null )
Expand Down
Loading