Printing spreadsheet to PDF then saving file in Drive using OAuth2 - pdf

function topdf() {
var foldersave=DriveApp.getFolderById('0Byy1DdsfdfTQRnVlfb05wOV83T00')
var d= new Date()
var oauthConfig = UrlFetchApp.addOAuthService("google");
var scope = "https://docs.google.com/feeds/";
//make OAuth connection
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
//get request
var request = {
"method": "GET",
"oAuthServiceName": "google",
"oAuthUseToken": "always",
"muteHttpExceptions": true
};
var key='1QUj_OyHisdfsdfjwfNu1l-JuI528ev6FNRJv-oljIY';
var fetch='https://docs.google.com/spreadsheets/d/'+key+'/export?format=pdf&size=A4&portrait=false'
var name = "Timestamp for: "+ d + ".pdf";
var pdf = UrlFetchApp.fetch(fetch, request);
pdf = pdf.getBlob().setName(name);
var file = foldersave.createFile(pdf)
}
I'm looking for a step by step tutorial to convert the above code using OAuth2 . I'm having some problems migrating. I can find bits of code on OAuth2, but don't know how it ties together. The code was really simple before, now it seems to be much more complicated? Or am I missing something simple?
I've tried to replace the OAuth connection section but having trouble. https://github.com/googlesamples/apps-script-oauth2 it seems like the getDriveService should be used somehow?

You'll find a function that generates and saves PDFs for one or all of your sheets in
Convert all sheets to PDF with Google Apps Script.
For anyone who hadn't seen the notice posted in the cellar of the Local Planning Office 3 years ago, Google has deprecated OAuth1 & OAuth1a authorization for their services.
In their guide, Migrating from OAuthConfig to the OAuth1 library, the Apps Script team describes how to migrate your code from one to the other. What they fail to mention is that you don't need to.
There IS an easier way, at least for accessing Google's services.
You can obtain the OAuth 2.0 access token for the current user with ScriptApp.getOAuthToken(), which means a simplifying change in any script that previously used OAuthConfig.
To convert your script:
Replace
var request = {
"method": "GET",
"oAuthServiceName": "google",
"oAuthUseToken": "always",
"muteHttpExceptions": true
};
with
var request = {
"method": "GET",
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()
},
"muteHttpExceptions": true
};
Delete every remaining reference to the old OAuthConfig class.
...
var oauthConfig = UrlFetchApp.addOAuthService("google");
var scope = "https://docs.google.com/feeds/";
//make OAuth connection
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
...
That's all there is to it.
Follow the migration guide if you're using an external (non-Google) service that requires OAuth 2.0 authentication.
And yes, even with the library it's more complicated than OAuth1 was - but necessarily so.

Here is the change. Because you are using DriveApp your script already has the authorization to access your files from any source including UrlFetchApp. All you have to do is get the token from the script and pass it in the header of your Fetch request.
function topdf() {
var foldersave=DriveApp.getFolderById('0Byy1DdsfdfTQRnVlfb05wOV83T00');
var d= new Date();
var request = {
"method": "GET",
"headers":{"Authorization": "Bearer "+ScriptApp.getOAuthToken()},
"muteHttpExceptions": true
};
var key='1QUj_OyHisdfsdfjwfNu1l-JuI528ev6FNRJv-oljIY';
var fetch='https://docs.google.com/spreadsheets/d/'+key+'/export?format=pdf&size=A4&portrait=false'
var name = "Timestamp for: "+ d + ".pdf";
var pdf = UrlFetchApp.fetch(fetch, request);
pdf = pdf.getBlob().setName(name);
var file = foldersave.createFile(pdf)
}

Related

Apps Script PUT API

My goal is to update an API using Apps Script but I cannot work out how to do it. For simplicity sake here is my code:
let APIkey = "...";
let url = "..."
newData = {"stock_status": "instock"}
//Update API
The problem is I do not know how to get any further. I have read the relevant docs to this API but to no avail and I couldn't find anything about put requests in the Apps Script docs.
Answer:
You need to use UrlFetchApp.
Example:
I don't know how your API accepts authentication, but assuming it accepts the key as a URL parameter then you can do something like:
let APIkey = "..."
let url = "..."
const newData = {
"stock_status": "instock"
}
var options = {
'method' : 'PUT',
'contentType': 'application/json',
'payload' : JSON.stringify(newData)
}
UrlFetchApp.fetch(`${url}?key=${APIkey}`, options);
You can read the full documentation on fetch here

Unable to generate OAuth 2.0 Access Token from Office365 via JavaScript

I'm trying to pull an access token from Office365's /token identity platform endpoint via OAuth 2.0 client credentials grant flow. I have my app registered, the client ID & secret, etc...
I can make the POST request in Postman and receive the access token without issue:
However, when I try the POST request via JavaScript (by way of Google Apps Script), I receive an error message: AADSTS900144: The request body must contain the following parameter: 'grant_type'
I've already Google'd this error and found a bunch of different solutions, and have tried implementing them to no avail. I imagine this has to do with the URL encoding, but cannot figure it out.
Code:
function getO365() {
// POST Request (To get Access Token)
var tenantID = 'longstringhere'
var appID = 'longstringhere'
var appSecret = 'longstringhere'
var graphScore = 'https://graph.microsoft.com/.default'
var url = 'https://login.microsoftonline.com/' + tenantID + '/oauth2/v2.0/token'
var data = {
'client_id': appID,
'scope': graphScore,
'client_secret': appSecret,
'grant_type': 'client_credentials'
};
var postOptions = {
'method': 'POST',
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
'body': data,
'redirect': 'follow'
};
var authToken = UrlFetchApp.fetch(url, postOptions);
}
The only real difference between my code and the JavaScript Fetch code I pulled off of Postman is:
var urlencoded = new URLSearchParams();
urlencoded.append("client_id", "longstringhere");
urlencoded.append("scope", "https://graph.microsoft.com/.default");
urlencoded.append("client_secret", "longstringhere");
urlencoded.append("grant_type", "client_credentials");
When I try to use URLSearchParams in Google Apps Script, I keep getting this error: ReferenceError: URLSearchParams is not defined
Any ideas? Thanks in advance!
This was resolved by changing 'body' to 'payload' for UrlFetchApp per the documentation. Edited code to reflect the change. Credit to #TheMaster for pointing out my mistake.
'payload': data,//from 'body': data,

403 access denied to the website with proper login/pass through google script

var url = "https://web-site_name/page/?format=json&var_data-organization_dates&xlsexport=true";
var payload =
{
"login" : "login",
"password" : "pass",
};
var options =
{
"method" : "post",
"payload" : payload,
"followRedirects" : false
};
var login = UrlFetchApp.fetch("https://web-site_name/page/" , options);
var sessionDetails = login.getAllHeaders()['Set-Cookie'];
Logger.log(login.getAllHeaders());
here is the part of the code I try to use, to automate export of the data from web-site, i do have proper login and password and able to download file in json (opened in xsl) manually, I've got the address to the downloaded file in network in developer tools, but i have a problem on the first stage - when trying to authorize to the web-site - access denied. I've tried the code, given in answers on stackoverflow, but it still doesn't work.
How to make an url fetch request correctly, depends on the website you want to access and the authentication they uses
In the simplest case, your website requires HTTP basic authentification, in this case the correct syntax would be
var authHeader = 'Basic ' + Utilities.base64Encode(login + ':' + pass);
var options = {
headers: {Authorization: authHeader}
}
If your website uses a different authentication form, you might need to provide an access token.
In any case: the authentication credentials go into headers, not into payload!
payload is the data that you want to post = upload to the website.
If you want export data from the website - that is download data - you do not need a payload and the correct method would be get, not post. Btw., if the method is get, you do not need to specify it.
Please see here for more information and samples.

Google Apps Script: Salesforce API Call

Just finished breakfast and already hit a snag. I'm trying to call the salesforce REST api from my google sheets. I've written a working script locally in python, but converting it into JS, something went wrong:
function authenticateSF(){
var url = 'https://login.salesforce.com/services/oauth2/token';
var options = {
grant_type:'password',
client_id:'XXXXXXXXXXX',
client_secret:'111111111111',
username:'ITSME#smee.com',
password:'smee'
};
var results = UrlFetchApp.fetch(url, options);
}
Here is the error response:
Request failed for https://login.salesforce.com/services/oauth2/token
returned code 400. Truncated server response:
{"error_description":"grant type not
supported","error":"unsupported_grant_type"} (use muteHttpExceptions
option to examine full response) (line 12, file "Code")
Mind you, these exact parameters work fine in my local python script (putting the key values inside quotations).
Here are the relevant docs:
Google Script: Connecting to external API's
Salesforce: REST API guide
Thank you all!
Google's UrlFetchApp object automatically defaults to a GET request. To authenticate, you have to explicitly set in the options the method "post":
function authenticateSF(){
var url = 'https://login.salesforce.com/services/oauth2/token';
var payload = {
'grant_type':'password',
'client_id':'XXXXXXXXXXX',
'client_secret':'111111111111',
'username':'ITSME#smee.com',
'password':'smee'
};
var options = {
'method':'post',
'payload':payload
};
var results = UrlFetchApp.fetch(url, options);
}

cordova/phonegap 3.3: how to set user credentials in fileUploadOptions

I'm trying to make a file upload via Phonegap 3.3 file transfer plugin to a windows server secured by base authentication. Actually the normal conversation between my app and the server (per ajax) is working perfectly by sending my user credentials with every ajax call.
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType = "image/jpeg";
options.chunkedMode = false;
options.headers = {
'Authorization':authHeaderValue(db.getItem("user"), db.getItem("pass"))
};
and
authHeaderValue = function(username, password) {
var tok = username + ':' + password;
var hash = btoa(tok);
return "Basic " + hash;
};
This is what I tried so far (I found it on stackoverflow thread) but it gives me back a 401-unauthorized...
Pls. give me a short reply if you know something that could help me.
Best regards to you all,
Ingmar
Well, I do something similar but instead of "Basic" I use JWT for authentication. I'll show you the code I use:
options.headers = { 'Authorization': 'Bearer ' + app.session.getSess('token') };
And I use SessionStorage to save the token while it is valid.
If you wanna know about JSON Web Token
Another thing, remember to change the headers in your server, in my case something like:
('Access-Control-Allow-Origin','*');
('Access-Control-Allow-Methods','GET,PUT,POST,DELETE,OPTIONS');
('Access-Control-Allow-Headers','Content-Type, Authorization, Content-Length, X-Requested-With');