Upload fail for DrievItems in Drive of SitePages List - microsoft-graph-api

Upload fail for all the DrivesItems in Drive associated with SitePage list in a sharepoint site.
Graph API request:
UploadSession uploadSession = GraphCLient.Sites[{SiteId}].Drives[{DriveId of SitePages List }]. Items[{DriveFolderID}].ItemWithPath(driveItem.Item.Name).CreateUploadSession().Request().PostAsync().Result;
The uploadSession will be created sucessfully but chunkuploadprovider gives error.
Error response: Code: accessDenied Message: The caller does not have
permission to perform the action. Inner error
Code Snippet:
private void UploadItem(OneDriveJsonStructure driveItem)
{
try
{
MemoryStream memStream = (MemoryStream)driveItem.Content;
byte[] buffer = memStream.ToArray();
DriveItem item = null;
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer))
{
UploadSession uploadSession = this._SharepointOperations._GraphCLient.Sites[this._SiteId].Drives[this._DriveId].Items[this._DriveFolderId].ItemWithPath(driveItem.Item.Name).CreateUploadSession().Request().PostAsync().Result;
var provider = new ChunkedUploadProvider(uploadSession, this._SharepointOperations._GraphCLient, memStream);
var chunkRequests = provider.GetUploadChunkRequests();
var readBuffer = new byte[buffer.Length];
var trackedExceptions = new List<Exception>();
DriveItem itemResult = null;
foreach (var request in chunkRequests)
{
// Send chunk request
var result = provider.GetChunkRequestResponseAsync(request, readBuffer, trackedExceptions).Result;
if (result.UploadSucceeded)
{
itemResult = result.ItemResponse;
item = result.ItemResponse;
}
}
if (itemResult == null)
{
UploadChunkResult result = null;
// Retry the upload ...
foreach (var request in chunkRequests)
{
// Send chunk request
result = provider.GetChunkRequestResponseAsync(request, readBuffer, trackedExceptions).Result;
}
item = result.ItemResponse;
}
}
item.Permissions = driveItem.Item.Permissions;
GivePermission(item);
Permission Provide to Client App from Azure AD:
Graph Permission:
Sharepoint Permissions:
Even after all these permissions it gives this error message:
"The caller does not have permission to perform the action".
Which permissions are needed to perform this action?
Upload for driveItems of other drive execute sucessfully.

Now that uploading for driveItems of other drive execute successfully, your code should be OK.
So the key to the issue lies in the user's SharePoint permissions.
Please check if the user account can upload files into the target folder in your SharePoint site.
If the user doesn't have the permission to do that, you need to use an admin account to grant edit permission to the user.
Detailed steps:
Next to the folder name, click the Ellipsis…
On the file popup window, click Share.
On the Share dialog box, click Shared with, and then click
Advanced.
Click Stop Inheriting Permissions.
Add the user into an SharePoint Group which has Edit or Contribute
permission. (If you don't want to modify the default SharePoint
Group, just create a new one)
A quick method: Share this folder (with edit permission) with the user.
Next to the folder name, click the Ellipsis…. On the file popup window, click Share. On the Share dialog box, follow the screenshot.
UPDATE:
Note that we can't upload any documents into Site Pages document library. Using API is also not supported.

Related

Sending a chat message to a microsoft Teams channel using Microsoft Graph API C#

My goal is simple.
I want to send an automated chat message in to a MS Teams channel using the graph API.
This seems to be beta feature of the graph API and is only avalible in the Microsoft.Graph.Beta.
I have read the docs and have been trying to follow this example:
https://learn.microsoft.com/en-us/graph/api/channel-post-messages, I have all the permissions set correct in my azure portal. I keep getting 'Unknown Error' I have tried:
var graphServiceClient = MicrosoftGraphService.GetGraphServiceClient();
var chatMessage = new ChatMessage
{
Subject = null,
Body = new ItemBody
{
ContentType = BodyType.Text,
Content = messageText
}
};
var response = await graphServiceClient.Teams["77f9c17f-54ca-4275-82d4-fff7esdacda1"].Channels["2007765c-8185-4cc7-8064-fb1b10f27e6b"].Messages.Request()
.AddAsync(chatMessage);
I have also tried to to see if I can get anything from teams:
var teams = await graphServiceClient.Teams["77f9c17f-54ca-4275-2sed4-ffsde59acda1"].Request().GetAsync();
Again all I get is Unknown error, I have used GRAPH API before to do things like get users in an organisation, so I know the genreal set up is correct.
Has anyone on the Internet somewhere in the world got this to work?! becuase its driving me crazy
Same problem here :
Everything is ok with users or groups, but I can't get anything from Teams (unknownError)
All IDs are correct and checked
Here are the authorizations I have set for the app :
Read all users' teamwork activity feed
Read all groups
Send a teamwork activity to any user
Get a list of all teams
Here is my code (based on microsoft daemon app scenario)
The access token is ok
var graphClient = new GraphServiceClient(
"https://graph.microsoft.com/beta",
new DelegateAuthenticationProvider(async (requestMessage) =>
{
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", result.AccessToken);
}));
var chatMessage = new ChatMessage
{
Subject = "Message de test",
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = "Contenu de test"
}
};
await graphClient.Teams["218a4b1d-84d5-48a2-97a0-023e4e4c3e85"].Channels["19:adbf8ddf37a049aa9f63a0f8ee0e8054#thread.tacv2"].Messages
.Request()
.AddAsync(chatMessage);
And the result :
Token acquired
Code: UnknownError
Inner error:
AdditionalData:
request-id: e2e433d8-cedd-4401-b5b2-6f34cf5611cf
date: 2020-03-30T12:14:15
ClientRequestId: e2e433d8-cedd-4401-b5b2-6f34cf5611cf
Edit(2020-04-01) :
No solution at the time being : there are answers to comments at the bottom of the page "Create chatMessage in a channel" in ms doc (feedback section)
It seems that applications cannot be granted the permission to send chatMessages up to now.
RamjotSingh commented on Jun 11, 2019 Contributor
#pythonpsycho1337 - As the permission table above notes, Application
only context is not supported on this API at the moment.
RamjotSingh commented on Dec 16, 2019 Contributor
Supporting application permissions is something we plan to do but we do not have a date yet.
RamjotSingh commented a day ago Contributor
We will share on Microsoft Graph Blog once we have application
permissions for this API. Since the original question for this issue
was answered. Closing it.

Microsoft Graph API - Insufficient privileges to complete the operation

I am trying to use Microsoft Graph API to update another user in Active Directory.
I have the following permissions set for both user and application at https://apps.dev.microsoft.com/
I've requested the following scopes:
Directory.ReadWrite.All
User.ReadWrite.All
Group.ReadWrite.All
I am able to get a listing of all users in the directory, but when trying to update (in this case, the city) it fails:
GraphServiceClient graphClient = SDKHelper.GetAuthenticatedClient ();
var usersResponse = graphClient.Users.Request ().GetAsync ();
var users = usersResponse.Result;
// hard coding user id for now
var userId = "9a5b83cd-85ff-4ad1-ab2f-b443941a518e";
var user = users.FirstOrDefault (m => m.Id == userId);
if (user != null) {
user.City = "New York";
await graphClient.Me.Request ().UpdateAsync (user);
}
I get:
{
Code : Authorization_RequestDenied
Message : Insufficient privileges to complete the operation.
Inner error
}
The user I am logged in as is a Global Administrator of the directory.
I took the JWT token, headed over to https://jwt.io and these are the roles I am seeing:
Directory.Read.All
Directory.ReadWrite.All
Files.ReadWrite
Group.ReadWrite.All
Mail.Send
User.Read
User.Read.All
User.ReadWrite.All
Do I need other permissions to make this happen?
At the end of the day, I'd like to create a console app (not web app) that I can update other user information in the directory. But I figured using this sample app provided by Microsoft is a good start.
The reason you're seeing this is because you're passing the complete user object rather than only the city property. In other words, you're attempting to update every property in that user record, including several that are read-only.
This is one of those cases where having an SDK that wraps a REST API can be result in some confusing errors. As REST API, it is stateless so passing in the entire user property set is telling the API you want to PATCH all of those values.
You're also passing in a different user object into the me object (i.e. you're replacing all of your property values with this other user's property values):
await graphClient.Me.Request().UpdateAsync(user);
Instead, try this:
GraphServiceClient graphClient = SDKHelper.GetAuthenticatedClient ();
// hard coding user id for now
var userId = "9a5b83cd-85ff-4ad1-ab2f-b443941a518e";
await graphClient.Users[userId].Request ().UpdateAsync(new User
{
City = "New York"
});

Unable to save a query as a view table

I have a query that runs and can see the results. But while trying to save the query as a view table, I get error message saying
Failed to save view. No suitable credentials found to access Google
Drive. Contact the table owner for assistance.
I think the problem is caused by a table used in the query. The table is uploaded from a google sheet (with source URI), own by me. I have tried to enable Google Drive API from the project but no luck. Not sure how I can give BigQuery access to Google Drive.
I suspect the problem you are hitting is one of OAuth Scopes. In order to talk to the Google Drive API to read data, you need to use credentials that were granted access to that API.
If you are using the BigQuery web UI and have not explicitly granted access to Drive, it won't work. For example, the first time I tried to "Save to Google Sheets", the BigQuery UI popped up an OAuth prompt asking me to grant access to my Google Drive. After this it could save the results. Try doing this to make sure your credentials have the Drive scope and then "Save View" again.
If you are using your own code to do this, you should request scope 'https://www.googleapis.com/auth/drive' in addition to the 'https://www.googleapis.com/auth/bigquery' scope you are already using to talk to BigQuery.
If you are using the bq client, it has been updated to request this scope, but you may need to re-initialize your authentication credentials. You can do this with bq init --delete_credentials to remove the credentials, then your next action we re-request credentials.
Using Google App Script this worked for me:
function saveQueryToTable() {
var projectId = '...yourprojectid goes here...';
var datasetId = '...yourdatesetid goes here...';
var sourceTable = '...your table or view goes here...';
var destTable = '...destination table goes here...';
var myQuery;
//just a random call to activate the Drive API scope
var test = Drive.Properties.list('...drive file id goes here...')
//list all tables for the particular dataset
var tableList = BigQuery.Tables.list(projectId, datasetId).getTables();
//if the table exist, delete it
for (var i = 0; i < tableList.length; i++) {
if (tableList[i].tableReference.tableId == destTable) {
BigQuery.Tables.remove(projectId, datasetId, destTable);
Logger.log("DELETED: " + destTable);
}
};
myQuery = 'SELECT * FROM [PROJECTID:DATASETID.TABLEID];'
.replace('PROJECTID',projectId)
.replace('DATASETID',datasetId)
.replace('TABLEID',sourceTable)
var job = {
configuration: {
query: {
query: myQuery,
destinationTable: {
projectId: projectId,
datasetId: datasetId,
tableId: destTable
}
}
}
};
var queryResults = BigQuery.Jobs.insert(job, projectId);
Logger.log(queryResults.status);
}
The 'trick' was a random call to the Drive API to ensure both the BigQuery and Drive scopes are included.
Google Apps Script Project Properties

POST refused - Alfresco

I'm making a POST inside workflows, but if I have a login with admin, the post is made.
But if I make a post with another login of another user, I get this error:
{
"status" : {
"code" : 403,
"name" : "Forbidden",
"description" : "Server understood the request but refused to fulfill it." },
"message" : "01070001 org.alfresco.repo.security.permissions.AccessDeniedException: 01070015 Access Denied. You do not have the appropriate permissions to perform this operation.", "exception" : "org.springframework.extensions.webscripts.WebScriptException - 01070001 org.alfresco .repo.security.permissions.AccessDeniedException: 01070015 Access Denied. You do not have the appropriate permissions to perform this operation.",
"callstack" : [
"" ,"net.sf.acegisecurity.AccessDeniedException: Access is denied."
(....)
,"java.lang.Thread.run(Thread.java:745)"
,"org.alfresco.repo.security.permissions.AccessDeniedException: 01070015 Access Denied. You do not have the appropriate permissions to perform this operation."
,"org.alfresco.repo.security.permissions.impl.ExceptionTranslatorMethodInterceptor.invoke(ExceptionTranslatorMethodInterceptor .java:50)"
,"org.springframework.extensions.webscripts.WebScriptException: 01070001 org.alfresco.repo.security .permissions.AccessDeniedException: 01070015 Access Denied. You do not have the appropriate permissions to perform this operation."
,"org.springframework.extensions.webscripts.AbstractWebScript.createStatusException(AbstractWebScript .java:1112)"
],
"server" : "Community v5.0.0 (d r99759-b2) schema 8,022", "time" : "Feb 7, 2016 3:03:39 PM" }
Can you help me?
My post:
var base64str = pdfbase64;
var binary = atob(base64str.replace(/\s/g, ''));
var len = binary.length;
var buffer = new ArrayBuffer(len);
var view = new Uint8Array(buffer);
for (var i = 0; i < len; i++) {
view[i] = binary.charCodeAt(i);
}
var blob = new Blob( [view], { type: "application/pdf" });
var fd = new FormData();
if (Alfresco.util.CSRFPolicy && Alfresco.util.CSRFPolicy.isFilterEnabled())
{
url = url + "?" + Alfresco.util.CSRFPolicy.getParameter() + "=" + encodeURIComponent(Alfresco.util.CSRFPolicy.getToken());
}
fd.append("updatenoderef", nodeRef);
fd.append("filedata", blob);
fd.append("majorversion", "true");
fd.append("overwrite", "true");
var request = new XMLHttpRequest();
request.open("POST", url);
request.send(fd);
Any user can update a document if he/she has the write permissions on the node in Alfresco.
It works with admin because admin has write permissions on any node in Alfresco.
You did not write the url of the webscript that you are calling, but I presume it is the script to upload. You need to be sure that the user has the permissions to write on that node.
Where is it stored this node? Is it a Share site? If yes, has the user been invited to the site and with what role?
The roles for a Share site are:
Managers have full rights to all site content - what they have created
themselves and what other site members have created.
Collaborators have full rights to the site content that they own; they
have rights to edit but not delete content created by other site
members.
Contributors have full rights to the site content that they own; they
cannot edit or delete content created by other site members.
Consumers have view-only rights in a site: they cannot create their
own content.
Please notice that, if the file has been created by someone else, the user can modify it only with the "Collaborator" role.
UPDATE:
If admin creates a document, the document will be modifiable by Collaborators. This is the default behaviour and you do not need to do anything.
If you want that also contributors can modify the document, you can at the site level or at the document level gives "collaborator permissions" to "contributors". Use "Manage Permissions" on the document or on a parent folder to change this permission.
This works on a site.
If the document is not in a site, you have to use groups and assign collaborator permissions to the groups that should be able to change the document.

Google data API for .Net allows Sharing outside organization in Google apps account

I am using Google Data API for .Net(version 1.9) in my application.
I have created a Google apps account and i have set the "Users cannot share documents outside this organization" setting under Google Docs.
When i try to share a file outside of the domain(organization) from Google docs web, i get a error saying the file cannot be shared outside of my domain.
But when i try the same thing from the API, it succeeds. I get a 200 success from the API. When i try to access the file from the share link it says 'You need permission to access this resource'. My question is shouldn't the API return with a error? how can i handle this case?
Here is the code that I am using:
DocumentsRequest request = null;
/* request initialization */
string csBatchReqBody = "<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:gAcl="http://schemas.google.com/acl/2007" xmlns:batch="http://schemas.google.com/gdata/batch"><category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/acl/2007#accessRule"/><entry><id>https://docs.google.com/feeds/default/private/full/document:1DsELtiNwq-ogOrp8cAONdMpGR4gBF79PjijTae-vVNg/acl/user:myusername#mydomain.com</id><batch:operation type="query"/></entry><entry><batch:id>1</batch:id><batch:operation type="insert"/><gAcl:role value="reader"/><gAcl:scope type="user" value="myusername#gmail.com"/></entry>"
string Url = "https://docs.google.com/feeds/default/private/full/document:1DsELtiNwq-ogOrp8cAONdMpGR4gBF79PjijTae-vVNg/acl/batch";
byte[] byteArray = Encoding.ASCII.GetBytes(csBatchReqBody);
MemoryStream inputStream = new MemoryStream(byteArray);
AtomEntry reply = request.Service.Insert(new Uri(Url), inputStream, "application/atom+xml", "");
MemoryStream stream = new MemoryStream();
reply.SaveToXml(stream);
The API actually returns a 400 if you try to share a file outside the domain and the admins have set the "Users cannot share documents outside this organization" flag.
Your code sends a batch request (even if for a single element), you'd have to check the batch response to notice the error.
Instead, use the following code to share a document to a single user, it assumes that entry is the DocumentEntry you want to share:
AclEntry acl = new AclEntry();
acl.Scope = new AclScope("username#gmail.com", "user");
acl.Role = new AclRole("reader");
acl = service.Insert(new Uri(entry.AccessControlList), acl);

Resources