mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged BRANCHES/DEV/HEAD_QUICK_SHARE_TMP to HEAD:
41501: Creating Quick Share branch for merging into head 41524: Merged THOR1 & THOR1_SPRINTS to HEAD_QUICK_SHARE_TMP 30997: Firefox scrollbars removed on "invitation" and "signup" pages (now using new helper method Alfresco.util.createYUIOverlay) 36011: Merged BRANCHES/DEV/THOR1_QUICK_SHARE to BRANCHES/DEV/THOR1_SPRINTS: 34685: Creating Quick Share branch 34826: First cut of THOR-1270 "F387: As the link receiver, I can view the Document Preview in the browser without having to login" 34868: More on THOR-1270 "F387: As the link receiver, I can view the Document Preview in the browser without having to login" 34901: QuickShare REST API - WIP ... note: API will change :-) 34933: QuickShare REST API - WIP 34934: QuickShare REST API - WIP 34941: QuickShare REST API - WIP ... note: API will change :-) 34989: QuickShare REST API - WIP 34995: QuickShare REST API - WIP 34996: QuickShare REST API - WIP 35011: QuickShare/PublicView REST API 35025: F387: As the link receiver, I can view the Document Preview in the browser without having to login 35035: QuickShare/PublicView REST API 35052: QuickShare/PublicView REST API 35069: More on THOR-1270 "F387 As the link receiver, I can view the Document Preview in the browser without having to login" 35094: Removed cpnfig property that was commited by mistake 35111: First cut of THOR-1268 "F378: As a user I can choose to share a document" 35252: THOR-1271 "F388: From the view page, I can easily sign up or login for Alfresco. Sign Up is embedded in the page and Login will redirect you to the Alfresco Login page" partial commit 35254: First cut of THOR-1268 "F378: As a user I can choose to share a document" part 2 35255: THOR-1270 "F387: As the link receiver, I can view the Document Preview in the browser without having to login" 35264: QuickShare/PublicView REST API 35317: THOR-1322: New metadata doesn't return "webpreview" in thumbnails (part 1) 35319: QuickShare REST API - fix tenant ref when share'ing 35330: QuickShare REST API - fix THOR-1322: New metadata doesn't return "webpreview" in thumbnails (part 2) 35368: QuickShare REST API - THOR-1336: (F418) Get context (nodeRef, siteId, tenantDomain) for a shared_id 35376: QuickShare REST API - fix THOR-1273 (unshare document) 35424: THOR-1271 "F388: From the view page, I can easily sign up or login for Alfresco. Sign Up is embedded in the page and Login will redirect you to the Alfresco Login page" partial commit 35425: THOR-1271 "F388: From the view page, I can easily sign up or login for Alfresco. Sign Up is embedded in the page and Login will redirect you to the Alfresco Login page" partial commit 35566: Fixed THOR-1268 "F378: As a user I can choose to share a document" 35617: THOR-1350: Update Slingshot API (doclib2) - make the "qshare:sharedBy" return full details (instead of just userName) 35624: THOR-1339: QuickShare REST API 35682: Fixed THOR-1268, THOR-1339 & THOR-1269 35935: QuickShare REST API - add "system.quickshare.enabled" prop (if set to false then disables QuickShare service/API) 35996: Fixed THOR-1369 & THOR-1270 35997: Fixed THOR-1369 & THOR-1270 part 2 36000: Fixed THOR-1369 & THOR-1270 part 3 41550: Merged THOR1 & THOR1_SPRINTS to HEAD_QUICK_SHARE_TMP part 2 41569: Updated web.xml to add support for URLRewrite filtering for Quick Share 41572: Merged THOR1 & THOR1_SPRINTS to HEAD_QUICK_SHARE_TMP part 3 41640: Merged THOR1_SPRINTS to HEAD_QUICK_SHARE_TMP 36082: THOR-1270 "F387: As the link receiver, I can view the Document Preview in the browser without having to login" - Re-added "Document Details" link public share page git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@41736 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
<webscript>
|
||||||
|
<shortname>QuickShare - get some "shared" content</shortname>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Note: Unauthenticated => if QuickShare exists then gets the content stream for the specified document
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
- do we need both options (/node/content/{shared_id} vs /node/{shared_id}/content) ?
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<url>/api/internal/shared/node/content{property}/{shared_id}?a={attach?}</url>
|
||||||
|
<url>/api/internal/shared/node/{shared_id}/content{property}?a={attach?}</url>
|
||||||
|
|
||||||
|
<format default="">argument</format>
|
||||||
|
<authentication>none</authentication>
|
||||||
|
<transaction allow="readonly"/>
|
||||||
|
<lifecycle>internal</lifecycle>
|
||||||
|
</webscript>
|
@@ -0,0 +1,15 @@
|
|||||||
|
<webscript>
|
||||||
|
<shortname>QuickShare - get some "shared" thumbnail content</shortname>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Note: Unauthenticated => if QuickShare exists then gets the content stream for the specified document thumbnail/rendition
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<url>/api/internal/shared/node/{shared_id}/content{property}/thumbnails/{thumbnailname}?a={attach?}</url>
|
||||||
|
|
||||||
|
<format default="">argument</format>
|
||||||
|
<authentication>none</authentication>
|
||||||
|
<transaction allow="readonly"/>
|
||||||
|
<lifecycle>internal</lifecycle>
|
||||||
|
</webscript>
|
@@ -0,0 +1,12 @@
|
|||||||
|
<webscript>
|
||||||
|
<shortname>QuickShare - get some limited metadata for "shared" content (including thumbnail defs)</shortname>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Note: Unauthenticated => if QuickShare exists then gets the limited metadata for the specified document
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
<url>/api/internal/shared/node/{shared_id}/metadata</url>
|
||||||
|
<format default="json" />
|
||||||
|
<authentication>none</authentication>
|
||||||
|
<transaction allow="readonly">required</transaction>
|
||||||
|
</webscript>
|
@@ -0,0 +1,2 @@
|
|||||||
|
<#import "metadata.lib.ftl" as metadataLib />
|
||||||
|
<@metadataLib.resultsJSON item=item />
|
@@ -0,0 +1,12 @@
|
|||||||
|
<webscript>
|
||||||
|
<shortname>Get some limited metadata for content (including thumbnail defs)</shortname>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Note: authenticated version of the metadata script
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
<url>/api/node/{store_protocol}/{store_id}/{node_id}/metadata</url>
|
||||||
|
<format default="json" />
|
||||||
|
<authentication>user</authentication>
|
||||||
|
<transaction allow="readonly">required</transaction>
|
||||||
|
</webscript>
|
@@ -0,0 +1,2 @@
|
|||||||
|
<#import "metadata.lib.ftl" as metadataLib />
|
||||||
|
<@metadataLib.resultsJSON item=item />
|
@@ -0,0 +1,43 @@
|
|||||||
|
<#macro resultsJSON item>
|
||||||
|
<#escape x as jsonUtils.encodeJSONString(x)>
|
||||||
|
{
|
||||||
|
"name": "${item.name}",
|
||||||
|
"title": "${item.title!""}",
|
||||||
|
"mimetype": "${item.mimetype!""}",
|
||||||
|
"size": ${item.size?c},
|
||||||
|
"modifiedOn": "${xmldate(item.modified)}",
|
||||||
|
"modifier":
|
||||||
|
{
|
||||||
|
"firstName": "${item.modifierFirstName!""}",
|
||||||
|
"lastName": "${item.modifierLastName!""}"
|
||||||
|
},
|
||||||
|
"thumbnailDefinitions":
|
||||||
|
[
|
||||||
|
<#if item.thumbnailDefinitions??>
|
||||||
|
<#list item.thumbnailDefinitions as thumbnailDefinition>
|
||||||
|
"${thumbnailDefinition}"
|
||||||
|
<#if thumbnailDefinition_has_next>,</#if>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
],
|
||||||
|
"thumbnails":
|
||||||
|
[
|
||||||
|
<#if item.thumbnailNames??>
|
||||||
|
<#list item.thumbnailNames as thumbnailName>
|
||||||
|
"${thumbnailName}"
|
||||||
|
<#if thumbnailName_has_next>,</#if>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
],
|
||||||
|
"lastThumbnailModificationData":
|
||||||
|
[
|
||||||
|
<#if item.lastThumbnailModificationData??>
|
||||||
|
<#list item.lastThumbnailModificationData as lastThumbnailMod>
|
||||||
|
"${lastThumbnailMod}"
|
||||||
|
<#if lastThumbnailMod_has_next>,</#if>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</#escape>
|
||||||
|
</#macro>
|
@@ -0,0 +1,12 @@
|
|||||||
|
<webscript>
|
||||||
|
<shortname>Get some node context (nodeRef, tenantDomain, siteId) for given shared_id</shortname>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Note: authenticated script
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
<url>/api/internal/shared/share/{shared_id}</url>
|
||||||
|
<format default="json" />
|
||||||
|
<authentication>user</authentication>
|
||||||
|
<transaction allow="readonly">required</transaction>
|
||||||
|
</webscript>
|
@@ -0,0 +1,8 @@
|
|||||||
|
<#escape x as jsonUtils.encodeJSONString(x)>
|
||||||
|
{
|
||||||
|
"sharedId" : "${sharedId}",
|
||||||
|
"nodeRef" : "${nodeRef}",
|
||||||
|
"tenantDomain" : "${tenantDomain}",
|
||||||
|
"siteId" : "${siteId}"
|
||||||
|
}
|
||||||
|
</#escape>
|
@@ -0,0 +1,17 @@
|
|||||||
|
<webscript>
|
||||||
|
<shortname>QuickShare - "share" some content => enable public/unauthenticated access</shortname>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Note: Authenticated - you must have read access to the content in order to "share" it.
|
||||||
|
|
||||||
|
Returns {shared_id}
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<url>/api/internal/shared/share/{store_protocol}/{store_id}/{node_id}</url>
|
||||||
|
|
||||||
|
<format default="json">argument</format>
|
||||||
|
<authentication>user</authentication>
|
||||||
|
<lifecycle>internal</lifecycle>
|
||||||
|
</webscript>
|
@@ -0,0 +1,5 @@
|
|||||||
|
<#escape x as jsonUtils.encodeJSONString(x)>
|
||||||
|
{
|
||||||
|
"sharedId" : "${sharedId}"
|
||||||
|
}
|
||||||
|
</#escape>
|
@@ -0,0 +1,14 @@
|
|||||||
|
<webscript>
|
||||||
|
<shortname>QuickShare - "unshare" some content => disable public/unauthenticated access</shortname>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Note: Authenticated - you must have read access to the content in order to "unshare" it.
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<url>/api/internal/shared/unshare/{shared_id}</url>
|
||||||
|
|
||||||
|
<format default="json">argument</format>
|
||||||
|
<authentication>user</authentication>
|
||||||
|
<lifecycle>internal</lifecycle>
|
||||||
|
</webscript>
|
@@ -0,0 +1,5 @@
|
|||||||
|
<#escape x as jsonUtils.encodeJSONString(x)>
|
||||||
|
{
|
||||||
|
"success" : ${success?string}
|
||||||
|
}
|
||||||
|
</#escape>
|
@@ -1840,4 +1840,64 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- BEGIN: QuickShare (aka PublicView) -->
|
||||||
|
|
||||||
|
<!-- unauthenticated (note: equivalent to authenticated "content.get") -->
|
||||||
|
<bean id="webscript.org.alfresco.repository.quickshare.content-noauth.get" class="org.alfresco.repo.web.scripts.quickshare.QuickShareContentGet" parent="webscript">
|
||||||
|
<property name="referenceFactory" ref="CMISReferenceFactory" />
|
||||||
|
<property name="namespaceService" ref="NamespaceService" />
|
||||||
|
<property name="permissionService" ref="PermissionService" />
|
||||||
|
<property name="nodeService" ref="NodeService" />
|
||||||
|
<property name="contentService" ref="ContentService" />
|
||||||
|
<property name="dictionaryService" ref="DictionaryService" />
|
||||||
|
<property name="mimetypeService" ref="MimetypeService" />
|
||||||
|
<property name="CMISRenditionService" ref="CMISRenditionService" />
|
||||||
|
<property name="attributeService" ref="AttributeService" />
|
||||||
|
<property name="tenantService" ref="tenantService" />
|
||||||
|
<property name="enabled" value="${system.quickshare.enabled}" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- unauthenticated (note: equivalent to authenticated "thumbnail.get") -->
|
||||||
|
<bean id="webscript.org.alfresco.repository.quickshare.content-thumbnail-noauth.get" class="org.alfresco.repo.web.scripts.quickshare.QuickShareThumbnailContentGet" parent="webscript.org.alfresco.repository.quickshare.content-noauth.get">
|
||||||
|
<property name="thumbnailService" ref="ThumbnailService" />
|
||||||
|
<property name="scriptThumbnailService" ref="thumbnailServiceScript" />
|
||||||
|
<property name="serviceRegistry" ref="ServiceRegistry"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="org.alfresco.repository.quickshare.abstract" class="org.alfresco.repo.web.scripts.quickshare.AbstractQuickShareContent" abstract="true">
|
||||||
|
<property name="nodeService" ref="NodeService" />
|
||||||
|
<property name="attributeService" ref="AttributeService" />
|
||||||
|
<property name="tenantService" ref="tenantService" />
|
||||||
|
<property name="enabled" value="${system.quickshare.enabled}" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- unauthenticated (note: equivalent to authenticated "metadata.get" (limited version with thumbnail data - see below) -->
|
||||||
|
<bean id="webscript.org.alfresco.repository.quickshare.metadata-noauth.get" class="org.alfresco.repo.web.scripts.quickshare.QuickShareMetaDataGet" parent="org.alfresco.repository.quickshare.abstract">
|
||||||
|
<property name="personService" ref="PersonService" />
|
||||||
|
<property name="thumbnailService" ref="ThumbnailService" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- authenticated -->
|
||||||
|
<bean id="webscript.org.alfresco.repository.quickshare.metadata.get" class="org.alfresco.repo.web.scripts.quickshare.MetaDataGet" parent="org.alfresco.repository.quickshare.abstract">
|
||||||
|
<property name="personService" ref="PersonService" />
|
||||||
|
<property name="thumbnailService" ref="ThumbnailService" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- authenticated -->
|
||||||
|
<bean id="webscript.org.alfresco.repository.quickshare.share.post" class="org.alfresco.repo.web.scripts.quickshare.ShareContentPost" parent="org.alfresco.repository.quickshare.abstract">
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- authenticated -->
|
||||||
|
<bean id="webscript.org.alfresco.repository.quickshare.share.get" class="org.alfresco.repo.web.scripts.quickshare.ShareContentGet" parent="org.alfresco.repository.quickshare.abstract">
|
||||||
|
<property name="siteService" ref="SiteService" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- authenticated -->
|
||||||
|
<bean id="webscript.org.alfresco.repository.quickshare.unshare.delete" class="org.alfresco.repo.web.scripts.quickshare.UnshareContentDelete" parent="org.alfresco.repository.quickshare.abstract" init-method="init">
|
||||||
|
<property name="policyComponent" ref="policyComponent" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- END: QuickShare (aka PublicView) -->
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 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.quickshare;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.alfresco.repo.tenant.TenantService;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||||||
|
import org.alfresco.service.cmr.attributes.AttributeService;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuickShare/PublicView
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*/
|
||||||
|
public abstract class AbstractQuickShareContent extends DeclarativeWebScript
|
||||||
|
{
|
||||||
|
protected NodeService nodeService;
|
||||||
|
protected AttributeService attributeService;
|
||||||
|
protected TenantService tenantService;
|
||||||
|
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttributeService(AttributeService attributeService)
|
||||||
|
{
|
||||||
|
this.attributeService = attributeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantService(TenantService tenantService)
|
||||||
|
{
|
||||||
|
this.tenantService = tenantService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled)
|
||||||
|
{
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isEnabled()
|
||||||
|
{
|
||||||
|
return this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Pair<String, NodeRef> getTenantNodeRefFromSharedId(final String sharedId)
|
||||||
|
{
|
||||||
|
return getTenantNodeRefFromSharedId(attributeService, tenantService, sharedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ static Pair<String, NodeRef> getTenantNodeRefFromSharedId(final AttributeService attributeService, final TenantService tenantService, final String sharedId)
|
||||||
|
{
|
||||||
|
final NodeRef nodeRef = TenantUtil.runAsDefaultTenant(new TenantRunAsWork<NodeRef>()
|
||||||
|
{
|
||||||
|
public NodeRef doWork() throws Exception
|
||||||
|
{
|
||||||
|
return (NodeRef)attributeService.getAttribute(ShareContentPost.ATTR_KEY_SHAREDIDS_ROOT, sharedId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (nodeRef == null)
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find: " + sharedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: relies on tenant-specific (ie. mangled) nodeRef
|
||||||
|
String tenantDomain = tenantService.getDomain(nodeRef.getStoreRef().getIdentifier());
|
||||||
|
|
||||||
|
return new Pair<String, NodeRef>(tenantDomain, tenantService.getBaseName(nodeRef));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 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.quickshare;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.thumbnail.ThumbnailDefinition;
|
||||||
|
import org.alfresco.repo.web.scripts.WebScriptUtil;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.security.NoSuchPersonException;
|
||||||
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
|
import org.springframework.extensions.webscripts.Status;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuickShare/PublicView
|
||||||
|
*
|
||||||
|
* GET web script to get limited metadata (including thumbnail defs) => authenticated web script (using a nodeRef)
|
||||||
|
*
|
||||||
|
* Note: authenticated web script (equivalent to unauthenticated version - see QuickShareMetaDataGet)
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*/
|
||||||
|
public class MetaDataGet extends AbstractQuickShareContent
|
||||||
|
{
|
||||||
|
private static final Log logger = LogFactory.getLog(QuickShareMetaDataGet.class);
|
||||||
|
|
||||||
|
private PersonService personService;
|
||||||
|
private ThumbnailService thumbnailService;
|
||||||
|
|
||||||
|
public void setPersonService(PersonService personService)
|
||||||
|
{
|
||||||
|
this.personService = personService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setThumbnailService(ThumbnailService thumbnailService)
|
||||||
|
{
|
||||||
|
this.thumbnailService = thumbnailService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, Object> executeImpl(final WebScriptRequest req, Status status, Cache cache)
|
||||||
|
{
|
||||||
|
// create map of params (template vars)
|
||||||
|
Map<String, String> params = req.getServiceMatch().getTemplateVars();
|
||||||
|
final NodeRef nodeRef = WebScriptUtil.getNodeRef(params);
|
||||||
|
if (nodeRef == null)
|
||||||
|
{
|
||||||
|
String msg = "A valid NodeRef must be specified!";
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Map<String, Object> model = getMetaDataModel(nodeRef);
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Retrieved limited metadata: "+nodeRef+" ["+model+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
catch (InvalidNodeRefException inre)
|
||||||
|
{
|
||||||
|
logger.error("Unable to find node: "+inre.getNodeRef());
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find nodeRef: "+inre.getNodeRef());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected Map<String, Object> getMetaDataModel(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
QName typeQName = nodeService.getType(nodeRef);
|
||||||
|
if (! typeQName.equals(ContentModel.TYPE_CONTENT))
|
||||||
|
{
|
||||||
|
throw new InvalidNodeRefException(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<QName, Serializable> nodeProps = nodeService.getProperties(nodeRef);
|
||||||
|
ContentData contentData = (ContentData)nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
|
||||||
|
|
||||||
|
String modifierUserName = (String)nodeProps.get(ContentModel.PROP_MODIFIER);
|
||||||
|
Map<QName, Serializable> personProps = null;
|
||||||
|
if (modifierUserName != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
NodeRef personRef = personService.getPerson(modifierUserName);
|
||||||
|
if (personRef != null)
|
||||||
|
{
|
||||||
|
personProps = nodeService.getProperties(personRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NoSuchPersonException nspe)
|
||||||
|
{
|
||||||
|
// absorb this exception - eg. System (or maybe the user has been deleted)
|
||||||
|
if (logger.isInfoEnabled())
|
||||||
|
{
|
||||||
|
logger.info("MetaDataGet - no such person: "+modifierUserName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> metadata = new HashMap<String, Object>(8);
|
||||||
|
|
||||||
|
metadata.put("name", nodeProps.get(ContentModel.PROP_NAME));
|
||||||
|
metadata.put("title", nodeProps.get(ContentModel.PROP_TITLE));
|
||||||
|
|
||||||
|
if (contentData != null)
|
||||||
|
{
|
||||||
|
metadata.put("mimetype", contentData.getMimetype());
|
||||||
|
metadata.put("size", contentData.getSize());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metadata.put("size", 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata.put("modified", nodeProps.get(ContentModel.PROP_MODIFIED));
|
||||||
|
|
||||||
|
if (personProps != null)
|
||||||
|
{
|
||||||
|
metadata.put("modifierFirstName", personProps.get(ContentModel.PROP_FIRSTNAME));
|
||||||
|
metadata.put("modifierLastName", personProps.get(ContentModel.PROP_LASTNAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
// thumbnail defs for this nodeRef
|
||||||
|
List<String> thumbnailDefs = new ArrayList<String>(7);
|
||||||
|
if (contentData != null)
|
||||||
|
{
|
||||||
|
// Note: thumbnail defs only appear in this list if they can produce a thumbnail for the content
|
||||||
|
// found in the content property of this node. This will be determined by looking at the mimetype of the content
|
||||||
|
// and the destination mimetype of the thumbnail.
|
||||||
|
List<ThumbnailDefinition> thumbnailDefinitions = thumbnailService.getThumbnailRegistry().getThumbnailDefinitions(contentData.getMimetype(), contentData.getSize());
|
||||||
|
for (ThumbnailDefinition thumbnailDefinition : thumbnailDefinitions)
|
||||||
|
{
|
||||||
|
thumbnailDefs.add(thumbnailDefinition.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadata.put("thumbnailDefinitions", thumbnailDefs);
|
||||||
|
|
||||||
|
// thumbnail instances for this nodeRef
|
||||||
|
List<NodeRef> thumbnailRefs = thumbnailService.getThumbnails(nodeRef, ContentModel.PROP_CONTENT, null, null);
|
||||||
|
List<String> thumbnailNames = new ArrayList<String>(thumbnailRefs.size());
|
||||||
|
for (NodeRef thumbnailRef : thumbnailRefs)
|
||||||
|
{
|
||||||
|
thumbnailNames.add((String)nodeService.getProperty(thumbnailRef, ContentModel.PROP_NAME));
|
||||||
|
}
|
||||||
|
metadata.put("thumbnailNames", thumbnailNames);
|
||||||
|
|
||||||
|
metadata.put("lastThumbnailModificationData", (List<String>)nodeProps.get(ContentModel.PROP_LAST_THUMBNAIL_MODIFICATION_DATA));
|
||||||
|
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>(1);
|
||||||
|
model.put("item", metadata);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 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.quickshare;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.model.QuickShareModel;
|
||||||
|
import org.alfresco.repo.tenant.TenantService;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||||||
|
import org.alfresco.repo.web.scripts.content.ContentGet;
|
||||||
|
import org.alfresco.service.cmr.attributes.AttributeService;
|
||||||
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuickShare/PublicView
|
||||||
|
*
|
||||||
|
* GET web script to get stream "shared" content (ie. enabled for public/unauthenticated access) from the repository
|
||||||
|
*
|
||||||
|
* WARNING: **unauthenticated** web script (equivalent to authenticated version - see ContentGet.java)
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*/
|
||||||
|
public class QuickShareContentGet extends ContentGet
|
||||||
|
{
|
||||||
|
private static final Log logger = LogFactory.getLog(QuickShareContentGet.class);
|
||||||
|
|
||||||
|
private NodeService nodeService;
|
||||||
|
private NamespaceService namespaceService;
|
||||||
|
private AttributeService attributeService;
|
||||||
|
private TenantService tenantService;
|
||||||
|
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
super.setNodeService(nodeService);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNamespaceService(NamespaceService namespaceService)
|
||||||
|
{
|
||||||
|
this.namespaceService = namespaceService;
|
||||||
|
super.setNamespaceService(namespaceService);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttributeService(AttributeService attributeService)
|
||||||
|
{
|
||||||
|
this.attributeService = attributeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantService(TenantService tenantService)
|
||||||
|
{
|
||||||
|
this.tenantService = tenantService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled)
|
||||||
|
{
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isEnabled()
|
||||||
|
{
|
||||||
|
return this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final WebScriptRequest req, final WebScriptResponse res) throws IOException
|
||||||
|
{
|
||||||
|
if (! isEnabled())
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "QuickShare is disabled system-wide");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create map of template vars (params)
|
||||||
|
final Map<String, String> params = req.getServiceMatch().getTemplateVars();
|
||||||
|
final String sharedId = params.get("shared_id");
|
||||||
|
if (sharedId == null)
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "A valid sharedId must be specified !");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Pair<String, NodeRef> pair = ShareContentPost.getTenantNodeRefFromSharedId(attributeService, tenantService, sharedId);
|
||||||
|
final String tenantDomain = pair.getFirst();
|
||||||
|
final NodeRef nodeRef = pair.getSecond();
|
||||||
|
|
||||||
|
TenantUtil.runAsSystemTenant(new TenantRunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
if (! nodeService.getAspects(nodeRef).contains(QuickShareModel.ASPECT_QSHARE))
|
||||||
|
{
|
||||||
|
throw new InvalidNodeRefException(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
executeImpl(nodeRef, params, req, res, null);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, tenantDomain);
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("QuickShare - retrieved content: "+sharedId+" ["+nodeRef+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (InvalidNodeRefException inre)
|
||||||
|
{
|
||||||
|
logger.error("Unable to find: "+sharedId+" ["+inre.getNodeRef()+"]");
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find: "+sharedId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void executeImpl(NodeRef nodeRef, Map<String, String> templateVars, WebScriptRequest req, WebScriptResponse res, Map<String, Object> model) throws IOException
|
||||||
|
{
|
||||||
|
// render content
|
||||||
|
QName propertyQName = ContentModel.PROP_CONTENT;
|
||||||
|
String contentPart = templateVars.get("property");
|
||||||
|
if (contentPart.length() > 0 && contentPart.charAt(0) == ';')
|
||||||
|
{
|
||||||
|
if (contentPart.length() < 2)
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Content property malformed");
|
||||||
|
}
|
||||||
|
String propertyName = contentPart.substring(1);
|
||||||
|
if (propertyName.length() > 0)
|
||||||
|
{
|
||||||
|
propertyQName = QName.createQName(propertyName, namespaceService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine attachment
|
||||||
|
boolean attach = Boolean.valueOf(req.getParameter("a"));
|
||||||
|
|
||||||
|
// Stream the content
|
||||||
|
streamContent(req, res, nodeRef, propertyQName, attach, model);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 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.quickshare;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.alfresco.model.QuickShareModel;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||||||
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
|
import org.springframework.extensions.webscripts.Status;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuickShare/PublicView
|
||||||
|
*
|
||||||
|
* GET web script to get limited metadata (including thumbnail defs) for some "shared" content
|
||||||
|
*
|
||||||
|
* WARNING: **unauthenticated** web script (equivalent to authenticated version - see MetaDataGet.java)
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*/
|
||||||
|
public class QuickShareMetaDataGet extends MetaDataGet
|
||||||
|
{
|
||||||
|
private static final Log logger = LogFactory.getLog(QuickShareMetaDataGet.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, Object> executeImpl(final WebScriptRequest req, Status status, Cache cache)
|
||||||
|
{
|
||||||
|
if (! isEnabled())
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "QuickShare is disabled system-wide");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create map of params (template vars)
|
||||||
|
Map<String, String> params = req.getServiceMatch().getTemplateVars();
|
||||||
|
final String sharedId = params.get("shared_id");
|
||||||
|
if (sharedId == null)
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "A valid sharedId must be specified !");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Pair<String, NodeRef> pair = getTenantNodeRefFromSharedId(attributeService, tenantService, sharedId);
|
||||||
|
final String tenantDomain = pair.getFirst();
|
||||||
|
final NodeRef nodeRef = pair.getSecond();
|
||||||
|
|
||||||
|
Map<String, Object> model = TenantUtil.runAsSystemTenant(new TenantRunAsWork<Map<String, Object>>()
|
||||||
|
{
|
||||||
|
public Map<String, Object> doWork() throws Exception
|
||||||
|
{
|
||||||
|
if (! nodeService.getAspects(nodeRef).contains(QuickShareModel.ASPECT_QSHARE))
|
||||||
|
{
|
||||||
|
throw new InvalidNodeRefException(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
return getMetaDataModel(nodeRef);
|
||||||
|
}
|
||||||
|
}, tenantDomain);
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("QuickShare - retrieved metadata: "+sharedId+" ["+nodeRef+"]["+model+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
catch (InvalidNodeRefException inre)
|
||||||
|
{
|
||||||
|
logger.error("Unable to find: "+sharedId+" ["+inre.getNodeRef()+"]");
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find: "+sharedId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 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.quickshare;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
|
import org.alfresco.repo.model.Repository;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
import org.alfresco.repo.web.scripts.BaseWebScriptTest;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
|
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.PropertyMap;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.json.JSONTokener;
|
||||||
|
import org.springframework.extensions.webscripts.TestWebScriptServer.DeleteRequest;
|
||||||
|
import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest;
|
||||||
|
import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest;
|
||||||
|
import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class tests QuickShare REST API
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
* @since Cloud/4.1
|
||||||
|
*/
|
||||||
|
public class QuickShareRestApiTest extends BaseWebScriptTest
|
||||||
|
{
|
||||||
|
private static final String USER_ONE = "UserOne";
|
||||||
|
private static final String USER_TWO = "UserTwo";
|
||||||
|
|
||||||
|
private final static String SHARE_URL = "/api/internal/shared/share/{node_ref_3}";
|
||||||
|
|
||||||
|
private final static String UNSHARE_URL = "/api/internal/shared/unshare/{shared_id}";
|
||||||
|
private final static String SHARE_METADATA_URL = "/api/internal/shared/node/{shared_id}/metadata";
|
||||||
|
private final static String SHARE_CONTENT_URL = "/api/internal/shared/node/{shared_id}/content";
|
||||||
|
private final static String SHARE_CONTENT_THUMBNAIL_URL = "/api/internal/shared/node/{shared_id}/content/thumbnails/{thumbnailname}?c=force";
|
||||||
|
|
||||||
|
// note: node_ref_3 => three segments, eg. store_protocol/store_id/node_uuid
|
||||||
|
private final static String AUTH_METADATA_URL = "/api/node/{node_ref_3}/metadata";
|
||||||
|
private final static String AUTH_CONTENT_URL = "/api/node/{node_ref_3}/content";
|
||||||
|
private final static String AUTH_CONTENT_THUMBNAIL_URL = "/api/node/{node_ref_3}/content/thumbnails/{thumbnailname}?c=force";
|
||||||
|
|
||||||
|
private static final String APPLICATION_JSON = "application/json";
|
||||||
|
|
||||||
|
private NodeRef testNode;
|
||||||
|
private final static String TEST_NAME = "test node";
|
||||||
|
private final static String TEST_CONTENT = "test content";
|
||||||
|
private final static String TEST_MIMETYPE_TEXT_PLAIN = MimetypeMap.MIMETYPE_TEXT_PLAIN;
|
||||||
|
private final static String TEST_MIMETYPE_IMAGE_PNG = MimetypeMap.MIMETYPE_IMAGE_PNG;
|
||||||
|
|
||||||
|
private MutableAuthenticationService authenticationService;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private PersonService personService;
|
||||||
|
private PermissionService permissionService;
|
||||||
|
private ContentService contentService;
|
||||||
|
private Repository repositoryHelper;
|
||||||
|
private RetryingTransactionHelper transactionHelper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
authenticationService = (MutableAuthenticationService) getServer().getApplicationContext().getBean("AuthenticationService");
|
||||||
|
nodeService = (NodeService) getServer().getApplicationContext().getBean("NodeService");
|
||||||
|
contentService = (ContentService) getServer().getApplicationContext().getBean("ContentService");
|
||||||
|
personService = (PersonService) getServer().getApplicationContext().getBean("PersonService");
|
||||||
|
permissionService = (PermissionService) getServer().getApplicationContext().getBean("PermissionService");
|
||||||
|
repositoryHelper = (Repository) getServer().getApplicationContext().getBean("repositoryHelper");
|
||||||
|
transactionHelper = (RetryingTransactionHelper)getServer().getApplicationContext().getBean("retryingTransactionHelper");
|
||||||
|
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||||
|
|
||||||
|
createUser(USER_ONE);
|
||||||
|
createUser(USER_TWO);
|
||||||
|
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE);
|
||||||
|
|
||||||
|
testNode = transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>()
|
||||||
|
{
|
||||||
|
public NodeRef execute() throws Throwable
|
||||||
|
{
|
||||||
|
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
|
||||||
|
props.put(ContentModel.PROP_NAME, TEST_NAME);
|
||||||
|
ChildAssociationRef result = nodeService.createNode(repositoryHelper.getUserHome(personService.getPerson(USER_ONE)),
|
||||||
|
ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
|
||||||
|
ContentModel.TYPE_CONTENT, props);
|
||||||
|
|
||||||
|
NodeRef nodeRef = result.getChildRef();
|
||||||
|
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||||
|
writer.setMimetype(TEST_MIMETYPE_TEXT_PLAIN);
|
||||||
|
writer.putContent(TEST_CONTENT);
|
||||||
|
|
||||||
|
return nodeRef;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(USER_TWO);
|
||||||
|
|
||||||
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(testNode, PermissionService.READ));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
super.tearDown();
|
||||||
|
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE);
|
||||||
|
|
||||||
|
transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
if (testNode != null && nodeService.exists(testNode))
|
||||||
|
{
|
||||||
|
nodeService.deleteNode(testNode);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||||
|
|
||||||
|
deleteUser(USER_ONE);
|
||||||
|
deleteUser(USER_TWO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSanityCheckUrls() throws Exception
|
||||||
|
{
|
||||||
|
final int expectedStatusOK = 200;
|
||||||
|
final int expectedStatusNotFound = 404;
|
||||||
|
final int expectedStatusServerError = 500; // currently mapped from AccessDenied (should it be 403, 404 or does it depend on use-case)
|
||||||
|
|
||||||
|
String testNodeRef_3 = testNode.toString().replace("://", "/");
|
||||||
|
|
||||||
|
// As user one ...
|
||||||
|
|
||||||
|
// get metadata for node (authenticated)
|
||||||
|
Response rsp = sendRequest(new GetRequest(AUTH_METADATA_URL.replace("{node_ref_3}", testNodeRef_3)), expectedStatusOK, USER_ONE);
|
||||||
|
JSONObject jsonRsp = new JSONObject(new JSONTokener(rsp.getContentAsString()));
|
||||||
|
String name = jsonRsp.getString("name");
|
||||||
|
assertEquals(TEST_NAME, name);
|
||||||
|
String mimetype = jsonRsp.getString("mimetype");
|
||||||
|
assertEquals(TEST_MIMETYPE_TEXT_PLAIN, mimetype);
|
||||||
|
|
||||||
|
// get content for node (authenticated)
|
||||||
|
rsp = sendRequest(new GetRequest(AUTH_CONTENT_URL.replace("{node_ref_3}", testNodeRef_3)), expectedStatusOK, USER_ONE);
|
||||||
|
String content = rsp.getContentAsString();
|
||||||
|
assertEquals(TEST_CONTENT, content);
|
||||||
|
|
||||||
|
// get content thumbnail for node (authenticated)
|
||||||
|
rsp = sendRequest(new GetRequest(AUTH_CONTENT_THUMBNAIL_URL.replace("{node_ref_3}", testNodeRef_3).replace("{thumbnailname}", "doclib")), expectedStatusOK, USER_ONE);
|
||||||
|
String type = rsp.getContentType();
|
||||||
|
assertEquals(TEST_MIMETYPE_IMAGE_PNG, type);
|
||||||
|
|
||||||
|
// As user two ...
|
||||||
|
|
||||||
|
rsp = sendRequest(new GetRequest(AUTH_METADATA_URL.replace("{node_ref_3}", testNodeRef_3)), expectedStatusServerError, USER_TWO);
|
||||||
|
rsp = sendRequest(new GetRequest(AUTH_CONTENT_URL.replace("{node_ref_3}", testNodeRef_3)), expectedStatusServerError, USER_TWO);
|
||||||
|
rsp = sendRequest(new GetRequest(AUTH_CONTENT_THUMBNAIL_URL.replace("{node_ref_3}", testNodeRef_3).replace("{thumbnailname}", "doclib")), expectedStatusServerError, USER_TWO);
|
||||||
|
|
||||||
|
// As user one ...
|
||||||
|
|
||||||
|
// share
|
||||||
|
rsp = sendRequest(new PostRequest(SHARE_URL.replace("{node_ref_3}", testNodeRef_3), "", APPLICATION_JSON), expectedStatusOK, USER_ONE);
|
||||||
|
jsonRsp = new JSONObject(new JSONTokener(rsp.getContentAsString()));
|
||||||
|
String sharedId = jsonRsp.getString("sharedId");
|
||||||
|
assertNotNull(sharedId);
|
||||||
|
assertEquals(22, sharedId.length()); // note: we may have to adjust/remove this check if we change length of id (or it becomes variable length)
|
||||||
|
|
||||||
|
// As user two ...
|
||||||
|
|
||||||
|
// get metadata for share (note: can be unauthenticated)
|
||||||
|
rsp = sendRequest(new GetRequest(SHARE_METADATA_URL.replace("{shared_id}", sharedId)), expectedStatusOK, USER_TWO);
|
||||||
|
jsonRsp = new JSONObject(new JSONTokener(rsp.getContentAsString()));
|
||||||
|
name = jsonRsp.getString("name");
|
||||||
|
assertEquals(TEST_NAME, name);
|
||||||
|
mimetype = jsonRsp.getString("mimetype");
|
||||||
|
assertEquals(TEST_MIMETYPE_TEXT_PLAIN, mimetype);
|
||||||
|
|
||||||
|
// get content for share (note: can be unauthenticated)
|
||||||
|
rsp = sendRequest(new GetRequest(SHARE_CONTENT_URL.replace("{shared_id}", sharedId)), expectedStatusOK, USER_TWO);
|
||||||
|
content = rsp.getContentAsString();
|
||||||
|
assertEquals(TEST_CONTENT, content);
|
||||||
|
|
||||||
|
// get content thumbnail for share (note: can be unauthenticated)
|
||||||
|
rsp = sendRequest(new GetRequest(SHARE_CONTENT_THUMBNAIL_URL.replace("{shared_id}", sharedId).replace("{thumbnailname}", "doclib")), expectedStatusOK, USER_TWO);
|
||||||
|
type = rsp.getContentType();
|
||||||
|
assertEquals(TEST_MIMETYPE_IMAGE_PNG, type);
|
||||||
|
|
||||||
|
// As user one ...
|
||||||
|
|
||||||
|
// unshare
|
||||||
|
rsp = sendRequest(new DeleteRequest(UNSHARE_URL.replace("{shared_id}", sharedId)), expectedStatusOK, USER_ONE);
|
||||||
|
|
||||||
|
// As user two ...
|
||||||
|
|
||||||
|
// -ve test (should not be able to get metadata or content via sharedId) - whether authenticated or not
|
||||||
|
rsp = sendRequest(new GetRequest(SHARE_METADATA_URL.replace("{shared_id}", sharedId)), expectedStatusNotFound, USER_TWO);
|
||||||
|
rsp = sendRequest(new GetRequest(SHARE_CONTENT_URL.replace("{shared_id}", sharedId)), expectedStatusNotFound, USER_TWO);
|
||||||
|
rsp = sendRequest(new GetRequest(SHARE_CONTENT_THUMBNAIL_URL.replace("{shared_id}", sharedId).replace("{thumbnailname}", "doclib")), expectedStatusNotFound, USER_TWO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createUser(String userName)
|
||||||
|
{
|
||||||
|
if (! authenticationService.authenticationExists(userName))
|
||||||
|
{
|
||||||
|
authenticationService.createAuthentication(userName, "PWD".toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! personService.personExists(userName))
|
||||||
|
{
|
||||||
|
PropertyMap ppOne = new PropertyMap(4);
|
||||||
|
ppOne.put(ContentModel.PROP_USERNAME, userName);
|
||||||
|
ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName");
|
||||||
|
ppOne.put(ContentModel.PROP_LASTNAME, "lastName");
|
||||||
|
ppOne.put(ContentModel.PROP_EMAIL, "email@email.com");
|
||||||
|
ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle");
|
||||||
|
|
||||||
|
personService.createPerson(ppOne);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteUser(String userName)
|
||||||
|
{
|
||||||
|
if (personService.personExists(userName))
|
||||||
|
{
|
||||||
|
personService.deletePerson(userName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 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.quickshare;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
|
||||||
|
import org.alfresco.repo.jscript.ScriptNode;
|
||||||
|
import org.alfresco.repo.thumbnail.script.ScriptThumbnailService;
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.mozilla.javascript.Scriptable;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuickShare/PublicView
|
||||||
|
*
|
||||||
|
* GET web script to stream "shared" thumbnail content (ie. enabled for public/unauthenticated access) from the repository
|
||||||
|
*
|
||||||
|
* WARNING: **unauthenticated** web script (equivalent to authenticated version - see "thumbnail.get.js")
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*/
|
||||||
|
public class QuickShareThumbnailContentGet extends QuickShareContentGet
|
||||||
|
{
|
||||||
|
private static final Log logger = LogFactory.getLog(QuickShareContentGet.class);
|
||||||
|
|
||||||
|
private ThumbnailService thumbnailService;
|
||||||
|
private ScriptThumbnailService scriptThumbnailService;
|
||||||
|
private ServiceRegistry serviceRegistry;
|
||||||
|
|
||||||
|
public void setThumbnailService(ThumbnailService thumbnailService)
|
||||||
|
{
|
||||||
|
this.thumbnailService = thumbnailService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScriptThumbnailService(ScriptThumbnailService scriptThumbnailService)
|
||||||
|
{
|
||||||
|
this.scriptThumbnailService = scriptThumbnailService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceRegistry(ServiceRegistry services)
|
||||||
|
{
|
||||||
|
this.serviceRegistry = services;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void executeImpl(NodeRef nodeRef, Map<String, String> templateVars, WebScriptRequest req, WebScriptResponse res, Map<String, Object> model) throws IOException
|
||||||
|
{
|
||||||
|
String thumbnailName = templateVars.get("thumbnailname");
|
||||||
|
if (thumbnailName == null)
|
||||||
|
{
|
||||||
|
logger.error("Thumbnail name was not provided: "+nodeRef);
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate whether or not the thumbnail can be cached by the browser. Caching is allowed if the lastModified
|
||||||
|
// argument is provided as this is an indication of request uniqueness and therefore the browser will have
|
||||||
|
// the latest thumbnail image.
|
||||||
|
if (model == null)
|
||||||
|
{
|
||||||
|
model = new HashMap<String, Object>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.getParameter("lastModified") != null)
|
||||||
|
{
|
||||||
|
model.put("allowBrowserToCache", "true"); // note: must be String not boolean
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
model.put("allowBrowserToCache", "false"); // note: must be String not boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NodeRef thumbnailNodeRef = thumbnailService.getThumbnailByName(nodeRef, ContentModel.PROP_CONTENT, thumbnailName);
|
||||||
|
|
||||||
|
if (thumbnailNodeRef == null)
|
||||||
|
{
|
||||||
|
// Get the queue/force create setting
|
||||||
|
boolean qc = false;
|
||||||
|
boolean fc = false;
|
||||||
|
String c = req.getParameter("c");
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
if (c.equals("queue"))
|
||||||
|
{
|
||||||
|
qc = true;
|
||||||
|
}
|
||||||
|
else if (c.equals("force"))
|
||||||
|
{
|
||||||
|
fc = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the place holder flag
|
||||||
|
boolean ph = false;
|
||||||
|
String phString = req.getParameter("ph");
|
||||||
|
if (phString != null)
|
||||||
|
{
|
||||||
|
ph = new Boolean(phString);
|
||||||
|
}
|
||||||
|
|
||||||
|
Scriptable scope = new BaseScopableProcessorExtension().getScope(); // note: required for ValueConverter (collection)
|
||||||
|
ScriptNode node = new ScriptNode(nodeRef, serviceRegistry, scope);
|
||||||
|
|
||||||
|
// Queue the creation of the thumbnail if appropriate
|
||||||
|
if (fc)
|
||||||
|
{
|
||||||
|
ScriptNode thumbnailNode = node.createThumbnail(thumbnailName, false);
|
||||||
|
if (thumbnailNode != null)
|
||||||
|
{
|
||||||
|
thumbnailNodeRef = thumbnailNode.getNodeRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (qc)
|
||||||
|
{
|
||||||
|
node.createThumbnail(thumbnailName, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thumbnailNodeRef == null)
|
||||||
|
{
|
||||||
|
if (ph == true)
|
||||||
|
{
|
||||||
|
// Try and get the place holder resource. We use a method in the thumbnail service
|
||||||
|
// that by default gives us a resource based on the content's mime type.
|
||||||
|
String phPath = null;
|
||||||
|
ContentData contentData = (ContentData)this.serviceRegistry.getNodeService().getProperty(nodeRef, ContentModel.PROP_CONTENT);
|
||||||
|
if (contentData != null)
|
||||||
|
{
|
||||||
|
phPath = scriptThumbnailService.getMimeAwarePlaceHolderResourcePath(thumbnailName, contentData.getMimetype());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phPath == null)
|
||||||
|
{
|
||||||
|
// 404 since no thumbnail was found
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Thumbnail was not found and no place holder resource set for '" + thumbnailName + "'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set the resouce path in the model ready for the content stream to send back to the client
|
||||||
|
model.put("contentPath", phPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 404 since no thumbnail was found
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Thumbnail was not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.executeImpl(thumbnailNodeRef, templateVars, req, res, model);
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("QuickShare - retrieved thumbnail content: "+thumbnailNodeRef+" ["+nodeRef+","+thumbnailName+"]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 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.quickshare;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.site.SiteInfo;
|
||||||
|
import org.alfresco.service.cmr.site.SiteService;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
|
import org.springframework.extensions.webscripts.Status;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuickShare/PublicView
|
||||||
|
*
|
||||||
|
* GET web script to lookup some context (nodeRef, tenantDomain, siteId) for a given "Share"
|
||||||
|
*
|
||||||
|
* Note: authenticated web script
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*/
|
||||||
|
public class ShareContentGet extends AbstractQuickShareContent
|
||||||
|
{
|
||||||
|
private static final Log logger = LogFactory.getLog(ShareContentPost.class);
|
||||||
|
|
||||||
|
protected SiteService siteService;
|
||||||
|
|
||||||
|
public void setSiteService(SiteService siteService)
|
||||||
|
{
|
||||||
|
this.siteService = siteService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||||
|
{
|
||||||
|
if (! isEnabled())
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "QuickShare is disabled system-wide");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create map of params (template vars)
|
||||||
|
Map<String, String> params = req.getServiceMatch().getTemplateVars();
|
||||||
|
final String sharedId = params.get("shared_id");
|
||||||
|
if (sharedId == null)
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "A valid sharedId must be specified !");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Pair<String, NodeRef> pair = getTenantNodeRefFromSharedId(attributeService, tenantService, sharedId);
|
||||||
|
final String tenantDomain = pair.getFirst();
|
||||||
|
final NodeRef nodeRef = pair.getSecond();
|
||||||
|
|
||||||
|
SiteInfo siteInfo = siteService.getSite(nodeRef);
|
||||||
|
|
||||||
|
String siteId = null;
|
||||||
|
if (siteInfo != null)
|
||||||
|
{
|
||||||
|
siteId = siteInfo.getShortName();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>(3);
|
||||||
|
model.put("sharedId", sharedId);
|
||||||
|
model.put("nodeRef", nodeRef.toString());
|
||||||
|
model.put("siteId", siteId);
|
||||||
|
model.put("tenantDomain", tenantDomain);
|
||||||
|
|
||||||
|
if (logger.isInfoEnabled())
|
||||||
|
{
|
||||||
|
logger.info("QuickShare - get shared context: "+sharedId+" ["+model+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
catch (InvalidNodeRefException inre)
|
||||||
|
{
|
||||||
|
logger.error("Unable to find: "+sharedId+" ["+inre.getNodeRef()+"]");
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find: "+sharedId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 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.quickshare;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.model.QuickShareModel;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||||||
|
import org.alfresco.repo.web.scripts.WebScriptUtil;
|
||||||
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.safehaus.uuid.UUID;
|
||||||
|
import org.safehaus.uuid.UUIDGenerator;
|
||||||
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
|
import org.springframework.extensions.webscripts.Status;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuickShare/PublicView
|
||||||
|
*
|
||||||
|
* POST web script to "Share" access to some content (ie. enable unauthenticated access to this node)
|
||||||
|
*
|
||||||
|
* Note: authenticated web script
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*/
|
||||||
|
public class ShareContentPost extends AbstractQuickShareContent
|
||||||
|
{
|
||||||
|
private static final Log logger = LogFactory.getLog(ShareContentPost.class);
|
||||||
|
|
||||||
|
/* package */ static final String ATTR_KEY_SHAREDIDS_ROOT = ".sharedIds";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||||
|
{
|
||||||
|
if (! isEnabled())
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "QuickShare is disabled system-wide");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create map of params (template vars)
|
||||||
|
Map<String, String> params = req.getServiceMatch().getTemplateVars();
|
||||||
|
final NodeRef nodeRef = WebScriptUtil.getNodeRef(params);
|
||||||
|
if (nodeRef == null)
|
||||||
|
{
|
||||||
|
String msg = "A valid NodeRef must be specified!";
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
QName typeQName = nodeService.getType(nodeRef);
|
||||||
|
if (! typeQName.equals(ContentModel.TYPE_CONTENT))
|
||||||
|
{
|
||||||
|
throw new InvalidNodeRefException(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String sharedId;
|
||||||
|
|
||||||
|
if (! nodeService.getAspects(nodeRef).contains(QuickShareModel.ASPECT_QSHARE))
|
||||||
|
{
|
||||||
|
UUID uuid = UUIDGenerator.getInstance().generateRandomBasedUUID();
|
||||||
|
sharedId = Base64.encodeBase64URLSafeString(uuid.toByteArray()); // => 22 chars (eg. q3bEKPeDQvmJYgt4hJxOjw)
|
||||||
|
|
||||||
|
Map<QName,Serializable> props = new HashMap<QName,Serializable>(2);
|
||||||
|
props.put(QuickShareModel.PROP_QSHARE_SHAREDID, sharedId);
|
||||||
|
props.put(QuickShareModel.PROP_QSHARE_SHAREDBY, AuthenticationUtil.getRunAsUser());
|
||||||
|
|
||||||
|
nodeService.addAspect(nodeRef, QuickShareModel.ASPECT_QSHARE, props);
|
||||||
|
|
||||||
|
final NodeRef tenantNodeRef = tenantService.getName(nodeRef);
|
||||||
|
|
||||||
|
TenantUtil.runAsDefaultTenant(new TenantRunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
attributeService.setAttribute(tenantNodeRef, ATTR_KEY_SHAREDIDS_ROOT, sharedId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (logger.isInfoEnabled())
|
||||||
|
{
|
||||||
|
logger.info("QuickShare - shared content: "+sharedId+" ["+nodeRef+"]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sharedId = (String)nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDID);
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("QuickShare - content already shared: "+sharedId+" ["+nodeRef+"]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>(1);
|
||||||
|
model.put("sharedId", sharedId);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
catch (InvalidNodeRefException inre)
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find node: " + nodeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 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.quickshare;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.model.QuickShareModel;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies;
|
||||||
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||||||
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.EqualsHelper;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
|
import org.springframework.extensions.webscripts.Status;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptException;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuickShare/PublicView
|
||||||
|
*
|
||||||
|
* DELETE web script to "Unshare" access to some content (ie. disable unauthenticated access to this node)
|
||||||
|
*
|
||||||
|
* Note: authenticated web script
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
*/
|
||||||
|
public class UnshareContentDelete extends AbstractQuickShareContent implements NodeServicePolicies.BeforeDeleteNodePolicy
|
||||||
|
{
|
||||||
|
private static final Log logger = LogFactory.getLog(ShareContentPost.class);
|
||||||
|
|
||||||
|
protected PolicyComponent policyComponent;
|
||||||
|
|
||||||
|
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||||
|
{
|
||||||
|
this.policyComponent = policyComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initialise method
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
// Register interest in the beforeDeleteNode policy - note: currently for content only !!
|
||||||
|
policyComponent.bindClassBehaviour(
|
||||||
|
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||||
|
ContentModel.TYPE_CONTENT,
|
||||||
|
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||||
|
{
|
||||||
|
if (! isEnabled())
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "QuickShare is disabled system-wide");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create map of params (template vars)
|
||||||
|
Map<String, String> params = req.getServiceMatch().getTemplateVars();
|
||||||
|
final String sharedId = params.get("shared_id");
|
||||||
|
if (sharedId == null)
|
||||||
|
{
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "A valid sharedId must be specified !");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Pair<String, NodeRef> pair = getTenantNodeRefFromSharedId(attributeService, tenantService, sharedId);
|
||||||
|
final String tenantDomain = pair.getFirst();
|
||||||
|
final NodeRef nodeRef = pair.getSecond();
|
||||||
|
|
||||||
|
TenantUtil.runAsSystemTenant(new TenantRunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
QName typeQName = nodeService.getType(nodeRef);
|
||||||
|
if (! typeQName.equals(ContentModel.TYPE_CONTENT))
|
||||||
|
{
|
||||||
|
throw new InvalidNodeRefException(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
String nodeSharedId = (String)nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDID);
|
||||||
|
|
||||||
|
if (! EqualsHelper.nullSafeEquals(nodeSharedId, sharedId))
|
||||||
|
{
|
||||||
|
logger.warn("SharedId mismatch: expected="+sharedId+",actual="+nodeSharedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeService.removeAspect(nodeRef, QuickShareModel.ASPECT_QSHARE);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, tenantDomain);
|
||||||
|
|
||||||
|
removeSharedId(sharedId);
|
||||||
|
|
||||||
|
if (logger.isInfoEnabled())
|
||||||
|
{
|
||||||
|
logger.info("QuickShare - unshared content: "+sharedId+" ["+nodeRef+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>(1);
|
||||||
|
model.put("success", Boolean.TRUE);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
catch (InvalidNodeRefException inre)
|
||||||
|
{
|
||||||
|
logger.error("Unable to find: "+sharedId+" ["+inre.getNodeRef()+"]");
|
||||||
|
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find: "+sharedId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// behaviour - currently registered for content only !!
|
||||||
|
// note: will remove "share" even if node is only being archived (ie. moved to trash) => a subsequent restore will *not* restore the "share"
|
||||||
|
public void beforeDeleteNode(final NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
String sharedId = (String)nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDID);
|
||||||
|
if (sharedId != null)
|
||||||
|
{
|
||||||
|
removeSharedId(sharedId);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeSharedId(final String sharedId)
|
||||||
|
{
|
||||||
|
TenantUtil.runAsDefaultTenant(new TenantRunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
attributeService.removeAttribute(ShareContentPost.ATTR_KEY_SHAREDIDS_ROOT, sharedId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user