Microsoft Graph ToDo Task Get not able to expand open extension with other users - axios

I'm using M Graph REST API v1.0. In particular to create, edit or update tasks in ToDo using a WebApp. I'm using an open extension to store more data that I need after.
The extension is expanded if the owner of the list or the user who create the task, get the task. However if other user, who share also this list, try to get the task the extension is not there. I mean the axios call responde with the task but without the extension.
The axios call is simple:
axios
.get(
"https://graph.microsoft.com/v1.0/me/todo/lists/" +
list.id +
"/tasks" +
"?$expand=Extensions($filter=id%20eq%20'microsoft.graph.openTypeExtension.Ch.mycompany.extrasTask')",
{
headers: {
Authorization: "Bearer " + String(this.tokenGraph),
Accept: "application/json;odata.metadata=none",
},
}
)

Related

Salesforce Rest API call from typescript using axios

I am trying to fetch records from a scratch org using the tooling API provided by salesforce and user access token. Lets say
accesstoken = "abcd"
url = "https://example.my.salesforce.com/services/data/v49.0/tooling/query?q=SELECT+Id,Name+FROM+Account"
I have used axios node module to make the API call as given below
const options = {
headers: {
"Authorization": "Bearer " + accessToken,
"Content-Type": "application/json"
}
};
axios.get(url, options).then(response => {
console.log(response.status);
if(response.status == 200){
console.log(response.data);
} else {
//do something else
}
});
The call responds with a status 200 i.e the request provided a response. But instead of correct records from Account object, I get the login html page
' Login | Salesforcehtml{visibility:
hidden;}a{color:#0070d2;}body{background-color:#F4F6F9;}#content,.container{background-color:#ffffff;}#header{color:#16325c;}body{display:
table;
width:100%;}#content{margin-bottom:24px;}#wrap{height:100%;} html { visibility: hidden; } if (self == top)
{document.documentElement.style.visibility = 'visible';} else
{document.write = ''; top.location = self.location;
setTimeout(function(){document.body.innerHTML='';},
1);window.self.onload=function(evt){document.body.innerHTML='';};}var
SFDCSessionVars={"server":"https://test.salesforce.com/login/sessionserver212.html","im":true,"ah":"active","save":"Save","saveOne":"Save
1 Change","sum":"#p# Saved Usernames","iaac":false,"hac":"Choose a
Username","suo":"1 Saved Username","title":" |
Salesforce","saveMany":"Save #p#
Changes","lpt":"Login","lllbl":"Lightning
Login","host":"test.salesforce.com","le":false,"heu":"Edit Username
List","ic":false,"lh":false,"ur":"https://business-data-8148-dev-ed.cs79.my.salesforce.com","hidp":"Log
In Using","ih":"inactive","dc":"Username removed. Click Save to Commit
Changes."};LoginHint.hideLoginForm();Edit ListSaveCancel
UsernamePassword Caps Lock is on.Remember
meForgot Your
Password?To go to your company's login
page, enter the custom domain name.Custom Domainhttps://domain.my.salesforce.comContinueBackLog In with a Different
Username© 2020
salesforce.com, inc. All rights reserved.<iframe frameborder="0" src="/s.gif" id="marketing"
name="marketing" scrolling="no" title="Marketing"
tabindex="-1"sandbox="allow-forms allow-pointer-lock allow-popups
allow-same-origin allow-scripts" >LoginLoginHint.getSavedIdentities(false);function
handleLogin(){document.login.un.value=document.login.username.value;document.login.width.value=screen.width;document.login.height.value=screen.height;document.getElementById("Login").disabled=true;document.getElementById("login_form").submit();}function
lazyload(){document.getElementById("pwcapsicon").src="/img/icon/capslock_blue.png";document.getElementById("marketing").src="https://c.salesforce.com/login-messages/promos.html";}loader();
'
Does anyone know what am I missing in here? According to salesforce documentation
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_query.htm
the accessToken in the header should be enough to make the API call.
Note: I gained the access token by running
sfdx force:user:display -u <username>
Your query is wrong. You selected Tooling API service which is for metadata (info about classes, triggers, objects, fields, deployments, running unit tests...). If you want to query Accounts - that's normal data. Try just /services/data/v49.0/query?q=SELECT+Id,Name+FROM+Account
I don't think you need Content-Type header in there. You don't POST anything. At best you can send Accept (application/json, application/xml)
Are you sure the session id was valid? As in you could go to the org, Setup -> Session management, see it there? Or in the user's login history?
It might be that your SF admin did something nasty like locking sessions down to IP from which they originated or maybe the user doesn't have API access... See if you can create your call in Workbench -> Utilities -> REST Explorer first, then go back to Axios?

make meteor restful api/web-service

I have created a new url/route in my app where I need to write a web-service. I need to write a service that deletes user according to the parameters passed in the service. For now, anyone should be able to call that service (will make it secure at later stage). App is built on meteor.
My url is : loaclhost:3000/deleteUser. Now one should be able to call my delete user function defined on this page and pass json structure data as an argument to it. If the data is valid, then the user should be deleted.
Using simple:rest package
Meteor.publish("delUser", function (a, b) {
UserDetails.remove({}); //delete user according to data received
}, {
url: "/testing/delUser", //url where third party will call the function
getArgsFromRequest: function (request) {
// Let's say we want this function to accept a form-encoded request
// with fields named `a` and `b`.
console.log('received : ' + JSON.stringify(request.body) );
var content = request.body;
// Since form enconding doesn't distinguish numbers and strings, we need
// to parse it manually
return [content.a, content.b];
}
})
How to access the function, delUser from a thrid party? I also need to add authentication at a later stage.
Personnally, I use this :
simple:rest
simple:json-routes
simple:rest-accounts-password
I find it easier to implement.
even iron:router comes with server side routes where you can build your own functions and api calls.
http://iron-meteor.github.io/iron-router/#restful-routes
Sample (Server side code) :
Router.map(function () {
this.route("api", {path: "/api/:paramsYouNeed",
where: "server",
action: function(){
this.response.writeHead(200, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
if (this.request.method == 'POST') {
var response;
//do whatever you want to do
this.response.end(response);
}
}
});
The other user can call this by making a http.post request to the above url (http:www.a****a.com/api/params)
The easiest way to do this is use the restivus package.
https://atmospherejs.com/nimble/restivus
Restivus makes building REST APIs in Meteor 0.9.0+ easier than ever
before! The package is inspired by RestStop2 and Collection API, and
is built on top of Simple JSON Routes to provide:
A simple interface for creating REST APIs
Easy setup of CRUD endpoints for Mongo Collections
User authentication via the API
Optional login and logout endpoints
Access to this.user in authenticated endpoints
Custom authentication if needed
Role permissions for limiting access to specific endpoints
Works alongside the alanning:roles package - Meteor's accepted role permission package

Upload and Name a File Using Google Drive REST API v3 and Angular 2

I'm creating a Google Drive service using the Drive REST Api v3 in Angular 2. Most of the functionality is in place: view file, download, create etc.. but I cannot find how to name a file (either when creating a file or updating).
I'm using the following docs pages: create and update. They say the file name should be part of the request body. The relevant code from my Google Drive service is bellow.
createFile(name :string, content :string) :Promise<Object> {
let headers = new Headers({
'Content-Type': 'text/markdown',
'Authorization': 'Bearer ' + this.token,
'name': name //TODO name not working!
});
let options = new RequestOptions({ headers: headers }); // Create a request option
return this.http
.post('https://www.googleapis.com/upload/drive/v3/files' + '?uploadType=multipart', content, options)
.toPromise();
}
updateFile(id :string, content :string, name :string) :Promise<Object> {
let headers = new Headers({
'Content-Type': 'text/markdown',
'Authorization': 'Bearer ' + this.token,
'id': id,
'name': name //TODO name not working!
}); //generate headers
let options = new RequestOptions({ headers: headers }); // Create a request option
return this.http
.patch('https://www.googleapis.com/upload/drive/v3/files/' + id + '?uploadType=multipart', content, options)
.toPromise();
}
To summarise files are being created and updated fine (including content) but naming and renaming a file doesn't work at all.
Thanks for any help.
Try placing name in the request body and not in the request header as described in the Files: create:
Request body
In the request body, supply a Files resource with the following properties as the metadata. For more information, see the document on media upload.
To test it, try using API Explorer to help you explore various Google APIs interactively.
Sample Request:
POST https://www.googleapis.com/drive/v3/files?key={YOUR_API_KEY}
{
"name": "My File"
}
Response:
200
{
"kind": "drive#file",
"id": "fileID",
"name": "My File"
}
There is also a related SO post that explain how to insert file to Google Drive through API.
Hope this helps.
I also faced that problem. I think there is 3 solutions:
Use multipart upload https://developers.google.com/drive/v3/web/multipart-upload with different headers for file metadata and actual file. Me myself stuck there, didn't found how to add boundaries to separate request headers in Angular 2+
Upload file in two requests. First to create empty file with metadata (response will provide id of the file) and second to actually "update" the file.
Use resumable upload. First request to "setup metadata" (will not even create empty file) and get "special link" where to send request to upload actual file. And this approach have some other features, like uploading in chunks.https://developers.google.com/drive/v3/web/resumable-upload
Here is the link to another Question with implementation of resumable upload in Angular 2 and DRIVE REST API V3
Angular 2+ HTTP POST and GDrive API. Resumable file upload with name
I hope it might be useful.
You are trying to set the name using an http header. This is wrong. I can't begin to understand how you thought that was the way to do it, so you need to go back and reread the Drive API documentation.
In short, the name: "name" should be a JSON object passed in the body of the request, not in an http header.

Sharepoint GetListsOfType in Rest API

Is there anyway to have similar results of GetListsOfType with REST API. I am trying to get only lists for document library with REST API.
Similar to this code in C#;
SPListCollection docs = web1.GetListsOfType(SPBaseType.DocumentLibrary);
Or alternatively is there anyway to find a list type (for example DocumentLibrary) from retrieved list from REST API in XML format?
The following example shows how to retrieve lists of specific type (101 for ListTemplateType.DocumentLibrary).
Url: /_api/web/lists?$filter=BaseTemplate eq 101
Method: GET
Headers:
Authorization: "Bearer " + accessToken
Accept: "application/atom+xml"

Can't update OData__ModerationStatus using HTTPSEND

I have tried to update the value of the OData__ModerationStatus column AKA "Approval Status" 3 different ways but only one works. Using VS 2013 the WorkFlow update Item activity from the toolbox and you can see that it's missing X-RequestDigest in the header and does not allow an update to the approval status and results in a security validation error. I believe the error is related to the missing header. Here is the code from the UpdateListItem.
RequestHeaders = (InArgument<DynamicValue>) ((Activity<DynamicValue>) new SetDynamicValueProperties()
{
Properties = {
{
"If-Match",
(InArgument) new InArgument<string>("*")
},
{
"X-HTTP-Method",
(InArgument) new InArgument<string>("MERGE")
},
{
"Accept",
(InArgument) new InArgument<string>("application/json;odata=verbose")
},
{
"Content-Type",
(InArgument) new InArgument<string>("application/json;odata=verbose")
}
}
}),
RequestContent = (InArgument) listItemProperties,
So I used 2 SendHttp activities, one to get the X-RequestDigest using a POST with the url siteurl/_api/contextinfo the second POST using the following headers & Body.
HEADER:
X-RequestDigest:[FormDigestValue from the previous POST]
Accept: application/json; odata=verbose
Content-Type: application/json; odata=verbose
IF-MATCH: *
X-HTTP-Method: MERGE
BODY: [I have tried the following 3]
String.Format("{ '__metadata': { 'type': '" + type + "' },'OData__ModerationStatus':'0' }")
{ '__metadata': { 'type': 'SP.Data.Shared_x0020_DocumentsItem' },
'OData__ModerationStatus':'0' }
Used a BuildDynamicValue activity to set the RequestContent.
All three come error with Microsoft.SharePoint.SPException: Invalid text value. A text field contains invalid data. If I use any other field it works, If i use Fiddler or Advanced Rest Client it updates the value.
Can someone help me understand or explain why it works via REST calls but I can't use VS and the UpdateItem/HTTPSend to set the value.
I have included a image with a successful workflow that updates the Title
We were able to get the scenario working.
After further investigations we could see that the workflow does not have Approve permissions.
We could see this by capturing the REST calls in fiddler for the workflow
{"error":{"code":"-2147024891, System.UnauthorizedAccessException","message":{"lang":"en-US","value":"Access denied. You do not have permission to perform this action or access this resource."},"innererror":{"message":"0x80070005owssvr.dll: (unresolved symbol, module offset=0000000000015BC3) at 0x000007F988885BC3\nMicrosoft.SharePoint.Library.ni.dll
The VS 2013 SP 2013 workflows are really like provider hosted apps and have a default permission which does not include approve items.
Perform the below steps to fix this
• Go to Site Settings  Site App Permissions
Find the App Workflow as copy the first guid as shown below
• Go to http:///_layouts/15/appInv.aspx.
Enter the Guid copied in previous step in the App ID and click on Lookup.
This will populate the Title, App Domain and Redirect URL columns.
Copy the below in Permission Request XML (do NOT change the scope)
<AppPermissionRequests>
<AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="FullControl" /></AppPermissionRequests>
• Tested the workflow again and it started working.