Microsoft Graph putting null to /users/:id/photo/$value causing 500 - microsoft-graph-api

I am using the microsoft graph node.js sdk, making an app-only request to PUT to /users/f580eac0-9ece-413a-a26f-7964df1f2025/photo/$value, and I get the following:
{ statusCode: 500,
code: 'ErrorInternalServerError',
message: 'Value cannot be null.\r\nParameter name: userPrincipalName',
requestId: 'a5f0429d-ad3f-4f83-9e50-f540e5c8f9b8',
date: 2017-07-20T23:17:17.000Z,
body:
{ code: 'ErrorInternalServerError',
message: 'Value cannot be null.\r\nParameter name: userPrincipalName',
innerError:
{ 'request-id': 'a5f0429d-ad3f-4f83-9e50-f540e5c8f9b8',
date: '2017-07-20T23:17:17' } } }
How can I clear the photo for this user?

Unfortunately deleting a photo (or setting to null) is not supported currently. This is something that is being worked on, but I don't have a clear ETA and it may be some time before it's available.
The only (nasty) workaround I'm aware of is to PUT a 1x1 transparent photo.
Hope this helps,

Related

Is it possible to get a list of all streams using the spring cloud dataflow java rest client?

I'm using the spring cloud dataflow java rest client (https://docs.spring.io/spring-cloud-dataflow/docs/current/api/) and want to use it to retrieve all currently deployed streams.
It's easy enough to get a StreamOperations object and get a list of streams from it:
val template = DataFlowTemplate(<someUri>)
val streamOperations = template.streamOperations()
val streamDefinitionResources = streamOperations.list()
The streamDefinitionResources in the above is actually a PagedModel<StreamDefinitionResource>, that holds the first page of results using a page size of 2000.
I don't, however, see any way to iterate through all the pages to get all the streams using the java rest client (i.e. there's no paging support available via the StreamOperations or StreamDefinitionResource classes).
Is it possible to get all the streams using only the java rest client? Am I missing something?
Summary
The PagedModel<StreamDefinitionResource> has a getNextLink() method that you can use to manually traverse the "next" page of results.
Details
The underlying Dataflow REST API supports paging via page number and size request parameters and returns HAL responses that include _links to the next and previous pages.
For example, given 10 stream definitions this HTTP request:
GET localhost:9393/streams/definitions?page=0&size=2
returns the following response:
{
_embedded: {
streamDefinitionResourceList: [
{
name: "ticktock1",
dslText: "time | log",
originalDslText: "time | log",
status: "undeployed",
description: "",
statusDescription: "The app or group is known to the system, but is not currently deployed",
_links: {
self: {
href: "http://localhost:9393/streams/definitions/ticktock1"
}
}
},
{
name: "ticktock2",
dslText: "time | log",
originalDslText: "time | log",
status: "undeployed",
description: "",
statusDescription: "The app or group is known to the system, but is not currently deployed",
_links: {
self: {
href: "http://localhost:9393/streams/definitions/ticktock2"
}
}
}
]
},
_links: {
first: {
href: "http://localhost:9393/streams/definitions?page=0&size=2"
},
self: {
href: "http://localhost:9393/streams/definitions?page=0&size=2"
},
next: {
href: "http://localhost:9393/streams/definitions?page=1&size=2"
},
last: {
href: "http://localhost:9393/streams/definitions?page=4&size=2"
}
},
page: {
size: 2,
totalElements: 10,
totalPages: 5,
number: 0
}
}
The Dataflow Java REST client exposes this HAL response in the PagedModel<StreamDefinitionResource> response which provides a getNextLink() method.
Caveat 1) However, the current implementation (as you pointed out) is hardcoded to page size of 2000. This means you would not see this behavior until you had more than 2000 stream definitions.
Caveat 2) Another point to note is that traversal of the link to the "next" page is not automatically handled and you would need to manually invoke the links URL to retrieve the next page.
Assume the StreamOperations.list accepted a page size parameter the code could look something like this:
int pageSize = 2;
PagedModel<StreamDefinitionResource> pageOfStreamDefs = streamOperations().list(pageSize);
pageOfStreamDefs.getNextLink()
.ifPresent((link) -> someFunctionToInvokeAndProcessNextPage(link.getHref());
More details on the REST API parameters can be found here.
I guess I'm a bit late, but I had the same issue and found a workaround. As onobc said, the PagedModel of any resource has a getNextLink() method that returns a Link with the next page address.
You can use the same RestTemplate from DataflowTemplate to handle these next requests:
PagedModel<StreamDefinitionResource> streamDefPage = dataflowTemplate.streamOperations().list();
// Process page here
if (streamDefPage.getNextLink().isPresent()) {
Link link = streamDefPage.getNextLink().get();
PagedModel<StreamDefinitionResource> streamDefNextPage = dataflowTemplate.getRestTemplate().getForObject(link.getHref(), StreamDefinitionResource.Page.class);
// Process next page here
}
And so on.
Hope this helps!

Create team from group fails with exception

I created teams in Microsoft Teams (from groups as documented here) via the C# graph-api sdk without any problems - everything was working just fine.
But suddenly this is not working anymore. I will always get the following exception at the line return await graphServiceClient.Teams.Request().AddAsync(team);:
Message: Failed to execute Templates backend request
CreateTeamFromGroupWithTemplateRequest. Request Url:
https://teams.microsoft.com/fabric/emea/templates/api/groups/theGroupId/team,
Request Method: PUT,
And further:
Team Visibility can not be specified as it is inherited from the
group.
I know that the visibility property must not be set if creating the team from a group as it states in the Microsoft documentation:
The team that's created will always inherit from the group's display name, visibility, specialization, and members. Therefore, when making this call with the group#odata.bind property, the inclusion of team displayName, visibility, specialization, or members#odata.bind properties will return an error.
But the currently used code below shows that I am not setting any forbidden properties - and this code worked for the last few days, too:
private async Task<Team> CreateTeamFromGroup(string groupId)
{
var graphServiceClient = [...]
var groupResourceLink = $"https://graph.microsoft.com/v1.0/groups('{groupId}')";
var team = new Team
{
AdditionalData = new Dictionary<string, object>()
{
{ "template#odata.bind", "https://graph.microsoft.com/beta/teamsTemplates('standard')" },
{ "group#odata.bind", groupResourceLink }
},
Channels = new TeamChannelsCollectionPage
{
new Channel
{
DisplayName = "WhatEver"
}
}
};
return await graphServiceClient.Teams.Request().AddAsync(team);
}
Is anyone else experiencing this problem? Was there an API change? Was the teams backend changed? Anyone any ideas?
P.S.: I am using the latest NuGet-Package for Microsoft Graph - downgrading didn't help.
Update (with a not very satisfying work-around)
The error can be reproduced via the graph api explorer, too.
The POST command above issues a PUT command, that is described here. With this request, the team can be created.
The documentation and the graph api snippet for C# is out-dated, though. You have to add odatatype = null to the properties when using the sdk
Unfortunately it is not possible to add channels in the same step. If you specify the property 'channels' it will just be ignored.
Update (Detailed error message)
System.AggregateException: 'One or more errors occurred. (Code:
BadRequest Message: Failed to execute Templates backend request
CreateTeamFromGroupWithTemplateRequest. Request Url:
https://teams.microsoft.com/fabric/emea/templates/api/groups/theGroupId/team,
Request Method: PUT, Response Status Code: BadRequest,
ErrorMessage : {"errors":[{"message":"Team Visibility can not be
specified as it is inherited from the
group."}],"operationId":"639448e414ece64caee8f52839585bf7"} Inner
error: AdditionalData: date: 2020-11-24T10:21:22 request-id:
37a28cac-3ac5-4bd2-a061-daf44c442fac client-request-id:
37a28cac-3ac5-4bd2-a061-daf44c442fac ClientRequestId:
37a28cac-3ac5-4bd2-a061-daf44c442fac )'
Just tested this morning and I can say, that the "old way" by using the beta API to create a team with a template works again. Don't know, how many other ways exist to do these things, but here is our current request, that works now (again).
POST https://graph.microsoft.com/beta/teams
{
"displayName": "My Group Name",
"description": "Some description",
"template#odata.bind": "https://graph.microsoft.com/beta/teamsTemplates('educationClass')",
"owners#odata.bind": [
"https://graph.microsoft.com/beta/users('<someValidUserId>')"
]
}
I think this will be just an intermediate state and when the bugs are fixed, they will publish the new version again and this kind of creation will fail again, but if in this case the v1.0 documented way will work this wouldn't be a big problem. But being informed BEFORE there roll-out starts would be great.
This was a Microsoft issue/ bug and is currently being fixed as stated here.

Microsoft Graph Beta SDK Search throws exception "The call failed, please try again." 0x713DBA9F

I'm trying to search with app-only credentials and the MS Graph Beta SDK.
The search query works fine in the graph explorer. I've copied the C# code snippet from there:
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var requests = new List<SearchRequestObject>()
{
new SearchRequestObject
{
EntityTypes = new List<EntityType>()
{
EntityType.DriveItem
},
Query = new SearchQuery
{
Query_string = new SearchQueryString
{
Query = "test"
}
},
From = 0,
Size = 25
}
};
await graphClient.Search
.Query(requests)
.Request()
.PostAsync();
However the request returns an exception:
Microsoft.Graph.ServiceException: 'Code: 0x713DBA9F Message: The
call failed, please try again. Inner error: AdditionalData: date:
2020-07-01T10:13:47 request-id: db08906e-2b78-4a57-8109-dcbc6b306c2e
ClientRequestId: db08906e-2b78-4a57-8109-dcbc6b306c2e
It should not be a permission error, as I fixed one exception about permission by adding Files.Read.All to the App in AD and giving consent to the tenant.
How can I find out what's going wrong?
I found this which seems to show /beta/search is not supported for application token, but needs delegate token.
I'll try to use /drives/{drive-id}/root/search(q='{search-text}') instead which should support application tokens.
https://github.com/microsoftgraph/microsoft-graph-docs/issues/7727

Cant find information about acceptable response from my site to zapier app on test step (It's "Action" on my site )

I can't find information about acceptable response content or code status from my site to zapier app on test step.
I have my site on Laravel and Zapier app for this site. In my Zapier app I have an action: "Create New Project". I made my "create" according to the example. Everything works except the testing step. I tested with the following zap:
Trello -> "New card created" trigger. Test successful.
My app -> "Create new project". Test fails with We had trouble sending your test through. Could not handle special, non-standard characters. Please contact support.
Strangely, the project was created successfully. Therefore, I think the problem lies in the response from my site to zapier:
// creates/project.js
// My perform function:
perform: (z, bundle) => {
const promise = z.request({
url: `${process.env.BASE_URL}/api/folder`,
method: 'POST',
body: JSON.stringify({
title: bundle.inputData.title,
}),
headers: {
'content-type': 'application/json',
}
});
return promise.then((response) => JSON.parse(response.content));
}
//ZapierController.php
public function addFolder(Request $request)
{
// Made record to DB, and other, after this returned same data which in request
return response()->json(['title' => $request['title']]);
}
Expected result - successful test on "Test this step". Can anyone help me?
David here, from the Zapier Platform team.
I already answered your support ticket, but I figured I'd reply here in case anyone else has the same issue.
The root problem is made clear when you run zapier logs on the cli:
== Log
Unhandled error: CheckError: Invalid API Response:
- Got a non-object result, expected an object from create ("title")
What happened:
Executing creates.сFolder.operation.perform with bundle
Invalid API Response:
- Got a non-object result, expected an object from create ("title")
Your server can reply with any 2xx status code, but the output needs to be valid json. Something like {"title": "my title here"} would certainly work. Users find it more helpful to get info about the project they just created, so the name, id, etc would be even better.
As for why this surfaced as a character encoding issue, I have no clue. We plan on getting to the bottom of it though!

Can server side logic be added to firebase to implement an automatically incremental key?

I am new to firebase, and I am trying to implement an iOS chat app. I am wondering if there is a way to add a incremental id to the received message.
For example:
I send the following message to firebase
{date: "2015-10-14T04:30:43", name: "Jacob" text:"Hi" userId: "y8jFdNwRAX" }
Is that possible that firebase add a messageId key to it
{msgId:1, date: "2015-10-14T04:30:43", name: "Jacob" text:"Hi" userId: "y8jFdNwRAX"};
and if I send another msg, firebase add msgId and increase it by 1:
{msgId:2, date: "2015-10-14T04:31:40", name: "Jacob" text:"morning" userId: "y8jFdNwRAX"};
Not sure if firebase can do this or not? Any help is appreciated. Thank you in advance.
So the answer to the question is no, it's not going to happen with some kind of automated server side logic. And, that's a bad idea in general.
There are ways to emulate a counter but it can be really tricky to work with and there are so many ways it can go wrong, it's just not good code.
So I would suggest looking for another solution:
Perhaps for each message has a child node that tracks whether it's been read?
message_id_1
timestamp: "2015-10-14T04:30:43"
name: "Jacob"
text: "Hi"
userId: "y8jFdNwRAX"
read: "yes"
message_id_2
timestamp: "2015-10-14T04:30:50"
name: "Bob"
text: "Hi Back At Ya"
userId: "y9jaksjk"
read: "no"
You could even have a 'read' node and an 'unread' node
read_messages
message_id_1
timestamp: "2015-10-14T04:30:43"
name: "Jacob"
text: "Hi"
userId: "y8jFdNwRAX"
unread_messages
message_id_2
timestamp: "2015-10-14T04:30:50"
name: "Bob"
text: "Hi Back At Ya"
userId: "y9jaksjk"
And here's a tricky one: Store messages in their own node and a reference to those unread ones in the users node
all_messages
message_id_1
timestamp: "2015-10-14T04:30:43"
from_userId: "y9jaksjk"
text: "This is message 1"
message_id_2
timestamp: "2015-10-14T04:30:50"
from_userId: "y9jaksjk"
text: "this is message 2"
users
"y8jFdNwRAX"
my_unread_messages:
message_id_1: true
(message_id_1: true saved as a child of the user is a reference that indicates the message is for that user and has not been read. When read, remove the reference.)
All of this is conjecture as we don't know the scope of the app and the use of the messages.
You may want to visit the docs a bit more and review some of the sample code provided for other options.
In case someone has the same question. I used timestamp as sort of "messageId" in server side to track the order(Probably not a good idea, but it solves what I need), and you can create '.indexon' on this "messageId" in the security rules to get better performance.
Here is an example for the security rule:
{
"rules": {
"Messages":{
"$Message":{
".indexOn": "messageId"
}
}
}
setup code in iOS:
msg[#"messageId"] = kFirebaseServerValueTimestamp;
Note, there is a possible bug for Firebase: the one you received timestamp from FEventTypeChildAdded seems different with the one saved in Firebase DB sometimes(a couple hundred ms diff).
i had the same problem for another reason
incremented keys can be achieved by transactions:
https://www.firebase.com/docs/ios/api/#firebase_runTransactionBlock
an example for swift:
let messagesRef = ...
let counterRef = ... //you need to keep the count of messages
counterRef.runTransactionBlock({ (currentData) -> FTransactionResult! in
var value = currentData.value as? Int
if (value == nil) {value=0}
currentData.value = value! + 1
return FTransactionResult.successWithValue(currentData)
}) { (error, commited, snap) -> Void in
if error != nil {
print(error)
}
if commited {
//if increment is made set message
let messageInfo = ....
messagesRef.childByAppendingPath(snap.value).setValue(messageInfo)
}
if the only goal is ordering, childbyautoid function would be enough since it creates the keys accordingly
messagesRef.childByAutoId().setValue(messageInfo)
hope this helps someone

Resources