FusionAuth / fusionauth-python-client

FusionAuth Python Client
https://fusionauth.io
Apache License 2.0
24 stars 12 forks source link

Documentation and/or test cases? #9

Open dhait opened 3 years ago

dhait commented 3 years ago

The documentation and/or test case coverage for this package is woefully lacking.

For example: I just took several hours of debugging, including stepping into this package code, to discover the correct format for the "request" parameter in the update_user(id,request) function (hint: you don't include the 'user' key).

Could you please add an example for each call or document the usage more carefully?

mooreds commented 3 years ago

Hi David,

Sorry, I'm sure that was frustrating.

When I started using the client libraries, I found I bounced back and forth between the source code of the client library and the API documentation, which contained the JSON structure I needed to build. It's not the optimal workflow, but the API documentation is very thorough about the JSON objects it expects as part of the payload. This is noted here.

We have some example applications, which may be worth looking at, and there are a few in this repo as well. Not as many as we'd like, of course.

That said, we're always looking at ways to improve our client libraries and documentation. Perhaps we need to look at adding pydoc or some other way of pointing to the canonical API documentation.

Again, I'm sorry. I've banged my head against enough SDKs myself, and it's frustrating. Can you check out the API docs and see if they help any, esp in conjunction with the source code of the library (which is pretty much a thin wrapper over the REST api)?

On a separate note, you wrote:

(hint: you don't include the 'user' key)

That worries me a bit because I believe you have to. You should provide the user key to do an update or a patch. At least this code works for me (on v1.19.8 of the library and fusionauth):

from fusionauth.fusionauth_client import FusionAuthClient

def run():
    api_key='...'
    client = FusionAuthClient(api_key, "http://localhost:9011")
    userobj = dict()
    userobj['user'] = dict()
    userobj['user']['lastName'] = 'JohnJohn'

    # patch updates only attributes provided
    client_response = client.patch_user('633b5549-eef6-4501-8f1a-54d4a76e7f30', userobj)
    if client_response.was_successful():
        print(client_response.success_response)
    else:
        print(client_response.error_response)

    # update RESETS the entire user object to whatever is in userobj
    # userobj['user']['email'] = 'test@example.com'
    #client_response = client.update_user('633b5549-eef6-4501-8f1a-54d4a76e7f30', userobj)
    #if client_response.was_successful():
        #print(client_response.success_response)
    #else:
        #print(client_response.error_response)

if __name__ == "__main__":
    run()

and this code doesn't:

def runbusted():
    api_key='...'
    client = FusionAuthClient(api_key, "http://localhost:9011")
    userobj = dict()
    userobj['lastName'] = 'JohnJohn2';
    client_response = client.patch_user('633b5549-eef6-4501-8f1a-54d4a76e7f30', userobj)
    if client_response.was_successful():
        print(client_response.success_response)
    else:
        print(client_response.error_response)

The runbusted function runs and prints a successful response, but doesn't change the user object. The JSON is not what patch is expecting and so it is ignored.

When I run this code:

def runbusted():
    api_key='...'
    client = FusionAuthClient(api_key, "http://localhost:9011")
    userobj = dict()
    userobj['lastName'] = 'JohnJohn2';

    # update RESETS the entire user object to whatever is in userobj
    userobj['email'] = 'test@example.com';
    client_response = client.update_user('633b5549-eef6-4501-8f1a-54d4a76e7f30', userobj)
    if client_response.was_successful():
        print(client_response.success_response)
    else:
        print(client_response.error_response)

I get this error message:

{'fieldErrors': {'user': [{'code': '[missing]user', 'message': 'Your request is missing the User information as JSON in the entity-body.'}]}}

What am I missing? Are you seeing different behavior? What version are you running?

dhait commented 3 years ago

You are correct, my error: "user": should be the tag on the request.

But, I had to switch from "update_user" to "patch_user", because FA gives no indication of what is wrong with the request, other than error 500. At very least, the FA system log should have more detailed information about why the request was rejected. Here again, example code for each call would be useful. The example code you have barely scratches the surface of the API.

mooreds commented 3 years ago

@dhait

Thanks for clearing up what your JSON looks like.

I understand your comments. We're looking at various ways to improve the documentation and appreciate the feedback.

For now, as I mentioned above, having the library source code and the API documentation, which contained the JSON structure I needed to build, open in two tabs is what I've found to be best. It's definitely not the optimal workflow, but the API documentation is very thorough about the JSON objects it expects as part of the payload, and mapping between the two is not too bad.

As we look at ways to improve the documentation, I'll keep your suggestions to add more tests and examples in mind. If you have additional specific suggestions, would love to hear them. In particular, I'd love to look at your code that gives the 500 error you mention.

Thanks!