I am developing a Google Docs Add-on and need to know if the user currently using the add-on has used it before in the current document or any document. I can't figure out which service gives me some kind of unique identifier for the current user that I can use to identify the current user.
The base service's User.getEmail is not good enough as it doesn't give access to the email under certain conditions and is not reliable.
Thoughts on best way to do this?
Unfortunately, there is no such service. Google wants users' personal information to remain private, so AFAIK you won't usually get even user's email, unless your script is written for Google Apps domain and the user is in the same domain as the script's author.
The only thing you can do in the situation is use something like DocumentApp.getActiveDocument().getId() and check if the script was used in this document, but of course this won't give you an idea if user has used your script in other documents or not.
Also you can show a Prompt Dialog to user, asking him to enter email, but of course there is no way you can check if he entered his real email.
Unique user identifier you can get for apps script is Session.getEffectiveUser().getEmail()
This will return the email of user for which the script run. This is better than ActiveUser because if you use trigger EffectiveUser will well return the email of the user who install the script.
I use that for several apps to identify license assignment and it works great.
It looks like the best solution is to roll your own solution using the following to set the userId at an appropriate time:
PropertiesService.getUserProperties().setProperty("userId",<someGeneratedUId>)
then whenever you want to look up if this user is a recognizable user,
var userId = PropertiesServices.getUserProperties().getProperty("userId")
Looks like once set, the UserProperties thus set is available to this particular user (per user) running this add-on everywhere (i.e. all docs, not just the current on) that have this particular add-on enabled/running.
I'll validate this further but seems like this works in my tests.
Related
I have a Google Sheets Add-on about which I'd like to determine feasibility of monetizing. To do this I'd like to see frequency level of users; users per domain as well as how often they use the add-on.
I've read a bit about properties in the documentation, and I'm pretty sure that is at the heart of what I need to work on to start getting this data. My question is about routing that to a form I can use to crunch numbers.
I have considered just having the Properties Service send the user's email and date generated in the Add-on (not the current date, but the date for the content generated). Once that gets sent to a spreadsheet in my drive, I can use a script bound to the spreadsheet to determine if the user has been logged yet. If so, we move the date to the row for that user. If not, we create a new entry. I can also have the script order users based on domain so I can see domains with heavier usage.
I've never done this before, so I'm looking to see if I'm thinking in the right direction or if I'm overlooking something.
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.
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!
My students all have a Google account, but use different emails (like john#hotmail.com).I tried to write a webapp that would get from my grade spreadsheet the row with the webapp's user's email address, so that each student would only see his or her grades. That webapp uses: Session.getActiveUser().getEmail()
This only works for users in the same domain as the script, I have to run the script as the webapp user (which is ok -- my students trust me that far!). Here is that restriction:
Returns a User object describing the current user. In
limited-privilege executions (such as in response to onOpen or
onEdit), we only return the identity of the active user if both the
user and the script owner are part of the same domain. This is to
protect the privacy of consumer users, who may not want their email
address exposed.
My script works, but I have to put the table of grades directly in the script and update the webapp each time I update my spreadsheet. Yeck!
I can't share my grade spreadsheet because then they would see each other's grades. So now I am brainstorming other workarounds.
Here is one example:
Share a second spreadsheet, copy the grades from my spreadsheet with an update function that encrypts the grades. The webapp sucks up the data from the shared spreadsheet and decrypts. Now a simple update of a spreadsheet is all that is needed -- the webapp doesn't need to be republished. (There are some simple encryption options, like base64encode with maybe a little scrambling...?)
Find a way to automatically update the webapp and republish. (Don't know how to do that.)
????
Any suggestions?
PS: if 1 seems feasible, some suggestions for simple encryption code?
There are some simple encryption options, like base64encode with maybe a little scrambling...?
Yes, the GAS has functions to encode/decode using the Base64 algorithm - Utilities.base64Encode, Utilities.base64Decode, but I think, it is not an option even with a little scrambling. Students are very clever. My opinion is to use a JavaScript implementation of a encryption algorithm, for instance the Blowfish. There are a number of its implementations on JavaScript (here and here). These implementations should work in the GAS environment without any changes or with small modifications. It is should be sufficient to copy and paste the source code to the GAS Editor.
I dont understand why you say "My script works, but I have to put the table of grades directly in the script and update the webapp each time I update my spreadsheet"
It is very easy to create a webapp that shows a part of a spreadsheet using a flextable for example. Each instance of the app will have a user related content automatically and you will only have to update your master spreadsheet to get what you want. I don't know why you want to encode data for this... I think the user identification through the google login should be enough, don't you ?
Here is an example of such a webapp, the numbers you see are taken from a specific column in a master spreadsheet (for this public copy I set the app as running as "me" to avoid the authorization process but in real every user is identified and sees only his data).
The Spreadsheet itself and the code are viewable here, do not hesitate to come back if you need further information.
Is it an option to sync your sheet with a scriptDB?
And then query the DB where user=loginID
I have a spreadsheet with a UI app script. The app reads/updates from the spreadsheet.
My current settings are: Execute the app as "me".
Who has access to the app: "anyone".
I'm essentially sending out workflows that have assignments by email. Those emails can be outside of the domain but would all be gmail addresses.
I had hoped I'd be able to access the Session.getActiveUser() as I need to allow certain functionality on the app based on user accessing the UiApp. That function does not seem to provide any info unless I'm logged in as the script owner. Session.getActiveUser() is blank when accessing from a different address.
Is there a way to get the active user without having to Execute the app as "User accessing the app". I'd rather not have to share the spreadsheet with all the end users.
Thanks for any suggestions.
Rewrite from comments for readability :
Sharing the spreadsheet in this context doesn't mean anybody could open the spreadsheet directly as a document as long as the url of the spreadsheet remains unknown. The app will indeed need to have access to it if you deploy your app as 'User accessing the webapp' but no one can find the url of the sheet unless you publish it. I use this configuration very often but of course I don't know your exact use case... ;-) In my case the app itself determines what a specific user can do or not (by enabling /disabling certain functions / panels depending on the logged user.
Here is an example of an app like this, can you find the source spreadsheet ?
My spreadsheet has "anyone with the link" so the app can read and write to it but the name of the spreadsheet and its url is unknown (except for me) so it never appears in the document list of the user even if the user "writes" something in the document through the webapp (since he never actually "opens" it). I checked that on different accounts and never found any exception.
The active user and the property's like email etc.. Are not accessible with a public google account. It is accessible and useable with a google apps account within your own domain. See http://www.google.com/intl/en/enterprise/apps/business/pricing.html
Otherwise it's just a point of privacy on the web.
A litle disappointing i can imagine but logical if you think about it.
I do have another tip for you. Have al look at this link http://shop.oreilly.com/product/0636920023210.do
O'reilly also implemented a workflowsystem. It uses the url parameters to pass email (identity) information. Not really secure, but in combination with the Utilities.DigestAlgorithm SHA encoding you could take steps to encode your url email-parameters.
Hope this is helpfull.