cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1776
Views
3
Helpful
9
Replies

NonGadgetPythonSample

Keith Abbott
Level 1
Level 1

Good Day,

Im playing around a little with the sample python code created by dekwan ( https://github.com/CiscoDevNet/finesse-sample-code/tree/master/NonGadgetPythonSample )

using REST APIs and python to see/change agent states, with the end game of checking for agents in 50002 state and change them back to their previous state.

Long before there at step 1, Im just trying to get the sample code running. We're running Finesse 11.6

Im starting with dekwan's code with no changes except updating the

URL / domain / finesse user login id  and pw / scheme (http or https) and port

For the latter 2 Im using https and port 8445 (Ive tried other ports and http with other ports)   -    for user id and pw Im using a finesse agent login that I am able to successfully log in with interactively.    -    for the URL Im using the host and domain portion of the same url Id use to log into finesse interactively.

however on  'Executing GET 'https://finesseSvr.ourCompany.com:8445/finesse/api/User/myUser' I get a string of various errors similar to this:
GET User - ID: myUser
REST API URL is: 'https://finesseSvr.ourCompany.com:8445/finesse/api/User/myUser'
Executing GET 'https://finesseSvr.ourCompany.coms.com:8445/finesse/api/User/myUser'
C:\Program Files (x86)\Python38-32\lib\site-packages\urllib3\connectionpool.py:979: InsecureRequestWarning: Unverified HTTPS request is being made to host 'myUser.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
warnings.warn(
GET() - Status: 401
GET() - Text: <ApiErrors>
<ApiError>
<ErrorType>Invalid Authorization User Specified</ErrorType>
<ErrorData>myuser</ErrorData>
<ErrorMessage>The user specified in the authentication credentials and the uri don&apos;t match</ErrorMessage>
</ApiError>
</ApiErrors>

I DO, subsequently, get a successful connection to XMPP  

"Connecting to the Finesse Notification Service.
Waiting 2 seconds to establish a connection.
The XMPP connection is successful."

but on the subsequent puts, etc I continue to get the 401s (along with the '<ErrorType>User does not belong to Supervisor's Teams</ErrorType>' Errors.   (BTW 'myUser' is a supervisor of all teams as well as an agent)

Ive read a couple of other threads in places where it seemed the problem was usually the agent id/pw but Ive double and triple checked that unless Im misunderstanding and should be using some other credentials.

Does anyone have any suggestions on how I can move forward?

thanks

2 Accepted Solutions

Accepted Solutions

Keith Abbott
Level 1
Level 1

Wait! I Got it thanks to a tip in another post by dekwan

"Scenario 1 should work as far as agents being able to access their own information. For UCCE, you must use the agentId rather than the agent login name. So in your case, it should be /finesse/User/47483650"

at https://community.cisco.com/t5/contact-center/how-to-get-once-the-stanza-from-the-xmpp-connection/m-p/3584744#M7748

Thanks for your help!

 

View solution in original post

Hi @Keith Abbott ,

The unique reason code IDs are system generated and not exposed to the users directly. What you have passed might be the numeric reason code that you created.

For retrieving the reason code IDs belonging to the reason codes associated with a particular agent's team, you can issue a GET request on the resource /finesse/api/User/<user-id>/ReasonCodes?category=<NOT_READY|LOGOUT|ALL>.

Please refer to https://developer.cisco.com/docs/finesse/#!user%e2%80%94get-reason-code-list/userget-reason-code-list

Here is a sample response:

#> curl -k https://finesse-primary-node:8445/finesse/api/User/1001050/ReasonCodes?category=NOT_READY -u '1001050:pwdfor50'


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ReasonCodes category="NOT_READY">
<ReasonCode>
<uri>/finesse/api/ReasonCode/7618</uri>
<id>7618</id>
<category>NOT_READY</category>
<code>25137</code>
<label>Tea break</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
<ReasonCode>
<uri>/finesse/api/ReasonCode/7619</uri>
<id>7619</id>
<category>NOT_READY</category>
<code>26960</code>
<label>Lunch Break</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
<ReasonCode>
<uri>/finesse/api/ReasonCode/7622</uri>
<id>7622</id>
<category>NOT_READY</category>
<code>48673</code>
<label>Other</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
</ReasonCodes>

Regards,

Renjith Alexander

View solution in original post

9 Replies 9

realexan
Cisco Employee
Cisco Employee

Hi @Keith Abbott ,

For calling the API endpoint /finesse/api/User/myUser, the credentials(loginid & pwd) used should be of the user 'myUser' itself, or the administrator. For security reasons, one user's data cannot be accessed by another user's credentials. The error clearly says that the user ID in the URL and in the authentication header are different.

This holds good for PUT requests too(here additionally the supervisor can change state). Looks like the login ID and password that you set are not of 'myUser'

 

Update: Edited. Supervisor of the user cannot access the User object of another user. Only the user or the administrator can access the User details.

Regards,

Renjith Alexander

Thanks for the reply realexan,

Let me see if I can review the code and see where its falling down

Hi realexan,

I hate to be a slow-coach but Im still not finding the problem.

I added a buncha print statements in each sub, to see where things were going and what was being passed, and it all looked good minus the part where it fails.

The first thing (non-setup) it hits is sub __init__, which code is:

def __init__(self, username, password, scheme, fqdn, port, domain):
# Get the information from the config file
print("INsub __init__")
print ("UN '%s'\n" % username)
print ("PW '%s'\n" % password)
print ("scheme '%s'\n" % scheme)
print ("fqdn'%s'\n" % fqdn)
print ("port '%s'\n" % port)
print ("domain '%s'\n" % domain)
self.scheme = scheme
self.fqdn = fqdn
self.port = port
self.domain = domain

self.username = username
self.password = password

# Call the GET user API (and store the XML response)
self.getUser(id=self.username)

# Establish a connection to the Finesse Notification Service
self.xmppConnection = Jabber(self.username, password, self.domain)
self.xmppConnection['feature_mechanisms'].unencrypted_plain = True
print("Connecting to the Finesse Notification Service.")
if self.xmppConnection.connect(address=(self.fqdn, 5222), use_tls=False, use_ssl=False):
print("Waiting 2 seconds to establish a connection.")
self.xmppConnection.process(block=False)

# Need to wait a couple of seconds before calling a REST API
self.waitForNotification()
print("The XMPP connection is successful.")
else:
print("Failed to connect to XMPP.")
sys.exit(0)
print("OUT __init__")

This code results in output/error(each sub call is bounded by an INsub/OUTsub print statement pair:

INsub __init__

UN 'myUser'
PW '12345abc'
scheme 'https'
fqdn'finesseSVR.ourCompany.com'
port '8445'
domain 'ourCompany.com'

INsub getUser

GET User - ID: myUser

INsub getURLPrefix

REST API URL is: 'https://finesseSVR.ourCompany.com:8445/finesse/api/User/myUser'

OUTsub getURLPrefix

Executing subGET 'https://finesseSVR.ourCompany.com:8445/finesse/api/User/myUser'
UN'myUser'
PW'12345abc'

C:\Program Files (x86)\Python38-32\lib\site-packages\urllib3\connectionpool.py:979: InsecureRequestWarning: Unverified HTTPS request is being made to host 'finesseSVR.ourCompany.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
warnings.warn(

Insub printRESTAPIResponse

GET() - Status: 401
GET() - Text: <ApiErrors>
<ApiError>
<ErrorType>Invalid Authorization User Specified</ErrorType>
<ErrorData>myUser</ErrorData>
<ErrorMessage>The user specified in the authentication credentials and the uri don&apos;t match</ErrorMessage>
</ApiError>
</ApiErrors>

OUTsub printRESTAPIResponse

OUTsub getUser

IN CLASS Jabber

self'<__main__.Jabber object at 0x02EEACA0>'
UN 'myUser'
PW '12345abc'
domain '%s'<blank>'%s'

OUT CLASS Jabber

Connecting to the Finesse Notification Service.
Waiting 2 seconds to establish a connection.
The XMPP connection is successful.

OUT __init__

As you can see (or at least as it appears to me) Im passing the same creds each time. Those creds are for my agent which is a member of a team on which Im a supervisor, so covered both ways. It appears to die at sub 'printRESTAPIResponse' which code is this:


def printRESTAPIResponse(prefix='printRESTAPIResponse()', response=''):

"""
Print the REST API response with the HTTP Request status code
and the Response body text
"""
print("Insub printRESTAPIResponse")
print (prefix + " - Status: ", response.status_code) # This is the http request status
print (prefix + " - Text: ", response.text)
print ("\n")
print("OUTsub printRESTAPIResponse")

Any thoughts/pointings on where to go from here?

Thx

 

Keith Abbott
Level 1
Level 1

Wait! I Got it thanks to a tip in another post by dekwan

"Scenario 1 should work as far as agents being able to access their own information. For UCCE, you must use the agentId rather than the agent login name. So in your case, it should be /finesse/User/47483650"

at https://community.cisco.com/t5/contact-center/how-to-get-once-the-stanza-from-the-xmpp-connection/m-p/3584744#M7748

Thanks for your help!

 

Great.... I thought 'myUser' was a placeholder for the actual user ID, as you didn't want to expose agent IDs here.

That was indeed true, but it did mask a user login rather than a userID.

Now just trying to figure out why

PUT() data:
<User>
<state>NOT_READY</state>
</User>

Gives error


PUT() - Status: 400
PUT() - Text: <ApiErrors>
<ApiError>
<ErrorType>Parameter Missing</ErrorType>
<ErrorData>finesse.api.reasoncode.require_reasoncode</ErrorData>


<ErrorMessage>The state change requires a valid reason code.</ErrorMessage>
</ApiError>
</ApiErrors>

I assume (as it says) that a reason code is required when changing states. But Ive tried using both the ReasonCodeID, and ReasonCode (5004 and 1008) as strings and both produce this (with appropriate number)

PUT() data:
<User>
<state>NOT_READY</state>
<reasonCodeId>5004</reasonCodeId>
</User>

PUT() - Status: 400
PUT() - Text: <ApiErrors>
<ApiError>
<ErrorType>Invalid Input</ErrorType>
<ErrorData>finesse.api.reasoncode.not_valid</ErrorData>
<ErrorMessage>The Reason Code specified in the request does not exist</ErrorMessage>
</ApiError>
</ApiErrors>

 

Interestingly, 1008 gives a slightly different error:

404 and ReasonCode does not exist, codeId=1008</ErrorMessage>

Is ReasonCodeID the correct code to use (vs ReasonCode)?
Any thoughts on why the correct one is saying it doesnt exist?  I have verified the 1008/5004 code is a reason code available for my team.

 

thanks

 

Hi @Keith Abbott ,

The unique reason code IDs are system generated and not exposed to the users directly. What you have passed might be the numeric reason code that you created.

For retrieving the reason code IDs belonging to the reason codes associated with a particular agent's team, you can issue a GET request on the resource /finesse/api/User/<user-id>/ReasonCodes?category=<NOT_READY|LOGOUT|ALL>.

Please refer to https://developer.cisco.com/docs/finesse/#!user%e2%80%94get-reason-code-list/userget-reason-code-list

Here is a sample response:

#> curl -k https://finesse-primary-node:8445/finesse/api/User/1001050/ReasonCodes?category=NOT_READY -u '1001050:pwdfor50'


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ReasonCodes category="NOT_READY">
<ReasonCode>
<uri>/finesse/api/ReasonCode/7618</uri>
<id>7618</id>
<category>NOT_READY</category>
<code>25137</code>
<label>Tea break</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
<ReasonCode>
<uri>/finesse/api/ReasonCode/7619</uri>
<id>7619</id>
<category>NOT_READY</category>
<code>26960</code>
<label>Lunch Break</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
<ReasonCode>
<uri>/finesse/api/ReasonCode/7622</uri>
<id>7622</id>
<category>NOT_READY</category>
<code>48673</code>
<label>Other</label>
<forAll>true</forAll>
<systemCode>false</systemCode>
</ReasonCode>
</ReasonCodes>

Regards,

Renjith Alexander

Keith Abbott
Level 1
Level 1

Perfect!

Thanks Realexan.

My ver came up a little different than your sample response but I used the URI code and it worked like a charm:


ReasonCodes category="NOT_READY">
<ReasonCode>
<uri>/finesse/api/ReasonCode/33</uri>
<category>NOT_READY</category>
<code>1008</code>
<label>IS Problem</label>
<forAll>false</forAll>
<systemCode>false</systemCode>
</ReasonCode>
<ReasonCode>

Hopefully with the tools you provided I can move forward!

Hi @Keith Abbott 

Glad to hear that it helped.

You must be using an older release of Finesse. The more recent versions have the ID as part of the URL as well as within a separate tag.

Regards,

Renjith Alexander