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="activityService" ref="activityService"/>
|
||||
<property name="discussionService" ref="DiscussionService"/>
|
||||
<property name="permissionService" ref="PermissionService" />
|
||||
</bean>
|
||||
|
||||
<!-- Fetches the details of one discussions post or topic -->
|
||||
<!--
|
||||
<bean id="webscript.org.alfresco.repository.discussions.posts.forum-post.get"
|
||||
class="org.alfresco.repo.web.scripts.discussion.ForumPostGet"
|
||||
parent="abstractDiscussionWebScript">
|
||||
</bean>
|
||||
-->
|
||||
|
||||
<!-- Deletes a discussion post or topic -->
|
||||
<bean id="webscript.org.alfresco.repository.discussions.posts.forum-post.delete"
|
||||
|
@@ -23,7 +23,10 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
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.discussion.DiscussionService;
|
||||
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.NodeService;
|
||||
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.site.SiteInfo;
|
||||
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);
|
||||
|
||||
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
|
||||
protected NodeService nodeService;
|
||||
protected SiteService siteService;
|
||||
protected PersonService personService;
|
||||
protected ActivityService activityService;
|
||||
protected DiscussionService discussionService;
|
||||
protected PermissionService permissionService;
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
@@ -78,11 +90,6 @@ public abstract class AbstractDiscussionWebScript extends DeclarativeWebScript
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public void setDiscussionService(DiscussionService discussionService)
|
||||
{
|
||||
this.discussionService = discussionService;
|
||||
}
|
||||
|
||||
public void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
@@ -93,6 +100,16 @@ public abstract class AbstractDiscussionWebScript extends DeclarativeWebScript
|
||||
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
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
if(username == null || username.length() == 0)
|
||||
@@ -220,36 +271,105 @@ public abstract class AbstractDiscussionWebScript extends DeclarativeWebScript
|
||||
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>();
|
||||
res.put("topic", topic);
|
||||
res.put("node", topic.getNodeRef());
|
||||
res.put("name", topic.getSystemName());
|
||||
res.put("title", topic.getTitle());
|
||||
res.put("tags", topic.getTags());
|
||||
|
||||
// Both forms used for dates
|
||||
res.put("createdOn", topic.getCreatedAt());
|
||||
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)
|
||||
{
|
||||
res.put(key, "");
|
||||
}
|
||||
Map<String, Object> item = new HashMap<String, Object>();
|
||||
item.put(KEY_IS_TOPIC_POST, false);
|
||||
item.put(KEY_POST, post.getNodeRef());
|
||||
item.put(KEY_CAN_EDIT, canUserEditPost(post, site));
|
||||
item.put(KEY_AUTHOR, buildPerson(post.getCreator()));
|
||||
return item;
|
||||
}
|
||||
|
||||
return res;
|
||||
/*
|
||||
* 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);
|
||||
|
||||
// Ensure we got a primary post
|
||||
if(posts.getPage().size() == 0)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_PRECONDITION_FAILED,
|
||||
"First (primary) post was missing from the topic, can't fetch");
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -310,6 +430,13 @@ public abstract class AbstractDiscussionWebScript extends DeclarativeWebScript
|
||||
{
|
||||
String name = templateVars.get("path");
|
||||
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") &&
|
||||
|
@@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.discussion;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.discussion.PostInfo;
|
||||
@@ -47,14 +46,7 @@ public class ForumPostDelete extends AbstractDiscussionWebScript
|
||||
Status status, Cache cache)
|
||||
{
|
||||
// Build the common model parts
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put("topic", topic);
|
||||
model.put("post", post);
|
||||
if(site != null)
|
||||
{
|
||||
model.put("siteId", site.getShortName());
|
||||
model.put("site", site);
|
||||
}
|
||||
Map<String, Object> model = buildCommonModel(site, topic, post, req);
|
||||
|
||||
|
||||
// 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