1Password / connect-sdk-python

Python SDK for 1Password Connect
https://developer.1password.com/docs/connect
MIT License
200 stars 31 forks source link

Updating an existing item changes the layout of field #34

Closed t0ny-peng closed 1 year ago

t0ny-peng commented 2 years ago

Your environment

SDK Version: v1.1.0

Connect Server Version: Docker image 1password/connect-sync@sha256:ea4ee8de21de22edcf35b4218fe4ce0c18f3806b7e3b259e5a7e0f98065fed45, created around 2021-05-20

OS: Ubuntu 20.04

Python Version: 3.8

What happened?

We created a default password item in a vault, here's the initial structure:

{
  "id": "6go6qftma5enrxxxxxxxx",
  "title": "AWS_ACCESS_KEY_ID",
  "version": 1,
  "vault": { "id": "akvk5ifqsjge7xxxxxxxxx" },
  "category": "PASSWORD",
  "sections": [{ "id": "linked items", "label": "Related Items" }],
  "fields": [
    {
      "id": "password",
      "type": "CONCEALED",
      "purpose": "PASSWORD",
      "label": "password",
      "value": "xxxxxxxxxxxxxxxxxx"
    },
    {
      "id": "notesPlain",
      "type": "STRING",
      "purpose": "NOTES",
      "label": "notesPlain"
    }
  ],
  "lastEditedBy": "xxxxxxxxxxxxx",
  "createdAt": "2022-01-17T23:41:32Z",
  "updatedAt": "2022-01-17T23:41:32Z"
}

Then, we used the API to update the password

    # Update 1Password item
    item = Item(
        vault=ItemVault(id=op_vault),
        id=op_uuid_access_key,
        sections=[{ "id": "linked items", "label": "Related Items" }],
        fields=[
            Field(
                id="password",
                type="CONCEALED",
                label="password",
                value=response["AccessKey"]["AccessKeyId"],
            )
        ],
    )
    op_client.update_item(op_uuid_access_key, op_vault, item)

However, instead of modifying the first element in the fields area, the Python SDK adds a new one to the bottom, like this"

{
  "id": "6go6qftma5enrxxxxxxxx",
  "title": "AWS_ACCESS_KEY_ID",
  "version": 2,
  "vault": { "id": "akvk5ifqsjge7xxxxxxxxx" },
  "category": "PASSWORD",
  "sections": [{ "id": "linked items", "label": "Related Items" }],
  "fields": [
    {
      "id": "password",
      "type": "CONCEALED",
      "purpose": "PASSWORD",
      "label": "password"
    },
    {
      "id": "notesPlain",
      "type": "STRING",
      "purpose": "NOTES",
      "label": "notesPlain"
    },
    {
      "id": "password",
      "type": "CONCEALED",
      "label": "password",
      "value": "xxxxxxxxxxxxxxxxxxxxxxxxx"
    }
  ],
  "lastEditedBy": "xxxxxxxxxxxxx",
  "createdAt": "2022-01-17T23:41:32Z",
  "updatedAt": "2022-01-17T23:41:32Z"
}

What did you expect to happen?

The SDK should modify the existing one.

Steps to reproduce

  1. Create a normal Password item
  2. Save its original structure
  3. Use the scripts above to edit it
  4. Compare the updated structure

Notes & Logs

edif2008 commented 2 years ago

Hey @t0ny-peng,

For Items of category PASSWORD, the password field is a special one compared to other fields. Therefore, some extra input needs to be mentioned in the updated item to make sure Connect understands what you really want to update.

In this case, saying the Item's category (PASSWORD), as well as the field's purpose (PASSWORD), should do the update as expected. The purpose attribute means that the field can be used for autofilling a certain type of field on the browser (in this case, the field where the password is expected).

    # Update 1Password item
    item = Item(
        vault=ItemVault(id=op_vault),
        id=op_uuid_access_key,
        category="PASSWORD",  # added line
        sections=[{ "id": "linked items", "label": "Related Items" }],
        fields=[
            Field(
                id="password",
                type="CONCEALED",
                purpose="PASSWORD",  # added line
                label="password",
                value=response["AccessKey"]["AccessKeyId"],
            )
        ],
    )
    op_client.update_item(op_uuid_access_key, op_vault, item)

Does this suggestion solve your issue?

jessewindebank1809 commented 1 year ago

Thanks @edif2008 - this solved my problem.

In case someone else has the same requirement as me. Here is my slightly different code snippet which updates username, password and creates a new field:

item = onepasswordconnectsdk.models.Item(
                                    vault=ItemVault(id=vaultId),
                                    id = itemId, 
                                    category='LOGIN',        
                                    fields=[
                                            Field(
                                                id='username', #standard field
                                                label='username',
                                                purpose='USERNAME',
                                                value="username"),
                                            Field(
                                                id='password', #standard field
                                                label='password',
                                                purpose='PASSWORD',
                                                value="pass"),
                                            Field(
                                                label="token", #new field
                                                value="123")
                                                    ],
                                      )
 client.update_item(itemId, vaultId, item)

I think this should be added to the documentation.

Thank you

edif2008 commented 1 year ago

Heey @jessewindebank1809,

Glad to hear that the suggestion worked for you. Thank you for sharing the snippet that will address your use case so that others will see it as well.

I really appreciate you suggesting to add this in the documentation. We will add it as part of examples for using the sdk.