PUT / POST Not working as expected

This topic has 3 replies, 2 voices, and was last updated 1 week, 4 days ago by Bill Nelson.

  • Author
    Posts
  • #28364

    I am migrating from IDM version v2.5 to v6.5.0.4.

    The old server is generating a list of all id’s and sequentially calling the internal IDM v2.5 endpoint objVal = openidm.query("managed/user", objParams);

    var objParams = {
        "_queryId": "find-by-id",
        "id": id
    }

    This returns the account object as JSON.

    I then call the new IDM v6.5.0.4 endpoint _queryId=for-userName&uid= to see if the account object exists in the new IDM.

    If it does then I call the managed/user endpoint with PUT and pass the account object as JSON.

    openidm.action("external/rest", {
            "_url": "{{im.restUrl}}/openidm/managed/user/" + userObj[0]._id,
            "_method": "PUT",
            "_headers": {
              "Content-Type": "application/json",
              "Accept-Language": "en-us",
              "Accept-Charset": "UTF-8",
              "X-OpenIDM-Username": "xxx",
              "X-OpenIDM-Password": "xxx"
            },
            "_body": jsonStringify(userObj[0])
          });

    This is supposed to ‘UPDATE’ the account object if it already exists. If I made the call with a POST then it would ‘CREATE’ a new object. According to the Integrators Guide, or my understanding of.

    But when I call the new IDM v6.5.0.4 with PUT and pass the JSON payload it searches the new IDM managed/user repo finds that the account already exists, and then try’s to create a duplicate account. Strange……

    Luckily MySQL catches this duplicate account violation and throws an error.

    But this leaves me with no simple way to migrate the old IDM accounts to the new IDM.

    Am I misunderstanding the documentation?

    Section D.7.2. Managing Users Over REST of the IDM Integrators Guide has the following regarding endpoints and PUT vs POST.

    /openidm/managed/user/_id PUT Update a user entry (replaces the entire entry)

    /openidm/managed/user?_action=create POST Create a new user

    /openidm/managed/user?_action=patch&_queryId=for-userName&uid= userName POST Update a user (can be used to replace the value of one or more existing attributes)

    /openidm/managed/user/_id PATCH Update specified fields of a user entry

    I understand I could query both old and new, then build a map and compare each attribute then attempt a PATCH. But that seems extreme when IDM should just accept the entire JSON payload and determine what’s changed and update accordingly. Am I misunderstanding?

    Thanks
    Zach

    #28365
     Bill Nelson
    Participant

    Hi Zachary,

    You can use a PUT to either create or update an entry in your 6.5 instance. Using a PUT in this manner means that you need to send the entire object and specify the value of the _id that you want to use. In the case where there is no existing object, you create a new object. In the case where there is an existing object, then you will overwrite/replace the existing one with the one you are sending from your 2.5 instance (assuming you use the same _id in your PUT as the 6.5 instance). So as long as you do not want to retain any of the 6.5 properties or values for that object, then this approach should work. So everything you say in this regard seems correct.

    A couple thoughts/questions.

    First, do you want to retain the _id created in the 2.5 instance in the 6.5 instance? If so, then you cannot take the approach you are using when it comes to existing users. Existing user objects in 6.5 will have a different value for their _id than what you have in your 2.5 instance and if you are PUTing the 2.5 data (which contains the 2.5 _id) against IDM 6.5, then you are actually PUTing a new object. It would work great for creations as you are able to create objects in 6.5 with the same _id as that used in 2.5.

    Second, if you don’t care about retaining the _id from the 2.5 instance in the 6.5 instance, then I would ask, what value for userObj[0]._id are you passing in the external rest call? Is it the value of the _id returned from your 6.5 query? If so, then a PUT should overwrite that object. If you are passing in the _id from the 2.5 instance, then again, you are actually attempting to create (not update) since you are PUTing an entirely different identifier.

    Third, do you have the default uniqueness policy on for the userName property? If so, you should be rejecting the record in IDM by policy even before it gets to MySQL. Not sure why you are not seeing that behavior if that policy is being enforced.

    Finally you may need an If-Match * header in your PUT if the get the other items sorted.

    bill

    #28366

    Thank you Bill, you nailed it. My problem was the JSON representation of the account object from the old v.2.5 IDM contained the ‘old’ _id. I am updating the migration script to scrub that out and use the new IDM v.6.5.0.4 _id value. So simple I completely overlooked it. Much appreciate the help.

    Thanks
    Zach

    #28367
     Bill Nelson
    Participant

    That’s great news, Zachary. I’m glad it helped.

Viewing 4 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic.

©2020 ForgeRock - we provide an identity and access platform to secure every online relationship for the enterprise market, educational sector and even entire countries. Click to view our privacy policy and terms of use.

Log in with your credentials

Forgot your details?