Montag, 17. Februar 2014

Alfresco Share - remove Create Site Link from new header bar (4.2.e)

The header menu bar in Alfresco Share changed in 4.2.d to a completely new design. With the new design, there also comes a new way for customization and since I have not found an instruction to remove the "Create Site" menu entry for non admin users, I decided to document that here.
This instruction will ONLY work from 4.2.e and I only tested in on 4.2.e. There are some good blog entries why it is not working on 4.2.d, so I will not discuss that here anymore.

I will not create an own JAR file for that customization, but do all in the shared directory. Perhaps I will provide a JAR file too, if I have some time which is quite rare.

1. Create a share module
create file shared/classes/alfresco/web-extension/site-data/extension/remove-create-site-extension.xml
<extension>
 <modules>
  <module>
   <id>Remove create site menu option for non admin users</id>
   <version>1.0</version>
   <customizations>
    <customization>
     <targetPackageRoot>org.alfresco.share.header</targetPackageRoot>
     <sourcePackageRoot>ingen.header</sourcePackageRoot>
    </customization>
    <customization>
     <targetPackageRoot>org.alfresco.components.dashlets</targetPackageRoot>
     <sourcePackageRoot>ingen.dashlets</sourcePackageRoot>
    </customization>
   </customizations>
  </module>
 </modules>
</extension>
2. customize header webscript
create file shared/classes/alfresco/web-extension/site-webscripts/ingen/header/share-header.get.js
//Find the "Sites" menu...
var sitesMenu = widgetUtils.findObject(model.jsonModel, "id", "HEADER_SITES_MENU");

if (sitesMenu != null) {
 if (!user.isAdmin) {
  sitesMenu.config.showCreateSite = false;
 }
}
3. the 'my sites' dashlet
create file shared/classes/alfresco/web-extension/site-webscripts/ingen/dashlets/my-sites.get.js
if (!user.isAdmin) {
 model.showCreateSite = false;
}
4. don't forget the dynamic-welcome dashlet
Thanks Douglas for remembering me about the dynamic-welcome dashlet and the create site link in there. To remove that link create file shared/classes/alfresco/web-extension/site-webscripts/ingen/dashlets/dynamic-welcome.get.js
if (args.dashboardType == "user" && !user.isAdmin) {
 model.columns[1].actionMsg = null;
 model.columns[1].actionHref = null;
}
5. restart alfresco share
6. activate module

Now everything should be fine. But don't forget to restrict the service calls too - especially if you want to be sure that any left link, direct call and alternative frontend (mobile, ...) are save too ;)

Sonntag, 16. Februar 2014

Alfresco Share - disable site creation for non admin user

It's quite a common use case to restrict site creation in Alfresco Share to admin users only.

There are some good instructions out there describing how to do that: http://www.chipnick.com/blog/2013/04/09/restrict-site-creation-to-administrators-in-alfresco/ 

Short description:
  • configure permissions (important, otherwise the user can call the link directly or use another interface (like mobile app))
  • remove site creation link in front end

I will concentrate on the permission part in this post only. There will be another post how to remove the link (especially in 4.2.e onwards).

Without RM module just configure the security layer to restrict calls to the createSite Method of the SiteService. You can do that by simply creating a file shared/classes/alfresco/extension/custom-public-services-security-context.xml:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>

<beans>
    
    <!-- ============ -->
    <!-- Site Service -->
    <!-- ============ -->
    
    <bean id="SiteService_security" class="org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityInterceptor">
        <property name="authenticationManager"><ref bean="authenticationManager"/></property>
        <property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
        <property name="afterInvocationManager"><ref bean="afterInvocationManager"/></property>
        <property name="objectDefinitionSource">
            <value>
               org.alfresco.service.cmr.site.SiteService.cleanSitePermissions=ACL_NODE.0.sys:base.ReadProperties
               org.alfresco.service.cmr.site.SiteService.createContainer=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
               org.alfresco.service.cmr.site.SiteService.createSite=ACL_METHOD.ROLE_ADMINISTRATOR
               org.alfresco.service.cmr.site.SiteService.deleteSite=ACL_METHOD.ROLE_ADMINISTRATOR
               org.alfresco.service.cmr.site.SiteService.findSites=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
               org.alfresco.service.cmr.site.SiteService.getContainer=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
               org.alfresco.service.cmr.site.SiteService.listContainers=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
               org.alfresco.service.cmr.site.SiteService.getMembersRole=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.getMembersRoleInfo=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.resolveSite=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.getSite=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
               org.alfresco.service.cmr.site.SiteService.getSiteShortName=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
               org.alfresco.service.cmr.site.SiteService.getSiteGroup=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.getSiteRoleGroup=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.getSiteRoles=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.getSiteRoot=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
               org.alfresco.service.cmr.site.SiteService.hasContainer=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.hasCreateSitePermissions=ACL_METHOD.ROLE_ADMINISTRATOR
               org.alfresco.service.cmr.site.SiteService.hasSite=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.isMember=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.listMembers=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.listMembersInfo=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.listMembersPaged=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.listSites=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
               org.alfresco.service.cmr.site.SiteService.listSitesPaged=ACL_ALLOW,AFTER_ACL_NODE.sys:base.ReadProperties
               org.alfresco.service.cmr.site.SiteService.removeMembership=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.canAddMember=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.setMembership=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.updateSite=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.countAuthoritiesWithRole=ACL_ALLOW
               org.alfresco.service.cmr.site.SiteService.*=ACL_DENY
            </value>
        </property>
    </bean>
 
</beans>
So everything should be fine. BUT NOT if you have installed the records management module (RM).

The RM module adds some own custom security settings (adds a rmEntryVoter voter in file rm-public-services-security-context.xml to the bean accessDecisionManager) which "overrides" the normal security settings and breaks the customization from above.

Customization with RM module:

It's much easier as you might except. Just add a file shared/classes/alfresco/extension/rm-method-security.properties with following content:
rm.methodsecurity.org.alfresco.service.cmr.site.SiteService.createSite=ACL_METHOD.ROLE_ADMINISTRATOR
rm.methodsecurity.org.alfresco.service.cmr.site.SiteService.hasCreateSitePermissions=ACL_METHOD.ROLE_ADMINISTRATOR
I tested that with Alfresco Community 4.2.e and RM version 2.1.0-621.

Credits:
Thanks to Ahmed (Ashex on #alfresco irc channel) for discussing the problem on IRC and for your good instructions on your blog.

Freitag, 31. Januar 2014

Alfresco Share Previewer - set default zoom level to "Fit Width"

The default zoom level of Alfresco Share's Previewer is "Fit Page", which is not perfect for all of us. In our use case we needed default of "Fit Width", but there is no option/overridable setting for that. The only way is to recompile the flash file.

Here is a step-by-step guide to change the setting:


1. check out source of webpreviewer:

I think every developer has some SVN client of his/her choice installed. If not and you don't understand what this means, you should stop now ;)

svn co http://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/HEAD/root/projects/slingshot/source/as/webpreviewer webpreviewer

2. download/install Adobe Flash Builder Premium 4.7

You can use the evaluation version, there is nor difference in the outcome. Of course you can do that with the free Flex SDK too, but it is more work.

3. open Flash Builder and import a new project:


Select the folder where you checked out the source. Its important to set the SDK to "FLEX 3.6A" to support older flash players.

No changes on the second screen.

Click on browser for the main application file - choose the WebPreviewer.mxml.

After clicking "Finish" you should see the project in your workspace.

4. Change source

Open the file PreviewerClass.as and change method onDocumentSnapPointsChange(...) in line 289:

zoomSlider.value = event.fitToWidth;


5. compile the project with "Export release build"


6. Deploy File

Copy the file WebPreviewer.swf that was just created to your share web application folder.
/tomcat/webapps/share/components/preview/ and override the original file. Perhaps you want to make a backup copy of the original file ;)

7. Test

Open Share in your browser, no server restart needed. Perhaps you have to refresh your browser cache.


You should see the previewer opening in the new default view mode.