A Quick Script to add Public Links to all assets in the Sitecore Content Hub

Intro

Adding public links to all assets in Sitecore Content Hub is a task that often needs to be done during migration projects. In this document, I will provide a recipe for accomplishing this task.

Prerequisites

  • Familiarity with Sitecore Content Hub
  • Access to Content Hub and the ability to execute scripts

Please refer to the Sitecore documentation for more information on how to create, manage, and execute scripts in Content Hub.

Recipe

The following script can be executed in Content Hub to add public links to all assets:

  1. Find assets that match specific filtering criteria: Modify the script to match your specific criteria. In the example provided, the script matches assets created by a specific user using the createdByUser field. Update this field as needed.
  2. Create an Entity ID scroller: This allows you to update a large number of assets. Note that other types of iterators may only work on smaller collections.
  3. Create an asset rendition and attach a public link: In the example, a single downloadOriginal rendition is created. You can add additional renditions by changing the value of the rendition parameter in the CreateRendition function.

The script includes basic logging functionality as an example. Feel free to update the logging according to your needs. Refer to the Sitecore documentation for more details on script logging.

Script

using System.Linq;
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Stylelabs.M.Base.Querying;
using Stylelabs.M.Base.Querying.Linq;

try
{
    MClient.Logger.Info($"Init query");
    var query = Query.CreateQuery(entities =>
                            from e in entities
                            where (e.DefinitionName == "M.Asset" && e.CreatedByUsername == "sergey.yatsenko@xcentium.com")
                            select e);
    MClient.Logger.Info($"Init results");
    var results = new List<long>();
    //Deal with very large result sets (over 50 for OOTB queries and over 10000 for iterators)
    var scroller = MClient.Querying.CreateEntityIdScroller(query, TimeSpan.FromSeconds(30));
    while (await scroller.MoveNextAsync().ConfigureAwait(false))
    {
        var ids = scroller.Current.Items;
        if (ids != null && ids.Any())
        {
            results.AddRange(ids);
        }
    }
    if (results != null && results.Any())
    {
        MClient.Logger.Info($"Found entities. Count: {results.Count}, IDs: {String.Join(",", results)}");
        foreach(var entityId in results)
        {
            await CreateRendition("downloadOriginal", entityId);
        }
    }
}
catch (Exception ex)
{
    //Log and re-throw the exception
    MClient.Logger.Error($"error message: {ex.Message}");
    throw;
}
async Task<bool> CreateRendition(string rendition, long assetId)
{
    try
    {
        var publicLink = await MClient.EntityFactory.CreateAsync("M.PublicLink");
        if (publicLink.CanDoLazyLoading())
        {
            await publicLink.LoadMembersAsync(new PropertyLoadOption("Resource"), new RelationLoadOption("AssetToPublicLink"));
        }
        publicLink.SetPropertyValue("Resource", rendition);
        var relation = publicLink.GetRelation<IChildToManyParentsRelation>("AssetToPublicLink");
        if (relation == null)
        {
            MClient.Logger.Error("Unable to create public link: no AssetToPublicLink relation found.");
            return false;
        }
        relation.Parents.Add(assetId);
        await MClient.Entities.SaveAsync(publicLink);
        return true;
    }
    catch (Exception ex)
    {
        //Log and swallow the exception
        MClient.Logger.Error($"error message: {ex.Message}");
        return false;
    }
}