OneLogin Python SDK log_user_out() not working - onelogin

I am trying to implement the Python SDK to log a user out. However, it is not working as expected. It returns False and does not log the user out even though I am passing valid parameters. According to the documentation, it will return True on a success.
I also tested with curl using the same parameters and API credentials. That worked as expected.
I am referencing the Python SDK documentation for log_user_out(self, user_id):
https://onelogin.github.io/onelogin-python-sdk/v2/api.client.html
And for CURL:
https://developers.onelogin.com/api-docs/1/users/log-user-out
Python Test
I use the SDK to query for a user, then use that user's ID to log the user out but it returns False. I am logged in as the test user in a browser and the user is not logged off. I then grab the token to use in the following curl command test.
>>> onelogin_client = OneLoginClient(client_id, client_secret)
>>>
>>> onelogin_client.get_access_token()
<onelogin.api.models.onelogin_token.OneLoginToken object at 0x10e319970>
>>>
>>> query_parameters = {"email": "aaatestuserbob#eou.edu"}
>>> users = onelogin_client.get_users(query_parameters)
>>>
>>> print(users[0])
User : {'id': 179124057, 'external_id': None, 'email': 'aaatestuserbob#eou.edu', 'username': 'aaatestuserbob#eou.edu', 'firstname': 'Bobby', 'lastname': 'Lasterson', 'distinguished_name': 'redacted', 'phone': None, 'company': '', 'department': '', 'title': '', 'status': 1, 'member_of': '', 'samaccountname': 'aaatestuserbob', 'userprincipalname': '', 'group_id': 442079, 'role_ids': [], 'custom_attributes': {}, 'openid_name': '', 'locale_code': '', 'comment': '', 'directory_id': 50400, 'manager_ad_id': None, 'trusted_idp_id': None, 'manager_user_id': None, 'activated_at': datetime.datetime(2022, 6, 3, 18, 9, 21, 159000, tzinfo=tzutc()), 'created_at': datetime.datetime(2022, 6, 3, 18, 9, 21, 164000, tzinfo=tzutc()), 'updated_at': datetime.datetime(2022, 6, 10, 21, 14, 31, 835000, tzinfo=tzutc()), 'password_changed_at': datetime.datetime(2022, 6, 3, 18, 9, 21, 102000, tzinfo=tzutc()), 'invitation_sent_at': None, 'invalid_login_attempts': 0, 'last_login': datetime.datetime(2022, 6, 10, 21, 14, 31, 580000, tzinfo=tzutc()), 'locked_until': None, 'state': 1}
>>>
>>> print(users[0].id)
179124057
>>>
>>> id = users[0].id
>>>
>>> onelogin_client.log_user_out(id)
False
>>>
>>>
>>>
>>>
>>> print(onelogin_client.get_access_token())
OneLoginToken : {'access_token': 'redacted_access_token', 'refresh_token': 'redacted_refresh_token', 'account_id': redacted_account_id, 'token_type': 'bearer', 'created_at': datetime.datetime(2022, 6, 13, 15, 4, 33, 753000, tzinfo=tzutc()), 'expires_in': 36000}
>>>
CURL Test
Using the same API credentials that I just used in the Python Test I get the expected results using CURL. The response shows success and the test user is signed out of the browser.
➜ ~ curl 'https://eou.onelogin.com/api/1/users/179124057/logout' \
-X PUT \
-H "Authorization: bearer: redacted_access_token"
{"status":{"error":false,"code":200,"type":"success","message":"Success"}}%
➜ ~
Why does this work with CURL but not the Python SDK? Am I missing something obvious here? Thanks for your help.
EDIT
Some additional information... I took a look at the SDK code and found the error attributes. Below are the results. It looks like an exception was raised. It appears to be a JSONDecodeError.
https://github.com/onelogin/onelogin-python-sdk/blob/d752664dfe71243c3b7a8120a0f3abffb0f51010/src/onelogin/api/client.py#L937
>>> onelogin_client.error
500
>>>
>>> onelogin_client.error_description
'Expecting value: line 1 column 1 (char 0)'
>>>
>>> onelogin_client.error_attribute
>>>
Also, I realized the SDK uses a different API URL than is recommended here: https://developers.onelogin.com/api-docs/1/users/log-user-out
eou.onelogin.com vs api.us.onelogin.com
The URL that the SDK uses also works with curl.
➜ ~ curl 'https://api.us.onelogin.com/api/1/users/179124057/logout' \
-X PUT \
-H "Authorization: bearer: redacted_access_token"
{"status":{"error":false,"code":200,"type":"success","message":"Success"}}%
➜ ~

This does not answer the question directly, but there are a couple of things that can fix these issues.
The python sdk you linked uses the deprecated Onelogin API. It also uses python2. Using python3 sdk against the version 2 API shouldn't have the issues you're experiencing.

Related

Subset Sum/ Combination sum2 solution not working for larger numbers?

I'm trying to use subset sum/combination sum 2 solution to solve a problem.
Currently, it works for smaller numbers and certain numbers in my list. But it doesnt work for all. In fact, when I put up larger numbers, the output I get is an empty list. I was wondering if any of you had a smiliar problem and a possible solution.
To give you an idea, with the code I currently have, if the input is the following:
trial_list = [1.5,2.5,3.7,4,4.3,5,5,5,3,10]
trial_list_target = 20.5
combinationSum2(trial_list, trial_list_target)
the output that I currently get is
[[1.5, 4, 5, 5, 5],
[1.5, 4, 5, 10],
[2.5, 3, 5, 5, 5],
[2.5, 3, 5, 10],
[2.5, 3.7, 4.3, 5, 5],
[2.5, 3.7, 4.3, 10]]
which is correct
And if I use this as an input:
trial_list2 = [10,15,20,20,25,30,15,87,10,7,100]
trial_list2_target = 107
combinationSum2(trial_list2, trial_list2_target)
The output is:
[[7, 10, 10, 15, 15, 20, 30],
[7, 10, 10, 15, 20, 20, 25],
[7, 10, 15, 20, 25, 30],
[7, 15, 15, 20, 20, 30],
[7, 100],
[10, 10, 87],
[20, 87]]
Again which is correct.
However, if I have the following list and target as an input:
trial_list3 = [806.0, 687.67, 590.9, 587.71, 561.88, 493.73, 427.16, 427.16, 412.04, 272.2, 262.82, 262.82, 86.15, 86.15, 86.15, 86.15, 86.15, 86.15, 3.0]
trial_list3_target = 959.87
combinationSum2(trial_list3, trial_list3_target)
The output I get is:
[]
Thats literally my output when it should be
[687.67,272.2].
please help, I'm literally struggling to get why this is happening
FYI, the argument for my function is passed through a pandas dataframe column. Thats the list I'm using as an argument.
This is the whole code I am using:
def combinationSum2(candidates, target):
# Sorting in earlier cell didnt work so sort here
candidates.sort()
result = []
combine_sum_2(candidates, 0, [], result, target)
return result
def combine_sum_2(nums, start, path, result, target):
# if sum greater than path, stop working
if not target:
result.append(path)
return
for i in range(start, len(nums)):
# Not sure what this does, copy paste stack overslow
if i > start and nums[i] == nums[i - 1]:
continue
# I think this is to limit search. i.e, if number > target then stop working
if nums[i] > target:
break
# We change the start to `i + 1` because one element only could
# be used once
combine_sum_2(nums, i + 1, path + [nums[i]],
result, target - nums[i])

How to convert the timestamp inside a JSON file format using Python

I'm a newbie in creating Python Lambda function and I'm trying to figure out how to convert all the timestamps inside my JSON data into a date time format (2021-08-31T11:20:42.264+08:00). Sample data below:
{'Id': 'jr_e10ba9a2ab867b3abb3b1f8955cfd1815e1ce00cc981230702dfad45fb49a4b9',
'Attempt': 0,
'JobName': 'my_job_name',
'StartedOn': datetime.datetime(2021, 8, 31, 3, 17, 34, 49000, tzinfo=tzlocal()),
'LastModifiedOn': datetime.datetime(2021, 8, 31, 3, 19, 34, 855000, tzinfo=tzlocal()),
'CompletedOn': datetime.datetime(2021, 8, 31, 3, 19, 34, 855000, tzinfo=tzlocal()),
'JobRunState': 'FAILED'}
If you are writing your dictionary to a .json file, you can make your own serializer:
import json
...
def default_serialize(val):
if isinstance(val, datetime.datetime):
ret = val.isoformat()
else:
ret = str(val)
return ret
with open("my_data.json", "w") as fp:
json.dump(dct, fp, indent=4, default=default_serialize)
# Add empty line at EOF
fp.write("\n")
datetime luckily has a .isoformat function which will convert a datetime.datetime object to an isoformat, which is close to the one you want above.
You could just iterate through each key/value, and rewrite each key like:
my_json = {'Id': 'jr_e10ba9a2ab867b3abb3b1f8955cfd1815e1ce00cc981230702dfad45fb49a4b9',
'Attempt': 0,
'JobName': 'my_job_name',
'StartedOn': datetime.datetime(2021, 8, 31, 3, 17, 34, 49000, tzinfo=tzlocal()),
'LastModifiedOn': datetime.datetime(2021, 8, 31, 3, 19, 34, 855000, tzinfo=tzlocal()),
'CompletedOn': datetime.datetime(2021, 8, 31, 3, 19, 34, 855000, tzinfo=tzlocal()),
'JobRunState': 'FAILED'}
for key, value in my_json.items():
if isinstance(value, datetime.datetime):
my_json[key] = value.isoformat()
This iterates through the key and value of the json, checks if it is a datetime object, then converts it to the specified isoformat.
Please keep in mind that you need to load the JSON if you're loading it from an external file to do this, as JSON parsing in Python will lead to a dictionary, which is what I'm assuming you have here based off of what you gave above.

List of dictionaries representing rows with datetime object to be loaded into database

I have the below lines in a text file which I dumped from a database table using python.
[{'id': 1, 'name': 'abcd', 'date': datetime.datetime(2021, 3, 13, 18, 54, 40, 314716), 'comments': None, 'status': 'Success'}, {'id': 2, 'name': 'efgh', 'date': datetime.datetime(2021, 3, 14, 10, 4, 49, 9217), 'comments': None, 'status': 'Success'},...]
I want the read the file as a list and iterate over the dictionaries representing each row and load the database table.
The loading of this data from the file as a list in python works with ast.literal_eval but it works only in case there is no datetime object in the list inside file.
with open('file.txt') as f:
data = ast.literal_eval(f.read())
However, when there is a datetime object present I get the following error:
ValueError: malformed node or string: <_ast.Call object at 0x000001C1A755D240>
Is there any way to read the data in file as a list of dictionaries in python such that it even works with the datetime object and thus its possible to load the data into the database table?
Any other way to load the rows into the database table from file would also help. The database I'm using is Postgres.
You can remove the datetime.datetime part throughout the string, leaving you with a tuple, then run ast.literal_eval() and convert each tuple to a datetime.datetime() object.
import ast
import datetime
with open('file.txt') as f:
data = ast.literal_eval(f.read().replace('datetime.datetime',''))
data
# [
# {
# 'id': 1, 'name': 'abcd', 'date': (2021, 3, 13, 18, 54, 40, 314716),
# 'comments': None, 'status': 'Success'
# },
# {
# 'id': 2, 'name': 'efgh', 'date': (2021, 3, 14, 10, 4, 49, 9217),
# 'comments': None, 'status': 'Success'
# }
# ]
data_w_datetime = [
{k: datetime.datetime(*v) if k == 'date' else v for k, v in d.items()}
for d in data
]
data_w_datetime
# [
# {
# 'id': 1, 'name': 'abcd',
# 'date': datetime.datetime(2021, 3, 13, 18, 54, 40, 314716),
# 'comments': None, 'status': 'Success'
# },
# {
# 'id': 2, 'name': 'efgh',
# 'date': datetime.datetime(2021, 3, 14, 10, 4, 49, 9217),
# 'comments': None, 'status': 'Success'
# }
# ]
Then, you can use psycopg2 to load the data into Postgres without iterating, using execute_values.
import psycopg2
from psycopg2.extras import execute_values
columns = data_w_datetime[0].keys()
query = "INSERT INTO mytable ({}) VALUES %s".format(','.join(columns))
# extract values from each dictionary and put them in a list of lists
values = [[value for value in d.values()] for d in data_w_datetime]
conn = psycopg2.connect(**db_params) # specify your own connection params
cursor = conn.cursor()
execute_values(cursor, query, values)
conn.commit()
cur.close()

typeError in python 3

i'm very new in python and i don't understand what the error say and what i do wrong
any help would be appreciated
thanks
my code:
class TSP:
def __init__(self, initial_node, adjacency_matrix):
self.initial_node = initial_node
self.adjacency_matrix = adjacency_matrix
stack = {"cost": {}, "distances": {}}
def distance(self, start_node, end_node):
self.stack["distances"]["dist%s-%s" %(start_node, end_node)] = self.adjacency-matrix[start_node][end_node]
def cost(self, visit_nodes, end_node_cost):
if len(visit_nodes) == 2:
node_set = visit_nodes.remove(end_node_cost)
self.distance(node_set[0], end_node_cost)
print (self.stack)
test = TSP(1, [[0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]])
print (test.cost([1, 2], 2))
and my error is :
TypeError: 'NoneType' object has no attribute '__getitem__'
You need to study the backtrace to discover where the error is coming from.
visit_nodes.remove() returns None (see the official docs for the list.remove method—no return value is mentioned). Therefore node_set is None. Therefore node_set[0] in the subsequent line fails. You presumably mean to dereference the list itself, i.e. visit_nodes[0].

Python: Retrieve result from inner dictionary

I'm fairly new to python and I don't know how can I retrieve a value from a inner dictionary:
This is the value I have in my variable:
variable = {'hosts': 1, 'key':'abc', 'result': {'data':[{'licenses': 2, 'id':'john'},{'licenses': 1, 'id':'mike'}]}, 'version': 2}
What I want to do is assign a new variable the number of licenses 'mike' has, for example.
Sorry for such a newbie, and apparent simple question, but I'm only using python for a couple of days and need this functioning asap. I've search the oracle (google) and stackoverflow but haven't been able to find an answer...
PS: Using python3
Working through it and starting with
>>> from pprint import pprint
>>> pprint(variable)
{'hosts': 1,
'key': 'abc',
'result': {'data': [{'id': 'john', 'licenses': 2},
{'id': 'mike', 'licenses': 1}]},
'version': 2}
First, let's get to the result dict:
>>> result = variable['result']
>>> pprint(result)
{'data': [{'id': 'john', 'licenses': 2}, {'id': 'mike', 'licenses': 1}]}
and then to its data key:
>>> data = result['data']
>>> pprint(data)
[{'id': 'john', 'licenses': 2}, {'id': 'mike', 'licenses': 1}]
Now, we have to scan that for the 'mike' dict:
>>> for item in data:
... if item['id'] == 'mike':
... print item['licenses']
... break
...
1
You could shorten that to:
>>> for item in variable['result']['data']:
... if item['id'] == 'mike':
... print item['licenses']
... break
...
1
But much better would be to rearrange your data structure like:
variable = {
'hosts': 1,
'version': 2,
'licenses': {
'john': 2,
'mike': 1,
}
}
Then you could just do:
>>> variable['licenses']['mike']
1
You can use nested references as follows:
variable['result']['data'][1]['licenses'] += 1
variable['result'] returns:
{'data':[{'licenses': 2, 'id':'john'},{'licenses': 1, 'id':'mike'}]}
variable['result']['data'] returns:
[{'licenses': 2, 'id':'john'},{'licenses': 1, 'id':'mike'}]
variable['result']['data'][1] returns:
{'licenses': 1, 'id':'mike'}
variable['result']['data'][1]['licenses'] returns:
1
which we then increment using +=1

Resources