mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
ALF-9153 Convert the single topic/post fetch webscript to be Java backed and Lucene Free
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29765 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1,41 +0,0 @@
|
|||||||
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/repository/requestutils.lib.js">
|
|
||||||
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/repository/discussions/topicpost.lib.js">
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fetches the correct post data (either topic post or post depending on the node type
|
|
||||||
*/
|
|
||||||
function fetchPostData(node)
|
|
||||||
{
|
|
||||||
// we have to differentiate here whether this is a top-level post or a reply
|
|
||||||
// only in the first case we fetch all information (as returned by forum/.../posts)
|
|
||||||
if (node.type == "{http://www.alfresco.org/model/forum/1.0}topic")
|
|
||||||
{
|
|
||||||
model.postData = getTopicPostData(node);
|
|
||||||
}
|
|
||||||
else if (node.type == "{http://www.alfresco.org/model/forum/1.0}post")
|
|
||||||
{
|
|
||||||
model.postData = getReplyPostData(node);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
status.setCode(STATUS_BAD_REQUEST, "Incompatible node type. Required either fm:topic or fm:post. Received: " + node.type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function main()
|
|
||||||
{
|
|
||||||
// get requested node
|
|
||||||
var node = getRequestNode();
|
|
||||||
if (status.getCode() != status.STATUS_OK)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchPostData(node);
|
|
||||||
|
|
||||||
// fetch the contentLength param
|
|
||||||
var contentLength = args["contentLength"] != undefined ? parseInt(args["contentLength"]) : -1;
|
|
||||||
model.contentLength = isNaN(contentLength) ? -1 : contentLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
@@ -1568,15 +1568,14 @@
|
|||||||
<property name="personService" ref="PersonService"/>
|
<property name="personService" ref="PersonService"/>
|
||||||
<property name="activityService" ref="activityService"/>
|
<property name="activityService" ref="activityService"/>
|
||||||
<property name="discussionService" ref="DiscussionService"/>
|
<property name="discussionService" ref="DiscussionService"/>
|
||||||
|
<property name="permissionService" ref="PermissionService" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- Fetches the details of one discussions post or topic -->
|
<!-- Fetches the details of one discussions post or topic -->
|
||||||
<!--
|
|
||||||
<bean id="webscript.org.alfresco.repository.discussions.posts.forum-post.get"
|
<bean id="webscript.org.alfresco.repository.discussions.posts.forum-post.get"
|
||||||
class="org.alfresco.repo.web.scripts.discussion.ForumPostGet"
|
class="org.alfresco.repo.web.scripts.discussion.ForumPostGet"
|
||||||
parent="abstractDiscussionWebScript">
|
parent="abstractDiscussionWebScript">
|
||||||
</bean>
|
</bean>
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- Deletes a discussion post or topic -->
|
<!-- Deletes a discussion post or topic -->
|
||||||
<bean id="webscript.org.alfresco.repository.discussions.posts.forum-post.delete"
|
<bean id="webscript.org.alfresco.repository.discussions.posts.forum-post.delete"
|
||||||
|
@@ -23,7 +23,10 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.query.PagingRequest;
|
import org.alfresco.query.PagingRequest;
|
||||||
|
import org.alfresco.query.PagingResults;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.site.SiteServiceImpl;
|
||||||
import org.alfresco.service.cmr.activities.ActivityService;
|
import org.alfresco.service.cmr.activities.ActivityService;
|
||||||
import org.alfresco.service.cmr.discussion.DiscussionService;
|
import org.alfresco.service.cmr.discussion.DiscussionService;
|
||||||
import org.alfresco.service.cmr.discussion.PostInfo;
|
import org.alfresco.service.cmr.discussion.PostInfo;
|
||||||
@@ -31,6 +34,8 @@ import org.alfresco.service.cmr.discussion.TopicInfo;
|
|||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
import org.alfresco.service.cmr.security.PersonService;
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
import org.alfresco.service.cmr.site.SiteInfo;
|
import org.alfresco.service.cmr.site.SiteInfo;
|
||||||
import org.alfresco.service.cmr.site.SiteService;
|
import org.alfresco.service.cmr.site.SiteService;
|
||||||
@@ -61,12 +66,19 @@ public abstract class AbstractDiscussionWebScript extends DeclarativeWebScript
|
|||||||
|
|
||||||
private static Log logger = LogFactory.getLog(AbstractDiscussionWebScript.class);
|
private static Log logger = LogFactory.getLog(AbstractDiscussionWebScript.class);
|
||||||
|
|
||||||
|
protected static final String KEY_IS_TOPIC_POST = "isTopicPost";
|
||||||
|
protected static final String KEY_TOPIC = "topic";
|
||||||
|
protected static final String KEY_POST = "post";
|
||||||
|
protected static final String KEY_CAN_EDIT = "canEdit";
|
||||||
|
protected static final String KEY_AUTHOR = "author";
|
||||||
|
|
||||||
// Injected services
|
// Injected services
|
||||||
protected NodeService nodeService;
|
protected NodeService nodeService;
|
||||||
protected SiteService siteService;
|
protected SiteService siteService;
|
||||||
protected PersonService personService;
|
protected PersonService personService;
|
||||||
protected ActivityService activityService;
|
protected ActivityService activityService;
|
||||||
protected DiscussionService discussionService;
|
protected DiscussionService discussionService;
|
||||||
|
protected PermissionService permissionService;
|
||||||
|
|
||||||
public void setNodeService(NodeService nodeService)
|
public void setNodeService(NodeService nodeService)
|
||||||
{
|
{
|
||||||
@@ -78,11 +90,6 @@ public abstract class AbstractDiscussionWebScript extends DeclarativeWebScript
|
|||||||
this.siteService = siteService;
|
this.siteService = siteService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDiscussionService(DiscussionService discussionService)
|
|
||||||
{
|
|
||||||
this.discussionService = discussionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPersonService(PersonService personService)
|
public void setPersonService(PersonService personService)
|
||||||
{
|
{
|
||||||
this.personService = personService;
|
this.personService = personService;
|
||||||
@@ -93,6 +100,16 @@ public abstract class AbstractDiscussionWebScript extends DeclarativeWebScript
|
|||||||
this.activityService = activityService;
|
this.activityService = activityService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDiscussionService(DiscussionService discussionService)
|
||||||
|
{
|
||||||
|
this.discussionService = discussionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissionService(PermissionService permissionService)
|
||||||
|
{
|
||||||
|
this.permissionService = permissionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected String getOrNull(JSONObject json, String key) throws JSONException
|
protected String getOrNull(JSONObject json, String key) throws JSONException
|
||||||
{
|
{
|
||||||
@@ -206,7 +223,41 @@ public abstract class AbstractDiscussionWebScript extends DeclarativeWebScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Is this needed?
|
/**
|
||||||
|
* Is the current user allowed to edit this post?
|
||||||
|
* In order to be deemed allowed, you first need write
|
||||||
|
* permissions on the underlying node of the post.
|
||||||
|
* You then also need to either be the cm:creator of
|
||||||
|
* the post node, or a site manager
|
||||||
|
*/
|
||||||
|
protected boolean canUserEditPost(PostInfo post, SiteInfo site)
|
||||||
|
{
|
||||||
|
// Are they OK on the node?
|
||||||
|
AccessStatus canEdit = permissionService.hasPermission(post.getNodeRef(), PermissionService.WRITE);
|
||||||
|
if(canEdit == AccessStatus.ALLOWED)
|
||||||
|
{
|
||||||
|
// Only the creator and site managers may edit
|
||||||
|
String user = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||||
|
if(post.getCreator().equals(user))
|
||||||
|
{
|
||||||
|
// It's their post
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(site != null)
|
||||||
|
{
|
||||||
|
String role = siteService.getMembersRole(site.getShortName(), user);
|
||||||
|
if(SiteServiceImpl.SITE_MANAGER.equals(role))
|
||||||
|
{
|
||||||
|
// Managers may edit
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If in doubt, you may not edit
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected Object buildPerson(String username)
|
protected Object buildPerson(String username)
|
||||||
{
|
{
|
||||||
if(username == null || username.length() == 0)
|
if(username == null || username.length() == 0)
|
||||||
@@ -220,36 +271,105 @@ public abstract class AbstractDiscussionWebScript extends DeclarativeWebScript
|
|||||||
return person;
|
return person;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Match JS
|
/*
|
||||||
protected Map<String, Object> renderTopic(TopicInfo topic)
|
* Was topicpost.lib.js getReplyPostData
|
||||||
|
*
|
||||||
|
* TODO Switch the FTL to prefer the Info object rather than the ScriptNode
|
||||||
|
*/
|
||||||
|
protected Map<String, Object> renderPost(PostInfo post, SiteInfo site)
|
||||||
{
|
{
|
||||||
Map<String, Object> res = new HashMap<String, Object>();
|
Map<String, Object> item = new HashMap<String, Object>();
|
||||||
res.put("topic", topic);
|
item.put(KEY_IS_TOPIC_POST, false);
|
||||||
res.put("node", topic.getNodeRef());
|
item.put(KEY_POST, post.getNodeRef());
|
||||||
res.put("name", topic.getSystemName());
|
item.put(KEY_CAN_EDIT, canUserEditPost(post, site));
|
||||||
res.put("title", topic.getTitle());
|
item.put(KEY_AUTHOR, buildPerson(post.getCreator()));
|
||||||
res.put("tags", topic.getTags());
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Was topicpost.lib.js getTopicPostData / getTopicPostDataFromTopicAndPosts
|
||||||
|
*
|
||||||
|
* TODO Switch the FTL to prefer the Info object rather than the ScriptNode
|
||||||
|
*/
|
||||||
|
protected Map<String, Object> renderTopic(TopicInfo topic, SiteInfo site)
|
||||||
|
{
|
||||||
|
// Fetch all the posts for the topic
|
||||||
|
// TODO We actually only need the count, the first and the last
|
||||||
|
// In the interest of keeping our life simply, get all of them
|
||||||
|
PagingRequest paging = new PagingRequest(MAX_QUERY_ENTRY_COUNT);
|
||||||
|
paging.setRequestTotalCountMax(MAX_QUERY_ENTRY_COUNT);
|
||||||
|
PagingResults<PostInfo> posts = discussionService.listPosts(topic, paging);
|
||||||
|
|
||||||
// Both forms used for dates
|
// Ensure we got a primary post
|
||||||
res.put("createdOn", topic.getCreatedAt());
|
if(posts.getPage().size() == 0)
|
||||||
res.put("modifiedOn", topic.getModifiedAt());
|
|
||||||
res.put("created", topic.getCreatedAt());
|
|
||||||
res.put("modified", topic.getModifiedAt());
|
|
||||||
|
|
||||||
// FTL needs a script node of the people
|
|
||||||
res.put("createdBy", buildPerson(topic.getCreator()));
|
|
||||||
res.put("modifiedBY", buildPerson(topic.getModifier()));
|
|
||||||
|
|
||||||
// We want blank instead of null
|
|
||||||
for(String key : res.keySet())
|
|
||||||
{
|
{
|
||||||
if(res.get(key) == null)
|
throw new WebScriptException(Status.STATUS_PRECONDITION_FAILED,
|
||||||
{
|
"First (primary) post was missing from the topic, can't fetch");
|
||||||
res.put(key, "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
// Grab the posts of interest
|
||||||
|
PostInfo primaryPost = posts.getPage().get(0);
|
||||||
|
// The posts in a topic listing are ordered by created date
|
||||||
|
PostInfo mostRecentPost = posts.getPage().get(posts.getPage().size()-1);
|
||||||
|
|
||||||
|
// Build the details
|
||||||
|
Map<String, Object> item = new HashMap<String, Object>();
|
||||||
|
item.put(KEY_IS_TOPIC_POST, true);
|
||||||
|
item.put(KEY_TOPIC, topic.getNodeRef());
|
||||||
|
item.put(KEY_POST, primaryPost.getNodeRef());
|
||||||
|
item.put(KEY_CAN_EDIT, canUserEditPost(primaryPost, site));
|
||||||
|
item.put(KEY_AUTHOR, buildPerson(topic.getCreator()));
|
||||||
|
|
||||||
|
// The reply count is one less than all posts (first is the primary one)
|
||||||
|
item.put("totalReplyCount", posts.getTotalResultCount().getFirst() - 1);
|
||||||
|
|
||||||
|
// We want details on the most recent post
|
||||||
|
if(posts.getPage().size() > 1)
|
||||||
|
{
|
||||||
|
item.put("lastReply", mostRecentPost.getNodeRef());
|
||||||
|
item.put("lastReplyBy", buildPerson(mostRecentPost.getCreator()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include the tags
|
||||||
|
item.put("tags", topic.getTags());
|
||||||
|
|
||||||
|
// All done
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, Object> buildCommonModel(SiteInfo site, TopicInfo topic,
|
||||||
|
PostInfo post, WebScriptRequest req)
|
||||||
|
{
|
||||||
|
// Build the common model parts
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>();
|
||||||
|
model.put(KEY_TOPIC, topic);
|
||||||
|
model.put(KEY_POST, post);
|
||||||
|
|
||||||
|
// Capture the site details only if site based
|
||||||
|
if(site != null)
|
||||||
|
{
|
||||||
|
model.put("siteId", site.getShortName());
|
||||||
|
model.put("site", site);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The limit on the length of the content to be returned
|
||||||
|
int contentLength = -1;
|
||||||
|
String contentLengthS = req.getParameter("contentLength");
|
||||||
|
if(contentLengthS != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
contentLength = Integer.parseInt(contentLengthS);
|
||||||
|
}
|
||||||
|
catch(NumberFormatException e)
|
||||||
|
{
|
||||||
|
logger.info("Skipping invalid length " + contentLengthS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model.put("contentLength", contentLength);
|
||||||
|
|
||||||
|
// All done
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -310,6 +430,13 @@ public abstract class AbstractDiscussionWebScript extends DeclarativeWebScript
|
|||||||
{
|
{
|
||||||
String name = templateVars.get("path");
|
String name = templateVars.get("path");
|
||||||
topic = discussionService.getTopic(site.getShortName(), name);
|
topic = discussionService.getTopic(site.getShortName(), name);
|
||||||
|
|
||||||
|
if(topic == null)
|
||||||
|
{
|
||||||
|
String error = "Could not find topic: " + name;
|
||||||
|
throw new WebScriptException(Status.STATUS_NOT_FOUND, error);
|
||||||
|
}
|
||||||
|
nodeRef = topic.getNodeRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(templateVars.containsKey("store_type") &&
|
else if(templateVars.containsKey("store_type") &&
|
||||||
|
@@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.web.scripts.discussion;
|
package org.alfresco.repo.web.scripts.discussion;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.service.cmr.discussion.PostInfo;
|
import org.alfresco.service.cmr.discussion.PostInfo;
|
||||||
@@ -47,14 +46,7 @@ public class ForumPostDelete extends AbstractDiscussionWebScript
|
|||||||
Status status, Cache cache)
|
Status status, Cache cache)
|
||||||
{
|
{
|
||||||
// Build the common model parts
|
// Build the common model parts
|
||||||
Map<String, Object> model = new HashMap<String, Object>();
|
Map<String, Object> model = buildCommonModel(site, topic, post, req);
|
||||||
model.put("topic", topic);
|
|
||||||
model.put("post", post);
|
|
||||||
if(site != null)
|
|
||||||
{
|
|
||||||
model.put("siteId", site.getShortName());
|
|
||||||
model.put("site", site);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Are we deleting a topic, or a post in it?
|
// Are we deleting a topic, or a post in it?
|
||||||
|
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.web.scripts.discussion;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.discussion.PostInfo;
|
||||||
|
import org.alfresco.service.cmr.discussion.TopicInfo;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.site.SiteInfo;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
|
import org.springframework.extensions.webscripts.Status;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is the controller for the discussions page fetching forum-post.get webscript.
|
||||||
|
*
|
||||||
|
* @author Nick Burch
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class ForumPostGet extends AbstractDiscussionWebScript
|
||||||
|
{
|
||||||
|
private static final String KEY_POSTDATA = "postData";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, Object> executeImpl(SiteInfo site, NodeRef nodeRef,
|
||||||
|
TopicInfo topic, PostInfo post, WebScriptRequest req, JSONObject json,
|
||||||
|
Status status, Cache cache)
|
||||||
|
{
|
||||||
|
// Build the common model parts
|
||||||
|
Map<String, Object> model = buildCommonModel(site, topic, post, req);
|
||||||
|
|
||||||
|
// Did they want just one post, or the whole of the topic?
|
||||||
|
if(post != null)
|
||||||
|
{
|
||||||
|
model.put(KEY_POSTDATA, renderPost(post, site));
|
||||||
|
}
|
||||||
|
else if(topic != null)
|
||||||
|
{
|
||||||
|
model.put(KEY_POSTDATA, renderTopic(topic, site));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String error = "Node was of the wrong type, only Topic and Post are supported";
|
||||||
|
throw new WebScriptException(Status.STATUS_BAD_REQUEST, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All done
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user