Skip to content

Commit

Permalink
Add extra path support to XML REST API id element similar to the allo…
Browse files Browse the repository at this point in the history
…w-extra-path attribute in a XML Screen; first use in a new endpoint to get published wiki page, also added a couple more wiki page related endpoints but far from comprehensive for all or most in WikiServices.xml
  • Loading branch information
jonesde committed Nov 1, 2022
1 parent 83c88c8 commit 011382c
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 13 deletions.
19 changes: 13 additions & 6 deletions framework/service/org/moqui/impl/WikiServices.xml
Expand Up @@ -19,7 +19,7 @@ along with this software (see the LICENSE.md file). If not, see
<parameter name="wikiSpaceId"/>
<parameter name="pagePath"/>
<parameter name="wikiSpace" type="org.moqui.entity.EntityValue"/>
<parameter name="pageReference" type="org.moqui.content.ResourceReference"/>
<parameter name="pageReference" type="org.moqui.resource.ResourceReference"/>
<parameter name="attachmentList" type="List"><parameter name="attachmentInfo" type="Map">
<parameter name="filename"/><parameter name="contentType"/><parameter name="lastModified" type="Long"/>
</parameter></parameter>
Expand All @@ -42,6 +42,10 @@ along with this software (see the LICENSE.md file). If not, see
<in-parameters>
<parameter name="wikiSpaceId" required="true"/>
<parameter name="pagePath"/><!-- not required because for root page will be empty -->
<parameter name="pagePathList" type="List">
<description>Alternative to pagePath when caller has a list of path elements (instead of forward slash separated string)</description>
<parameter name="pathElement" type="String"/>
</parameter>
<parameter name="versionName"><description>Meant for testing, get this version instead of published.
To eliminate exposure of non-published versions explicitly set this to null.</description></parameter>
<parameter name="getPageText" type="Boolean" default="true"/>
Expand All @@ -59,6 +63,7 @@ along with this software (see the LICENSE.md file). If not, see
<field-map field-name="wikiSpaceId"/></entity-find-one>
<if condition="wikiSpace == null"><return message="No space found with ID ${wikiSpaceId}"/></if>

<if condition="pagePathList &amp;&amp; !pagePath"><set field="pagePath" from="pagePathList.join('/')"/></if>
<entity-find entity-name="moqui.resource.wiki.WikiPage" list="wikiPageList" cache="true">
<econdition field-name="wikiSpaceId"/><econdition field-name="pagePath" from="pagePath ?: null"/></entity-find>
<set field="wikiPage" from="wikiPageList ? wikiPageList[0] : null"/>
Expand Down Expand Up @@ -149,9 +154,9 @@ along with this software (see the LICENSE.md file). If not, see
<parameter name="wikiSpace" type="org.moqui.entity.EntityValue"/>
<parameter name="wikiPage" type="org.moqui.entity.EntityValue"/>
<parameter name="rootPageLocation"/>
<parameter name="rootPageRef"/>
<parameter name="rootPageRef" type="org.moqui.resource.ResourceReference"/>
<parameter name="spaceRootName"/>
<parameter name="pageReference" type="org.moqui.content.ResourceReference"/>
<parameter name="pageReference" type="org.moqui.resource.ResourceReference"/>
</out-parameters>
<actions>
<if condition="wikiPageId">
Expand Down Expand Up @@ -319,7 +324,7 @@ along with this software (see the LICENSE.md file). If not, see
<parameter name="pagePath"><description>Not required, is empty for the space root page. Can be a wikiPageId or the page path within the space.</description></parameter>
<parameter name="filename"><description>If not specified last segment of pagePath will be used</description></parameter>
</in-parameters>
<out-parameters><parameter name="attachmentReference" type="org.moqui.content.ResourceReference"/></out-parameters>
<out-parameters><parameter name="attachmentReference" type="org.moqui.resource.ResourceReference"/></out-parameters>
<actions>
<set field="pathList" from="pagePath ? pagePath.split('/') as List : []"/>
<!-- <log level="warn" message="begin wikiSpaceId ${wikiSpaceId} pagePath ${pagePath} filename ${filename} pathList ${pathList}"/> -->
Expand Down Expand Up @@ -371,7 +376,7 @@ along with this software (see the LICENSE.md file). If not, see
<parameter name="pagePath"><description>Not required, is empty for the space root page. Can be a wikiPageId or the page path within the space.</description></parameter>
<parameter name="attachmentFile" type="org.apache.commons.fileupload.FileItem"/>
</in-parameters>
<out-parameters><parameter name="attachmentReference" type="org.moqui.content.ResourceReference"/></out-parameters>
<out-parameters><parameter name="attachmentReference" type="org.moqui.resource.ResourceReference"/></out-parameters>
<actions>
<if condition="attachmentFile == null"><return message="No attachment uploaded"/></if>
<set field="filename" from="attachmentFile.getName()"/>
Expand Down Expand Up @@ -495,18 +500,20 @@ along with this software (see the LICENSE.md file). If not, see
<set field="wikiPageHistoryMap" from="[wikiPageId:wikiPageId, userId:ec.user.userId, changeDateTime:ec.user.nowTimestamp, versionName:versionName]"/>

<!-- move the page if applicable -->
<set field="origParentPath" from="pagePath.contains('/') ? pagePath.substring(0, pagePath.lastIndexOf('/')) : null"/>
<set field="origParentPath" from="pagePath.contains('/') ? pagePath.substring(0, pagePath.lastIndexOf('/')) : ''"/>
<set field="origPageName" from="pagePath.contains('/') ? pagePath.substring(pagePath.lastIndexOf('/')+1) : pagePath"/>
<!-- TODO: support change of wikiType too -->
<if condition="pageName &amp;&amp; (origParentPath != parentPath || origPageName != pageName)">
<log message="update#WikiPage path ${pagePath} pageName=${pageName} origPageName=${origPageName} parentPath=${parentPath} origParentPath=${origParentPath}"/>
<!-- move the page file -->
<set field="rootPageDirRef" from="rootPageRef.findMatchingDirectory()"/>
<set field="newPageLocation" value="${rootPageDirRef.location}${parentPath ? '/' + parentPath : ''}/${pageName}.${wikiType}"/>
<log message="update#WikiPage move page ${pageReference.location} to ${newPageLocation}"/>
<script>pageReference.move(newPageLocation)</script>
<!-- move the page's corresponding directory -->
<set field="pageDirReference" from="pageReference.findMatchingDirectory()"/>
<set field="newPageDirLocation" value="${rootPageDirRef.location}${parentPath ? '/' + parentPath : ''}/${pageName}"/>
<log message="update#WikiPage move directory ${pageDirReference.location} to ${newPageDirLocation}"/>
<script>pageDirReference.move(newPageDirLocation)</script>

<!-- save the old path in the WikiPageHistory (before the pagePath is set to the new path) -->
Expand Down
30 changes: 26 additions & 4 deletions framework/src/main/groovy/org/moqui/impl/service/RestApi.groovy
Expand Up @@ -622,15 +622,19 @@ class RestApi {
}

RestResult runByMethod(List<String> pathList, ExecutionContext ec) {
String method = getCurrentMethod(ec)
MethodHandler mh = (MethodHandler) methodMap.get(method)
if (mh == null) throw new MethodNotSupportedException("Method ${method} not supported at ${pathList}")
return mh.run(pathList, ec)
}
private String getCurrentMethod(ExecutionContext ec) {
HttpServletRequest request = ec.web.getRequest()
String method = request.getMethod().toLowerCase()
if ("post".equals(method)) {
String ovdMethod = request.getHeader("X-HTTP-Method-Override")
if (ovdMethod != null && !ovdMethod.isEmpty()) method = ovdMethod.toLowerCase()
}
MethodHandler mh = methodMap.get(method)
if (mh == null) throw new MethodNotSupportedException("Method ${method} not supported at ${pathList}")
return mh.run(pathList, ec)
return method
}

RestResult visitChildOrRun(List<String> pathList, int pathIndex, ExecutionContextImpl ec) {
Expand Down Expand Up @@ -671,6 +675,10 @@ class RestApi {
throw new ResourceNotFoundException("Resource ${nextPath} not valid, index ${pathIndex} in path ${pathList}; resources available are ${resourceMap.keySet()}")
}
} else {
// if there is a child id node and it has allow-extra-path=true then try using it, allow id with extra path to have no extra path
if (idNode != null && idNode.allowExtraPath && methodMap.get(getCurrentMethod(ec)) == null) {
return idNode.visit(pathList, nextPathIndex, ec)
}
return runByMethod(pathList, ec)
}
} finally {
Expand Down Expand Up @@ -764,13 +772,27 @@ class RestApi {
}
}
static class IdNode extends PathNode {
private boolean allowExtraPath = false
IdNode(MNode node, PathNode parent, ExecutionContextFactoryImpl ecfi) {
super(node, parent, ecfi, true)
allowExtraPath = "true".equals(node.attribute("allow-extra-path"))
}
RestResult visit(List<String> pathList, int pathIndex, ExecutionContextImpl ec) {
// logger.info("Visit id ${name}")
// set ID value in context
ec.context.put(name, pathList[pathIndex])
if (allowExtraPath) {
// handle allow-extra-path, make a List of this path element plus all after it
// path elements remaining to include in this list, including the current element
int elementsRemaining = pathList.size() - pathIndex
ArrayList<String> pathElements = new ArrayList<>()
// note that this may do nothing if pathIndex = pathList.size() (ie no extra path elements)
for (int i = pathIndex; i < pathList.size(); i++) pathElements.add(pathList.get(i))
ec.context.put(name, pathElements)
// add elementsRemaining - 1 (for the current element) to advance pathIndex to the end
pathIndex += (elementsRemaining - 1)
} else {
ec.context.put(name, pathList.get(pathIndex))
}
// visit child or run here
return visitChildOrRun(pathList, pathIndex, ec)
}
Expand Down
5 changes: 5 additions & 0 deletions framework/xsd/rest-api-3.xsd
Expand Up @@ -40,6 +40,11 @@ along with this software (see the LICENSE.md file). If not, see
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="require-authentication" type="authc-options" default="true"/>
<xs:attribute name="allow-extra-path" type="boolean" default="false">
<xs:annotation><xs:documentation>If set to true arbitrary path elements following this screen's path are allowed.
Default is false and an exception will be thrown if there is an extra path element that does not match a
resource below the id element, or it has a child id element.</xs:documentation></xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="method">
Expand Down
6 changes: 3 additions & 3 deletions framework/xsd/xml-screen-3.xsd
Expand Up @@ -98,9 +98,9 @@ along with this software (see the LICENSE.md file). If not, see
any subscreens, otherwise defaults to "/Login".</xs:documentation></xs:annotation>
</xs:attribute>
<xs:attribute name="allow-extra-path" type="boolean" default="false">
<xs:annotation><xs:documentation>If set to true arbitrary path follow this screen's path is allowed.
Default is false and an exception will be thrown if there is extra path that does not match a
subscreen, a transition, or content below the screen.</xs:documentation></xs:annotation>
<xs:annotation><xs:documentation>If set to true arbitrary path elements following this screen's path are allowed.
Default is false and an exception will be thrown if there is an extra path element that does not match a
subscreen, transition, or content (file) below the screen.</xs:documentation></xs:annotation>
</xs:attribute>
<xs:attribute name="render-modes" type="xs:string" default="all">
<xs:annotation><xs:documentation>
Expand Down

0 comments on commit 011382c

Please sign in to comment.