Skip to content

Commit

Permalink
Merge branch 'master' into 24842-remove-lodash-from-core-web
Browse files Browse the repository at this point in the history
  • Loading branch information
zJaaal authored Aug 24, 2024
2 parents fd119cb + 36f72e4 commit d0ab826
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 45 deletions.
2 changes: 1 addition & 1 deletion dotCMS/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<tomcat-dist-folder>dotserver/tomcat-${tomcat.version}</tomcat-dist-folder>
<tomcat-lib-folder>${assembly-directory}/${tomcat-dist-folder}/lib</tomcat-lib-folder>
<tomcat-log4j-lib-folder>${assembly-directory}/${tomcat-dist-folder}/log4j2/lib</tomcat-log4j-lib-folder>
<session-manager-lib-folder>${assembly-directory}/${tomcat-dist-folder}/session-manager/lib</session-manager-lib-folder>
<session-manager-lib-folder>${tomcat-lib-folder}</session-manager-lib-folder>
<tomcat9-overrides>${project.basedir}/src/main/resources/container/tomcat9</tomcat9-overrides>
<exploded-webapp-dir>${assembly-directory}/${tomcat-dist-folder}/webapps/ROOT</exploded-webapp-dir>
<war.output.file>${project.build.directory}/${project.build.finalName}-war.war</war.output.file>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@
import com.liferay.portal.model.User;
import com.liferay.portal.util.WebKeys;
import com.liferay.util.LocaleUtil;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
Expand All @@ -34,6 +44,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
Expand All @@ -52,8 +63,15 @@
* @version 3.7
* @since Jul 7, 2016
*/


@SuppressWarnings("serial")
@Path("/v1/authentication")
@Tag(name = "Authentication",
description = "Endpoints that perform operations related to user authentication",
externalDocs = @ExternalDocumentation(description = "Additional Authentication API information",
url = "https://www.dotcms.com/docs/latest/rest-api-authentication"))

public class AuthenticationResource implements Serializable {

static final String USER = "user";
Expand Down Expand Up @@ -90,8 +108,37 @@ protected AuthenticationResource(final LoginServiceAPI loginService,
@JSONP
@NoCache
@Produces({MediaType.APPLICATION_JSON, "application/javascript"})
public final Response authentication(@Context final HttpServletRequest request,
@Consumes({MediaType.APPLICATION_JSON})
@Operation(operationId = "postAuthentication",
summary = "Verifies user or application authentication",
description = "Takes a user's login ID and password and checks them against the user rolls.\n\n" +
"If the user is found and authenticated, a session is created.\n\n" +
"Otherwise the system will return an 'authentication failed' message.\n\n",
tags = {"Authentication"},
responses = {
@ApiResponse(responseCode = "200", description = "User authentication successful",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = ResponseEntityUserMapView.class))),
@ApiResponse(responseCode = "401", description = "User not authenticated"),
@ApiResponse(responseCode = "403", description = "Forbidden request"),
@ApiResponse(responseCode = "500", description = "Unexpected error")
}
)
public final Response authentication(
@Context final HttpServletRequest request,
@Context final HttpServletResponse response,
@RequestBody(description = "This method takes a user's credentials and language preferences to authenticate them.\n\n" +
"Requires a POST body consisting of a JSON object containing the following properties:\n\n" +
"| **Property** | **Value** | **Description** |\n" +
"|--------------|-----------|-----------------------------------------------|\n" +
"| `userId` | String | **Required.** ID of user attempting to log in |\n" +
"| `password` | String | User password |\n" +
"| `language` | String | Preferred language for user |\n" +
"| `country` | String | Country where user is located |\n",
required = true,
content = @Content(
schema = @Schema(implementation = AuthenticationForm.class)
))
final AuthenticationForm authenticationForm) {

Response res = null;
Expand Down Expand Up @@ -168,6 +215,20 @@ public final Response authentication(@Context final HttpServletRequest request,
@JSONP
@NoCache
@Produces({MediaType.APPLICATION_JSON, "application/javascript"})
@Operation(operationId = "getLogInUser",
summary = "Retrieves user data",
description = "Provides information about any users that are currently in a session.\n\n" +
"This retrieved data will be formatted into a JSON response body.\n\n",
tags = {"Authentication"},
responses = {
@ApiResponse(responseCode = "200", description = "User data successfully collected",
content = @Content(
schema = @Schema(implementation = ResponseEntityUserView.class)
)),
@ApiResponse(responseCode = "400", description = "Bad request"),
@ApiResponse(responseCode = "401", description = "Unauthorized request"),
@ApiResponse(responseCode = "404", description = "User not found")
})
@Path("logInUser")
public final Response getLoginUser(@Context final HttpServletRequest request){
Response res = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@
import com.liferay.portal.model.User;
import com.liferay.portal.util.PortalUtil;
import com.liferay.util.LocaleUtil;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import org.elasticsearch.common.collect.Map;
import org.glassfish.jersey.server.JSONP;

Expand Down Expand Up @@ -98,6 +109,8 @@ protected CreateJsonWebTokenResource(final LoginServiceAPI loginService,
@JSONP
@NoCache
@Produces({MediaType.APPLICATION_JSON, "application/javascript"})
@Deprecated
@Hidden //not shown in API playground
public final Response getApiToken(@Context final HttpServletRequest request,
@Context final HttpServletResponse response,
final CreateTokenForm createTokenForm) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dotcms.rest.api.v1.authentication;

import com.dotcms.rest.ResponseEntityView;

public class ResponseEntityUserMapView extends ResponseEntityView<AuthenticationForm> {
public ResponseEntityUserMapView(AuthenticationForm entity) {
super(entity);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dotcms.rest.api.v1.authentication;

import com.dotcms.rest.ResponseEntityView;

public class ResponseEntityUserView extends ResponseEntityView<AuthenticationForm> {
public ResponseEntityUserView(AuthenticationForm entity) {
super(entity);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.dotcms.variant.business.web.VariantWebAPI.RenderContext;
import java.io.IOException;
import java.util.Objects;
import java.util.Optional;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -521,9 +522,11 @@ protected final String inodePath(final Contentlet contentlet,
final String inode = live ? contentletVersionInfo.get().getLiveInode()
: contentletVersionInfo.get().getWorkingInode();

final Contentlet imageContentlet = APILocator.getContentletAPI()
final Contentlet imageContentlet = APILocator.getContentletAPI()
.find(inode, APILocator.systemUser(), false);

validateContentlet(imageContentlet, live, inode);

final String fieldVar = imageContentlet.isDotAsset() ?
DotAssetContentType.ASSET_FIELD_VAR : FILE_ASSET_DEFAULT;

Expand All @@ -536,6 +539,12 @@ protected final String inodePath(final Contentlet contentlet,
.append(StringPool.FORWARD_SLASH).append(field.variable()).toString();
}

private void validateContentlet(final Contentlet contentlet, final boolean live, final String inode) throws DotDataException {
if (Objects.isNull(contentlet)) {
final String versionType = live ? PageMode.LIVE.name() : PageMode.WORKING.name();
throw new DotDataException(String.format("No contentlet found for %s inode %s", versionType, inode));
}
}

protected final Optional<Field> resolveField(final Contentlet contentlet, final String tryField) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,6 @@ public String computeURL(HttpServletRequest request,
!desiredPort.equals(usingPort))
{
url.insert(0, startNewUrlString(request, desiredScheme, desiredPort));

// This is a hack to help us overcome the problem that some
// older browsers do not share sessions between http & https
// If this feature is diabled, session ID could still be added
// the previous call to the RequestUtils.computeURL() method,
// but only if needed due to cookies disabled, etc.
if (securePlugin.getSslExtAddSession() && url.toString().indexOf(";jsessionid=") < 0)
{
// Add the session identifier
url = new StringBuilder(toEncoded(url.toString(),
request.getSession().getId()));
}
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions dotCMS/src/main/resources/container/tomcat9/bin/setenv.bat
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ set "CATALINA_OPTS=%CATALINA_OPTS% -Dorg.apache.tomcat.util.digester.PROPERTY_SO
rem Check if log4j2.configurationFile is already set
echo %CATALINA_OPTS% | findstr /C:"-Dlog4j2.configurationFile" >nul
if %errorlevel% neq 0 (
echo Setting log4j2.configurationFile=%TOMCAT_HOME%\webapps\ROOT\WEB-INF\log4j\log4j2.xml
set "CATALINA_OPTS=%CATALINA_OPTS% -Dlog4j2.configurationFile=%TOMCAT_HOME%\webapps\ROOT\WEB-INF\log4j\log4j2.xml"
echo Setting log4j2.configurationFile=%CATALINA_HOME%\webapps\ROOT\WEB-INF\log4j\log4j2.xml
set "CATALINA_OPTS=%CATALINA_OPTS% -Dlog4j2.configurationFile=%CATALINA_HOME%\webapps\ROOT\WEB-INF\log4j\log4j2.xml"
) else (
echo Log4j configuration already set
)
Expand All @@ -49,7 +49,7 @@ if %errorlevel% neq 0 (
)

rem Set the CLASSPATH
set "ADDITIONAL_CLASSPATH=%CATALINA_HOME%\log4j2\lib\*;%CATALINA_HOME%\session-manager\lib\*"
set "ADDITIONAL_CLASSPATH=%CATALINA_HOME%\log4j2\lib\*"
if "%CLASSPATH%" neq "" (
set "CLASSPATH=%CLASSPATH%;%ADDITIONAL_CLASSPATH%"
) else (
Expand Down
6 changes: 3 additions & 3 deletions dotCMS/src/main/resources/container/tomcat9/bin/setenv.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export CATALINA_OPTS="$CATALINA_OPTS -Dorg.apache.tomcat.util.digester.PROPERTY_
if echo "$CATALINA_OPTS" | grep -q '\-Dlog4j2\.configurationFile'; then
echo "Log4j configuration already set"
else
echo "Setting log4j2.configurationFile=$TOMCAT_HOME/webapps/ROOT/WEB-INF/log4j/log4j2.xml"
export CATALINA_OPTS="$CATALINA_OPTS -Dlog4j2.configurationFile=$TOMCAT_HOME/webapps/ROOT/WEB-INF/log4j/log4j2.xml"
echo "Setting log4j2.configurationFile=$CATALINA_HOME/webapps/ROOT/WEB-INF/log4j/log4j2.xml"
export CATALINA_OPTS="$CATALINA_OPTS -Dlog4j2.configurationFile=$CATALINA_HOME/webapps/ROOT/WEB-INF/log4j/log4j2.xml"
fi

if echo "$CATALINA_OPTS" | grep -q '\-DLog4jContextSelector'; then
Expand All @@ -45,7 +45,7 @@ else
export CATALINA_OPTS="$CATALINA_OPTS -DLog4jContextSelector=org.apache.logging.log4j.core.async.BasicAsyncLoggerContextSelector"
fi

ADDITIONAL_CLASSPATH="$CATALINA_HOME/log4j2/lib/*:$CATALINA_HOME/session-manager/lib/*"
ADDITIONAL_CLASSPATH="$CATALINA_HOME/log4j2/lib/*"

if [ -n "$CLASSPATH" ]; then
CLASSPATH="$CLASSPATH:$ADDITIONAL_CLASSPATH"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,13 +406,11 @@ public String getGravatar(String postedBy){
x++;
%>
<tr <%=str_style %>>
<td>
<img border="0" src="/html/images/icons/<%= UtilMethods.getFileExtension(file.getFileName()).toLowerCase() %>.png"> &nbsp;
<a href="<%= file.getURI() %>" target="_blank">
<%= file.getFileName() %>
</a>

<%= file.getFileName() %>

</td>
<td>
<td>
<button dojoType="dijit.form.Button" type="button" class="dijitButtonDanger" style="float: right;" onClick="removeFile('<%= file.getInode() %>')"><%= LanguageUtil.get(pageContext, "remove") %></button>
</td>
</tr>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.dotcms.api;

import static org.testcontainers.shaded.org.awaitility.Awaitility.await;

import com.dotcms.DotCMSITProfile;
import com.dotcms.api.client.model.RestClientFactory;
import com.dotcms.api.client.model.ServiceManager;
Expand Down Expand Up @@ -34,13 +36,15 @@
import io.quarkus.test.junit.TestProfile;
import jakarta.inject.Inject;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.WebApplicationException;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -237,35 +241,34 @@ void Test_Create_Then_Update_Then_Delete_Content_Type() {
ContentType newContentType = contentTypes.get(0);
Assertions.assertNotNull(newContentType.id());
Assertions.assertEquals("_var_"+identifier, newContentType.variable());
//We make sure the CT exists because the following line does not throw 404

// We make sure the CT exists because the following line does not throw 404
client.getContentType(newContentType.variable(), 1L, true);
//Now lets test update

// Now lets test update
final ImmutableSimpleContentType updatedContentType = ImmutableSimpleContentType.builder().from(newContentType).description("Updated").build();
final SaveContentTypeRequest request = SaveContentTypeRequest.builder().
from(updatedContentType).build();
final ResponseEntityView<ContentType> responseEntityView = client.updateContentType(
request.variable(), request);
Assertions.assertEquals("Updated", responseEntityView.entity().description());
//And finally test delete

// And finally test delete
final ResponseEntityView<String> responseStringEntity = client.delete(updatedContentType.variable());
Assertions.assertTrue(responseStringEntity.entity().contains("deleted"));

try {
//a small wait to make sure the CT is deleted
//a simple Thread.sleep would do the trick but Sonar says it's not a good practice
int count = 0;
while (null != client.getContentType(updatedContentType.variable(), 1L, true)){
//We wait for the CT to be deleted
System.out.println("Waiting for CT to be deleted");
count++;
if(count > 10){
Assertions.fail("CT was not deleted");
}
// Use Awaitility to wait until the ContentType is actually deleted
await().atMost(20, TimeUnit.SECONDS).until(() -> {
try {
client.getContentType(updatedContentType.variable(), 1L, true);
return false; // If this succeeds, the ContentType still exists
} catch (WebApplicationException e) {
if (e.getResponse().getStatus() == 404) {
return true; // ContentType was successfully deleted
}
throw e; // Rethrow any unexpected exceptions
}
//This should throw 404 but under certain circumstances it does throw 400
}catch(jakarta.ws.rs.WebApplicationException e){
// Not relevant here
}
});
}

/**
Expand Down

0 comments on commit d0ab826

Please sign in to comment.