Public urls with expiration in Alfresco Share

How to deal with public documents in Alfresco

In the past, we published some blog posts about public shared content functionality in Alfresco Share, and the implications of having undesired and uncontrolled public content in production enviroments. 

In the previous posts, we tried to help Alfresco administrators to control the urls published by final users, via simple Alfresco FTS queries or even with a virtual folder template. But, in many situations we would like some kind of expiration date for that public content. In that case, we need:

  •  A custom behaviour for adding two properties for managing the expiration date. We use cm:effectivity aspect that defines two properties cm:from and cm:to (we only will use the last property). The custom behaviour would add aspect cm:effectivity, obtaining today's date, and setting cm:to for a month later by default. The behaviour is implemented with Javascript API on add aspect policy name. 
  •     <!-- Registration of JS content behaviour on Add Aspect-->
        <bean id="OnAddAspectPolicyOnQshared" class="org.alfresco.repo.policy.registration.ClassPolicyRegistration" parent="policyRegistration">
            <property name="policyName">
            <property name="className">
            <property name="behaviour">
                <bean class="org.alfresco.repo.jscript.ScriptBehaviour" parent="scriptBehaviour">
                    <property name="location">
                        <bean class="org.alfresco.repo.jscript.ClasspathScriptLocation">
  • //
    // add-aspect-effectivity.js
    // Effectivity script for custom behaviour on adding aspect qshared
    function getFormattedDate(mydate) {
        var str = mydate.getFullYear() + "-" + (mydate.getMonth() + 1) + "-" + mydate.getDate() 
        return str;
    // Have a look at the behaviour object that should have been passed
    if (behaviour == null) {
        logger.log("The behaviour object has not been set.");
        scriptFailed = true;
    // Check the name of the behaviour
    if ( == null && != "onUpdateProperties") {
        logger.log("The behaviour name has not been set correctly.");
        scriptFailed = true;
    } else {
        logger.log("Behaviour name: " +;
    // Check behaviour arguments
    if (behaviour.args == null) {
        logger.log("The args have not been set.");
        scriptFailed = true;
    } else {
        var node   = behaviour.args[0];
        var before = behaviour.args[1];
        var after  = behaviour.args[2];
        var date1  = new Date();
        var date2  = new Date();
   ["cm:from"] = getFormattedDate(date1);["cm:to"]   = getFormattedDate(date2);
        logger.warn("[zk] Setting effectivity sharing to: " + getFormattedDate(date2) );;
  •  We need also a daily quartz for checking cm:to and removing qshare:shared aspect. This is also implemented with Javascript API:
  • var nodes = search.luceneSearch('ASPECT:"qshare:shared" AND @cm\\:to:[MIN TO NOW]');
    var count = 0;
    logger.warn("[zk] Starting effectivity qshared:");
    for each(var node in nodes) {
      count = count + 1;
      logger.warn(count + ": "+node.displayPath+"/";
      logger.warn("[zk] This public url is expired --> "["cm:to"]);
      logger.warn("[zk] Cleaning the aspect..");
    logger.warn("[zk] Done.");
  •  Finally, the component uses custom metadata template and indicator for the managed content.

The full details on the customization are published in our corporate github:


More Blog Entries