PingDS 7.5.1

Patch

Examples in this documentation depend on features activated in the ds-evaluation setup profile. For details, refer to Learn about the evaluation setup profile.

The code samples demonstrate how to contact the server over HTTPS using the deployment CA certificate. Before trying the samples, generate the CA certificate in PEM format from the server deployment ID and password:

$ dskeymgr \
 export-ca-cert \
 --deploymentId $DEPLOYMENT_ID \
 --deploymentIdPassword password \
 --outputFile ca-cert.pem

The patch operation updates one or more fields of a resource. Use it when you must make fine-grained changes to a resource; for example:

  • Add a member to a static group.

  • Remove a member from a static group.

  • Add or remove a single mail address or telephone number.

If you intend only to replace fields' values, update the resource instead with HTTP PUT and a partial resource including just the fields to replace.

Add a member to a group

The following example adds Babs to a static group:

  • Curl

  • JavaScript

  • Python

  • Ruby

$ curl \
 --request PATCH \
 --cacert ca-cert.pem \
 --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
 --header 'Content-Type: application/json' \
 --data '[{
  "operation": "add",
  "field": "uniqueMember",
  "value": "dc=com/dc=example/ou=People/uid=bjensen"
  }]' \
 'https://localhost:8443/hdap/dc=com/dc=example/ou=Groups/cn=Directory%20Administrators?_prettyPrint=true'
{
  "_id" : "dc=com/dc=example/ou=Groups/cn=Directory%20Administrators",
  "objectClass" : [ "groupofuniquenames", "top" ],
  "cn" : [ "Directory Administrators" ],
  "ou" : [ "Groups" ],
  "uniqueMember" : [ "dc=com/dc=example/ou=People/uid=kvaughan", "dc=com/dc=example/ou=People/uid=rdaugherty", "dc=com/dc=example/ou=People/uid=hmiller", "dc=com/dc=example/ou=People/uid=bjensen" ]
}
(async () => {
    const { authenticate, doRequest, getOptions } = require('./utils')
    const options = getOptions({
        path: '/hdap/dc=com/dc=example/ou=Groups/cn=Directory%20Administrators',
        method: 'PATCH',
        body: [{
            "operation": "add",
            "field": "uniqueMember",
            "value": "dc=com/dc=example/ou=People/uid=bjensen"
        }]
    })
    const jwt = await authenticate(options)
    options.headers['Authorization'] = 'Bearer ' + jwt
    const response = await doRequest('HDAP: add group member', options)
    console.log(response)
})().catch(error => { console.error(error) })

Source files for this sample: patch-group-add.js, utils.js

#!/usr/bin/env python3

import requests
import utils

patch = [{
    'operation': 'add',
    'field': 'uniqueMember',
    'value': 'dc=com/dc=example/ou=People/uid=bjensen'
}]
jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
response = requests.patch(
    f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=Groups/cn=Directory%20Administrators',
    headers=headers,
    json=patch,
    verify=utils.ca_pem)
print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))

Source files for this sample: utils.py, patch-group-add.py

require_relative 'utils.rb'
require 'faraday'
require 'json'

utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
options = { ca_file: utils.ca_pem }
jwt = utils.authenticate
hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", ssl: options) do |f|
    f.headers['Content-Type'] = 'application/json'
    f.request :authorization, 'Bearer', jwt
end
patch = [{
    "operation" => "add",
    "field" => "uniqueMember",
    "value" => "dc=com/dc=example/ou=People/uid=bjensen"
}]
response = hdap.patch do |h|
    h.path = 'dc=com/dc=example/ou=Groups/cn=Directory%20Administrators'
    h.body = JSON.generate(patch)
end

puts "Status code: #{response.status}\nJSON: #{response.body}"

Source files for this sample: utils.rb, patch-group-add.rb

HDAP Ruby examples require Ruby 3.2 and the faraday and json gems.

Remove a member from a group

The following example removes Babs from the group:

  • Curl

  • JavaScript

  • Python

  • Ruby

$ curl \
 --request PATCH \
 --cacert ca-cert.pem \
 --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
 --header 'Content-Type: application/json' \
 --data '[{
  "operation": "remove",
  "field": "uniqueMember",
  "value": "dc=com/dc=example/ou=People/uid=bjensen"
  }]' \
 'https://localhost:8443/hdap/dc=com/dc=example/ou=Groups/cn=Directory%20Administrators?_prettyPrint=true'
{
  "_id" : "dc=com/dc=example/ou=Groups/cn=Directory%20Administrators",
  "objectClass" : [ "groupofuniquenames", "top" ],
  "cn" : [ "Directory Administrators" ],
  "ou" : [ "Groups" ],
  "uniqueMember" : [ "dc=com/dc=example/ou=People/uid=kvaughan", "dc=com/dc=example/ou=People/uid=rdaugherty", "dc=com/dc=example/ou=People/uid=hmiller" ]
}
(async () => {
    const { authenticate, doRequest, getOptions } = require('./utils')
    const options = getOptions({
        path: '/hdap/dc=com/dc=example/ou=Groups/cn=Directory%20Administrators',
        method: 'PATCH',
        body: [{
            "operation": "remove",
            "field": "uniqueMember",
            "value": "dc=com/dc=example/ou=People/uid=bjensen"
        }]
    })
    const jwt = await authenticate(options)
    options.headers['Authorization'] = 'Bearer ' + jwt
    const response = await doRequest('HDAP: remove group member', options)
    console.log(response)
})().catch(error => { console.error(error) })

Source files for this sample: patch-group-remove.js, utils.js

#!/usr/bin/env python3

import requests
import utils

patch = [{
    'operation': 'remove',
    'field': 'uniqueMember',
    'value': 'dc=com/dc=example/ou=People/uid=bjensen'
}]
jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
response = requests.patch(
    f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=Groups/cn=Directory%20Administrators',
    headers=headers,
    json=patch,
    verify=utils.ca_pem)
print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))

Source files for this sample: utils.py, patch-group-remove.py

require_relative 'utils.rb'
require 'faraday'
require 'json'

utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
options = { ca_file: utils.ca_pem }
jwt = utils.authenticate
hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", ssl: options) do |f|
    f.headers['Content-Type'] = 'application/json'
    f.request :authorization, 'Bearer', jwt
end
patch = [{
    "operation" => "remove",
    "field" => "uniqueMember",
    "value" => "dc=com/dc=example/ou=People/uid=bjensen"
}]
response = hdap.patch do |h|
    h.path = 'dc=com/dc=example/ou=Groups/cn=Directory%20Administrators'
    h.body = JSON.generate(patch)
end

puts "Status code: #{response.status}\nJSON: #{response.body}"

Source files for this sample: utils.rb, patch-group-remove.rb

HDAP Ruby examples require Ruby 3.2 and the faraday and json gems.

Add multiple values

To change multiple fields, include multiple operation objects in the patch payload:

  • Curl

  • JavaScript

  • Python

  • Ruby

$ curl \
 --request PATCH \
 --cacert ca-cert.pem \
 --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
 --header 'Content-Type: application/json' \
 --data '[{
  "operation": "add",
  "field": "telephoneNumber",
  "value": "+1 408 555 9999"
 }, {
  "operation": "add",
  "field": "mail",
  "value": "barbara.jensen@example.com"
 }]' \
 'https://localhost:8443/hdap/dc=com/dc=example/ou=People/uid=bjensen?_fields=mail,telephoneNumber&_prettyPrint=true'
{
  "_id" : "dc=com/dc=example/ou=People/uid=bjensen",
  "telephoneNumber" : [ "+1 408 555 1862", "+1 408 555 9999" ],
  "mail" : [ "bjensen@example.com", "barbara.jensen@example.com" ]
}
(async () => {
    const { authenticate, doRequest, getOptions } = require('./utils')
    const options = getOptions({
        path: '/hdap/dc=com/dc=example/ou=People/uid=bjensen?_fields=mail,telephoneNumber',
        method: 'PATCH',
        body: [{
            "operation": "add",
            "field": "telephoneNumber",
            "value": "+1 408 555 9999"
        }, {
            "operation": "add",
            "field": "mail",
            "value": "barbara.jensen@example.com"
        }]
    })
    const jwt = await authenticate(options)
    options.headers['Authorization'] = 'Bearer ' + jwt
    const response = await doRequest('HDAP: patch multiple fields', options)
    console.log(response)
})().catch(error => { console.error(error) })

Source files for this sample: patch-multiple.js, utils.js

#!/usr/bin/env python3

import requests
import utils

patch = [{
    'operation': 'add',
    'field': 'telephoneNumber',
    'value': '+1 408 555 9999'
}, {
    'operation': 'add',
    'field': 'mail',
    'value': 'barbara.jensen@example.com'
}]
jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
params = { '_fields': 'mail,telephoneNumber' }
response = requests.patch(
    f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People/uid=bjensen',
    headers=headers,
    json=patch,
    params=params,
    verify=utils.ca_pem)
print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))

Source files for this sample: utils.py, patch-multiple.py

require_relative 'utils.rb'
require 'faraday'
require 'json'

utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
options = { ca_file: utils.ca_pem }
jwt = utils.authenticate
fields = { '_fields': 'mail,telephoneNumber' }
hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: fields, ssl: options) do |f|
    f.headers['Content-Type'] = 'application/json'
    f.request :authorization, 'Bearer', jwt
end
patch = [{
    "operation" => "add",
    "field" => "telephoneNumber",
    "value" => "+1 408 555 9999"
}, {
    "operation" => "add",
    "field" => "mail",
    "value" => "barbara.jensen@example.com"
}]
response = hdap.patch do |h|
    h.path = 'dc=com/dc=example/ou=People/uid=bjensen'
    h.body = JSON.generate(patch)
end

puts "Status code: #{response.status}\nJSON: #{response.body}"

Source files for this sample: utils.rb, patch-multiple.rb

HDAP Ruby examples require Ruby 3.2 and the faraday and json gems.

For a multivalued attribute, the value field takes an array. whereas the value field takes a single value for a single-valued field. For single-valued fields, an add operation has the same effect as a replace operation.

Patch a specific revision

Use an If-Match: <revision> header to patch only a specific revision of a resource:

  • Curl

  • JavaScript

  • Python

  • Ruby

$ export JWT=$(echo $(curl \
 --request POST \
 --cacert ca-cert.pem \
 --header 'Content-Type: application/json' \
 --data '{ "password": "bribery" }' \
 --silent \
 'https://localhost:8443/hdap/dc=com/dc=example/ou=People/uid=kvaughan?_action=authenticate') | jq -r .access_token)

$ export REVISION=$(cut -d \" -f 8 <(curl \
 --get \
 --cacert ca-cert.pem \
 --header "Authorization: Bearer $JWT" \
 --header 'Content-Type: application/json' \
 --data '_fields=_rev' \
 --silent \
'https://localhost:8443/hdap/dc=com/dc=example/ou=People/uid=bjensen'))

$ curl \
 --request PATCH \
 --cacert ca-cert.pem \
 --header "Authorization: Bearer $JWT" \
 --header 'Content-Type: application/json' \
 --header "If-Match: $REVISION" \
 --data '[{
  "operation": "remove",
  "field": "telephoneNumber",
  "value": "+1 408 555 9999"
 }, {
  "operation": "remove",
  "field": "mail",
  "value": "barbara.jensen@example.com"
 }]' \
 'https://localhost:8443/hdap/dc=com/dc=example/ou=People/uid=bjensen?_fields=mail,telephoneNumber&_prettyPrint=true'
{
  "_id" : "dc=com/dc=example/ou=People/uid=bjensen",
  "telephoneNumber" : [ "+1 408 555 1862" ],
  "mail" : [ "bjensen@example.com" ]
}
(async () => {
    const { authenticate, doRequest, getOptions } = require('./utils')
    const options = getOptions({
        path: '/hdap/dc=com/dc=example/ou=People/uid=bjensen',
        body: [{
            "operation": "add",
            "field": "telephoneNumber",
            "value": "+1 408 555 9999"
        }, {
            "operation": "add",
            "field": "mail",
            "value": "barbara.jensen@example.com"
        }]
    })
    const jwt = await authenticate(options)
    options.headers['Authorization'] = 'Bearer ' + jwt
    let response = await doRequest('HDAP: read bjensen _rev', options)
    console.log(response)
    options.headers['If-Match'] = JSON.parse(response.data)._rev
    options.method = 'PATCH'
    response = await doRequest('HDAP: patch specific revision', options)
    console.log(response)
})().catch(error => { console.error(error) })

Source files for this sample: patch-rev.js, utils.js

#!/usr/bin/env python3

import requests
import utils

jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
rev = requests.get(f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People/uid=bjensen',
    headers=headers,
    verify=utils.ca_pem).json()['_rev']

headers['If-Match'] = rev
patch = [{
    'operation': 'add',
    'field': 'telephoneNumber',
    'value': '+1 408 555 9999'
}, {
    'operation': 'add',
    'field': 'mail',
    'value': 'barbara.jensen@example.com'
}]
params = { '_fields': 'mail,telephoneNumber' }
response = requests.patch(
    f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People/uid=bjensen',
    headers=headers,
    json=patch,
    params=params,
    verify=utils.ca_pem)
print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))

Source files for this sample: utils.py, patch-rev.py

require_relative 'utils.rb'
require 'faraday'
require 'json'

utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
options = { ca_file: utils.ca_pem }
jwt = utils.authenticate
fields = { '_fields': 'mail,telephoneNumber' }
hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: fields, ssl: options) do |f|
    f.headers['Content-Type'] = 'application/json'
    f.request :authorization, 'Bearer', jwt
end
patch = [{
    "operation" => "add",
    "field" => "telephoneNumber",
    "value" => "+1 408 555 9999"
}, {
    "operation" => "add",
    "field" => "mail",
    "value" => "barbara.jensen@example.com"
}]
resource = 'dc=com/dc=example/ou=People/uid=bjensen'
rev = JSON.parse(hdap.get(resource).body, symbolize_names: true)[:_rev]

response = hdap.patch do |h|
    h.path = resource
    h.body = JSON.generate(patch)
    h.headers['If-Match'] = rev
end

puts "Status code: #{response.status}\nJSON: #{response.body}"

Source files for this sample: utils.rb, patch-rev.rb

HDAP Ruby examples require Ruby 3.2 and the faraday and json gems.

The resource revision changes when the patch is successful.