From 3b1dbcb5af111068f0bdfaa71d01d38fd5d7de40 Mon Sep 17 00:00:00 2001 From: Penghai Date: Tue, 18 Feb 2020 15:34:41 +1100 Subject: [PATCH 1/9] Update version to 2019.1.4 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4ecc915fa8..5920c5d56b 100644 --- a/build.sbt +++ b/build.sbt @@ -113,7 +113,7 @@ name := "Equella" equellaMajor in ThisBuild := 2019 equellaMinor in ThisBuild := 1 -equellaPatch in ThisBuild := 3 +equellaPatch in ThisBuild := 4 equellaStream in ThisBuild := "Stable" equellaBuild in ThisBuild := buildConfig.value.getString("build.buildname") From 95889ff0d9cfadb4756fdbe3fbdd26235a7dcab2 Mon Sep 17 00:00:00 2001 From: PenghaiZhang <47203811+PenghaiZhang@users.noreply.github.com> Date: Thu, 9 Jan 2020 13:30:46 +1100 Subject: [PATCH 2/9] Enable Cloud Provider Proxy to handle Delete requests * Add a REST endpoint in oEQ to handle Cloud Provider Proxy Delete requests * Add a REST endpoint in IntegTester to respond to Delete requests PR #1405 --- .../com/tle/web/api/wizard/WizardApi.scala | 10 ++++++++++ autotest/IntegTester/ps/www/control.tsx | 14 ++++++++++++++ .../testprovider/TestingCloudProvider.scala | 2 ++ 3 files changed, 26 insertions(+) diff --git a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala index af2af88cd0..5ce1c9f316 100644 --- a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala +++ b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala @@ -211,6 +211,16 @@ class WizardApi { .streamBody(streamedBody) } } + + @DELETE + @Path("provider/{providerId}/{serviceId}") + def proxyDELETE(@PathParam("wizid") wizid: String, + @PathParam("providerId") providerId: UUID, + @PathParam("serviceId") serviceId: String, + @Context uriInfo: UriInfo, + @Context req: HttpServletRequest): Response = { + proxyRequest(wizid, req, providerId, serviceId, uriInfo)(sttp.delete) + } } class SimpleWorkflowOperation extends WorkflowOperation { diff --git a/autotest/IntegTester/ps/www/control.tsx b/autotest/IntegTester/ps/www/control.tsx index dc76171b5e..63943a8660 100644 --- a/autotest/IntegTester/ps/www/control.tsx +++ b/autotest/IntegTester/ps/www/control.tsx @@ -182,6 +182,20 @@ function TestControl(p: ControlApi) { > Execute + + ); diff --git a/autotest/IntegTester/src/main/scala/integtester/testprovider/TestingCloudProvider.scala b/autotest/IntegTester/src/main/scala/integtester/testprovider/TestingCloudProvider.scala index e33aebef1d..34a0fcb4ac 100644 --- a/autotest/IntegTester/src/main/scala/integtester/testprovider/TestingCloudProvider.scala +++ b/autotest/IntegTester/src/main/scala/integtester/testprovider/TestingCloudProvider.scala @@ -135,6 +135,8 @@ class TestingCloudProvider(implicit val cs: ContextShift[IO]) extends Http4sDsl[ case authReq @ GET -> Root / "myService" as user => val req = authReq.req Ok(ServiceResponse(user, "", req.queryString).asJson) + case authReq @ DELETE -> Root / "myService" as user => + Ok(ServiceResponse(user, "", authReq.req.queryString).asJson) } val oauthService = publicServices <+> middleware(protectedService) From 6ad8ee956cde748e195971c80c6b1c6d2406c15c Mon Sep 17 00:00:00 2001 From: PenghaiZhang <47203811+PenghaiZhang@users.noreply.github.com> Date: Wed, 15 Jan 2020 08:43:30 +1100 Subject: [PATCH 3/9] Support Cloud Provider Proxy PUT requests * Make sure headers are correctly sent to Cloud Provider services PR #1419 --- .../com/tle/web/api/wizard/WizardApi.scala | 53 ++++++++++-- autotest/IntegTester/ps/www/control.tsx | 86 ++++++++++--------- .../testprovider/TestingCloudProvider.scala | 31 +++++-- 3 files changed, 121 insertions(+), 49 deletions(-) diff --git a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala index 5ce1c9f316..a19ea25440 100644 --- a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala +++ b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala @@ -184,6 +184,30 @@ class WizardApi { } + private def getStreamedBody(content: InputStream): Stream[IO, ByteBuffer] = { + readInputStream(IO(content), 4096, Implicits.global).chunks.map(_.toByteBuffer) + } + + private def getRequestHeaders(req: HttpServletRequest): Map[String, String] = { + val headers = (for { + headerName <- req.getHeaderNames.asScala + } yield (headerName, req.getHeader(headerName))).toMap + + val filterCookies = { + val filterList = List("JSESSIONID") + val cookies = + req.getCookies.filter(cookie => filterList.exists(!_.startsWith(cookie.getName))) + // Generate a string which include cookie pairs separated by a semi-colon + cookies.map(cookie => s"${cookie.getName}=${cookie.getValue}").mkString(";") + } + // If have cookies apart from those unneeded then reset cookie in the header; otherwise remove cookie from the header. + if (!filterCookies.isEmpty) { + headers + ("cookie" -> filterCookies) + } else { + headers - "cookie" + } + } + @NoCache @GET @Path("provider/{providerId}/{serviceId}") @@ -192,7 +216,9 @@ class WizardApi { @PathParam("serviceId") serviceId: String, @Context uriInfo: UriInfo, @Context req: HttpServletRequest): Response = { - proxyRequest(wizid, req, providerId, serviceId, uriInfo)(sttp.get) + proxyRequest(wizid, req, providerId, serviceId, uriInfo) { uri => + sttp.get(uri).headers(getRequestHeaders(req)) + } } @POST @@ -203,12 +229,27 @@ class WizardApi { @Context uriInfo: UriInfo, @Context req: HttpServletRequest, content: InputStream): Response = { - val streamedBody = - readInputStream(IO(content), 4096, Implicits.global).chunks.map(_.toByteBuffer) proxyRequest(wizid, req, providerId, serviceId, uriInfo) { uri => sttp .post(uri) - .streamBody(streamedBody) + .headers(getRequestHeaders(req)) + .streamBody(getStreamedBody(content)) + } + } + + @PUT + @Path("provider/{providerId}/{serviceId}") + def proxyPUT(@PathParam("wizid") wizid: String, + @PathParam("providerId") providerId: UUID, + @PathParam("serviceId") serviceId: String, + @Context uriInfo: UriInfo, + @Context req: HttpServletRequest, + content: InputStream): Response = { + proxyRequest(wizid, req, providerId, serviceId, uriInfo) { uri => + sttp + .put(uri) + .headers(getRequestHeaders(req)) + .streamBody(getStreamedBody(content)) } } @@ -219,7 +260,9 @@ class WizardApi { @PathParam("serviceId") serviceId: String, @Context uriInfo: UriInfo, @Context req: HttpServletRequest): Response = { - proxyRequest(wizid, req, providerId, serviceId, uriInfo)(sttp.delete) + proxyRequest(wizid, req, providerId, serviceId, uriInfo) { uri => + sttp.delete(uri).headers(getRequestHeaders(req)) + } } } diff --git a/autotest/IntegTester/ps/www/control.tsx b/autotest/IntegTester/ps/www/control.tsx index 63943a8660..6452b3fb2e 100644 --- a/autotest/IntegTester/ps/www/control.tsx +++ b/autotest/IntegTester/ps/www/control.tsx @@ -1,6 +1,6 @@ import * as ReactDOM from "react-dom"; import * as React from "react"; -import axios from "axios"; +import axios, { AxiosResponse } from "axios"; import { ControlApi, @@ -93,6 +93,28 @@ function TestControl(p: ControlApi) { [failValidation, required] ); + interface TestingButtonProps { + buttonName: string; + onClick: () => Promise>; + } + const TestingButton = TestingButtonProps => ( + + ); + + const requestUrl = (query: String = queryString) => { + return p.providerUrl(serviceId) + "?" + query; + }; + React.useEffect(() => { p.registerValidator(validator); return () => p.deregisterValidator(validator); @@ -135,14 +157,6 @@ function TestControl(p: ControlApi) { onChange={e => setQueryString(e.target.value)} /> -
- POST Request?{" "} - setPostRequest(e.target.checked)} - /> -
{postRequest && (
Payload: @@ -165,37 +179,31 @@ function TestControl(p: ControlApi) { />
)} - - + axios.get(requestUrl())} /> + + + axios.post(requestUrl(), { + data: serviceContent + }) + } + /> + + axios.delete(requestUrl("param1=test_param_one"))} + /> + + + axios.put(requestUrl(), { + data: serviceContent + }) + } + /> ); diff --git a/autotest/IntegTester/src/main/scala/integtester/testprovider/TestingCloudProvider.scala b/autotest/IntegTester/src/main/scala/integtester/testprovider/TestingCloudProvider.scala index 34a0fcb4ac..6a15c7dbcd 100644 --- a/autotest/IntegTester/src/main/scala/integtester/testprovider/TestingCloudProvider.scala +++ b/autotest/IntegTester/src/main/scala/integtester/testprovider/TestingCloudProvider.scala @@ -11,6 +11,7 @@ import org.http4s._ import org.http4s.circe._ import org.http4s.dsl.Http4sDsl import org.http4s.server.AuthMiddleware +import org.http4s.util.CaseInsensitiveString import scalaoauth2.provider._ import scala.collection.JavaConverters._ @@ -127,16 +128,36 @@ class TestingCloudProvider(implicit val cs: ContextShift[IO]) extends Http4sDsl[ case req @ POST -> Root / "itemNotification" as user => System.err.println(req.req.queryString) Ok() + case authReq @ POST -> Root / "myService" as user => - val req = authReq.req + createResponse(true, authReq.req, user) + + case authReq @ PUT -> Root / "myService" as user => + createResponse(true, authReq.req, user) + + case authReq @ GET -> Root / "myService" as user => + createResponse(false, authReq.req, user) + + case authReq @ DELETE -> Root / "myService" as user => + createResponse(false, authReq.req, user) + } + def createResponse(decode: Boolean, req: Request[IO], user: TestUser): IO[Response[IO]] = { + val cookies = req.headers.get(CaseInsensitiveString("cookie")) + + // If header includes cookies then check if JSESSIONID exists; if yes then respond with a bad request. + if (cookies.isDefined) { + val jSessionId = cookies.get.value.split(";").exists(value => value.startsWith("JSESSIONID")) + if (jSessionId) { + return BadRequest("The unexpected cookie name (JSESSIONID) was found.") + } + } + if (decode) { req.decode[String] { serviceData => Ok(ServiceResponse(user, serviceData, req.queryString).asJson) } - case authReq @ GET -> Root / "myService" as user => - val req = authReq.req + } else { Ok(ServiceResponse(user, "", req.queryString).asJson) - case authReq @ DELETE -> Root / "myService" as user => - Ok(ServiceResponse(user, "", authReq.req.queryString).asJson) + } } val oauthService = publicServices <+> middleware(protectedService) From 4c195dae42cec76c77f1ef3467bd284cdcf9888c Mon Sep 17 00:00:00 2001 From: PenghaiZhang <47203811+PenghaiZhang@users.noreply.github.com> Date: Thu, 6 Feb 2020 12:36:59 +1100 Subject: [PATCH 4/9] Don't copy host from Headers for Cloud Provider requests PR #1467 --- .../core/cloudproviders/CloudProviderService.scala | 12 ++++++++++-- .../scalasrc/com/tle/web/api/wizard/WizardApi.scala | 11 +++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/core/cloudproviders/CloudProviderService.scala b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/core/cloudproviders/CloudProviderService.scala index 8986705b86..c0f5998e32 100644 --- a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/core/cloudproviders/CloudProviderService.scala +++ b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/core/cloudproviders/CloudProviderService.scala @@ -36,6 +36,7 @@ import com.tle.core.db._ import com.tle.core.httpclient._ import com.tle.core.oauthclient.OAuthClientService import fs2.Stream +import org.apache.commons.lang.RandomStringUtils import org.slf4j.LoggerFactory import scala.collection.JavaConverters._ @@ -87,7 +88,10 @@ object CloudProviderService { IO.fromEither( UriTemplateService.replaceVariables(serviceUri.url, provider.baseUrl, cparams ++ params)) } - req = f(uri) + req = f(uri) + requestContext = "[" + RandomStringUtils.randomAlphanumeric(6) + "] provider: " + provider.id + ", vendor: " + provider.vendorId + _ = Logger.debug( + requestContext + ", method: " + req.method.m + ", request: " + uri.toString.split('?')(0)) auth = provider.providerAuth response <- if (serviceUri.authenticated) { dbLiftIO.liftIO(tokenUrlForProvider(provider)).flatMap { oauthUrl => @@ -95,7 +99,11 @@ object CloudProviderService { .authorizedRequest(oauthUrl.toString, auth.clientId, auth.clientSecret, req) } } else dbLiftIO.liftIO(req.send()) - } yield response + + } yield { + Logger.debug(requestContext + ", response status: " + response.code) + response + } case class ControlListCacheValue( expiry: Instant, diff --git a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala index a19ea25440..454f1124fd 100644 --- a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala +++ b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/wizard/WizardApi.scala @@ -201,11 +201,14 @@ class WizardApi { cookies.map(cookie => s"${cookie.getName}=${cookie.getValue}").mkString(";") } // If have cookies apart from those unneeded then reset cookie in the header; otherwise remove cookie from the header. - if (!filterCookies.isEmpty) { - headers + ("cookie" -> filterCookies) - } else { - headers - "cookie" + val filterHeaders = { + if (!filterCookies.isEmpty) { + headers + ("cookie" -> filterCookies) + } else { + headers - "cookie" + } } + filterHeaders - "host" } @NoCache From 2707321908824eeef379301c3ceb6e91d972cb66 Mon Sep 17 00:00:00 2001 From: Jolse Maginnis Date: Wed, 17 Jul 2019 10:03:58 +1000 Subject: [PATCH 5/9] #1116 Treat logon.do as an external redirect --- .../com/tle/web/api/LegacyContentApi.scala | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala index d2eadd35f7..7d34f54083 100644 --- a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala +++ b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala @@ -104,6 +104,15 @@ object LegacyContentController extends AbstractSectionsController with SectionFi import LegacyGuice.urlService + def isClientPath(relUrl: RelativeUrl): Boolean = relUrl.path.parts match { + case Vector("logon.do") => false + case p => p.last.endsWith(".do") + } + + def internalRoute(uri: String): Option[String] = { + relativeURI(uri).filter(isClientPath).map(r => "/" + r.toString()) + } + def relativeURI(uri: String): Option[RelativeUrl] = { val baseUrl = AbsoluteUrl.parse(urlService.getBaseInstitutionURI.toString) val Host = baseUrl.host @@ -220,6 +229,7 @@ class LegacyContentApi { info }) } + path match { case "" => ("/home.do", identity) case p if p.startsWith("items/") => itemViewer(p.substring("items/".length), (_, vi) => vi) @@ -316,15 +326,13 @@ class LegacyContentApi { new BookmarkAndModify(context, menuLink.getHandlerMap.getHandler("click").getModifier)) .getHref - val relativized = - LegacyContentController.relativeURI(href).filter(_.path.parts.last.endsWith(".do")) - val route = Option(mc.getRoute) + val route = Option(mc.getRoute).orElse(LegacyContentController.internalRoute(href)) val iconUrl = if (mc.isCustomImage) Some(mc.getBackgroundImagePath) else None MenuItem( menuLink.getLabelText, - if (relativized.isEmpty && route.isEmpty) Some(href) else None, + if (route.isEmpty) Some(href) else None, Option(mc.getSystemIcon), - route.orElse(relativized.map(r => "/" + r.toString)), + route, iconUrl, "_blank" == menuLink.getTarget ) @@ -428,9 +436,9 @@ class LegacyContentApi { Option(req.getAttribute(LegacyContentController.RedirectedAttr).asInstanceOf[String]).map { url => Response.ok { - LegacyContentController.relativeURI(url) match { - case None => ExternalRedirect(url) - case Some(relative) => InternalRedirect(relative.toString, userChanged(req)) + LegacyContentController.internalRoute(url) match { + case Some(relative) => InternalRedirect(relative.substring(1), userChanged(req)) + case _ => ExternalRedirect(url) } } } From 2661cb90918dc6f11d7879033bdb02e600390ef1 Mon Sep 17 00:00:00 2001 From: PenghaiZhang <47203811+PenghaiZhang@users.noreply.github.com> Date: Fri, 15 Nov 2019 11:33:43 +1100 Subject: [PATCH 6/9] Fix the alert dialog bug when publishing items (#1330) * Ensure the URLs of Item Summary page are internal routes --- .../com/tle/web/api/LegacyContentApi.scala | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala index 7d34f54083..5ced9a9a19 100644 --- a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala +++ b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala @@ -104,9 +104,27 @@ object LegacyContentController extends AbstractSectionsController with SectionFi import LegacyGuice.urlService - def isClientPath(relUrl: RelativeUrl): Boolean = relUrl.path.parts match { - case Vector("logon.do") => false - case p => p.last.endsWith(".do") + def isClientPath(relUrl: RelativeUrl): Boolean = { + // This regex matches the relative url of Item Summary page + // For example 'items/95075bdd-4049-46ab-a1aa-043902e239a3/3/' + // The last forward slash does not exist in some cases + val itemSummaryUrlPattern = + "items\\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\\/\\d+\\/?".r + + // This regex explicitly matches the relative Url of logon + // For example, 'logon.do' or 'logon.do?.page=home.do' + val logonUrlPattern = "logon\\.do\\??.*".r + + // This regex matches the relative Urls of other pages + // For example, 'home.do' or 'access/runwizard.do?.wizid...' + val otherUrlPattern = ".+\\.do\\??.*".r + + relUrl.toString() match { + case logonUrlPattern() => false + case itemSummaryUrlPattern() => true + case otherUrlPattern() => true + case _ => false + } } def internalRoute(uri: String): Option[String] = { From 0839dcfbee11f605fcd4d624858e3cc0e4987ce9 Mon Sep 17 00:00:00 2001 From: PenghaiZhang <47203811+PenghaiZhang@users.noreply.github.com> Date: Mon, 24 Feb 2020 13:04:05 +1100 Subject: [PATCH 7/9] Fix "no tree for xxx" error caused by favourite search links PR #1495 --- .../service/FavouriteSearchServiceImpl.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Source/Plugins/Core/com.equella.core/src/com/tle/core/favourites/service/FavouriteSearchServiceImpl.java b/Source/Plugins/Core/com.equella.core/src/com/tle/core/favourites/service/FavouriteSearchServiceImpl.java index 7e01e80bab..33f7b0c617 100644 --- a/Source/Plugins/Core/com.equella.core/src/com/tle/core/favourites/service/FavouriteSearchServiceImpl.java +++ b/Source/Plugins/Core/com.equella.core/src/com/tle/core/favourites/service/FavouriteSearchServiceImpl.java @@ -18,6 +18,7 @@ package com.tle.core.favourites.service; +import com.dytech.edge.web.WebConstants; import com.tle.beans.Institution; import com.tle.common.Check; import com.tle.common.institution.CurrentInstitution; @@ -37,6 +38,7 @@ import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; +import org.apache.commons.lang.StringUtils; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.springframework.transaction.annotation.Transactional; @@ -68,7 +70,23 @@ public void deleteById(long id) { public void executeSearch(SectionInfo info, long id) { FavouriteSearch search = dao.getById(id); if (search != null) { - SectionInfo forward = info.createForwardForUri(search.getUrl()); + String url = search.getUrl(); + // When user favourites a normal search, cloud search or hierarchy search, + // the value of 'url' starts with '/access' if the fav search is added in old oEQ versions, + // which results in "no tree for xxx" error. Hence, remove "/access" if it exists. + if (url != null + && url.startsWith(WebConstants.ACCESS_PATH) + && StringUtils.indexOfAny( + url, + new String[] { + WebConstants.SEARCHING_PAGE, + WebConstants.HIERARCHY_PAGE, + WebConstants.CLOUDSEARCH_PAGE + }) + > -1) { + url = "/" + url.replaceFirst(WebConstants.ACCESS_PATH, ""); + } + SectionInfo forward = info.createForwardForUri(url); info.forwardAsBookmark(forward); } } From 53d2a832f95fdd01b6752b9138cb83df49379d8e Mon Sep 17 00:00:00 2001 From: PenghaiZhang <47203811+PenghaiZhang@users.noreply.github.com> Date: Tue, 25 Feb 2020 13:43:06 +1100 Subject: [PATCH 8/9] Remove the Scala MatchError from Resource-center logs for 'ajaxResponse' PR #1502 --- .../scalasrc/com/tle/web/api/LegacyContentApi.scala | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala index 5ced9a9a19..59a978d226 100644 --- a/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala +++ b/Source/Plugins/Core/com.equella.core/scalasrc/com/tle/web/api/LegacyContentApi.scala @@ -57,8 +57,9 @@ import io.lemonlabs.uri.{Path => _, _} import io.swagger.annotations.Api import javax.servlet.http.{HttpServletRequest, HttpServletResponse} import javax.ws.rs._ -import javax.ws.rs.core.Response.ResponseBuilder +import javax.ws.rs.core.Response.{ResponseBuilder, Status} import javax.ws.rs.core.{CacheControl, Context, Response, UriInfo} +import org.slf4j.LoggerFactory import scala.collection.JavaConverters._ import scala.collection.mutable @@ -235,6 +236,7 @@ object LegacyContentController extends AbstractSectionsController with SectionFi @Api("Legacy content") @Path("content") class LegacyContentApi { + val LOGGER = LoggerFactory.getLogger(classOf[LegacyContentApi]) def parsePath(path: String): (String, MutableSectionInfo => MutableSectionInfo) = { @@ -589,7 +591,7 @@ class LegacyContentApi { .map(bbr => SectionUtils.renderToString(context, bbr.getRenderable)) } - def ajaxResponse(info: MutableSectionInfo, arc: AjaxRenderContext) = { + def ajaxResponse(info: MutableSectionInfo, arc: AjaxRenderContext): Response.ResponseBuilder = { var resp: ResponseBuilder = null val context = LegacyContentController.prepareJSContext(info) @@ -622,6 +624,10 @@ class LegacyContentApi { case tr: TemplateResult => tr.getNamedResult(context, "body") case sr: SectionRenderable => sr case pr: PreRenderable => new PreRenderOnly(pr) + //Due to many unknowns of what could cause renderedBody being null, return a 500 error at the moment. + case _ => + LOGGER.debug("Unknown error at renderedBody - ajaxResponse"); + return Response.status(Status.NOT_IMPLEMENTED); } renderAjaxBody(renderedBody) val responseCallback = arc.getJSONResponseCallback From 0d85cc4a84376cd52184bd59bb961c902acaa5bf Mon Sep 17 00:00:00 2001 From: PenghaiZhang <47203811+PenghaiZhang@users.noreply.github.com> Date: Thu, 9 Jan 2020 10:15:21 +1100 Subject: [PATCH 9/9] Do not use 'cd -' after building import-export-tool in Codebuild PR #1408 --- buildspec.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildspec.yml b/buildspec.yml index 14f4f41913..d7b2e01c1a 100644 --- a/buildspec.yml +++ b/buildspec.yml @@ -20,7 +20,7 @@ phases: - (cd Source/Plugins/Core/com.equella.core/js && npm install && npm test) - sbt -no-colors -Dconfig.file=${HOME}/build.conf test installerZip writeLanguagePack writeScriptingJavadoc - sbt -mem 2048 -no-colors "project autotest" installEquella startEquella configureInstall setupForTests Tests/test Tests/Serial/test OldTests/test coverageReport - - (cd import-export-tool && ./gradlew build); cd - + - (cd import-export-tool && ./gradlew build) post_build: commands: - publishBuildResults