Experience Sitecore ! | March 2023

Experience Sitecore !

More than 200 articles about the best DXP by Martin Miles

Challenges of an international travelling in 2023 or how things can go unexpectedly wrong

I am the kind of person who tries to predict and avoid potential problems way before they even can occur. Risk Management presents in every single cell circulating in my blood – partly because of some sort of professional deformation as well as a natural curiosity and lessons learned from others’ mistakes. But sometimes things can go very unpredictably and you’re left on your own.

That is a triple miracle that I made it back to the US from the conference, but in fact that is a set of three independent miracles.

First, getting to and from Spain. It was a lucky coincidence of me buying both onward and return tickets on those rare lucky days right in between a series of air traffic control strikes across European airports.

I made my flight back early on Saturday and some of those who left for a weekend could not make it because of air control strikes in France and Germany. Even if you’re not French or German, there is a big change of making layout/change at one of their airports, as there are no direct flights to the USA from the medium Spanish airports. Likewise, when flying in, I changed the LAX plane in Frankfurt, for Malaga. After Spain itself joined the strikes from that weekend, it would be even fewer chances to fly away, so I feel exceptionally lucky from departing early and departing through the UK which joins the airport strikes slightly later giving me enough time to leave Europe.

Going next. Early Monday morning I showed up at Heathrow airport as normal and then got denied boarding for an “expired” barcode on my COVID certificate. I used one for flying all the time including in the UK and it has never been a problem. That could be a minor problem, at least I am vaccinated there in the UK and the records should be available. I memorize all my passwords so can easily log in to the app or the website…. Incorrect! Whoever did the app made it with mandatory 2-factor authentication by sending a text to your number. But I don’t have my old UK number, after moved back to the states. Now you see, how one minor problem turns into a much bigger one.

Trying to escalate it with all levels of management did not help at all, this type of person is just simply sitting their paid hours and do not want to step the extra mile. “Computer says no” – is an accurate description of dealing with them. So, I was denied boarding for a stupid reason, and the clock’s ticking…

In a critical situation, your mind works differently, brainstorming any possible outcomes under stress. I remembered that did switching that original number (I did not even remember the actual digits) to a pre-paid plan and put it somewhere in storage along with some old phone. Or had to call someone who could access it there, but it was 3AM there in California. Chances to: 1) wake up the right person in order to ..2) understand your uncertain instructions and... 3) manage to follow them up correctly - that multiplied together are so low! But I made all that happen in a permitted window of 30 minutes - such a miracle! Unbelievable!

After receiving the code, I was able to pass through a line of unwanted difficult questions and eventually generate my certificates in the mobile app. And guess what? That check-in lady neither did not scan the updated barcode nor entered it somewhere. At all! Just said “now ok” and that was it. So she potentially could let me board with an "expired" "barcode" since everything she “checked” was the date label above it. The impact of losing a flight and being stuck in an airport limbo with heavy bags on you (not to say $1-2K to pay for a replacement flight) is a huge penalty when things go wrong mainly because of inadequate and non-transparent procedures and human robots who follow them. This system is definitely broken. The humans behind it are also “broken” in a similar way.

That’s not all. By the time I passed the above line of traps for showing robots-people the right label they wanted to see, they had put my ticket into a STANBY status, which means I was not guaranteed a seat for BOTH legs of my flight, not just trans-Atlantic segment. They boarded me to Phoenix without giving me a following ticked, which I need to get there.

The first segment of my trip was delayed for 2 hours so I only had something less than 40 minutes to clear the customs and immigration, re-check the bags to a final destination (praying it reaches the plane in time) and run myself long way to the departure gate. Long story short, I was the fastest person to get off the plane and pass all the procedures, rechecking the bags, running through additional security, etc. but reached the “gate closed” door, and boarding assistance are just moving away. I had to run as fast as possible, waive my arm and shout "do not close" to pay their attention, then ask them to let me on the plane. Emotions burst and the timing was so precise - an extra 20 seconds would leave me staying overnight at Phoenix and possibly paying for a final segment, but this type of luck followed me the whole day so both I and my bags magically arrived at Orange County airport in time.

What a crazy day it was!

XM Cloud: a modern way to content management and import with Authoring GraphQL API

When it comes to content management, how would you deal with automating it?

You’ve probably thought of Data Exchange Framework for setting up content import from external sources on a regular basis, or Sitecore PowerShell Extensions as the universal Swiss Army knife that allows doing everything.

Sitecore XM Cloud is a modern SaaS solution and therefore offers you one more way of managing and importing content via GraphQL mutations. This is also an option for the latest 10.3 XM/XP platforms bringing them a step closer to the composable world of today.

There is a video walkthrough of the wholee exercise at the bottom of this post.

Please welcome: Authoring and Management API!

The documentation prompts a broad and awe-inspiring list of things you can do with Authoring API against your instance: create and delete items, templates, and media. It also empowers you to do some operations around site context and perform a content search on your CM instance.

Management API in addition gives you control over operations using queries and mutations for the following GraphQL types:

  • Archiving
  • Database
  • Indexing
  • Job
  • Language
  • Publishing
  • Security
  • Workflow
  • Rules

With that in mind, you can create and structure your content, reindex, and publish it to Experience Edge entirely using this API. So let’s take a look at how it works!

Uploading a picture to Media Library using GraphQL Authoring API

First of all, it is disabled by default, so we need to switch by setting Sitecore_GraphQL_ExposePlayground environmental variable to true. Since these variables expand at build time you also need to re-deploy the environments

Enable Api

Once deployment is complete, you can start playing with it. Security in a composable world typically works with OAuth, Authoring and Management API is not an exclusion here. In order to obtain an access token, you need to authorize it first with your client ID and client secret which you set up with XM Cloud Deploy app:

Token

There are different ways of authorization (for example, using CLI dotnet sitecore cloud login command), but since the need to fully automate the routine, I will be using /oauth/token endpoint. Also, it is worth mentioning that after getting initially already authorized with CLI, your client ID / secret pair is stored at .sitecore\user.json file so let’s take it from there. Here’s the code:

$userJson = "$PSScriptRoot/../../.sitecore/user.json"

if(-not(Test-Path$userJson)){
    Write-Error"The specified file '$userJson' does not exist."
    return
}

$userJson = Get-Content$userJson | ConvertFrom-Json
$clientId = $userJson.endpoints.xmCloud.clientId
$clientSecret = $userJson.endpoints.xmCloud.clientSecret
$authorityUrl = $userJson.endpoints.xmCloud.authority
$audience = $userJson.endpoints.xmCloud.audience
$grantType = "client_credentials"

$body = @{
    client_id = $clientId
    client_secret = $clientSecret
    audience = $audience
    grant_type = $grantType
}

$response = Invoke-RestMethod -Uri "${authorityUrl}oauth/token" -Method Post -ContentType "application/x-www-form-urlencoded" -Body $body
return $response.access_token

Now we got the access token and it should be passed as a header with every single request to GraphQL API:

“Authorization” = “Bearer <access_token>”

Next, let’s make a mutation query that returns us a pre-signed upload URL from the passing API endpoint and a target Sitecore path that you want to upload your media to. Here’s the code:

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true, HelpMessage="The URL of the endpoint where the file will be uploaded.")]
    [string]$EndpointUrl,
    [Parameter(Mandatory=$true, HelpMessage="The JWT token to use for authentication.")]
    [string]$JWT,
    [Parameter(Mandatory=$true, HelpMessage="The path of the file to be uploaded.")]
    [string]$UploadPath
)

$query = @"
mutation
{
  uploadMedia(input: { itemPath: "$UploadPath" }) {
    presignedUploadUrl
  }
}
"@

$body = @{ query = $query} | ConvertTo-Json
$headers = @{
    "Content-Type" = "application/json"
    "Authorization" = "Bearer $JWT"
}

# Invoke the GraphQL endpoint using Invoke-RestMethod and pass in the query and headers
$response = Invoke-RestMethod -Method POST -Uri $EndpointUrl -Headers $headers -Body $body
$result = $response.data.uploadMedia
return $result.presignedUploadUrl

Now that we have the pre-signed upload URL, we can perform media upload passing the local file to process:

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true, HelpMessage="The URL to upload the file to.")]
    [string]$UploadUrl,
    [Parameter(Mandatory=$true, HelpMessage="The JWT token to use for authentication.")]
    [string]$JWT,
    [Parameter(Mandatory=$true, HelpMessage="The path to the file to be uploaded.")]
    [string]$FilePath
)

if(-not(Test-Path$FilePath)){
    Write-Error"The specified file '$FilePath' does not exist."
    return
}

$result = & curl.exe --request POST $UploadUrl --header "Authorization: Bearer $JWT" --form =@"$FilePath" -s
$result = $result | ConvertFrom-Json
return $result

This script will return the details of a newly uploaded media item, such as:

  • item name
  • item full path
  • item ID

I combined all the above cmdlets into a single Demo-UploadPicture.ps1 script that cares about passing all the parameters and performs the upload operation:

Powershell

The upload immediately results in Media Library at the requested path:

Result

Pros:

  • a modern platform agnostic approach
  • works nicely with webhooks
  • allows automating pretty much everything
  • excellent management options making DevOps easier

Cons:

  • cumbersome token operations
  • doesn’t allow batching, therefore takes a request per each operation

Verdict

It is great to have a variety of different tools in your belt rather than having a single hammer in a hand with everything around turning into nails. Hope this new tool brings your automation skills to a new level!