Add member to distribution group using Azure AD API - node.js

I want to add a member to a distribution list. As apparently I can't do this using Microsoft Graph, I am trying to use Azure AD Graph API. I am using Node.js.
I am able to connect to Azure using the adal-node library. I get a token back, send requests, and get responses. (I can list groups, users, etc.).
I am following the Add Members documentation, but I am confused.
In the URL, is object_id the id of the Group to witch I want to add the member?
For myorganization, I am using the tennant_id.
Where do I specify the user data? Should I pass that in the POST? If so, whats' the format?
What is the $links in the URL?
Currently, I am doing this:
request.post(
"https://graph.windows.net/TENNANT_ID_HERE/groups/GROUP_ID_HERE/$links/members?api-version=1.6",
{
headers: {
Authorization: "Bearer " + TOKEN_HERE,
"Content-Type": "application/json"
},
form: { key: "value" } //should I put my user object here?
},
function(err, res, body) {
if (err) {
console.log("err: " + err);
} else {
console.log("res: " + JSON.stringify(res, null, 3));
}
}
);
I get the following error:
{
"odata.error": {
"code": "Request_BadRequest",
"message": {
"lang": "en",
"value": "A supported MIME type could not be found that matches the
content type of the response. None of the supported type(s) 'application/xml, text/xml,
application/json;odata=minimalmetadata;streaming=true, application/json;odata=minimalmetadata;
streaming=false, application/json;odata=minimalmetadata,
application/json;odata=fullmetadata;streaming=true,
application/json;odata=fullmetadata;streaming=false,
application/json;odata=fullmetadata,
application/json;odata=nometadata;streaming=true,
application/json;odata=nometadata;streaming=false,
application/json;odata=nometadata,
application/json;streaming=true,
application/json;streaming=false,
application/json;odata=verbose,
application/json'
matches the content type 'application/x-www-form-urlencoded'."
}
}
}

The short/most important answer is that neither Microsoft Graph or Azure AD Graph API supports distribution lists. From the documentation:
Important: You can only add members to security groups and mail-enabled security groups.
That said, this isn't technically why your call is failing here. Your code is reaching the point where it's failing due to the type of group you're working with. And while it won't help you with managing a distribution list, the following is what is actually happening.
The form: { key: "value" } option is telling request to send the payload as a URL Encoded Form (application/x-www-form-urlencoded). The API requires the payload be sent as JSON (application/json).
To send over JSON, you need to do two things:
Set the json option to true
Set the body value rather than the form value.
The proper code would look something like this:
request.post(
"https://graph.windows.net/{tenant-id}/groups/{group-id}/$links/members?api-version=1.6",
{
headers: {
Authorization: "Bearer " + TOKEN_HERE
},
json: true,
body: JSON.stringify({ url: "https://graph.windows.net/{tenant-id}/directoryObjects/{user-id}" })
},
function(err, res, body) {
if (err) {
console.log("err: " + err);
} else {
console.log("res: " + JSON.stringify(res, null, 3));
}
}
);
The $links parameter in the URI is telling the API that you're providing a link to another resource (in this case, a user record).

we could add member to a group with AD graph API.
post https://graph.windows.net/{tenantId}/groups/{groupobjectid}/$links/members?api-version=1.6
body
{
"url": "https://graph.windows.net/{tenantId}/directoryObjects/{userObjectId}"
}
Test it with Postman

Related

Weird Google Places Find Place API parsing fields parameter error with certain fields (not deprecated)

I try to run the google places "findplace" from text API. When I run it for the basic parameters, it works. However, when I add on the international phone number and website parameters it no longer works. I am returned the following error:
error_message: "Error while parsing 'fields' parameter: Unsupported field name 'international_phone_number'. ",
status: 'INVALID_REQUEST'
Here is my code:
let input = name;
let fields = "name%2cformatted_address%2Cplace_id%2Cbusiness_status%2Cinternational_phone_number%2Cwebsite";
let locationBias = "circle%3A1000%40" + latitude + "%2C" + longitude;
let url = "https://maps.googleapis.com/maps/api/place/findplacefromtext/json?fields=" + fields + "&language=en&input=" + input + "&inputtype=textquery&locationbias=" + locationBias + "&key=" + placesApiKey;
function getData(url) {
fetch(url, {
"headers": {
},
"body": null,
"method": "GET"
})
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.log(err));
}
getData(url);
Note, that when I cut off the international phone number and website parameters it executes successfully. When I google the property in question, the google place object does contain these two fields.
Any help would be greatly appreciated.
so the place search does not return this information. rather you can use Place Search to get a place_id, then use that Place ID to make a Place Details request.
https://developers.google.com/maps/documentation/places/web-service/search-find-place#maps_http_places_findplacefromtext_locationbias-txt

Where do I store custom data in an Event item so attendees can also fetch that custom data?

What properties can/should we use to store custom json data in an event item?
We're currently trying to develop a web add-in, which has a form that should be sent as json within a property of the Event item, so whenever another person (i.e. an attendee) opens the add-in, the same form will show for them.
In a VSTO C# add-in, we can set an Outlook.UserProperty for this, which seems to propagate to attendees whenever the organizer edits the value.
In javascript, I've tried the following:
Setting a CustomProperties value, by fetching the values with Office.context.mailbox.item.loadCustomPropertiesAsync and setting the value via properties.set(FORM_KEY, JSON.stringify(jsonObject)); properties.saveAsync(...);.
Creating a SingleValueExtendedProperty like so:
fetch(Office.context.mailbox.restUrl+"/v2.0/me/events('"+getRestId(itemId)+"')", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + accessToken
},
body: JSON.stringify({
SingleValueExtendedProperties: [
{
PropertyId: singleValueExtendedPropertyId,
Value: JSON.stringify(jsonObject)
}
]
})
})
Creating a data extension like so:
fetch(Office.context.mailbox.restUrl+"/v2.0/me/events('"+getRestId(itemId)+"')/extensions('Microsoft.OutlookServices.OpenTypeExtension."+extensionName+"')",
{
method: "PATCH",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + accessToken
},
body:
JSON.stringify({
"#odata.type": "Microsoft.OutlookServices.OpenTypeExtension",
ExtensionName: extensionName,
Value: JSON.stringify(jsonObject)
})
})
These all work for the organizer...
They are never propagated to the attendees.
Currently, storing custom data on events/meetings that is accessible to both the attendees and organizer is not supported. We track Outlook add-in feature requests on ourĀ user-voice page. Please add your request there. Feature requests on user-voice are considered, when we go through our planning process.

Access to a JSON Value in Angular 7

Hello I'm trying to access to an especific key from a JSON. I'm using node.js and angular 7
The JSON I got is stringfy and it comes from an API.
This is the JSON I got
"search": {
"entry": [
{
"dn": "uid=080030781,c=mx,ou=s,o=i.com",
"attribute": [
{ "name": "mail", "value": ["CAMILA.CAMPOS.TELLEZ#mail.com", "MX08#mail.com"] }]
}
],
"return": {
"code": 0,
"message": "Success",
"count": 1
}
}
}
I need to access to the key "value", because I need to get the value "camila.campos.tellez#mail.com".
I get the JSON from an API declarated in a node.js file called app.js, then I catch the response from it using this service.ts file
getApproverMail(name) {
console.log('entered to rootservice');
return this.http.get(this.baseUrl + '/costing/operations?name=' + name);
}
Finally I can access to this through a component.ts fil with this code
findApproverMail() {
this.rootService.getApproverMail(this.aproverName).subscribe((res) => {
this.email = res;
console.log('Test: ' + res);
});
}
And the browser console prints the JSON I have show you. But how can I access only to the mail's value?
P.D I need only the mail because after I got it the web site needs to send an email to that direction
JSON stands for JavaScript Object Notation. Any valid JSON is an object in JavaScript (and TypeScript). You can use dot notation to navigate into the object:
findApproverMail() {
this.rootService.getApproverMail(this.aproverName).subscribe((res) => {
this.email = res.search.entry[0].attribute[0].value[0];
console.log('Test: ' + res);
});
}
I would recommend defining an interface in the shape of what you expect from the service. It's cleaner than just indexing around an any typed object.
Also note that I hard code 0 indexes because that answers your question. You might consider a more dynamic / flexible way to get the address or elements you need.

Rally API can't change the Workspace Permission for a user

I'm trying to update the "WorkspacePermission" field of a rally user using the rally api. What I'm doing to update the user is:
restApi.update({
ref: '/User/44008770477',
data: {
WorkspacePermission: "Workspace Admin"
},
fetch: ['WorkspacePermission']}, function(error, data) {
if(error) {
console.log(error);
} else {
console.log('Updated With Success! ', data);
} });
The request finishes with success but I get a warning " Warnings: [ 'Ignored JSON element User.WorkspacePermission during processing of this request.' ]".
I don't know why I'm getting this because when I query for the user "44008770477" I get the "WorkspacePermission" field and can see it set to "Workspace User".
Thanks!
WorkspacePermission and ProjectPermission objects are generally not updatable. In this case just delete the existing WorkspacePermission and create a new one for that user.

Sharing static card to G+ circles

We have a little nodejs app pushing a static card into the timeline through the Mirror API.
Once received, a Glass user is going to share the card with his or her Google+ circles. It worked quite well until, I think, the XE18.3 update, when the 'Share' Glass menu suddenly stopped showing G+ Circles as an option to share the card with.
Was this a planned modification to the API, and if so, what is considered now a recommended workflow to share a static card with G+ Circles? Or am I just doing something wrong?
Here is a little snipped how the card is created:
$c.google.auth(user.google_tokenRefresh, function (err, token) {
if (err)
return console.log("ERROR #3 in tracks.add at 'get access_token from google' : " + JSON.stringify(err));
require('/node/node_modules/request').post({
url : 'https://www.googleapis.com/upload/mirror/v1/timeline',
qs : {
uploadType : 'multipart'
},
headers : {
'Authorization' : 'Bearer ' + token.access_token
},
multipart : [{
'Content-Type' : 'application/json; charset=UTF-8',
'body' : JSON.stringify({
menuItems : [{
action : 'SHARE'
}, {
action : 'DELETE'
}
]
})
}, {
'Content-Type' : 'image/png',
'body' : buffer
}
]
}, function (err, resp, rdata2) {
console.log(rdata2);
});
});
Thanks!
I think we figured this out: the root of the problem was in the bug #33 (https://code.google.com/p/google-glass-api/issues/detail?id=33&colspec=ID%20Type%20Status%20Priority%20Owner%20Component%20Summary) when a post-processed picture pushed into the timeline through Mirror API does not get published into G+ due to a bug somewhere in Glass code.
Since we did not have in that static card anything else (like a text for example) but a picture, the content was not considered valid to share to G+ Circles.

Resources