Overview

Account resource in IDHub maps to User in Confluence. If the User Account is a member of a Group, the corresponding Group is shown in the Groups array along with the details of the User Account when the corresponding REST API is called. To fetch the different spaces that the user can view, all spaces in Confluence Cloud domain needs to be fetched and the space which has “read space” permission for the user is accessible by the User Account.

After creating a directory in the Confluence Admin account for a specific domain, the provisioning APIs for the User Resource can be called using the directoryId.

Account Resource Schema Configuration

Resource Type

The Resource Type for Account is :

Resource Type Schema
{
  "schemas" : [
    "urn:ietf:params:scim:schemas:core:2.0:ResourceType"
  ],
  "id" : "Account",
  "name" : "Account",
  "description" : "This resource creates/modifies/deletes accounts in Confluence and returns your query to you in some form depending on the normal format of the endpoint (Resource or ListResponse).",
  "endpoint" : "Accounts",
  "schema" : "urn:sath:params:scim:api:confluence:1.0:Account"
}
CODE

User Schema

To fetch User resource schema from SCIM provider, call https://api.atlassian.com/scim/directory/{directoryId}/Schemas/urn:ietf:params:scim:schemas:core:2.0:User API with Authorization and Accept request header. The response of the API is shown under the heading Confluence User Schema. The schema of the IDHub Account is as shown :

Note : All resource body for the User Provisioning APIs should be in the format of Confluence User Schema to avoid BadRequestException

User Account Schema

Confluence User Schema

IDHub Account Schema

{
  "id": "urn:ietf:params:scim:schemas:core:2.0:User",
  "name": "User",
  "description": "User Account",
  "attributes": [
    {
      "name": "userName",
      "description": "Unique identifier for the User. REQUIRED.",
      "mutability": "readWrite",
      "type": "string",
      "multiValued": false,
      "caseExact": false,
      "returned": "default",
      "required": true
    },
    {
      "name": "name",
      "description": "The components of the user's real name.",
      "mutability": "readWrite",
      "type": "complex",
      "multiValued": false,
      "returned": "default",
      "required": false,
      "subAttributes": [
        {
          "name": "formatted",
          "description": "The full name, including all middle names, titles, and suffixes as appropriate, formatted for display (e.g., 'Ms. Barbara J Jensen, III').",
          "mutability": "readWrite",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "familyName",
          "description": "The last name/family name of the User",
          "mutability": "readWrite",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "givenName",
          "description": "The first name/given name of the User",
          "mutability": "readWrite",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "middleName",
          "description": "The middle name(s) of the User",
          "mutability": "readWrite",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "honorificPrefix",
          "description": "The honorific prefix(es) of the User(e.g., 'Ms.')",
          "mutability": "readWrite",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "honorificSuffix",
          "description": "The honorific suffix(es) of the User, or suffix in most Western languages (e.g., 'III' given the full name 'Ms. Barbara J Jensen, III').",
          "mutability": "readWrite",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        }
      ]
    },
    {
      "name": "displayName",
      "description": "The name of the User to be displayed",
      "mutability": "readWrite",
      "type": "string",
      "multiValued": false,
      "caseExact": false,
      "returned": "default",
      "required": false
    },
    {
      "name": "nickName",
      "description": "The casual way to address the user in real life",
      "mutability": "readWrite",
      "type": "string",
      "multiValued": false,
      "caseExact": false,
      "returned": "default",
      "required": false
    },
    {
      "name": "title",
      "description": "The user's job title, such as \"Vice President.\"",
      "mutability": "readWrite",
      "type": "string",
      "multiValued": false,
      "caseExact": false,
      "returned": "default",
      "required": false
    },
    {
      "name": "preferredLanguage",
      "description": "Indicates the User's preferred written or spoken language.  Generally used for selecting a localized user interface; e.g., 'en_US' specifies the language English and country US.",
      "mutability": "readWrite",
      "type": "string",
      "multiValued": false,
      "caseExact": false,
      "returned": "default",
      "required": false
    },
    {
      "name": "timezone",
      "description": "The User's time zone in the 'Olson' time zone database format, e.g., 'America/Los_Angeles'.",
      "mutability": "readWrite",
      "type": "string",
      "multiValued": false,
      "caseExact": false,
      "returned": "default",
      "required": false
    },
    {
      "name": "active",
      "description": "A Boolean value indicating the User's administrative status.",
      "mutability": "readWrite",
      "type": "boolean",
      "multiValued": false,
      "returned": "default",
      "required": false
    },
    {
      "name": "emails",
      "description": "Email addresses for the user",
      "mutability": "readWrite",
      "type": "complex",
      "multiValued": true,
      "returned": "default",
      "required": true,
      "subAttributes": [
        {
          "name": "value",
          "description": "Email addresses for the user",
          "mutability": "readWrite",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "type",
          "description": "A label indicating the attribute's function, e.g., 'work' or 'home'.",
          "canonicalValues": [
            "work",
            "home",
            "other"
          ],
          "mutability": "readWrite",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "primary",
          "description": "A Boolean value indicating the primary email address",
          "mutability": "readWrite",
          "type": "boolean",
          "multiValued": false,
          "returned": "default",
          "required": false
        }
      ]
    },
    {
      "name": "phoneNumbers",
      "description": "Phone numbers for the User",
      "mutability": "readWrite",
      "type": "complex",
      "multiValued": true,
      "returned": "default",
      "required": false,
      "subAttributes": [
        {
          "name": "value",
          "description": "Phone number of the User.",
          "mutability": "readWrite",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "type",
          "description": "A label indicating the attribute's function, e.g., 'work', 'home', 'mobile'.",
          "canonicalValues": [
            "work",
            "home",
            "mobile",
            "fax",
            "pager",
            "other"
          ],
          "mutability": "readWrite",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        }
      ]
    },
    {
      "name": "groups",
      "description": "A list of groups to which the user belongs, either through direct membership, through nested groups, or dynamically calculated.",
      "mutability": "readOnly",
      "type": "complex",
      "multiValued": true,
      "returned": "default",
      "required": false,
      "subAttributes": [
        {
          "name": "value",
          "description": "The identifier of the User's group.",
          "mutability": "readOnly",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "$ref",
          "referenceTypes": [
            "User",
            "Group"
          ],
          "description": "The URI of the corresponding 'Group' resource to which the user belongs.",
          "mutability": "readOnly",
          "type": "reference",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "display",
          "description": "A human-readable name, primarily used for display purposes.  READ-ONLY.",
          "mutability": "readOnly",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        },
        {
          "name": "type",
          "description": "A label indicating the attribute's function, e.g., 'direct' or 'indirect'.",
          "canonicalValues": [
            "direct",
            "indirect"
          ],
          "mutability": "readOnly",
          "type": "string",
          "multiValued": false,
          "caseExact": false,
          "returned": "default",
          "required": false
        }
      ]
    },
    {
      "name" : "meta",
      "multiValued" : false,
      "description" : "A complex attribute containing resource metadata.",
      "mutability" : "readOnly",
      "subAttributes" : [
        {
          "name" : "resourceType",
          "multiValued" : false,
          "description" : "The name of the resource type of the resource.",
          "mutability" : "readOnly",
          "caseExact" : true
        },
        {
          "name" : "created",
          "multiValued" : false,
          "type" : "dateTime",
          "description" : "The \"DateTime\" that the resource was added to the service provider."
        },
        {
          "name" : "lastModified",
          "multiValued" : false,
          "type" : "dateTime",
          "description" : "The most recent DateTime that the details of this resource were updated at the service provider.  If this resource has never been modified since its initial creation, the value MUST be the same as the value of \"created\"."
        },
        {
          "name" : "location",
          "multiValued" : false,
          "description" : "The URI where the resource is available",
          "mutability" : "readOnly",
          "caseExact" : true
        },
        {
          "name" : "version",
          "multiValued" : false,
          "description" : "The version of the resource being returned.  This value must be the same as the entity-tag (ETag) HTTP response header (see Sections 2.1 and 2.3 of [RFC7232]).  This attribute has \"caseExact\" as \"true\".  Service provider support for this attribute is optional and subject to the service provider's support for versioning (see Section 3.14 of [RFC7644]).  If a service provider provides \"version\" (entity-tag) for a representation and the generation of that entity-tag does not satisfy all of the characteristics of a strong validator (see Section 2.1 of [RFC7232]), then the origin server MUST mark the \"version\" (entity-tag) as weak by prefixing its opaque value with \"W/\" (case sensitive).",
          "mutability" : "readOnly",
          "caseExact" : true
        }
      ]
    },
    {
      "name" : "schemas",
      "multiValued" : true,
      "description" : "The \"schemas\" attribute is a REQUIRED attribute and is an array of Strings containing URIs that are used to indicate the namespaces of the SCIM schemas that define the attributes present in the current JSON structure.  This attribute may be used by parsers to define the attributes present in the JSON structure that is the body to an HTTP request or response.  Each String value must be a unique URI.  All representations of SCIM schemas MUST include a non-empty array with value(s) of the URIs supported by that representation.  The \"schemas\" attribute for a resource MUST only contain values defined as \"schema\" and \"schemaExtensions\" for the resource's defined \"resourceType\".  Duplicate values MUST NOT be included.  Value order is not specified and MUST NOT impact behavior.",
      "mutability" : "readOnly",
      "returned" : "always",
      "caseExact" : true,
      "required" : true
    }
  ]
}
CODE
{
  "schemas" : [
    "urn:ietf:params:scim:schemas:core:2.0:Schema"
  ],
  "id" : "urn:sath:params:scim:api:confluence:1.0:Account",
  "name" : "User",
  "description" : "To perform create/update/modify operations on confluence Accounts",
  "attributes" : [
    {
      "name" : "description",
      "multiValued" : true,
      "description" : "The description of the Account shown in IDHub. This is a Confluence User Account. OPTIONAL"
    },
    {
      "name" : "displayName",
      "multiValued" : false,
      "description" : "The display name of the User shown in IDHub. Formed by concatenating firstname and lastName, if provided. Otherwise same as userName. REQUIRED.",
      "returned" : "always",
      "required" : true
    },
    {
      "name" : "email",
      "multiValued" : false,
      "description" : "The primary email of the User. REQUIRED.",
      "returned" : "always",
      "required" : true
    },
    {
      "name" : "entitlements",
      "multiValued" : true,
      "description" : "The entitlements of the User. Updated by PATCH Only.",
      "caseExact" : true
    },
    {
      "name" : "externalId",
      "multiValued" : false,
      "description" : "A String that is an identifier for the resource as defined by the provisioning client.  The \"externalId\" may simplify identification of a resource between the provisioning client and the service provider by allowing the client to use a filter to locate the resource with an identifier from the provisioning domain, obviating the need to store a local mapping between the provisioning domain's identifier of the resource and the identifier used by the service provider.  Each resource MAY include a non-empty \"externalId\" value.  The value of the \"externalId\" attribute is always issued by the provisioning client and MUST NOT be specified by the service provider.  The service provider MUST always interpret the externalId as scoped to the provisioning domain.  While the server does not enforce uniqueness, it is assumed that the value's uniqueness is controlled by the client setting the value.  See Section 9 for additional considerations regarding privacy.  This attribute has \"caseExact\" as \"true\" and a mutability of \"readWrite\".  This attribute is OPTIONAL.\n",
      "mutability" : "readOnly",
      "returned" : "always",
      "caseExact" : true
    },
    {
      "name" : "firstName",
      "multiValued" : false,
      "description" : "The first name or given name of the User. OPTIONAL."
    },
    {
      "name" : "id",
      "multiValued" : false,
      "description" : "A unique identifier for a SCIM resource as defined by the service provider.  Each representation of the resource MUST include a non-empty \"id\" value.  This identifier MUST be unique across the SCIM service provider's entire set of resources.  It MUST be a stable, non-reassignable identifier that does not change when the same resource is returned in subsequent requests.  The value of the \"id\" attribute is always issued by the service provider and MUST NOT be specified by the client.  The string \"bulkId\" is a reserved keyword and MUST NOT be used within any unique identifier value.  The attribute characteristics are \"caseExact\" as \"true\", a mutability of \"readOnly\", and a \"returned\" characteristic of \"always\".  See Section 9 for additional considerations regarding privacy.",
      "mutability" : "readOnly",
      "returned" : "always",
      "caseExact" : true,
      "required" : true
    },
    {
      "name" : "jobTitle",
      "multiValued" : false,
      "description" : "The job title of the User. OPTIONAL."
    },
    {
      "name" : "lastName",
      "multiValued" : false,
      "description" : "The last name or family name of the User. OPTIONAL."
    },
    {
      "name" : "meta",
      "multiValued" : false,
      "description" : "A complex attribute containing resource metadata.",
      "mutability" : "readOnly",
      "subAttributes" : [
        {
          "name" : "resourceType",
          "multiValued" : false,
          "description" : "The name of the resource type of the resource.",
          "mutability" : "readOnly",
          "caseExact" : true
        },
        {
          "name" : "created",
          "multiValued" : false,
          "type" : "dateTime",
          "description" : "The \"DateTime\" that the resource was added to the service provider."
        },
        {
          "name" : "lastModified",
          "multiValued" : false,
          "type" : "dateTime",
          "description" : "The most recent DateTime that the details of this resource were updated at the service provider.  If this resource has never been modified since its initial creation, the value MUST be the same as the value of \"created\"."
        },
        {
          "name" : "location",
          "multiValued" : false,
          "description" : "The name of the resource type of the resource.",
          "mutability" : "readOnly",
          "caseExact" : true
        },
        {
          "name" : "version",
          "multiValued" : false,
          "description" : "The version of the resource being returned.  This value must be the same as the entity-tag (ETag) HTTP response header (see Sections 2.1 and 2.3 of [RFC7232]).  This attribute has \"caseExact\" as \"true\".  Service provider support for this attribute is optional and subject to the service provider's support for versioning (see Section 3.14 of [RFC7644]).  If a service provider provides \"version\" (entity-tag) for a representation and the generation of that entity-tag does not satisfy all of the characteristics of a strong validator (see Section 2.1 of [RFC7232]), then the origin server MUST mark the \"version\" (entity-tag) as weak by prefixing its opaque value with \"W/\" (case sensitive).",
          "mutability" : "readOnly",
          "caseExact" : true
        }
      ]
    },
    {
      "name" : "name",
      "multiValued" : false,
      "description" : "The id of the User shown in IDHub. REQUIRED.",
      "returned" : "always",
      "caseExact" : true,
      "required" : true
    },
    {
      "name" : "schemas",
      "multiValued" : true,
      "description" : "The \"schemas\" attribute is a REQUIRED attribute and is an array of Strings containing URIs that are used to indicate the namespaces of the SCIM schemas that define the attributes present in the current JSON structure.  This attribute may be used by parsers to define the attributes present in the JSON structure that is the body to an HTTP request or response.  Each String value must be a unique URI.  All representations of SCIM schemas MUST include a non-empty array with value(s) of the URIs supported by that representation.  The \"schemas\" attribute for a resource MUST only contain values defined as \"schema\" and \"schemaExtensions\" for the resource's defined \"resourceType\".  Duplicate values MUST NOT be included.  Value order is not specified and MUST NOT impact behavior.",
      "mutability" : "readOnly",
      "returned" : "always",
      "caseExact" : true,
      "required" : true
    },
    {
      "name" : "userName",
      "multiValued" : false,
      "description" : "The unique identifier for the User.REQUIRED.",
      "required" : true
    }
  ]
}
CODE

Sample User

A sample User created in Confluence is given below

Sample Confluence User Account Schema
{
      "schemas": [
        "urn:scim:schemas:extension:atlassian-external:1.0",
        "urn:ietf:params:scim:schemas:core:2.0:User",
        "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
      ],
      "urn:scim:schemas:extension:atlassian-external:1.0": {
        "atlassianAccountId": "607d3d5ef74b3f006a03a61g"
      },
      "id": "ff2862db-864d-48db-93a4-162e2427ee7b",
      "userName": "Jerome",
      "name": {
        "formatted": "Jerome A.",
        "familyName": "Andrews",
        "givenName": "Jerome"
      },
      "displayName": "Jerome",
      "active": true,
      "emails": [
        {
          "type": "WORK",
          "value": "jerome@example.com",
          "primary": true
        }
      ],
      "groups": [
        {
          "display": "Developers Group",
          "type": "Group",
          "value": "d84adcec-0818-4852-aad3-cbe79a614e1c",
          "$ref": "https://api.atlassian.com/scim/directory/{groupId}/Groups/{directoryId}"
        }
      ],
      "meta": {
        "created": "2021-06-14T13:54:45.689667Z",
        "location": "https://api.atlassian.com/scim/directory/{directoryId}/Users/{userId}",
        "lastModified": "2021-06-14T13:54:45.689667Z",
        "resourceType": "User"
      }
}
CODE

Group Membership Schema

The schema of a GroupMembership object to add accounts as group members is shown :

Group Membership Object Schema
"Operations":[
      {
         "op":"add",
         "path":"members",
         "value":[
            {
               "value":"c6993c94-dbda-40f1-b6f0-18c855522ade",
               "display":"dave.meyer@demotime.authteam.com"
            },
            {
               "value":"f0ae48f7-1466-445e-85ea-e83ef754aefd",
               "display":"lingbo.lu@demotime.authteam.com"
            },
            {
               "value":"432d6f10-2e28-454e-be99-0f8c732a046f",
               "display":"joanna@demotime.authteam.com"
            }
         ]
      }
   ]
CODE

Space Permission Schema

The following combinations of operation.key and operation.target values are valid for the operation object:

'create': 'page', 'blogpost', 'comment', 'attachment'
'read': 'space'
'delete': 'page', 'blogpost', 'comment', 'attachment', 'space'
'export': 'space'
'administer': 'space'
'archive': 'page'
'restrict_content': 'space'
CODE

The schema of a SpacePermission object to add spaces with permissions to an account is shown :

Space Permission Object Schema
{
  "subject": {
    "type": "user",
    "identifier": "<accountId>"
  },
  "operation": {
    "key": "read",
    "target": "space"
  }
}
CODE

Implementation

The following methods of the target system connector interface defined in the connector SPI needs to be implemented for Account resource.

Get Schema

public Schema getSchema() throws InternalServerErrorException, NotImplementedException {
    create desired IDHub account Schema
    handle the respective errors, if any
    return schema definition       
}
CODE

Get Resource Type

public ResourceType getResourceType() throws InternalServerErrorException, NotImplementedException {
    call https://api.atlassian.com/scim/directory/{directoryId}/ResourceTypes/User with Authorization and Accept header
    if error occurs during fetching resource type
	    throw InternalServerErrorException
	if no logic is implemented 
	    throw NotImplementedException
    return fetched resource type
}
CODE

Get SCIM Resource Service Information

public ResourceServiceInformation getScimResourceServiceInformation() throws InternalServerErrorException, NotImplementedException {
    call https://api.atlassian.com/scim/directory/{directoryId}/ServiceProviderConfig with Authorization and Accept header
    if error occurs during fetching SCIM information
	    throw InternalServerErrorException
	if no logic is implemented 
	    throw NotImplementedException
    return fetched SCIM information for resource
}
CODE

Get Health

public Health getHealth()
		throws InternalServerErrorException, NotImplementedException {
	implement /health actuator to fetch the health of the target system 
	if error occurs during fetching health information
	    throw InternalServerErrorException
	if no logic is implemented 
	    throw NotImplementedException
    return fetched health information in SCIM+JSON format or String containing SCIM+JSON
}
CODE

Create Resource

public String postResource(String resource) throws BadRequestException, ConflictException, InternalServerErrorException, NotImplementedException {
    create a JSON object having Confluence User schema containing username, primary email as mandatory parameters, other fields can be added as a part of IDHub requirement
    call https://api.atlassian.com/scim/directory/{directoryId}/Users with Authorization, Accept and Content as headers and JSON user object as the payload 
    from the api response, contruct the IDHubObject by mapping parameters with the resonse object
    if the payload has entitlements, add the entitlements to the account
    call getResource(String, Set<String>, Set<String>) method to fetch the recently created account along with the entitlements
    if resource is unparsable, syntactically incorrect, or violates schema
	    throw BadRequestException
	if api or service provider refuses to create a new, duplicate resource
	    throw ConflictException
    if error occurs during resource creation
	    throw InternalServerErrorException
	if no logic is implemented 
	    throw NotImplementedException
    return the IDHubObject in String format
}
CODE

Get Resource

public String getResource(String id, Set<String> attributes, Set<String> excludedAttributes) throws NotFoundException, InternalServerErrorException, NotImplementedException {
    call https://api.atlassian.com/scim/directory/{directoryId}/Users/{userId}?attributes={attributes} with Authorization and Accept as headers, either attributes or excludedAttributes can be added as query parameters
    from the api response, contruct the IDHubObject by mapping parameters with the resonse object
    if excludedAttributes does not contain entitlements, then fetch the entitlements for the user
    groups that the user is a member of is fetched from the same api and can be added to user entitlements
    for spaces, call https://your-domain.atlassian.net/wiki/rest/api/space with Authorization and Accept as headers
    from the response, find the spaces that have "read space" permission for the user and add the space to user entitlements
    if no resource exists for the given id
	    throw NotFoundException
	if error occurs during resource fetch
	    throw InternalServerErrorException
	if no logic is implemented 
	    throw NotImplementedException 
    return the IDHubObject in String format
}
CODE

Replace Resource

Note : The observations made while performing update operation are :

  • If no primary email is sent in the request body, Bad Request exception is thrown.

  • If the same primary email is sent in the request body, no change is reflected.

  • If different primary email is sent in the request body, all changes are reflected.

The alternative approach is :

  • If primary email of the payload is same as current primary email of the user account, then call patchResource(String, PatchOp) method with appropriate parameters desired in the final account

  • If primary email of the payload is different from the current primary email of the user account, then call the update API with the given payload.

public String putResource(String id, String resource) throws BadRequestException, ConflictException, NotFoundException, InternalServerErrorException, NotImplementedException {
    create a JSON object containing username, primary email as mandatory parameters, other fields can be added as a part of IDHub requirement
    fetch existing user by id 
    perform PUT operation on the entitlements :
        if entitlements in the payload account are same as that of the existing account, no operation is done on the entitlements
        if payload account has entitlements that are not present in the existing account, the entitlements from the payload are added to the existing account
        if the existing account has entitlements that are not present in the payload account, the entitlements are removed from the existing account
    if primary email of the payload account is same as that of the existing account, 
        call patchResource(String, PatchOp) method with appropriate fields as mentioned in the payload account 
        from the api response, contruct the IDHubObject by mapping parameters with the resonse object
    otherwise, 
        call https://api.atlassian.com/scim/directory/{directoryId}/Users/{userId} with Authorization, Accept and Content as headers and JSON user object as the payload
        call getResource(String, Set<String>, Set<String>) method to fetch the recently created account along with the entitlements
    if resource is unparsable, syntactically incorrect, or violates schema
	    throw BadRequestException
	if specified version number does not match the resource's latest version number
	    throw ConflictException
    if no resource exists for the given id
	    throw NotFoundException
	if error occurs during resource creation
	    throw InternalServerErrorException
	if no logic is implemented 
	    throw NotImplementedException 
    return the IDHubObject in String format
}
CODE

Update Resource

public String patchResource(String id, PatchOp patchOperations) throws BadRequestException, ConflictException, NotFoundException, InternalServerErrorException, NotImplementedException {
    fetch account by calling getResource(String, Set<String>, Set<String>) function
    if patch operation is to be carried out on group entitlements, construct a GroupMembership Object
          and call https://api.atlassian.com/scim/directory/{directoryId}/Groups/{id} with Authorization, Accept and Content as headers and JSON GroupMembership object as the payload 
    for patch operations on space entitlements, 
          in case of adding a space with permissions to an account, construct a SpacePermission Object
                and call https://iamsath.atlassian.net/wiki/rest/api/space/{spaceId}/permission with Authorization, Accept and Content as headers and JSON SpacePersmission object as the payload 
          in case of deleting a space with permissions from an account, call https://iamsath.atlassian.net/wiki/rest/api/space/{spaceId}/permission/{permissionid} with Authorization and Accept as headers
          in case of replacing a space with permissions in an account, delete and add if the space already exists otherwise add the space with permissions
    for patch operations on account, form a PatchOp object with fields corresponding to Confluence User schema 
          and call https://api.atlassian.com/scim/directory/{directoryId}/Users/{id} with Authorization, Accept and Content as headers and JSON PatchOp object as the payload
    call getResource(String, Set<String>, Set<String>) function to fetch the updated Account with all its entitlements
    if resource is unparsable, syntactically incorrect, or violates schema
	    throw BadRequestException
	if specified version number does not match the resource's latest version number
	    throw ConflictException
    if no resource exists for the given id
	    throw NotFoundException
	if error occurs during resource creation
	    throw InternalServerErrorException
	if no logic is implemented 
	    throw NotImplementedException
    return the IdhubObject in String format
}
CODE

Delete Resource 

public void deleteResource(String id) throws ConflictException, NotFoundException, InternalServerErrorException, NotImplementedException {
    call https://api.atlassian.com/scim/directory/{directoryId}/Users/{userId} with Authorization as header
    if specified version number does not match the resource's latest version number
	    throw ConflictException
    if no resource exists for the given id
	    throw NotFoundException
	if error occurs during resource creation
	    throw InternalServerErrorException
	if no logic is implemented 
	    throw NotImplementedException
}
CODE

Search Resource

public ListResponse searchResource(SearchRequest searchRequest) throws BadRequestException, PayloadTooLargeException, InternalServerErrorException, NotImplementedException {
    if the filter parameter is empty
		return all(*) instances of the given resource type are returned
    call https://api.atlassian.com/scim/directory/{directoryId}/Users with Authorization and Accept as headers to fetch Accounts with their entitlements
    in case of multiple pages, pagination can be done using startIndex and count in query parameters passed as the token
    if searchRequest is unparsable, syntactically incorrect, or violates schema 
	    throw BadRequestException
    if payload size in bytes exceeds the max payload size
	    throw PayloadTooLargeException
	if error occurs during resource search
	    throw InternalServerErrorException
	if no logic is implemented 
	    throw NotImplementedException
    return the list of resource objects matching the searchRequest
}
CODE