how to get a value of http response in logic apps - expression

i'm trying to get one value of the http response. which looks like this:
"body": {
"token_type": "string",
"expires_in": "number but as string",
"ext_expires_in": "same",
"expires_on": "same",
"not_before": "number but as string",
"resource": "string",
"access_token": "string"
}
i tried this expression in Set a variable: body('parse_JSON')?[variables('access_token')] which returned this error.
InvalidTemplate. Unable to process template language expressions in action 'Set_Access_Token' inputs at line '0' and column '0': 'The template language expression 'body('Parse_JSON')?[triggerBody()?['access_token']]' cannot be evaluated because property '' cannot be selected. Please see https://aka.ms/logicexpressions for usage details.'.
my workflow looks like this at the moment:
how can i get access_token value?

This can be done in 2 ways
WAY - 1
You can use Parse JSON action and extract the required variables which are directly generated. Below is the flow of my logic app.
Json Schema
{
"type": "object",
"properties": {
"body": {
"type": "object",
"properties": {
"token_type": {
"type": "string"
},
"expires_in": {
"type": "string"
},
"ext_expires_in": {
"type": "string"
},
"expires_on": {
"type": "string"
},
"not_before": {
"type": "string"
},
"resource": {
"type": "string"
},
"access_token": {
"type": "string"
}
}
}
}
}
RESULTS:
WAY - 2
You can use the below expression to extract access_tokenfrom the request.
body('Compose_2')?['access_token']
In your case its
body('HTTP_to_Refresh_Fibo')?['access_token']
RESULTS:

Related

How to extract content/text of an attachment from an MS Teams messaged generated by a webhook?

Automation #1 is ServiceNow > webhook > MS Teams > message.
Automation #2 is Power Automate > When keywords are mention (trigger) > read message from automation #1 > Post message in chat or channel
Problem: I am unable to workout the expression needed to read the content from the message body marked as the 2nd of the 3 blocks below i.e. "content":
"body": {
"contentType": "html",
"content": "<attachment id=\"x\"></attachment>",
"plainTextContent": ""
},
"channelIdentity": {
"teamId": "x",
"channelId": "x"
},
"attachments": [
{
"id": "x",
"contentType": "application/vnd.microsoft.teams.card.o365connector",
"contentUrl": null,
"content": "{\r\n \"summary\": \"P1/2 incident next action overdue [xx_NAO_P1-2]\",\r\n \"title\": \"P1/2 incident next action overdue [xx_NAO_P1-2]\",\r\n \"themeColor\": \"ff0000\",\r\n \"sections\": [\r\n {\r\n \"text\": \"Attn: <strong>name_here</strong> (email_here) \\n</br></br>\\nThe next action for case <strong>case_number</strong> is <span style=\\\"color:red\\\"><strong>over due</strong></span>. The stated action was:\\n</br></br>\\n<span style=\\\"color:blue\\\">This is the next action for case_number.</span>\",\r\n \"title\": \"\",\r\n \"activityTitle\": \"\",\r\n \"activitySubtitle\": \"\",\r\n \"activityText\": \"\",\r\n \"markdown\": false,\r\n \"startGroup\": false\r\n },\r\n {\r\n \"markdown\": true,\r\n \"startGroup\": false\r\n }\r\n ],\r\n \"potentialAction\": []\r\n}",
"name": null,
"thumbnailUrl": null
}
],
You can use the Body Content property for this.
Below is an example of this.
Btw, with an expression that would be:
outputs('Get_message_details')?['body/body/content']
Okay, this is my first ever Power Automate flow, so its not pretty. I think "Compose 2" and "Compose 3" are not required. If there are any suggestions on how to eliminate the need for 2x "Parse JSON" steps I am all ears. If there is a way to bypass the JSON steps altogether, even better.
I hope my experience, can help someone else.
Power Automate – Trigger
When keywords are mentioned
Message type: Channel
Keywords to search for: “[my keyword]”
Team: [my channel]
Channel – 1: General
Power Automate – Actions
Initialize variable – msg email
Name: msg_email
Type: String
Value: [empty]
Initialize variable – msg caseNumber
Name: msg_caseNumber
Type: String
Value: [empty]
Initialize variable – msg nextAction
Name: msg_nextAction
Type: String
Value: [empty]
Apply to each
Select an output from previous steps: Value = triggerOutputs()?[‘body/value’]
Get message details
Message: Message ID = items(‘Apply_to_each’)?[messageId’]
Message type: Channel
Team: Team ID = items(‘Apply_to_each’)?[‘teamId’]
Channel: Channel ID = items(‘Apply_to_each’)?[‘channelId’]
Parent message ID = [empty]
Parse JSON
Content: Body = body(‘Get_message_details’)
Schema: [I took the output of the message and generated a schema]
{
"type": "object",
"properties": {
"##odata.context": {
"type": "string"
},
"id": {
"type": "string"
},
"replyToId": {},
"etag": {
"type": "string"
},
"messageType": {
"type": "string"
},
"createdDateTime": {
"type": "string"
},
"lastModifiedDateTime": {
"type": "string"
},
"lastEditedDateTime": {},
"deletedDateTime": {},
"subject": {},
"summary": {
"type": "string"
},
"chatId": {},
"importance": {
"type": "string"
},
"locale": {
"type": "string"
},
"webUrl": {
"type": "string"
},
"policyViolation": {},
"eventDetail": {},
"from": {
"type": "object",
"properties": {
"device": {},
"user": {},
"application": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"displayName": {
"type": "string"
},
"applicationIdentityType": {
"type": "string"
}
}
}
}
},
"body": {
"type": "object",
"properties": {
"contentType": {
"type": "string"
},
"content": {
"type": "string"
},
"plainTextContent": {
"type": "string"
}
}
},
"channelIdentity": {
"type": "object",
"properties": {
"teamId": {
"type": "string"
},
"channelId": {
"type": "string"
}
}
},
"attachments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"contentType": {
"type": "string"
},
"contentUrl": {},
"content": {
"type": "string"
},
"name": {},
"thumbnailUrl": {}
},
"required": [
"id",
"contentType",
"contentUrl",
"content",
"name",
"thumbnailUrl"
]
}
},
"mentions": {
"type": "array"
},
"reactions": {
"type": "array"
},
"messageLink": {
"type": "string"
},
"threadType": {
"type": "string"
},
"teamId": {
"type": "string"
},
"channelId": {
"type": "string"
}
}
}
Apply to each 3
Select an output from previous steps: attachments = body(‘Parse_JSON’)?[‘attachments’]
Compose 2
Inputs: content x = items(‘Apply_to_each_3’)?[‘content’]
Parse JSON 2
Content: Outputs x = outputs(‘Compose_2’)
Schema: [I took the output of the attachment item and generated a schema]
{
"type": "object",
"properties": {
"summary": {
"type": "string"
},
"title": {
"type": "string"
},
"themeColor": {
"type": "string"
},
"sections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"text": {
"type": "string"
},
"title": {
"type": "string"
},
"activityTitle": {
"type": "string"
},
"activitySubtitle": {
"type": "string"
},
"activityText": {
"type": "string"
},
"markdown": {
"type": "boolean"
},
"startGroup": {
"type": "boolean"
}
},
"required": [
"markdown",
"startGroup"
]
}
},
"potentialAction": {
"type": "array"
}
}
}
Compose 3
Inputs: bodu(…) x = body(‘Parse_JSON_2’)[‘sections’][0][‘text’]
Note: after Compose 3 there are 3 parallel branches to create 3 variables which then converge back at Get an #mention token for a user.
1. Branch for variable msg_email
Find text position “(“
Text: Outputs x = outputs(‘Compose_3’)
Search Text: (
Substring email
Text: Outputs x = outputs(‘Compose_3’)
Starting Position: add(…) x = add(int(outputs('Find_text_position_"("')?['body']),1)
Length: sub(…) x = sub(sub(int(outputs('Find_text_position_")"')?['body']),int(outputs('Find_text_position_"("')?['body'])),1)
Set variable msg email
Name: msg_email
Value: Body x = body(‘Substring_email’)
2. Branch for variable msg_caseNumber
Find text position “[case prefix]“
Text: Outputs x = outputs(‘Compose_3’)
Search Text: [case prefix]
Substring caseNumber
Text: Outputs x = outputs(‘Compose_3’)
Starting Position: Body x = body(‘Find_text_position_”[case prefix]”’)
Length: 11
Set variable msg caseNumber
Name: msg_caseNumber
Value: Body x = body(‘Substring_caseNumber’)
3. Branch for variable msg_nextAction
Find text position “colour:blue“
Text: Outputs x = outputs(‘Compose_3’)
Search Text: color:blue
Substring nextAction+end tag
Text: Outputs x = outputs(‘Compose_3’)
Starting Position: add(…) x = add(12,int(outputs('Find_text_position_"color:blue"')?['body']))
Length: [empty]
Substring nextAction
Text: Body x = body(‘Substring_nextAction+end_tag’)
Starting Position: 0
Length: sub(…) x = sub(length(outputs('Substring_nextAction+end_tag')?['body']),7)
Set variable msg nextAction
Name: msg_nextAction
Value: Body = body(‘Substring_nextAction’)
Get an #mention token for a user
User: variables(‘msg_email’)
Reply with a message in a channel
Post as: Flow bot
Post in: Channel
Message ID: outputs(‘Get_message_deatils’)?[‘body/id’]
Channel: Channel ID = outputs(‘Get_message_details’)?[‘body/channelId’]
Message:
<p>#{outputs('Get_an_#mention_token_for_a_user')?['body/atMention']} Case #{variables('msg_caseNumber')} has an <span style="color: red"><strong>overdue Next Action</strong></span>. The stated action was:.<br>
<br>
<span style="color: blue"></span><span style="color: blue">#{variables('msg_nextAction')}</span><span style="color: blue"></span></p>

Validating yaml file by json scheme in monaco editor gives incorrect error

monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
validate: true,
schemas: \[
{
"$schema": "http://json-schema.org/draft-06/schema#",
"$ref": "#/definitions/Welcome1",
"definitions": {
"Welcome1": {
"type": "object",
"additionalProperties": false,
"properties": {
"inventory": {
"type": "array",
"items": {
"$ref": "#/definitions/Inventory"
}
}
},
"required": \[
"inventory"
\],
"title": "Welcome1"
},
"Inventory": {
"type": "object",
"additionalProperties": false,
"properties": {
"devices": {
"$ref": "#/definitions/Devices"
},
"pollfrequency": {
"type": "integer"
},
"scopedinventoryobject": {
"type": "string"
}
},
"required": \[
"devices",
"pollfrequency",
"scopedinventoryobject"
\],
"title": "Inventory"
},
"Devices": {
"type": "object",
"additionalProperties": false,
"properties": {
"platformtypes": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": \[
"platformtypes"
\],
"title": "Devices"
}
}
}
\]
});
Providing a screenshot for incorrect validation that i have. I haven't found a guide to use a monaco-yaml , so I am just trying to validate by json schema that i have for the file. Is it the right way for yaml validation in monaco editor? Or should i implement different approach right here?
I am facing the exact same problem. From what I understand when we set the schema to: monaco.languages.json.jsonDefaults.setDiagnosticsOptions
The schema is only referenced to the json language declared in model.
So, you are even defining the schema, but you are using a different language in the model. (Even so, the print error seems to be referenced to json)
I'm trying to use the package monaco-yaml because it seems that it already implements the validation

Add images via Shopware 6 API

I have a Shopware 6.3 shop and need to migrate images to it using the integration API.
How should I construct a body for a media upload? Do I need to put a file somewhere or just pass in the link?
I have managed to push new products into Shopware via guide here: https://docs.shopware.com/en/shopware-platform-dev-en/admin-api-guide/writing-entities?category=shopware-platform-dev-en/admin-api-guide#creating-entities but I am not sure how to handle media. In this guide it is only explained how to create links between already uploaded media files to products in here https://docs.shopware.com/en/shopware-platform-dev-en/admin-api-guide/writing-entities?category=shopware-platform-dev-en/admin-api-guide#media-handling but no examples as to how to actually push the media files.
I have URL's for each image I need (in the database, along with produc id's and image positions).
The entity schema describes media as:
"media": {
"name": "media",
"translatable": [
"alt",
"title",
"customFields"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"userId": {
"type": "string",
"format": "uuid"
},
"mediaFolderId": {
"type": "string",
"format": "uuid"
},
"mimeType": {
"type": "string",
"readOnly": true
},
"fileExtension": {
"type": "string",
"readOnly": true
},
"uploadedAt": {
"type": "string",
"format": "date-time",
"readOnly": true
},
"fileName": {
"type": "string",
"readOnly": true
},
"fileSize": {
"type": "integer",
"format": "int64",
"readOnly": true
},
"metaData": {
"type": "object",
"readOnly": true
},
"mediaType": {
"type": "object",
"readOnly": true
},
"alt": {
"type": "string"
},
"title": {
"type": "string"
},
"url": {
"type": "string"
},
"hasFile": {
"type": "boolean"
},
"private": {
"type": "boolean"
},
"customFields": {
"type": "object"
},
"createdAt": {
"type": "string",
"format": "date-time",
"readOnly": true
},
"updatedAt": {
"type": "string",
"format": "date-time",
"readOnly": true
},
"translated": {
"type": "object"
},
"tags": {
"type": "array",
"entity": "tag"
},
"thumbnails": {
"type": "array",
"entity": "media_thumbnail"
},
"user": {
"type": "object",
"entity": "user"
},
"categories": {
"type": "array",
"entity": "category"
},
"productManufacturers": {
"type": "array",
"entity": "product_manufacturer"
},
"productMedia": {
"type": "array",
"entity": "product_media"
},
"avatarUser": {
"type": "object",
"entity": "user"
},
"mediaFolder": {
"type": "object",
"entity": "media_folder"
},
"propertyGroupOptions": {
"type": "array",
"entity": "property_group_option"
},
"mailTemplateMedia": {
"type": "array",
"entity": "mail_template_media"
},
"documentBaseConfigs": {
"type": "array",
"entity": "document_base_config"
},
"shippingMethods": {
"type": "array",
"entity": "shipping_method"
},
"paymentMethods": {
"type": "array",
"entity": "payment_method"
},
"productConfiguratorSettings": {
"type": "array",
"entity": "product_configurator_setting"
},
"orderLineItems": {
"type": "array",
"entity": "order_line_item"
},
"cmsBlocks": {
"type": "array",
"entity": "cms_block"
},
"cmsSections": {
"type": "array",
"entity": "cms_section"
},
"cmsPages": {
"type": "array",
"entity": "cms_page"
},
"documents": {
"type": "array",
"entity": "document"
}
}
},
but it is not clear what fields are crucial. Do I need to create product-media folder first and then use it's id when making a POST request to media endpoint? Can I just specify the URL and will Shopware download the image itself to a folder or keep pointing to the URL I have used. I need to house the images inside the Shopware.
There is no problem for me to download the images from the URL and push them to Shopware but I am not sure how to use the API for it (there is a lot of images and they need to be done in bulk).
One possible solution:
FIRST: create a new media POST /api/{apiVersion}/media?_response=true
SECOND: "Upload Image" /api/{apiVersion}/_action/media/{mediaId}/upload?extension={extension}&fileName={imgName}&_response=true
more information can be found here: https://forum.shopware.com/discussion/comment/278603/#Comment_278603
In CASE images are for products use the endpoint POST /api/{apiVersion}/product-media and set the coverId
A complete listing of all routes is available via the OpenAPI schema: [your-domain/localhost]/api/v3/_info/openapi3.json
It's also possible to set all the media and the cover & coverId during product creation by one request. Therefore, set the product Cover and product Media
{
"coverId":"3d5ebde8c31243aea9ecebb1cbf7ef7b",
"productNumber":"SW10002","active":true,"name":"Test",
"description":"fasdf",
"media":[{
"productId":"94786d894e864783b546fbf7c60a3640",
"mediaId":"084f6aa36b074130912f476da1770504",
"position":0,
"id":"3d5ebde8c31243aea9ecebb1cbf7ef7b"
},
{
"productId":"94786d894e864783b546fbf7c60a3640",
"mediaId":"4923a2e38a544dc5a7ff3e26a37ab2ae",
"position":1,
"id":"600999c4df8b40a5bead55b75efe688c"
}],
"id":"94786d894e864783b546fbf7c60a3640"
}
Keep in mind to check if the bearer token is valid by checking for example like this:
if (JwtToken.ValidTo >= DateTime.Now.ToUniversalTime() - new TimeSpan(0, 5, 0))
{
return Client.Get(request);
}
else
{
// refresh the token by new authentication
IntegrationAuthenticator(this.key, this.secret);
}
return Client.Get(request);
This will work for Shopware 6.4
As a general advice, it depends. The APIs changed a little bit since 6.4 and there is also an official documentation available at https://shopware.stoplight.io/docs/admin-api/docs/guides/media-handling.md.
However, i think that it is always a little easier to have a real life example. What i do in our production environment is basically these steps.
(Optional) Check, if the media object exists
Create an media-file object using the endpoint GET /media-files/
If it exist then upload an image using the new media-id reference.
Let us assume the filename is yourfilename.jpg. What you also will need is a media-folder-id, which will reference the image-folder within Shopware. This can be obtained in Shopware via Admin > Content > Media > Product Media.
Step 0
Before uploading an image to Shopware, you want to ensure that the image does not exists, so that you can skip it.
This step is optional, as it is not mandatory to create an image. However you want to have some sort of validation mechanism in a production environment.
Request-Body
POST api/search/media
This will run a request against the Shopware-API with a response.
{
"filter":[
{
"type":"equals",
"field":"fileName",
"value":"yourfilename"
},
{
"type":"equals",
"field":"fileExtension",
"value":"jpg"
},
{
"type":"equals",
"field":"mediaFolderId",
"value":"d798f70b69f047c68810c45744b43d6f"
}
],
"includes":{
"media":[
"id"
]
}
}
Step 1
Create a new media-file
Request-Body
POST api/_action/sync
This request will create a new media-object in Shopware.
The value for media_id must be any UUID. I will use this value: 94f83a75669647288d4258f670a53e69
The customFields property is optional. I just use it to keep a reference of hash value which i could use to validate changed values.
The value for the media folder id is the one you will get from your Shopware-Backend.
{
"create-media": {
"entity": "media",
"action": "upsert",
"payload": [
{
"id": "{{media_id}}",
"customFields": {"hash": "{{file.hash}}"},
"mediaFolderId": "{{mediaFolderId}}"
}
]
}
}
Response
The response will tell you that everything works as expected.
{
"success":true,
"data":{
"create-media":{
"result":[
{
"entities":{
"media":[
"94f83a75669647288d4258f670a53e69"
],
"media_translation":[
{
"mediaId":"94f83a75669647288d4258f670a53e69",
"languageId":"2fbb5fe2e29a4d70aa5854ce7ce3e20b"
}
]
},
"errors":[
]
}
],
"extensions":[
]
}
},
"extensions":[
]
}
Step 2
This is the step where we will upload an image to Shopware. We will use a variant with the content-type image/jpg. However, a payload with an URL-Attribute would also work. See the details in the official documentation.
Request-Body
POST api/_action/media/94f83a75669647288d4258f670a53e69/upload?extension=jpg&fileName=yourfilename
Note that the media-id is part of the URL. And also the filename but without the file-extension JPG!
This body is pretty straightforward an in our case there is no payload, as we use an upload with Content-Type: "image/jpeg".
This would be a payload if you want to use an URL as resource:
{
"url": "<url-to-your-image>"
}

JSON Schema different properties must be related

Let say Im using JSON schema to validate an api spec. So, this is a minimal example of what I have :
{
"title": "spec",
"type": "object",
"properties": {
"swagger": {
"type": "string",
"pattern": "^(1[.]0|2[.]0|3[.]0)$"
},
"api-name": {
"type": "string",
"pattern": "^[a-zA-z]+[_][a-zA-z]+$"
},
"api-version": {
"type": "string",
"pattern": "^v[1-9]$"
},
"basePath": {
"type": "string",
"pattern": "^\/[a-zA-Z]{1,30}_[a-zA-Z]{1,30}(_[a-zA-Z]{1,30})?(_[a-zA-Z]{1,30})?(_[a-zA-Z]{1,30})?\/v[1-9]$"
}
}
}
And this an example of something that would validate as a valid input :
{
"swagger" : "2.0",
"api-name" : "get_products",
"api-version" : "v2",
"basePath" : "/fake_path/v5"
}
But I want basePath to be tied to the values of api-name and api-version so something like my input gets rejected. How can I achieve something like this?
I am using this for my testings :
https://www.jsonschemavalidator.net/

Querying inner objects by field name in Elasticsearch

I'm reading the documentation on this site: https://www.elastic.co/guide/en/elasticsearch/guide/current/complex-core-fields.html#_how_inner_objects_are_indexed
I'm interested in this paragraph:
Inner fields can be referred to by name (for example, first). To distinguish between two fields that have the same name, we can use the full path (for example, user.name.first) or even the type name plus the path (tweet.user.name.first).
so if I have the example from the linked docu site:
{
"gb": {
"tweet": {
"properties": {
"tweet": { "type": "string" },
"user": {
"type": "object",
"properties": {
"id": { "type": "string" },
"gender": { "type": "string" },
"age": { "type": "long" },
"name": {
"type": "object",
"properties": {
"full": { "type": "string" },
"first": { "type": "string" },
"last": { "type": "string" }
}
}
}
}
}
}
}
}
According to the docu I should be able to search with condition last: whatever, but it does not work. I always have to use the full path user.last: whatever. Is the documentation false or my understanding of it? Note that last occurs only in the inner object, so in theory full path should not be necessary to reference it.
edit:
query that works:
get /my_index/_search?q=user.name.last:test
query that does not work but should according to documentation:
get /my_index/_search?q=last:test

Resources