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
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
<Bundle-DocURL>https://www.dotcms.com/</Bundle-DocURL>
<Bundle-Activator>com.dotcms.userproxy.osgi.Activator</Bundle-Activator>
<Bundle-ClassPath>.,{maven-dependencies}</Bundle-ClassPath>
<Import-Package>*</Import-Package>
<Import-Package>*;version="0.0.0"</Import-Package>
<_nouses>true</_nouses>
<Export-Package>com.dotcms.userproxy</Export-Package>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Embed-Directory>lib</Embed-Directory>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package com.dotcms.userproxy.interceptor;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
Expand All @@ -21,11 +17,11 @@
import com.dotmarketing.beans.Host;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.business.web.WebAPILocator;
import com.dotmarketing.util.Logger;
import com.liferay.portal.model.User;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portal.util.WebKeys;

import io.vavr.Lazy;
import io.vavr.control.Try;

/**
Expand All @@ -35,14 +31,7 @@
*/
public class UserProxyInterceptor implements WebInterceptor {

private static final ConcurrentHashMap<String, List<UserProxyEntry>> lazyUserProxyMap = new ConcurrentHashMap<>();

public UserProxyInterceptor() {
resetLazyUserProxyMap();
}

public static void resetLazyUserProxyMap() {
lazyUserProxyMap.clear();
}

@Override
Expand All @@ -54,32 +43,64 @@ public String[] getFilters() {
public Result intercept(final HttpServletRequest request, final HttpServletResponse response) {

if (hasExistingAuth(request)) {
Logger.debug(this, () -> "UserProxy skip: request already has auth. method="
+ request.getMethod() + " uri=" + request.getRequestURI());
return Result.NEXT;
}

Host host = WebAPILocator.getHostWebAPI().getCurrentHostNoThrow(request);
if (host == null) {
Logger.warn(this, "UserProxy could not resolve current host. method="
+ request.getMethod() + " uri=" + request.getRequestURI());
return Result.NEXT;
}

List<UserProxyEntry> entries = lazyUserProxyMap.computeIfAbsent(host.getIdentifier(),
h -> UserProxyEntryMapper.buildListForHost(h));
List<UserProxyEntry> entries = UserProxyEntryMapper.buildListForHost(host.getIdentifier());

Logger.info(this, "UserProxy intercept: method=" + request.getMethod()
+ " uri=" + request.getRequestURI()
+ " remoteAddr=" + request.getRemoteAddr()
+ " hostId=" + host.getIdentifier()
+ " entries=" + entries.size());

if (entries.isEmpty()) {
Logger.warn(this, "UserProxy found no entries for hostId=" + host.getIdentifier()
+ " uri=" + request.getRequestURI());
return Result.NEXT;
}

// break on first match
for (UserProxyEntry entry : entries) {
if (entry.matches(request)) {
Logger.info(this, "UserProxy matched entry for method=" + request.getMethod()
+ " uri=" + request.getRequestURI()
+ " allowedMethods=" + entry.getMethods()
+ " patterns=" + Arrays.toString(entry.getUrls()));

final Optional<JWToken> token = APILocator.getApiTokenAPI()
.fromJwt(new String(entry.getUserToken()),
request.getRemoteAddr());

Logger.info(this, "UserProxy token lookup result for uri="
+ request.getRequestURI() + ": tokenPresent=" + token.isPresent());

User user = Try.of(() -> token.get().getActiveUser().get()).getOrNull();

if (user != null) {
Logger.info(this, "UserProxy authenticated userId=" + user.getUserId()
+ " for uri=" + request.getRequestURI());
request.setAttribute(WebKeys.USER, user);
request.setAttribute(WebKeys.USER_ID, user.getUserId());
break;
}

Logger.warn(this, "UserProxy match did not resolve an active user for uri="
+ request.getRequestURI() + " remoteAddr=" + request.getRemoteAddr());
} else {
Logger.debug(this, () -> "UserProxy entry did not match. method="
+ request.getMethod() + " uri=" + request.getRequestURI()
+ " allowedMethods=" + entry.getMethods()
+ " patterns=" + Arrays.toString(entry.getUrls()));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package com.dotcms.userproxy.listener;

import com.dotcms.api.system.event.message.MessageSeverity;
import com.dotcms.api.system.event.message.SystemMessageEventUtil;
import com.dotcms.api.system.event.message.builder.SystemMessageBuilder;
import com.dotcms.security.apps.AppSecretSavedEvent;

import com.dotcms.system.event.local.model.EventSubscriber;
import com.dotcms.system.event.local.model.KeyFilterable;
import com.dotcms.userproxy.interceptor.UserProxyInterceptor;
import com.dotcms.userproxy.model.UserProxyEntry;
import com.dotcms.userproxy.model.UserProxyEntryMapper;
import com.dotcms.userproxy.util.AppKey;
Expand Down Expand Up @@ -44,8 +40,7 @@ public void notify(final AppSecretSavedEvent event) {
Logger.info(this, "Missing event, aborting");
return;
}
Logger.info(this, "UserProxyAppListener updated, clearing UserProxy map");
UserProxyInterceptor.resetLazyUserProxyMap();
Logger.info(this, "UserProxyAppListener received AppSecretSavedEvent");

String jsonConfig = event.getAppSecrets().getSecrets().get(AppKey.APP_CONFIG_KEY.appValue).getString();

Expand All @@ -61,25 +56,9 @@ public void notify(final AppSecretSavedEvent event) {
return;
}
List<UserProxyEntry> entries = UserProxyEntryMapper.parseJsonToEntries(jsonConfig);
if (!entries.isEmpty()) {
return;
if (entries.isEmpty()) {
Logger.warn(this, "No valid User Proxy configuration found for users: " + users);
}
final SystemMessageBuilder systemMessageBuilder = new SystemMessageBuilder();
String velocityMessage = "No valid User Proxy configuration found.";

MessageSeverity severity = (false)
? MessageSeverity.INFO
: MessageSeverity.ERROR;

systemMessageBuilder.setMessage(velocityMessage)
.setLife(7 * 1000)
.setSeverity(severity).create();

SystemMessageEventUtil.getInstance().pushMessage(systemMessageBuilder.create(), users);







Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/dotcms/userproxy/osgi/Activator.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public void start(final org.osgi.framework.BundleContext context) throws IOExcep

// Adding APP yaml
Logger.info(Activator.class.getName(), "Copying UserProxy APP");
new FileMoverUtil().copyAppYml();
new FileMoverUtil().copyAppYml(context);


// set up app listener
Expand Down
27 changes: 16 additions & 11 deletions src/main/java/com/dotcms/userproxy/osgi/FileMoverUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@
import com.dotmarketing.util.ConfigUtils;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.UtilMethods;
import common.Assert;
import io.vavr.control.Try;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.apache.commons.io.IOUtils;
import org.osgi.framework.BundleContext;

public class FileMoverUtil {

Expand All @@ -40,7 +40,7 @@ public class FileMoverUtil {

};

public static List<JarEntry> listFilesInPackage(@Nonnull String packagePathStr) {
public static List<JarEntry> listFilesInPackage(String packagePathStr) {

String packagePath = stripPackagePath(packagePathStr);
List<JarEntry> jarEntries = new ArrayList<>();
Expand All @@ -66,7 +66,7 @@ public static List<JarEntry> listFilesInPackage(@Nonnull String packagePathStr)
return jarEntries;
}

public static Map<String, String> loadGQLQueryMap(@Nonnull String packagePathStr) {
public static Map<String, String> loadGQLQueryMap(String packagePathStr) {

return Map.of();
}
Expand All @@ -78,7 +78,7 @@ public static Map<String, String> loadGQLQueryMap(@Nonnull String packagePathStr
*
* @param packagePathInJar - the directory path in the jar to copy
*/
void copyFromJar(@Nonnull String packagePathInJar) {
void copyFromJar(String packagePathInJar) {
this.copyFromJar(packagePathInJar,
Try.of(() -> APILocator.getHostAPI().findDefaultHost(APILocator.systemUser(), false))
.getOrElseThrow(DotRuntimeException::new));
Expand All @@ -102,7 +102,7 @@ static String stripPackagePath(String packagePathInJar) {
* @param packagePathInJar - the directory path in the jar to copy
* @param site - the site to copy to
*/
void copyFromJar(@Nonnull String packagePathInJar, @Nonnull Host site) {
void copyFromJar(String packagePathInJar, Host site) {

String strippedPackagePath = stripPackagePath(packagePathInJar);

Expand Down Expand Up @@ -173,8 +173,9 @@ void copyFromJar(@Nonnull String packagePathInJar, @Nonnull Host site) {
dotfile.setProperty(Contentlet.DISABLE_WORKFLOW, true);

APILocator.getContentletAPI().publish(dotfile, APILocator.systemUser(), false);
Assert.verify(dotfile != null && dotfile.getIdentifier() != null,
"Unable to create file asset: " + fileName);
if (dotfile == null || dotfile.getIdentifier() == null) {
throw new DotRuntimeException("Unable to create file asset: " + fileName);
}
tmpFile.delete();
tmpDir.delete();

Expand All @@ -191,11 +192,15 @@ void copyFromJar(@Nonnull String packagePathInJar, @Nonnull Host site) {
*
* @throws IOException
*/
public void copyAppYml() throws IOException {
public void copyAppYml(BundleContext context) throws IOException {

Logger.info(this.getClass().getName(), "copying YAML File:" + installedAppYaml);
try (final InputStream in = this.getClass()
.getResourceAsStream("/" + AppKey.USER_PROXY_APP_VALUE.appValue + ".yml")) {
final String entryName = AppKey.USER_PROXY_APP_VALUE.appValue + ".yml";
final URL entry = context.getBundle().getEntry("/" + entryName);
if (entry == null) {
throw new IOException("Bundle entry not found: /" + entryName);
}
try (final InputStream in = entry.openStream()) {
IOUtils.copy(in, Files.newOutputStream(installedAppYaml.toPath()));
}
CacheLocator.getAppsCache().clearCache();
Expand Down