Giving Authorization or Permission to Apps Script goes wrong - google-apps-script

I wrote a telegrambot using Google Apps Script.
And I coded like this:
function setWebhook() {
const resp = UrlFetchApp.fetch(botUrl + "/setWebhook?url=" + hookUrl);
Logger.log("SetWebhook response:", resp.getResponseCode());
}
function getWebhook() {
const resp = UrlFetchApp.fetch(botUrl + "/getWebhookInfo");
if (resp.getResponseCode() == 200) {
const data = JSON.parse(resp.getContentText());
Logger.log("Current webhook is", data.result);
} else {
Logger.log("GetWebhook response:", resp.getResponseCode());
}
}
After I select the function getWebhook and click RUN, a pop-up window says "this app isn't verified".
screenshot
Then I click Advanced and click Go to TGBot (Unsafe), but the verification is still unsuccessful, and a toast says "Something went wrong, try again".
What I have tried:
switch my browser from Chrome to Edge
Use different Google accounts, and start a new project
Erase my browser data
But nothing is working.

According to this issue post
and documentation: Fix issues with multiple Google Accounts
Fix issues with multiple Google Accounts
If you're logged into multiple Google Accounts at the same time, you
might have trouble accessing your Apps Script projects, add-ons, and
web apps. Multi-login, or being logged into multiple Google Accounts
at once, isn't supported for Apps Script, add-ons, or web apps.
To fix issues from multi-login, try one of the following solutions:
Log out of all your Google Accounts and only log in to the one that has the Apps Script project, add-on, or web app you need to access.
Open an incognito window in Google Chrome, or an equivalent private browsing window, and log in to the Google Account that has the
Apps Script project, add-on, or web app you need to access.
In my case which was similar it helped.

Related

How to authorize Google Apps Scripts inside a Google Workspace when using Slack Events API

I can't seem to access a Google Scripts webapp via HTTP requests when it's exposed to only my workspace domain, though the same works when I allow anyone (even anonymous) to access it (from a personal account created for testing)
I'm currently trying to use the Events API from Slack's and listen to calls via a Google Apps Script. Here's what that looks like on Slack's side:
This is the screen I'm pasting the Scripts URL into
Now, if I do this with my personal account, it works with the following code in the script because I've configured it to run as myself and allow anyone on the internet to run it, even anonymously:
function doPost(e) {
var v = JSON.parse(e.postData.contents); // Added
return ContentService.createTextOutput(v.challenge); // Added
}
This is how the webapp's URL looks - https://script.google.com/a/macros/scripbox.com/s/{scriptId}/exec
However, if I try to do the same from my Google Workspace account, I don't have the option to allow anonymous users to have access. The broadest option I have is "Anyone within {{workspace}}". How can I add authorization to my script URL so that anyone from my workspace's domain is able to access/use this webapp via http requests?

Google Apps Script public dev link requiring signin

I'm trying to get into WebApp development with Google Apps Scripts.
const doPost = e => {
Logger.log(e)
}
I've published it, and when I browse, I get the page. I can browse to the weblink ... but if I browse to it in an incognito tab, it takes me to a Google signin page, instead. In this project, I need an unauthenticated device to be able to make POST and GET requests (just to be able to pass data in and out).
The deployment is listed to run as me, and to be visible to 'Anyone' (not just anyone with a Google account, which is one of the options). This behaviour is the same for the deployment link and the /dev link.

Is it possible to get fresh Google Slides presentation data in AppsScript?

It seems that if one uses SlidesApp.getActivePresentation() in AppsScript, the result of the function is not fresh but rather something that was already prepared beforehand.
Scenario
Imagine you have two users performing the following function in AppsScript simultaneously:
function updateSlideText(slideId) {
// Request exclusive write access to the document
var lock = LockService.getDocumentLock();
lock.waitLock(15000);
// Perform changes
var presentation = SlidesApp.getActivePresentation();
var textBox = presentation.getSlideById(MY_SLIDE_ID).getPageElementById(MY_TEXTBOX_ID);
textBox.asShape().getText().setText('My text');
// Save and release lock
presentation.saveAndClose();
lock.releaseLock();
}
If this function is called twice at the same time, the resulting slide contains text "My textMy text".
When I add Utilities.sleep(10000) just before the lock release, it delays the 2nd execution by 10s but after those 10s I still end up with the same result. On the other hand, if I actually delay calling the function 10s, the output is fine.
From this I conclude that it does not matter if I call saveAndClose and use locks. Once the function is called, it will always have stale data. Is there a way around this? Is it not possible to request that fresh data will be loaded after the lock is aquired?
More details
Some more pseudo-code to better illustrate the problem use-case:
// The addon frontend
websocket.onMessage((message) => {
if (message.type === 'pollUpdate') {
const slideWithPoll = store.getState().slides.find(
slide => slide.pollId === message.pollId
);
if (slideWithPoll.title !== message.poll.title) {
google.script.run.updateSlideText(slideWithPoll.id, message.poll.title);
}
}
});
I believe your goal as follows.
When 2 users are run your script for Google Slides, simultaneously, you want to run the script individually.
For this, how about this answer?
Issue and workaround:
When I tested your situation, I could confirm the same issue like My textMy text. When I tested several times, in this case, I thought that the LockService might not affect to Google Slides. So as a workaround, I would like to propose to use Web Apps as the wrapper. Because it has already been known that Web Apps can run exclusively by the LockService. The flow of this workaround is as follows.
When the script is run, the script requests to Web Apps.
At Web Apps, your script is run.
By this, even when the script is run, simultaneously, the script can be exclusively run with the LockService.
Usage:
The usage of this sample script is as follows. Please do the following flow.
1. Prepare script.
When your script is used, it becomes as follows. Please copy and paste the following script to the script editor. Please set MY_SLIDE_ID and MY_TEXTBOX_ID.
function doGet() {
// This is your script.
var presentation = SlidesApp.getActivePresentation();
var textBox = presentation.getSlideById(MY_SLIDE_ID).getPageElementById(MY_TEXTBOX_ID);
var text = textBox.asShape().getText();
text.setText('My text');
return ContentService.createTextOutput("ok");
}
// Please run this function.
function main() {
var lock = LockService.getDocumentLock();
if (lock.tryLock(10000)) {
try {
const url = "https://script.google.com/macros/s/###/exec"; // Please set the URL of Web Apps after you set the Web Apps.
const res = UrlFetchApp.fetch(url);
console.log(res.getContentText())
} catch(e) {
throw new Error(e);
} finally {
lock.releaseLock();
}
}
}
2. Deploy Web Apps.
On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".
Select "Me" for "Execute the app as:".
By this, the script is run as the owner.
Select "Anyone, even anonymous" for "Who has access to the app:".
In this case, no access token is required to be request. I think that I recommend this setting for testing this workaround.
Of course, you can also use the access token. At that time, please set this to "Anyone". And please include the scope of https://www.googleapis.com/auth/drive.readonly and https://www.googleapis.com/auth/drive to the access token. These scopes are required to access to Web Apps.
Click "Deploy" button as new "Project version".
Automatically open a dialog box of "Authorization required".
Click "Review Permissions".
Select own account.
Click "Advanced" at "This app isn't verified".
Click "Go to ### project name ###(unsafe)"
Click "Allow" button.
Click "OK".
Copy the URL of Web Apps. It's like https://script.google.com/macros/s/###/exec.
When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
Please set the URL of https://script.google.com/macros/s/###/exec to url of above script. And please redeploy Web Apps. By this, the latest script is reflected to the Web Apps. So please be careful this.
4. Test this workaround.
Please run the function of main() by 2 users, simultaneously as you have tested. By this, it is found that the script is run exclusively. In my environment, in this case, I confirmed that even when the LockService is not used, the script is exclusively run. But I would like to recommend to use the LockService just in case.
Note:
This is a simple sample script for explaining this workaround. So when you use this, please modify it for your actual situation.
About the situation that the LockService might not affect to Google Slides, in the current stage, although I'm not sure whether this is the bug, how about reporting this to the Google issue tracker? Unfortunately, I couldn't find this issue at the current Google issue tracker.
References:
Web Apps
Taking advantage of Web Apps with Google Apps Script

Refused to Connect Error while inserting Google Drive Link in HTML Services of Google API Script

The code.gs has the following code.
function doGet() {
var output = HtmlService.createHtmlOutputFromFile('userendhtml');
output.addMetaTag('viewport', 'width=device-width, initial-scale=1');
return output;
}
The userendhtml has the following code.
Lecture Notes
The Google Drive Link refers to pdf file shared publicly. When user runs the script, The output is correct. However when he clicks on the link, he get the error that drive refused to connect. This works when I make the link with target =_"blank". I want to open pdf in same tab. How to solve this error? Can it be restructured in a way that back (browser back) will also work?
It is a known issue in Apps Script and likely happens when you are logged into multiple Google accounts.
Try the same app inside Chrome's incognito mode or log out of all other Google accounts and only log into the main Google account.

Set email signature using Google Apps Script with Gmail API

I'm trying to set the Gmail signature of the user executing the script (Execute the app as: "User accessing the web app"; Who has access to the app: "Anyone within my domain") using the following function:
function setSignature(signature) {
var newSig = Gmail.newSendAs();
newSig.signature = signature;
Gmail.Users.Settings.SendAs.patch(newSig, "me", Session.getActiveUser().getEmail());
}
where signature is some html. This function is called from a client-side script when a form is submitted:
google.script.run.withSuccessHandler(signatureSuccess).setSignature($("#signatureParent").html());
The user is served a web app using the HtmlService containing the form. The Gmail API has been enabled in both the Advanced Google Services window as well as the Google API Console.
My issue is that when the I try and execute the function I receive the following console error message:
The message states that the auth scope gmail.settings.basic is missing. This is despite the user authorizing the web app before any html is served:
How do I fix or work around this issue?? The strange thing is I've had this working previously so I don't know what I'm doing wrong.
EDIT:
I've noticed that if I create a simple Apps Script with just the function:
function testSet() {
var testSig = "signature";
var newSig = Gmail.newSendAs();
newSig.signature = testSig;
Gmail.Users.Settings.SendAs.patch(newSig, "me", Session.getActiveUser().getEmail());
}
And leave out everything else I get presented with these permissions to authorize:
If I click Allow it works! So clearly "Manage your basic mail settings" a.k.a. auth scope gmail.settings.basic is required and isn't being asked for in the more involved script.
So how do I force that permission to be acquired or how do I rewrite my script to get the correct set of permissions needed?
After extensive testing I've determined that this issue is a bug in Google Apps Script in determining what scopes are required.
A basic version of my script requires these scopes (File > Project Properties > Scopes):
Extending the script to interact with Google Drive modifies the scopes to this:
By dropping the required gmail.settings.basic scope a critical function within the script is denied permission to run. Infuriating.
I was also facing the same issue on nodejs application, the solution is to generate referesh token using this required scope which is mentioned in the rest api documentation find below.
rest apis documentation
you can create refresh token using required scopes on this link if you're logged in developer account.
https://developers.google.com/oauthplayground: