Field Locking provides the ability to lock individual fields or objects from changes without explicit override of the locks.

Lock principles

A field inside a particular resource can be in 2 statuses: LOCKED, and in this case his value cannot be altered by a write request, or UNLOCKED. A locked field would be considered as readonly meaning that as long as the locked status is present, the field cannot be updated unless an override is provided.

If an override is explicitly provided in a store request, the field is allowed to be updated in the context of that request only, and his status (LOCKED) will not be changed. A store request can also unlock a previously locked field.

Field Locking is enabled per-service, check for fieldLocking inside the features list to if the functionality is enabled for a specific service, example:

curl -X GET https://metadata-.pikselpalette.com/descriptor/raw
'
{
    "name": "metadata",
    "urn": "urn:piksel:service:metadata",
    "title": "Metadata Service",
    "description": "Stores content metadata resources",
    "features": [
        {
            "name": "fieldLocking"
        }
    ],
    ....
'

Usage and examples

Locking a field is achieved by passing the following structure inside a resource in a write request:

"<resource_name>":[{
  .... //fields

  "metadata": {
    "fields": {
      "locking": {
        <fieldNamePath>: "<action>"
      }
    }
  }
}]

<fieldNamePath> represents the path of the field inside the resourceful schema and must be one or more field names separated by dot character. <action> represents the change of status for that field and can be one of LOCK, UNLOCK, OVERRIDE.

Lock statuses will be returned in read request in a similar structure:

"<resource_name>":[{
  .... //fields

  "metadata": {
    "fields": {
      "locks": {
        <fieldNamePath>: "LOCKED"
      }
    }
  }
}]

Locking fields

The LOCK action puts a field into the LOCKED state. This happens after supplied values are written, assuming the field is not already locked.

curl -v -X POST 'https://metadata-.pikselpalette.com/data/assets' \
    -H 'Content-Type: application/vnd.piksel+json' \
    -H 'Authorization: Bearer your-token' \
    -d \
'
{
  "assets": [
    {
      "owner": "demo",
      "name": "got-s1-e1",
      "type": "video",
      "videoTracks": [
        {
          "title": "Video track title",
          "description": "Video track description",
          "schema": "embedded-english-subtitles",
          "codec": "H.264",
          "duration": "PT1H30M",
          "bitrate": 250,
          "resolution": "1080p",
          "frameRate": 29.97,
          "aspectRatio": "16:9",
          "height": 1920,
          "width": 1080
        }
      ],
      "metadata": {
        "fields": {
          "locking": {
            "type": "LOCK",
            "videoTracks": "LOCK"
          }
        }
      }
    }
  ]
}
'

As the locked fields are not returned in the response to a store operation, a get operation (GET by id request) must be performed to retrieve the locks of a given resource - see Retrieving the lock status.

Locking nested fields

Nested fields or objects can be locked by specifying the path of the field inside the resource. Example:

curl -v -X POST 'https://metadata-.pikselpalette.com/data/assets' \
    -H 'Content-Type: application/vnd.piksel+json' \
    -H 'Authorization: Bearer your-token' \
    -d \
'
{
  "offerTemplates": [
    {
      "owner": "test",
      "name": "offer-template-1",
      "title": "Science Fiction Movies",
      "rights": {
        "deviceTypes": [
          "smartphone",
          "tablet"
        ],
        "usagePeriod": "P7D",
        "gracePeriod": "P7D",
        "rentalPeriod": "P7D",
        "airplay": true,
        "mirrorcast": true
      },
      "metadata": {
        "fields": {
          "locking": {
            "rights.mirrorcast": "LOCK",
            "rights.deviceTypes": "LOCK"
          }
        }
      }
    }
  ]
}
'

Locking array fields

When locking an array field, the lock will affect the whole array. It is not possible to lock specific elements within an array.

Unlocking fields

The UNLOCK action removes the LOCKED status from a field. This occurs before the supplied resource is stored so values in previously locked fields will be stored.

curl -v -X POST 'https://metadata-.pikselpalette.com/data/assets' \
    -H 'Content-Type: application/vnd.piksel+json' \
    -H 'Authorization: Bearer your-token' \
    -d \
'
{
  "assets": [
    {
      "owner": "demo",
      "name": "got-s1-e1",
      "type": "audio",
      "videoTracks": [
        {
          "title": "A NEW Video track title"
        }
      ],
      "metadata": {
        "fields": {
          "locking": {
            "videoTracks": "UNLOCK"
          }
        }
      }
    }
  ]
}
'

In this example, the videoTracks field has been changed (note that the entire object has been replaced). As an UNLOCK action has been provided the value will be updated and the final status for the field will be UNLOCKED.

This is how the metadata field for demo:got-s1-e1 resource would look like after the above request:

"metadata": {
  "fields": {
    "locking": {
      "type": "LOCKED"
    }
  }
}

Overriding locked fields

The OVERRIDE action allows the value of a locked field to be changed without having to unlock and relock the field.

curl -v -X POST 'https://metadata-.pikselpalette.com/data/assets' \
    -H 'Content-Type: application/vnd.piksel+json' \
    -H 'Authorization: Bearer your-token' \
    -d \
'
{
  "assets": [
    {
      "owner": "demo",
      "name": "got-s1-e1",
      "type": "audio",
      "videoTracks": [
        {
          "title": "A NEW Video track title"
        }
      ],
      "metadata": {
        "fields": {
          "locking": {
            "type": "OVERRIDE"
          }
        }
      }
    }
  ]
}
'

In this example, the type field has been changed. As an OVERRIDE action has been provided the value will be updated and the final status for the field will remain LOCKED.

This is how the metadata field for demo:got-s1-e1 resource would look like after the above request:

"metadata": {
  "fields": {
    "locking": {
      "type": "LOCKED"
    }
  }
}

Retrieving the lock status

The status of field-locks on a resource is only visible when performing a GET where supplying the id(s) of the resources are supplied. See the get operation in the API spec. A browse operation will not return the field-locks.

curl -X GET \ 'https://metadata-.pikselpalette.com/data/assets/demo/got-s1-e1' \
    -H 'Authorization: Bearer your-token'
'
{
  "assets": [
    {
      "owner": "demo",
      "name": "got-s1-e1",
      "type": "video",
      "videoTracks": [
        {
          "title": "A Video track title"
        }
      ],
      "metadata": {
        "fields": {
          "locks": {
            "type": "LOCKED",
            "videoTracks": "LOCKED"
          }
        }
      }
    }
  ]
}
'

Errors

Attempting to lock an un-lockable field will result in a 400 Bad Request. Example:

curl -v -X POST 'https://metadata-.pikselpalette.com/data/assets' \
    -H 'Content-Type: application/vnd.piksel+json' \
    -H 'Authorization: Bearer your-token' \
    -d \
'
{
  "assets": [
    {
      "owner": "demo",
      "name": "got-s1-e1",
      "version": "718765dbe4b86a9671e9c1bc271dd66ffccbf0b1",
      "type": "audio",
      "metadata": {
        "fields": {
          "locking": {
            "version": "LOCK"
          }
        }
      }
    }
  ]
}
'
Response:
{
    "statusCode": 400,
    "error": "Bad Request",
    "message": "Unlockable field version - readOnly fields cannot be locked",
    "validation": {
        "source": "payload",
        "keys": [
            "metadata.fields.lockings"
        ]
    }
}

In this case version is a readOnly field and as such it can’t be locked. readOnly, derived, transient and prohibited fields cannot be locked.

Also, attempting to lock a field that isn’t available in the resource schema will result in a 400 Bad Request.

curl -v -X POST 'https://metadata-.pikselpalette.com/data/assets' \
    -H 'Content-Type: application/vnd.piksel+json' \
    -H 'Authorization: Bearer your-token' \
    -d \
'
{
  "assets": [
    {
      "owner": "demo",
      "name": "got-s1-e1",
      "type": "audio",
      "metadata": {
        "fields": {
          "locking": {
            "non.existent": "LOCK"
          }
        }
      }
    }
  ]
}
'
Response:
{
    "statusCode": 400,
    "error": "Bad Request",
    "message": "locking non.existent references unknown field",
    "validation": {
        "source": "payload",
        "keys": [
            "metadata.fields.lockings"
        ]
    }
}

It is possible to lock a field that exists in the schema but that is not present in the supplied document, like in the following example:

curl -v -X POST 'https://metadata-.pikselpalette.com/data/assets' \
    -H 'Content-Type: application/vnd.piksel+json' \
    -H 'Authorization: Bearer your-token' \
    -d \
'
{
  "assets": [
    {
      "owner": "demo",
      "name": "got-s1-e1",
      "type": "audio",
      "videoTracks": [
        {
          "title": "A NEW Video track title"
        }
      ],
      "metadata": {
        "fields": {
          "locking": {
            "alternativeIdentifiers": "LOCK"
          }
        }
      }
    }
  ]
}
'

In this scenario, the field alternativeIdentifiers is a field specified in the resourceful schema which does not exist in the supplied document. The field becomes LOCKED with no value, adding a value would required an UNLOCK or OVERRIDE action to be provided.