I am attempting to call Session.getActiveUser in order to auto-fill certain fields in a Google Sheets document when other fields are edited. All users are in the same domain; however, I receive an error message, "You do not have permission to call getActiveUser." I was under the impression from existing documentation that users within the same domain can access one another's information through custom scripts - is this incorrect? If so, I know that there are several workarounds, but if not, is there something else I could be doing wrong?
Thanks in advance!
"user3889423" is correct, you need Authorization of the user, in order to call the getActiveUser().
You can find this information in this link below:
https://developers.google.com/apps-script/guides/sheets/functions#advanced
The link in KRR's answer contains the information you need. Here's the excerpt answering you question:
You definitely cannot call Session.getActiveUser() without user authorization, even for users within the same domain:
If your custom function throws the error message You do not have permission to call X service., the service requires user authorization and thus cannot be used in a custom function.
However, even with user authorization, you still cannot use Session.getActiveUser() in custom functions (directly in cells). You need to create a custom menu instead:
To use a service other than those listed above, create a custom menu that runs an Apps Script function instead of writing a custom function. A function that is triggered from a menu will ask the user for authorization if necessary and can consequently use all Apps Script services.
If that script runs without the explicit authorization of the user, you won't be able to get the ActiveUser (I think). It should work though when a user authorizes the script first.
Related
i wrote code for getting all viewers of spreadsheet in app script .
i have used getViewers() method to get viewers names who actually viewed it. but that method is returning me the names of people to whom i actually shared the spreadsheet....
is there any other way that i can get all viewers of spreadsheet.?
is there any web automation tools that can solve my problem?
Answer:
It is not possible to get a list of people that have opened your a Google Drive file using Google Apps Script - a method that returns this list does not exist. The getViewers() method returns the list of people with view and comment permissions for a file, while getEditors() retrieves the list of people that have edit permissions.
The Issue:
is there any other way that i can get all viewers of spreadsheet.? is there any web automation tools that can solve my problem?
There is no way of getting viewers of a Google Sheet as this is a huge security issue. This information is not stored and is therefore not retrievable.
Workaround:
You can make a custom function which stores the username of a person when they open the file - though be aware that triggers have restrictions and will only run if the person opening the file has edit access. I have included a list of Apps Script Trigger Restrictions below for you to look through and decide what is the best approach for you.
Code:
function onOpen(e) {
var user = e.user.getEmail();
// do some code to store or save this parameter
// for example save it to a hidden sheet or email it to yourself
// though an email would require an installable trigger to be made
}
Simple Trigger Restrictions:
These are not all of the restrictions (full restrictions are available here), but these are the ones that I believe to be most relevant for you.
As per the Google Apps Script Simple Triggers documentation:
They do not run if a file is opened in read-only (view or comment) mode.
They cannot access services that require authorization. For example, a simple trigger cannot send an email because the Gmail service requires authorization, but a simple trigger can translate a phrase with the Language service, which is anonymous.
They can modify the file they are bound to, but cannot access other files because that would require authorization.
They may or may not be able to determine the identity of the current user, depending on a complex set of security restrictions.
This last point is important - getting information about the current user is possible depending on the security policies of the the G Suite domain. A detailed explanation of this can be found in the getActiveUser() method documentation:
If security policies do not allow access to the user's identity, User.getEmail() returns a blank string. The circumstances in which the email address is available vary: for example, the user's email address is not available in any context that allows a script to run without that user's authorization, like a simple onOpen(e) or onEdit(e) trigger, a custom function in Google Sheets, or a web app deployed to "execute as me" (that is, authorized by the developer instead of the user). However, these restrictions generally do not apply if the developer runs the script themselves or belongs to the same G Suite domain as the user.
There are big security issues with getting a list of people that have viewed a file, for good reason, and so what you are looking to do it highly restricted by Google.
References:
Class File of Google Apps Script
getViewers() method of Class File
getEditors() method of Class File
Simple Triggers
onOpen(e) Trigger
Simple Trigger Restrictions
Installable Triggers
Event objects
Class User of Apps Script
User.getEmail() method
Class Session
getActiveUser() method of Session Class
I am building an Google Apps Script add-on for Google Spreadsheets.
In the manifest I have explicitly requested the following scopes:
"https://www.googleapis.com/auth/script.container.ui",
"https://www.googleapis.com/auth/spreadsheets"
Also the "OAuth consent screen" within my Google Cloud project has the same scopes and these are already verified by Google.
Nevertheless it is not possible for me to give feedback to my users in case of a wrong input. I have tried the following:
SpreadsheetApp.getActiveSpreadsheet().show(htmlApp);
SpreadsheetApp.getActiveSpreadsheet().toast(message);
SpreadsheetApp.getUi().alert('Wrong input.');
SpreadsheetApp.getUi().showSidebar(html);
Browser.msgBox('Wrong input.');
Nothings seems to work, I always see the error "Authorisation is required to perform that action" within the stackdriver logs.
What would work is to create an "error sheet" and log all input errors into it, or to make one cell within the main sheet to an "error cell" and log all input errors into it. I think this is not a good solution in terms of user experience.
It seems that this problem has something to do with the authMode: https://developers.google.com/gsuite/add-ons/concepts/editor-auth-lifecycle#authorization_modes
Because "Access to user interface" is only possible within "FULL" authMode, which is not the case during onEdit().
The strange thing is, that other add-ons are able to show an alert/popup. Is this a hack? Or do I need more scopes? Or do I have to change anything else?
EDIT 08.10.2019:
#Jacques-Guzel Heron:
For instance: the user inputs a date in cell A1 and another in cell B1. Within the onEdit(e) trigger I want to check if the date in B1 is after the date in A1, if not I want to alert the user. All the above listed methods lead to the error "Authorisation is required to perform that action", when the app is published. When the app is not published .toast(), .alert() and .msgBox() work within my test environment. The strange thing is, that these methods then create a DIV-element, whereas the other add-ons create an IFRAME-element for their alert/dialog-box. Therefore I think they use another method and it has nothing to do with scopes. In addiation I had a look during the OAuth verification process of these add-ons and the scopes are listed within the dev-tools. They do not use any special "ui-scope", so I doubt the cause for this error is scope related.
EDIT 09.10.2019:
Now I know how an alert/dialog-box containing of an IFRAME-element can be made. To do this, these methods can be used:
var htmlString, msg, htmlOutput;
htmlString = '<p>my html string</p>';
msg = 'my message';
htmlOutput = HtmlService
.createHtmlOutput(htmlString)
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setHeight(140);
SpreadsheetApp
.getUi()
.showModalDialog(htmlOutput, msg);
But it is also not possible to call this method during onEdit(e).
All the above listed methods can be called, through clicking on the menu items and also through clicking on buttons within the sidebar, but not during onEdit(e).
In addition I have added all the scopes which other add-ons are using, but in vain. So again my assumption got confirmed that the problem is not scope related.
I have the impression that some smart people have managed to find an inofficial workaroung, please let me know :)
You are right on all your approach. And yes, this is intended behavior as documented on authorization modes.
Those add-ons use custom menus to use a formula that checks the cell after being called pressing a button.
On that documentation you can find information to develop your alert. Please describe what you are trying to accomplish so I can help you better, otherwise ask me for more clarification without hesitating.
The solution are installable triggers: https://developers.google.com/apps-script/guides/triggers/installable
They are running in FULL authMode and therefore are allowed to access the user interface: https://developers.google.com/gsuite/add-ons/concepts/editor-auth-lifecycle#authorization_modes
I've published a Google Apps Script standalone spreadsheet add-on, while I met some problem using PropertiesService.getUserProperties() in a custom function.
If User A has installed the add-on and saved some data in the user property.
Then User A shared the spreadsheet to User B. When user B run the custom function, he can get the saved data in user property for user A. This is not what I suppose user Property works. Both User A and B should get their own saved data.
So what is the active user for a shared spreadsheet? I don't want all the spreadsheet viewers to get the saved data for the spreadsheet creator. Is there anything I'm doing wrong in code or "Cloud Platform project" option?
In other words, how can I get different data saved in user properties for different viewers in a shared spreadsheet?
I tried to get the active user email in a custom function, but it does not work.
Please note, I can't use Session.getActiveUser in the custom function, because Google Apps Script Custom function does not support Session service. It will get an invalid permission exception.
https://developers.google.com/apps-script/guides/sheets/functions#Advanced
Thanks,
After writing tons of code to test different scenarios, I believe it has no way to solve the above problem.
So I will use a workaround to achieve the goal. In case someone also run into the trouble. I will put down my test results here.
If Google account A shared spreadsheet to Google account B.
In custom function, they all get A's user property.
From a webpage, call into server function via script.run, both A and B can
get their own user property.
Custom functions can't access PropertiesServices.userProperties() (maybe the exception is the spreadsheet owner).
According to https://developers.google.com/apps-script/guides/sheets/functions
Unlike most other types of Apps Scripts, custom functions never ask users to authorize access to personal data. Consequently, they can only call services that do not have access to personal data, specifically the following:
While Properties is included on the list and there isn't any note for this service, since the custom function doesn't ask users to authorize to access personal data it should not return PropertiesServices.userProperties() as it potentially store user personal data.
I've been trying to get some custom validations and access checks done in spreadsheets,
based on the groups the users belong to.
As far as I know, the following trigger bound to a container(a spreadsheet) should have the rights of the user accessing the spreadsheet:
function onEdit(event) {
var groups = GroupsApp.getGroups();
Logger.log(groups);
}
Still, it runs into an error: "Execution failed: You do not have permission to call getGroups".
The same function called from a standalone script file(in theory the same access) will see the groups of the user.
My questions are:
Am I doing something wrong?
If not, is there a way to access the groups of a user from a spreadsheet event?
Probably not relevant, but using Windows 8 and Chrome 30.0.1599.101 m.
Zig Mandel's answer is correct as simple events like onEdit are unable to call methods that require authorization,however you were trying to get the user's group and that will be a problem since installable triggers run under the authority of the author of the script (in fact the person that set up the trigger which is usually the script author) which means not the user's group but yours...
So I'm afraid what you are trying to do won't be possible because in contradiction with the privacy rules in spreadsheet scripts.(read the doc that Zig refers to in his answer)
The only way to access the user's group information is using a direct function call in a menu or using a button that will ask for authorization., no automation in there ...
If you were to read onEdit documentation it says that you cant call methods that require authentication. Install the trigger with a different name instead of using the simple trigger.
HiMy problem is following: I would like to create small web page, on which it will be possible to create event in Google Calendar, but with some restrictions. In my case this calendar could be edited by my flatmates to reserve washing machine. This reservation cannot overlap and also all of us has limited number of days when we can use it. I have created private calendar, and I have created script which validate requests, and if everything is ok add event to calendar. This script is executed as me (because only I have permission to edit this calendar).
But I have problem with fetching information which user execute this script (me or one of my flatmate). Class Session contains 2 methods getActiveUser() and getEffectiveUser() but active user does not work (I guess because privacy protection policy). But if I create another script which is executed as user accessing the web I can get active user.
Does anybody know if is it possible to communicate somehow between this 2 scripts embedeed on the same site? I want to pass email of active user from one script to another. Or maybe do you know better solution how to solve this problem?
Regards
Adam
As you noticed, you need to set the script to run as the user accessing it to get his email. Then, instead of accessing the calendar directly (which you obviously can't) you can call another script published, but running as yourself allowing anonymous access that will receive this request from the "viewing" script and create the calendar events for it.
After you publish this "background" script, get its url and use it on a UrlfetchApp.fetch call to it. Then pass the parameters as url paremeters (or on payload if you prefer to use post instead of get).
The background script may even use ContentService to give nice return values to the calling script.
Sure, you can do so, but it's not as simple as you'd like. Make your admin level script run a web service that responds to the other script. It can probably be hacked as you can't authenticate the users, but comon, this is a washing macine!