Programmatically accepting Microsoft Graph shared calendar invites - microsoft-graph-api

I'm working on a script for management of shared calendars using a service account. For security and compliance reasons, we cannot use application level permissions and the service account only has delegate permissions. This requires that users opting into the service share their calendars with the service account.
The goal is to be able to list all of the shared calendars for the service account using
GET https://graph.microsoft.com/v1.0/me/calendars
and manage each of those calendars (events being created, deleted, edited, etc.) using
POST https://graph.microsoft.com/v1.0/me/calendars/{shared-calendar-id}/events
or
PATCH or DELETE https://graph.microsoft.com/v1.0/me/calendars/{shared-calendar-id}/events/{event-id}
That all works fine once the calendar has been shared and accepted. The problem is accepting the share invitation.
Since the introduction of the "new" sharing system, the recipient of the share receives a sharing notification in their mailbox which they have to accept.
Being that this is a service account and dealing with several hundred users, manually checking and accepting all of the share invites will not be feasible and we need a programmatic way of doing this.
Is there an MS Graph endpoint to accept a calendar share invite?
Once a user sends a calendar share invite, parsing messages using
GET https://graph.microsoft.com/v1.0/me/messages
the calendar invite shows up as having these additional fields
"#odata.type": "#microsoft.graph.calendarSharingMessage",
"sharingMessageAction": {
"importance": "primary",
"actionType": "accept",
"action": "acceptAndViewCalendar"
},
"sharingMessageActions": [
{
"importance": "primary",
"actionType": "accept",
"action": "acceptAndViewCalendar"
}
]
Furthermore, the calendar becomes visible with the below endpoint
GET https://graph.microsoft.com/v1.0/users/{user-id}/calendars/
but is not listed on /me/calendars until the invite is accepted (and the shared copy is created).
There is an accept url in the body of the share invite email, but trying to use this url always results in a 500 error.
The documentation covers accepting a shared event where POST to the /tentativelyAccept endpoint of the event is used. Unfortunately I have been unable to find any similar documentation for calendar shares.
If anyone has a way to accept calendar share invites that do not involve manually clicking on the button in the email, please let me know :)
Thanks!

Related

Authorization denied for bot when attempting to create conversation via API

I'm trying to develop a bot to be used exclusively for proactive messaging (since unfortunately, it appears Connectors do not support direct messaging). I stood up a web service, and was able to receive the payload from Teams when I sent a message to the bot.
I'm now trying to send a proactive message from the bot back to my user, as described here. Per the instructions, I am POSTing the following payload to <serviceUrl>/v3/conversations. (Values in brackets are interpolated from the payload I received from Teams)
{
"bot": {
"id": <recipient.id>,
"name": <recipient.name>
},
"isGroup": false,
"members": [
{
"id": <from.id>,
"name": <from.name>
}
],
"tenantId": <channelData.tenant.id>,
"topicName": "News Alert"
}
I also included a Bearer token that I got by calling https://login.microsoftonline.com/<channelData.tenant.id>/oauth2/v2.0/token. Yet, whenever I try to create the conversation, it fails with an error that "Authorization has been denied for this request." As far as I can tell, the token should be valid, so I'm not sure what else could be going on here. I saw something about trusting the service URL, but I'm not sure how I would do that since I'm not using the Bot SDK. Perhaps I'm going about this wrong and should be trying to create an Activity rather than a Conversation?
There are basically two steps in sending pro-active messages. The first step is just a once-off - it's getting the unique ID of the conversation between the bot and the user. It's the paragraph you're linking to in your original question, and it's the payload sample you're showing. Once you've got that conversation id, you'd then proceed to sending messages at any time in the future (that's this paragraph).
However, in Teams, the first part is handled differently. Rather than calling the bot framework conversation endpoint (recall that bot framework is used for other things aside from Teams bots), you wait for the user to install the app, which includes your bot. When this is done, your bot will receive a conversationUpdate event. When this fires, you'll be sent a payload which includes the conversationId of the newly-created conversation. This replaces the call you're currently making.
You need to save the conversationId, and the serviceUrl (which will be similar too 'https://smba.trafficmanager.net/apis', but unique for Teams, and will be the 'base' of the URL you'll call later).
Importantly, it is possible to "pre-install" an app for a user, using the Graph API. See Install app for user.
That should help with what you're missing. However, as an 'fyi', you can use libraries for this instead of making the call directly yourself. In dotnet, for instance, you can reference Microsoft.Bot.Connector.ConnectorClient (in Microsoft.Bot.Connector), which has a Conversations.SendToConversationAsync(..) method.
I think I've figured out the problem. I sent my token request to https://login.microsoftonline.com/<channelData.tenant.id>/oauth2/v2.0/token, which was successful and gave me a token back. However, the instructions outlined here say not to use <channelData.tenant.id>, but instead just the hardcoded string botframework.com. After requesting the token that way, my requests appear to be working.

Jira ServiceDesk API - response suddenly missing the field emailAddress

I am getting a list of users in an organisation from the Jira ServiceDesk API, as documented on this page.
So far this is working as expected but today all off a sudden the code is broken. That is to say; the results im getting from the API have changed. As the docs state i SHOULD be getting values that include the field emailAddress. However since today i am getting the right users, but there is no longer an emailAddress field. The following is the result (structure) i'm recieving:
{
"size": 1,
"start": 0,
"limit": 50,
"isLastPage": true,
"_links": {
"self": "https://someprefix.atlassian.net/rest/servicedeskapi/organization/1/user?start=0&limit=50",
"base": "BaseURL",
"context": ""
},
"values": [
{
"accountId": "123456:SomeGUID",
"name": "SomeUserName",
"key": "someusername",
"displayName": "Some Username",
"active": true,
"timeZone": "Europe/Amsterdam",
"_links": {
"jiraRest": "LinkToTheThisUser",
"avatarUrls": {
"48x48": "LinkTo48X48Url",
"24x24": "LinkTo24X24Url",
"16x16": "LinkTo16X16Url",
"32x32": "LinkTo32X32Url"
},
"self": "LinkToThisResource"
}
}
]
}
I asked to check the setting User email visibility and it is currently set to logged in users only.
My question:
Why is this field suddenly missing from the API? Is there or are there settings i'm unaware off that influence this field being present or not?
Ok, it seems this is by design to keep in line with GDPR guidelines. Long story short; emailAddress will no longer be reliably part of the API's since a user now has to consent to it. If not all users emailAddresses are reliably part of the response this makes for a poor field of comparison in synchronization applications.
Which profile information will apps be able to access?
Any personal information users set as Anyone will be available for apps to use. For
example, apps will be able to access this information, store it, and
show it to other users.
Users' local times and locations will always be available to apps,
regardless of their visibility settings. This lets apps customize
their experiences.
Users' email addresses will be available to some apps that have been
approved by Atlassian. Note that if a user chooses to set their email
address to Anyone, then any installed apps will be able to use it.
When users install apps, the apps will request that they consent to
share their profile information with the apps. If they consent, the
apps will have access to all of their profile information. This is not
applicable to admins.
However. There will be a new API giving access to user emailAddresses regardless of user settings. Access to this API is restricted to approved applications. More about this can be found on this page.
In order to apply for access to this API the app must meet all current
requirements for being listed on Atlassian Marketplace (even if the
app is not listed on Atlassian Marketplace).
This means:
The app developer has provided a privacy policy
The app developer has provided a customer terms of use agreement
The app developer must signal whether or not the app collects and stores personal data.
If the app is storing personal data the app must report the accountIDs that have been collected and stored every 15 days.

How to link slack user with github account?

I am creating a slack bot and want to be able to link the slack user with the github account.
Is there a way I can link the 2 either via slack or github API's?
I was thinking if of storing users slack username and github username in a JSON object, i.e.:
{
"slack_username": "JoeBlogs",
"github_username": "JoeBlogs123"
}
In order to do this, I would need to retrieve the users' username from slack API when the user authorises the app / bot.
I was thinking if I add a redirect_url to my slack app then it would redirect user to http://example.com/redirect if the users data is sent along to this redirect url, I would be able save it in a database of sorts.
If I then did the same with the github API then I could reference database in order to find slack users JoeBlogs github account and vice versa.
Is it possible to use the redirect_url like this? I couldn't see any user data being sent to but maybe it is nested somewhere I couldn't see it?
Is there a better way to link the 2 accounts?
Assuming you are using Install button to install your Slack app into the workspace, this is a payload which will be sent to your response_url:
{
"access_token": "xoxp-XXXXXXXX-XXXXXXXX-XXXXX",
"scope": "incoming-webhook,commands,bot",
"team_name": "Team Installing Your Hook",
"team_id": "XXXXXXXXXX",
"incoming_webhook": {
"url": "https://hooks.slack.com/TXXXXX/BXXXXX/XXXXXXXXXX",
"channel": "#channel-it-will-post-to",
"configuration_url": "https://teamname.slack.com/services/BXXXXX"
},
"bot":{
"bot_user_id":"UTTTTTTTTTTR",
"bot_access_token":"xoxb-XXXXXXXXXXXX-TTTTTTTTTTTTTT"
}
}
See for details.
Then, using access_token in combination with users.identity API method you will get basic information about Slack user (playing with the scopes you requested during the install process you can get different fields of Slack user identity).

How can I add a user to organization in ASANA via API?

I'd like to add a new user to ASANA programmatically. I already have the OAUTH App and the user token.
Looking at the API I can't find a way to "create a new user".
Is it possible to create a new user simple via API?
Otherwise, is it possible to "invite" a new user via given email? Like from the UI where you can put the EMAIL and the system send an invitation link!
I tried with:
https://app.asana.com/api/1.0/workspaces/[WORKSPACEID]/addUser?user=[NEW USER EMAIL]
But I get a BAD REQUEST in response:
{
"errors": [
{
"message": "Could not parse request data, invalid JSON",
"help": "For more information on API status codes and how to handle them, read the docs on errors: https://asana.com/developers/documentation/getting-started/errors"
}
]
}
Thank you very much
I've never tried to do that specifically, but recently I did attempt to add members to a project through the API. There was nothing in the documentation about it, and I was told that it wasn't a supported API operation.
I would guess that if there's no mention of this feature in the documentation that it's also not supported for a similar reason.

Using Email Settings API from app engine with service account

I'm trying to use the Email Settings API from within a google marketplace app. Because I need all the logic to happen offline (in a cron job). I'm using an app engine Service Account, but when I'm trying to actually change the email settings for the users of the domain that installed it I'm getting this error:
You are not authorized to access this API.
Error 403
this is the scope: https://apps-apis.google.com/a/feeds/emailsettings/2.0/
I'm probably missing something, but I couldn't find the right docs to show me the way. How would I go about implementing an app that accesses the email settings even when the admin is offline?
You need to set the prn attribute to address of an admin account.
Examples for the directory API are at:
https://developers.google.com/admin-sdk/directory/v1/guides/delegation#instantiate_an_admin_sdk_directory_service_object
In terms of accessing the Email Settings API, you're really unlikely to get people to give you Service Account access to their domain.
On the other hand, if it's your domain (and thus you can add Service Account access), couple of pointers below:
What is important is that you add the following to the header:
"Authorization" = "Bearer <your_token>"
(note the very specific syntax - "Bearer+<1 space>+", as per https://www.rfc-editor.org/rfc/rfc6750 section 2.1)
"Content-Type" = "application/atom+xml"
(important for POST/PUT/DELETE requests, doesn't matter for GET)
that should get you up and running.

Resources