How to retrieve a user with parameter false or undefined using search on OKTA users api? - okta

We have a attribute 'is_admin' (special logick requirement) on our user profile with type boolean, as we know from here the booleans attributes have three values on okta (true, false and undefined). At beginning of our project we do not set this attribute as required, so we have a lot of users with value undefined. The problem is that we need to query for all user who is_admin value is not true, so it should be false or undefined. We try a lot of mixes, but for all of them we get bad request:
It's not uri encoded for more clarity.
.../api/v1/users/users?search=profile.is_admin eq false or profile.is_admin eq "" => 400
.../api/v1/users?search=profile.is_admin eq false or profile.is_admin eq undefined => 400
.../api/v1/users?search=profile.is_admin eq false or profile.is_admin eq null => 400
.../api/v1/users?search=profile.is_admin ne true => 400
.../api/v1/users?search=profile.is_admin gt true and profile.is_admin lt true => 400
.../api/v1/users?search=profile.is_admin gt true or profile.is_admin lt true => 400
.../api/v1/users?search=not profile.is_admin eq true => 400
.../api/v1/users?search=not(profile.is_admin eq true) => 400
.../api/v1/users?search=profile.is_admin not eq true => 400
So here is my question: How can I get all user who his 'is_admin' attribute is not equal to true?

Their search API doesn't support ne(not equal) operator.
Note that their doc: https://developer.okta.com/docs/reference/core-okta-api/#operators says
Note: The ne (not equal) operator isn't supported for some objects, but you can obtain the same result by using lt ... or ... gt. For example, to see all user agents except for "iOS", use (client.userAgent.os lt "iOS" or client.userAgent.os gt "iOS").
But this trick of less than + greater than will not work either.
The best thing you can do is to use 'list user' with a filter(https://developer.okta.com/docs/reference/api/users/#list-users-with-a-filter) like profile.is_admin+neq+%22true%22 (profile.is_admin not equal to true):
curl \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: SSWS ${api_token}" \
"https://trial-5603560-admin.okta.com/api/v1/users?filter=profile.is_admin%20ne%20%22true%22"
scratch that. My bad thene does not work in this case either you can only filter "true" and "false" but not unassigned value(which in Okta UI maybe display as undefine).
curl GET https://trial-5603560-admin.okta.com/api/v1/users?search=(profile.is_admin+eq+%22false%22) \
--header 'Authorization: SSWS xxxx' \
--header 'Content-Type: application/json'
curl GET https://trial-5603560-admin.okta.com/api/v1/users?search=(profile.is_admin+eq+%22false%22) \
--header 'Authorization: SSWS xxx' \
--header 'Content-Type: application/json'
In fact when you access a particular User directly via
https://...admin.okta.com/admin/user/profile/view/{UserID}
you'll find the users that have undefined shown on UI for the field completely missing that particular node in the JSON compared to ones that hold true or false. I think your original query was correct and their API prob has a bug.
Usually, I'd log in to https://support.okta.com/help/s/?language=en_US with your Okta admin account. And talk to them directly, providing the id in the request/response. Occasionally they can escalate to a dev in to fix things quickly.

Related

How to send a POST request with Kotlin/Native using libcurl?

I'm trying to send a JSON through a POST request with a Kotlin/Native application using libcurl. I'm working on a Windows 11 machine, and the endpoint lies under a Spring Boot (version 2.7.8) backend written with Kotlin and Java 11.
The following is the code I wrote to accomplish this task.
import kotlinx.cinterop.*
import libcurl.*
fun main() {
val curl = curl_easy_init()
curl?.let {
var headers: CValuesRef<curl_slist>? = null
headers = curl_slist_append(headers, "Content-Type: application/json")
setCurl(curl, headers)
val res = curl_easy_perform(curl)
if (res != CURLE_OK) println("curl_easy_perform() failed ${curl_easy_strerror(res)?.toKString()}")
curl_easy_cleanup(curl)
curl_slist_free_all(headers)
} ?: println("curl_easy_init() failed to return curl easy handle")
}
private fun setCurl(curl: COpaquePointer?, headers: CPointer<curl_slist>?) {
val body = "{ JSON object }"
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers)
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body)
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:8080/dishes/add/")
}
The JSON string I need to send represents a simple Dish object having three fields: name, type and description.
These are the attempts I made to correctly format the JSON string to initialize the val body and the relative outputs that the Spring Boot endpoint return:
{\"name\":\"Fish\",\"type\":\"Second\",\"description\":\"Fry\"} => HTTP 200;
{\"name\":\"Fish fry\",\"type\":\"Second course\",\"description\":\"Lots of fresh fish to delight the palate with an excellent, fried second course\"} => HTTP 400: JSON parse error: Unexpected character (' ' (code 160)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false');
{\\\"name\\\":\\\"Fish fry\\\",\\\"type\\\":\\\"Second course\\\",\\\"description\\\":\\\"Lots of fresh fish to delight the palate with an excellent, fried second course\\\"} => HTTP 400: JSON parse error: Illegal character ((CTRL-CHAR, code 0)): only regular white space (\r, \n, \t) is allowed between tokens;
"\"{\\\"name\\\":\\\"Fish fry\\\",\\\"type\\\":\\\"Second course\\\",\\\"description\\\":\\\"Lots of fresh fish to delight the palate with an excellent, fried second course\\\"}\"" => HTTP 400: JSON parse error: Unexpected character (' ' (code 160)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
From the above tests, I can effectively POST something on the backend only with the first body string, but if I try to send a longer one with even the same format (see the second one), the POST request fails too.
Besides, I also tried to execute a POST request using Postman and the terminal (with the following command: curl -H "Content-Type: application/json" -X POST -d "{\"name\":\"Fish fry\",\"type\":\"Second course\",\"description\":\"Lots of fresh fish to delight the palate with an excellent, fried second course\"}" http://localhost:8080/dishes/add/), and with both, I can correctly send the POSTs. And since using the commands prompt, curl accepts the last body JSON I tried, maybe it could be the right approach to format the string, but I'm not sure.
What am I missing?
Thanks for your precious time!
UPDATE 1:
I just discovered the --libcurl curl parameter, which lets you convert a curl command into libcurl code.
Using this helpful tool, I converted my working cmd POST request
curl -H "Content-Type: application/json" -X POST -d "{\"name\":\"Fish fry\",\"type\":\"Second course\",\"description\":\"Lots of fresh fish to delight the palate with an excellent, fried second course\"}" http://localhost:8080/dishes/add/
Into the following, Kotlin adapted, C snippet:
private fun setCurl(hnd: COpaquePointer?, certPath: String, url: String) {
var headers: CValuesRef<curl_slist>? = null
headers = curl_slist_append(headers, "Content-Type: application/json")
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L)
curl_easy_setopt(hnd, CURLOPT_URL, "http://localhost:8080/dishes/add/")
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L)
curl_easy_setopt(
hnd,
CURLOPT_POSTFIELDS,
"{\"name\":\"Fish fry\",\"type\":\"Second course\",\"description\":\"Lots of fresh fish to delight the palate with an excellent, fried second course\"}"
)
val postFieldSize: curl_off_t = 138
curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, postFieldSize)
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers)
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/7.83.1")
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L)
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST")
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L)
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L)
}
But still, my Kotlin/Native application failed to execute the request with Spring Boot returning the same error: Unexpected character (' ' (code 160)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false').
At this time, I ran out of ideas. Please, let me know about any other solutions.
UPDATE 2:
Since the first val body initialization was the only one to be successful (despite the body string having to be small), I started to do some other tests with that type of formatted JSON, so I found that the POST request is successful if the entire string does not cross the 63 chars of length otherwise, the Spring Boot endpoint fires the error regarding the code 160 unexpected character.
The body string I'm currently using is the following one, which length is exactly 63 chars.
{\"name\":\"Fettuccine Alfredo\",\"type\":\"Main co\",\"description\":\"\"}
I don't know why this situation is happening, and I'm very frustrated.
Every tip of advice is much appreciated.

API to get price of Binance Smart Chain token on PancakeSwap

I have address of a token and I need to get its price in BUSD or BNB.
It's not a problem to use paid API, if there is no other way. This token may not be listed on popular listings so it would be nice to get price somehow directly from PancakeSwap.
Here is a way to get it directly from PancakeSwap
https://api.pancakeswap.info/api/v2/tokens/0x8076c74c5e3f5852037f31ff0093eeb8c8add8d3
A friend of mine used Moralis.
https://docs.moralis.io/introduction/readme
https://docs.moralis.io/moralis-dapp/web3-api/token#gettokenprice
Maybe you can already do something with the documentation, I have otherwise asked my colleague for example code
curl -X 'GET' \
'https://deep-index.moralis.io/api/v2/erc20/0x42F6f551ae042cBe50C739158b4f0CAC0Edb9096/price?chain=bsc&exchange=PancakeSwapv2' \
-H 'accept: application/json' \
-H 'X-API-Key: MY-API-KEY'
Result:
{
"nativePrice": {
"value": "8409770570506626",
"decimals": 18,
"name": "Ether",
"symbol": "ETH"
},
"usdPrice": 19.722370676,
"exchangeAddress": "0x1f98431c8ad98523631ae4a59f267346ea31f984",
"exchangeName": "Uniswap v3"
}
Greetings.
Alternatively, if you are using React you can try the following package: react-pancakeswap-token-price
you can scrape charts.bogged.finance or poocoin.app

google docs api delete all content

I noticed from the google docs API
I can do
{
"requests": [
{
"deleteContentRange": {
"range": {
"startIndex": 1,
"endIndex": 80
}
}
}
]
}
but if the endindex is greater than the total length of characters in the document, I get the following error:
{
"error": {
"code": 400,
"message": "Invalid requests[0].deleteContentRange: Index 79 must be less than the end index of the referenced segment, 7.",
"status": "INVALID_ARGUMENT"
}
}
but I just want to delete all of the content, even though I don't know the end range value.
So: is it possible to get the endIndex somehow, or delete all content another way?
You want to delete all contents in Google Document using Docs API.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Issue:
In the current stage, in order to use "DeleteContentRangeRequest", both values of startIndex and endIndex are required. It seems that this is the specification. So in your case, I think that is it possible to get the endIndex somehow, or delete all content another way? leads to the method for resolving your issue.
Flow of workaround:
Here, as the workaround, the following flow is used.
1. Retrieve the object of content from Google Document.
The sample curl command is as follows. When you use this, please set the Document ID. In this case, body.content(startIndex,endIndex) is used as the fields. By this, it is easy to see the response value.
curl \
'https://docs.googleapis.com/v1/documents/###?fields=body.content(startIndex%2CendIndex)' \
--header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
--header 'Accept: application/json'
The response value is like below.
{
"body": {
"content": [
{"endIndex": 1},
{"startIndex": 1, "endIndex": 100},
{"startIndex": 100, "endIndex": 200}
]
}
}
endIndex of the last index of content is the value for this.
2. Retrieve endIndex from the object.
From above response value, it is found that startIndex and endIndex are 1 and 199, respectively. If endIndex is 200, an error occurs. Please be careful this. So please reduce 1 from it.
3. Delete all contents using startIndex and endIndex.
The sample curl command is as follows.
curl --request POST \
'https://docs.googleapis.com/v1/documents/###:batchUpdate' \
--header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"requests":[{"deleteContentRange":{"range":{"startIndex":1,"endIndex":199}}}]}'
References:
Method: documents.get
Method: documents.batchUpdate
DeleteContentRangeRequest
If I misunderstood your question and this was not the direction you want, I apologize.

How to delete all attributes from the schema in solr?

Deleting all documents from solr is
curl http://localhost:8983/solr/trans/update?commit=true -d "<delete><query>*:*</query></delete>"
Adding a (static) attribute to the schema is
curl -X POST -H 'Content-type:application/json' --data-binary '{ "add-field":{"name":"trans","type":"string","stored":true, "indexed":true},}' http://localhost:8983/solr/trans/schema
Deleting one attribute is
curl -X POST -H 'Content-type:application/json' -d '{ "delete-field":{"name":"trans"}}' http://arteika:8983/solr/trans/schema
Is there a way to delete all attributes from the schema?
At least in version 6.6 of the Schema API and up to the current version 7.5 of it, you can pass multiple commands in a single post (see 6.6 and 7.5 documenation, respectively). There are multiple accepted formats, but the most intuitive one (I think) is just passing an array for the action you want to perform:
curl -X POST -H 'Content-type: application/json' -d '{
"delete-field": [
{"name": "trans"},
{"name": "other_field"}
]
}' 'http://arteika:8983/solr/trans/schema'
So. How do we obtain the names of the fields we want to delete? That can be done by querying the Schema:
curl -X GET -H 'Content-type: application/json' 'http://arteika:8983/solr/trans/schema'
In particular, the copyFields, dynamicFields and fields keys in the schema object in the response.
I automated clearing all copy field rules, dynamic field rules and fields as follows. You can of course use any kind of script that is available to you. I used Python 3 (might work with Python 2, I did not test that).
import json
import requests
# load schema information
api = 'http://arteika:8983/solr/trans/schema'
r = requests.get(api)
# delete copy field rules
names = [(o['source'], o['dest']) for o in r.json()['schema']['copyFields']]
payload = {'delete-copy-field': [{'source': name[0], 'dest': name[1]} for name in names]}
requests.post(api, data = json.dumps(payload),
headers = {'Content-type': 'application/json'})
# delete dynamic fields
names = [o['name'] for o in r.json()['schema']['dynamicFields']]
payload = {'delete-dynamic-field': [{'name': name} for name in names]}
requests.post(api, data = json.dumps(payload),
headers = {'Content-type': 'application/json'})
# delete fields
names = [o['name'] for o in r.json()['schema']['fields']]
payload = {'delete-field': [{'name': name} for name in names]}
requests.post(api, data = json.dumps(payload),
headers = {'Content-type': 'application/json'})
Just a note: I received status 400 responses at first, with null error messages. Had a bit of a hard time figuring out how to fix those, so I'm sharing what worked for me. Changing the default of updateRequestProcessorChain in solrconfig.xml to false (default="${update.autoCreateFields:false}") and restarting the Solr service made those errors go away for me. The fields I was deleting were created automatically, that may have something to do with that.

Create inventory Square API / UNIREST Picture Upload

I want to create a product on my website and have it be created on square (which is working). However I also want to set the initial inventory which is seems there is no way to do it from the documentation. https://docs.connect.squareup.com/api/connect/v1/#post-inventory-variationid
If I go into my square account I can manually set up an initial amount, then query that entry and get the id and update it, but who wants to do anything manually. It defeats the purpose. Is there a way to create an inventory entry?
My second struggle is with uploading an image using unirest.
function uploadItemImage($itemId, $image_file)
{
global $accessToken, $locationId, $connectHost;
$requestHeaders = array
(
'Authorization' => 'Bearer ' . $accessToken,
'Accept' => 'application/json',
'Content-Type' => 'multipart/form-data;'
);
$request_body = array
(
'image_data'=>Unirest\Request\Body::file($image_file, 'text/plain', myproduct.jpg')
);
$response = Unirest\Request::post($connectHost . '/v1/' . $locationId . '/items/'.$itemId.'/image', $requestHeaders, $request_body);
print(json_encode($response->type, JSON_PRETTY_PRINT));
}
where $itemId is taken from the product created earlier and $image_file is the direct link to the file on my server
I keep getting this error...
> PHP Fatal error: Uncaught exception 'Unirest\Exception' with message
> 'couldn't open file "https://somewebsite/myPicture.jpg" ' in
> rootFolder/Unirest/Request.php:479 Stack trace:
> #0 rootFolder/Unirest/Request.php(292): Unirest\Request::send('POST', 'https://connect...', Array, Array, NULL, NULL)
> #1 rootFolder/
Any help is much appreciated!
Way to maximise the use of your question!
There is not currently a way to set initial inventory via API, but new item and inventory management APIs are in the works, read more on the Square Blog
I'm assuming that you are not literally using "https://somewebsite/myPicture.jpg" but it seems like unirest thinks you are trying to use a web url instead of getting a file from your filesystem. Try the following curl command and see if you can match up all the parts to unirest:
:)
curl --request POST \
--url https://connect.squareup.com/v1/XXXXXX/items/XXXXX/image \
--header 'authorization: Bearer sq0atp-XXXXX' \
--header 'cache-control: no-cache' \
--header 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
--form image_data=#/Users/ManuEng13/Desktop/test.png

Resources