I am adding a new static tab to an existing teams app.
One of the new features is that the chat will publish a deep link to the static tab. This is creating a dilemna when I am contemplating deployment.
Obviously I can’t put my entire application up here, but we can assume a situation like this:
The manifest I have in production that is in the App Store looks like this:
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.9/MicrosoftTeams.schema.json",
"manifestVersion": "1.9",
"version": "2.0.1",
"id": "23232322-7676-4848-5555-44444444444",
"packageName": "xxxxx",
"developer": {
"name": "xxxxx",
"websiteUrl": "https://www.xxxx.com/",
"privacyUrl": "https://www.xxxx.com/legal/privacy",
"termsOfUseUrl": "https://www.xxxxx.com/legal/privacy"
},
"icons": {
"color": "color.png",
"outline": "outline.png"
},
"name": {
"short": "abra",
"full": "abra cadabra"
},
"description": {
"short": "short",
"full": "full"
},
"accentColor": "#FFFFFF",
"bots": [
{
"botId": "11111111-2222-3333-4444-555555555555",
"scopes": [
"personal"
],
"commandLists": [
{
"scopes": [
"personal"
],
"commands": [
{
"title": "Test",
"description": "Test"
}
]
}
],
"supportsFiles": false,
"isNotificationOnly": false
}
],
"permissions": [
"identity",
"messageTeamMembers"
],
"validDomains": [
"token.botframework.com",
"teams.microsoft.com",
"*.ngroc.io"
]
}
And in my bot in response to the “Test” command I return a simple text message, i.e.
return await step.prompt('textPrompt', { prompt: 'In the next version we will have a test tab' })
Now in development, I have added the following section to the manifest (after “bots”)
"staticTabs": [
{
"entityId": "conversations",
"scopes": [
"personal"
]
},
{
"entityId": "testtab”,
"contentBotId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"name": “Go To Test Tab",
"scopes": [ "personal" ]
},
{
"entityId": "about",
"scopes": [
"personal"
]
}
],
And I have updated the value of the version from 2.0.1 to 2.1.0
Now, in response to the “Test” message I am returning an adaptiveCard that looks like this:
{
type: 'AdaptiveCard',
version: '1.3',
body: [],
actions: [
{
type: 'Action.OpenUrl',
title: 'Go To Test Tab',
url: ‘https://teams.microsoft.com/l/entity/23232322-7676-4848-5555-44444444444/testtab’
}
]
}
This works very nicely and when I press the “go to Test Tab” it opens up the test tab as desired.
My problem is with deploying.
If I submit my new manifest to the App Store, without updating my production server, those testing the new version will continue to get the message “In the next version we will have a test tab” and be missing the link to the new tab.
If I update my production server now, before the update in the App Store, my current users will get the adaptive card with the button that will fail if they press it.
Clearly, neither of these options are good.
Ideally, my response should be something like:
If tabExists() {
Return {… the adaptive card }
Else {
return await step.prompt('textPrompt', { prompt: 'In the next version we will have a ‘test tab })
}
However, I don't know how to write "tabExists()" - I was thinking maybe there was some way to access the version number from the bot manifest, or the list of static tabs, and use that information, but I am happy for alternative suggestions.
We can get the manifest version using below Graph API or using SDK method:
https://learn.microsoft.com/en-us/graph/api/appcatalogs-list-teamsapps?view=graph-rest-1.0&tabs=http#example-4-list-applications-with-a-given-id-and-return-the-submission-review-state
So, before sending the Adaptive Card or message, you can put a custom condition to check the manifest version and send the message accordingly.
You can check the manifest version as explained by Chetan, i tried the same and figured its actually not the best idea.
It always should be best practice to have a "production" and "test" server or something like that.
Having different manifest versions point to the same server and running checks which version you're on will more than likely lead to issues sooner or later.
I sometimes even have 3 different instances running (prod, staging, test) to try various builds and things.
You can check that in your code but imo its not advisable to do so.
Related
I am trying to redirect the request sent to https://site/script1.js to a modified script stored locally chrome-extension://ext_id/my_script.js.
(Basically trying to emulate the behaviour of webRequests.onBeforeRequest -> return redirect to local file)
My rules.json :
[
{
"id": 1,
"priority": 10,
"action":
{ "type": "redirect",
"redirect" : {"extensionPath" : "/my_script.js"}
},
"condition":
{"urlFilter": "https://site/script1.js",
"resourceTypes": ["script"]
}
}
]
If I change the action type to block the chrome dev tools shows the request as blocked, and the website doesnt load, however on redirects, nothing happens and the request goes through. It doesnt work for Images either.
Is there possibly a workaround for this (to modify the script a site receives from a request)?
Edit:
I'll just try to get an image to work first, the declarativeNetRequest Docs single out Redirects for a script.
The website (https://www.example.com/a/b) sends a request to https://cdn.example.com/file.jpg. I want that request to return a file `my_file.jpg' stored locally .
I have :
Rules.json
[
{
"id": 2,
"priority": 9,
"action":
{ "type": "redirect",
"redirect" : {"extensionPath" : "/my_file.jpg"}
},
"condition":
{"urlFilter": "https://cdn.example.com/file.jpg",
"resourceTypes": ["image"]
}
}
]
and Manifest.json includes:
"host_permissions": [
"https://www.example.com/*"
],
"web_accessible_resources":[
{
"resources": ["my_file.jpg"],
"matches" :["https://www.example.com/*"]
}
]
I have an ARM template that deploys API's to an API Management instance
Here is an example of one API
{
"properties": {
"authenticationSettings": {
"subscriptionKeyRequired": false
},
"subscriptionKeyParameterNames": {
"header": "Ocp-Apim-Subscription-Key",
"query": "subscription-key"
},
"apiRevision": "1",
"isCurrent": true,
"subscriptionRequired": true,
"displayName": "DDD.CRM.PostLeadRequest",
"serviceUrl": "https://test1/api/FuncCreateLead?code=XXXXXXXXXX",
"path": "CRMAPI/PostLeadRequest",
"protocols": [
"https"
]
},
"name": "[concat(variables('ApimServiceName'), '/mms-crm-postleadrequest')]",
"type": "Microsoft.ApiManagement/service/apis",
"apiVersion": "2019-01-01",
"dependsOn": []
}
When I am deploying this to different environments I would like to be able to substitute the service url depending on the environment. I'm wondering the best approach?
Can I read in a config file or something like that?
At the time of deployment I have a variable that tells me the environment so I can base decisions on that. Just not sure the best way to do it
See about ARM template parameters: https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authoring-templates#parameters They can be specified in a separate file. So you will have single template, but environment specific parameter files.
relatively new to Postman, having problem with the following simple scenario - I have a collection of Postman requests that all point to a local IP where I am developing my application. Let's suppose I finished my local development, deployed the application on some other server, and want to repeat the requests I previously created on THAT server. I know that probably one way to do this would be to use variables.
Instead of that, though, I did an export of the collection, and did a manual edit of the exported JSON file, replacing all the old local IP's with the new server IP. Also changed the collection name, and ID to something arbitrary. While the import back to Postman works, and I see the requests, they all have the old IP still hanging there, as if my replace didn't work, or as if Postman somehow caches the requests and thinks that that new collection is the same as the old one. I also tried "Duplicating" a collection and exporting the duplicated one / replacing / importing again - but the behavior seems to be the same.
Did I miss something, or should I approach what I want to do differently?
Thank you.
duh, I am dumb enough to have been substituting the "raw" URL, while right below there were the old values for "host" and "port" that are the ones Postman constructs URL from:
{
"info": {
"_postman_id": "1499274a-07bc-4ed2-87d4-b10d0cef8f8f",
"name": "some-collection-DEVSERVER",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "login (success - bad locale)",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"value": "application/json",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n\t\"username\" : \"TEST\",\n\t\"password\" : \"123456\",\n\t\"locale\" : \"asd\"\n}"
},
"url": {
"raw": "http://SERVER-IP:SERVER-PORT/new-path/login",
"protocol": "http",
"host": [
"127",
"0",
"0",
"1"
],
"port": "8081",
"path": [
"old-path",
"login"
]
}
},
"response": []
},
...
]
}
So, after suggestion to use variables I ended up creating two Collection variables "base-URL-LOCAL" and "base-URL-SERVER", that play the role of constants, and a third variable "base-url" which e.g. could have the value of {{base-URL-LOCAL}} (both initial and current values have to be updated). In my exported JSON collection, i substituted all "url" elements with something like the following:
"url": {
"raw": "{{base-url}}/login",
"host": [
"{{base-url}}"
],
"path": [
"login"
]
}
That way somebody who gets my collection won't have to have pre-defined environments set up, and will have to edit collection variables, setting e.g. base-url to {{base-URL-SERVER}}
I'm battling with the WikiEditor extension of MediaWiki 1.27. When a user tries to use the fancy image upload button from the enhanced editor toolbar, I get the message "You must be logged in to upload files."
So far I've narrowed it down to the user rights returned from the API being incomplete. I've tested with the following two API calls:
The one WikiEditor uses: action=query&meta=userinfo&uiprop=rights
returns:
{
"batchcomplete": "",
"query": {
"userinfo": {
"id": 1006,
"name": "john_smith",
"rights": [
"read",
"createpage",
"createtalk",
"writeapi",
"editmyusercss",
"editmyuserjs",
"viewmywatchlist",
"editmywatchlist",
"viewmyprivateinfo",
"editmyprivateinfo",
"editmyoptions",
"autocreateaccount"
]
}
}
}
However, this API call: action=query&list=users&ususers=john_smith&usprop=rights returns:
{
"batchcomplete": "",
"query": {
"users": [
{
"userid": 1006,
"name": "john_smith",
"rights": [
"block",
"createaccount",
"delete",
"bigdelete",
"deletedhistory",
"deletedtext",
"undelete",
"editinterface",
"editusercss",
"edituserjs",
"editcontentmodel",
"import",
"importupload",
"move",
"move-subpages",
"move-rootuserpages",
"move-categorypages",
"patrol",
"autopatrol",
"protect",
"editprotected",
"rollback",
"upload",
"reupload",
"reupload-shared",
"unwatchedpages",
"autoconfirmed",
"editsemiprotected",
"ipblock-exempt",
"blockemail",
"markbotedits",
"apihighlimits",
"browsearchive",
"noratelimit",
"movefile",
"unblockself",
"suppressredirect",
"mergehistory",
"managechangetags",
"deleterevision",
"read",
"createpage",
"createtalk",
"writeapi",
"editmyusercss",
"editmyuserjs",
"viewmywatchlist",
"editmywatchlist",
"viewmyprivateinfo",
"editmyprivateinfo",
"editmyoptions",
"autocreateaccount",
"edit",
"minoredit",
"purge",
"sendemail",
"applychangetags",
"changetags"
]
}
]
}
}
I'm totally stumped and at a loss of why these two very similar API calls return a different set of rights. As a result, users are not able to upload images via the enhanced editor button.
I am trying to load a simple CSV file to OrientDB and it always throws this exception.
CSV File Content
id, name, role
1, Sarath, Architect
2, Anoop, Project Manager
3, Nazeem, Lead Developer
4, Rini, Senior Developer
5, Shine, iOS Developer
6, Vishnu, iOS Developer
json config file
{
"source": { "file": { "path": "./dev.csv" } },
"extractor": { "row": {} },
"transformers": [
{
"csv": {}
},
{ "vertex": { "class": "Person" } }
],
"loader": {
"orientdb": {
"dbURL": "remote:localhost/dev",
"dbType": "graph",
"dbUser": "root",
"dbPassword": "root",
"dbAutoCreate": true,
"classes": [
{"name": "Person", "extends": "V"}
], "indexes": [
{"class":"Person", "fields":["id:integer"], "type":"UNIQUE" }
]
}
}
}
All the time it shows this exception. I tried different CSV options but it did not work. Looks like the file reading itself throwing exception.
» oetl posts.json sarat#Saraths-MacBook-Air
OrientDB etl v.2.0.1 (build #BUILD#) www.orientechnologies.com
Exception in thread "main" com.orientechnologies.orient.core.exception.OConfigurationException: Error on loading config file: posts.json
at com.orientechnologies.orient.etl.OETLProcessor.main(OETLProcessor.java:151)
Platform Details
OS X 10.10.2
java version "1.8.0_25"
OrientDB - v.2.0.1
The stack trace gives you the cause of the problem (you only showed the first, not interesting lines in your example).
Check:
The server is running (you specified remote:localhost/dev, so the server must be running on the default port at the same machine).
The database exists and has "root" / "root" as credentials (note that mostly "admin" "admin" is used)
The file dev.csv is present in the current directory
Tried out your example and works without modification.
I had the same problem, and it was due to one of the directories in the path to the JSON config file having a space in it. The oetl script doesn't handle this well and thus can't find the script.
#rmuller: The OP showed the entire traceback. That's all you get in this case.