How can my Google Apps Script be run by others the Sheet is shared with? - google-apps-script

I've got a Google Apps Script that works fine for me. Others who the sheet is shared with that try to use it get the message:
You do not have access to perform that action. Please ask the owner of
this item to grant access to you.
The script is used to update an existing sheet with new rows of data. It's triggered using a menu item added to the UI and does the following:
Finds a .xlsx file in a GDrive folder (this file is exported by a web service and manually placed by us into the GDrive Folder, we have no control over the contents of the file or its format)
Converts the file from .xlsx to .gsheet using UrlFetchApp (uploadType=media&convert=true)
Changes the filename and folder location of the resulting .gsheet using UrlFetchApp. The folder location now matches that of the .xlsx file (when a file is converted using UrlFetchApp the resulting file seems to be placed in the root of GDrive)
Gets the .gsheet using DriveApp and then opens it for access by the script
Stores all the data from the .gsheet into a 2d array using column headers as the keys for each element in a row
Stores all the ID values (unique) of the existing data from the destination sheet into a 1d array
Compares the two arrays and removes any rows from the 2d array that contain an ID that matches one in the 1d array, leaving only new data in the 2d array
Loops through each row of the 2d array and then through each column of the destination sheet adding data from the 2d array row to a new row at the bottom of the data in the destination sheet, using the value of the column header as the key for each element
I know there's no problem with the code because it works fine for me so it must be a problem with permissions, but I can't figure out how. The sheet is shared with them and the GDrive folder that the files are stored in is shared with them. When I first ran the script myself, I had to grant permissions for the script to access the GDrive folder, which has obviously now been done.
I'm the developer of our group and not the user of the data but atm I'm having to run the script to update the data for the users every time it needs doing instead of them just doing it themselves, which is... annoying.
Any help in trying to figure out where the problem is here greatly appreciated.
EDIT: Reading through this again its occurred to me that when the file is converted, at first its saved to the GDrive root which is why I then have to change the folder. Being the root, it's not shared with the users of this file. Could this be the reason? If so, how can I get around this? Can I specify at convert time which folder the resulting file should be saved to?

To fix this, you need to deploy the script as a web app (the idea comes from #MarioR answer, but the settings are different):
With the owner account, open the sheet, then script editor
Click on Publish and then Deploy as web app
For Execute the app as, choose User accessing the web app and for Who has access to the app, choose Anyone
The first time the users try to use the script, they will have to allow the script (if they get a This app isn't verified, they should click on Advanced at the bottom and then Go to <script name> (unsafe)). After this, they may need to refresh the sheet to be able to run the script.
If the owner shares the sheet to a new user, after the script has been deploy as a web app, the new user may need to wait 15 minutes (or so) before being allowed to authorize the script (meanwhile this user will continue to get the red warning).
Only the owner can deploy as a web app, the other users who try do to it won't get a message error, just a popup Fetching Data that remains stuck forever!)
To change the owner: open the sheet with the owner account, click on Share > Advanced > Click on the arrow that triggers the dropdown next to the "owner-to-be" > Set as owner

In my experience, I created a Spreadsheet that retrieves G Suite License information for users every time the Spreadsheet is opened. What I did was that I created the script with a Super Admin but when the Spreadsheet was shared the other users had the same problem until I went to Publish > Deploy as Webb App from the Apps Script menu, I leave the options like this image
That worked for me, I hope it works for you. After this update, all users with Edit rights on the spreadsheet were able to retrieve the information on behalf of the Super Admin every time the spreadsheet opens. Just make sure to execute the App as you and not as the user who will use the script or spreadsheet.
Usually other users are not able to run scripts that required admin rights but this resolves my issue. Please let me know if this worked for you!
Greetings.

I've got "doGet" after trying out the script as a Web App. What does "doGet" mean?

I confirm #MagTun's and #browly's solution to share the file and wait for 15 minutes. I faced this problem last week even if I had given Edit permission to the file programatically. Tricky because some users get the screen to grant permission (correct) but some get either "You need permission" message or "Sorry, unable to open file at this time" (wrong). But I observed that after some time, the user is able to run the script with or without requesting access to the file explicitly. So there's really nothing else needed but wait for about 15 minutes and it prompts for permission consistently. Thanks for the tips, it confirmed the solution to my problem.

Related

Disable Spreadsheet copy - Google Sheets

I would like to allow users to use my spreadsheet but not copy it as it contains intellectual property. I tried going to sharing settings and disabling:
Editors can change permissions and share
Viewers and commenters can see the option to download, print, and copy
But the sheet can still be copied. Ideas?
Unfortunately, it is not possible to disable copy / download for editors.
You can only do that for commenters and viewers.
As a workaround, I would advice you to keep your sensitive information into one master file and then importrange or copy via a script the shareable information into another file. So even if they copy or download the latter your sensitive information won't be copied / downloaded.
Related questions:
How to disable copy/ download access for editors in google sheets
Prevent editors from downloading the file
Disable download & Copy to Option in Google Spreadsheet
I think the simplest solution would be to copy and paste from the master file the range of values you want to share with the other document. In this scenario the editors of the other document won't have access to neither the code nor the full data of the master file since the latter won't be shared with them.
The copy and paste part can be done automatically via a script and a trigger mechanism to update the data automatically so you won't have to do anything manually and the master file won't be exposed to any user.
There isn't any sure way to hide your data. Once something is published on the internet, you should consider it saved on many devices all over the world. Consider some ways to get hidden spreadsheet data
Attack scenarios:
By far the easiest way is CTRLC and CTRLV(Copy and Paste)
Editor menu options: File->Copy and File->Export
Once your file id is visible, any editor or even viewer with access to the file can easily copy the file itself through
Url manipulation: Adding /copy at the end instead of /edit
google-drive-api: File:get and File:copy
google-sheets-api: Useful to directly get data as json
google-vizualization-api: Can get data as html,csv or json(google query). See endpoints
Screenshot and use OCR(Optical character recognition)
View source code in the browser and directly copy the table
web-scraping Simulate browser using selenium
Hiding data:
Data may be hidden from naive users. Data cannot be hidden from users, who know the basics of how the web works.
Add ?rm=minimal to url, when sharing the sheets file. This hides all menu options.See here
Frame the edior in a iframe in your own website and use css to hide the top portion of the web page.
Hiding Logic:
You may still be able to hide logic of your code.
IMPORTRANGE: This is a very basic and easy way to hide your logic. But there are limitations and any editor can access any part of your master spreadsheet.
You can implement a IMPORTRANGE like logic using custom functions and webapps. This gives more control over the connector and secures your master spreadsheet much better than IMPORTRANGE. Here,
Two web apps are created, each associated with a spreadsheet(Master and client).
You use two KEYs to communicate between them. One for access and other for encryption.
Once access is verified, the data from master spreadsheet is encrypted and sent back to the custom function. Simultaneously the encryption key is posted to the client webapp.
The key here is the Master/Server webapp posts the encryption key only to the published client web app link. So, no other sheet or anything else can intercept the key or decrypt the data. Furthermore, a random key is generated for each access.
Another option is to let go off the spreadsheet completely and use a single webapp to show the data. This hides the logic in server scripts and linked spreadsheets.
Comment thoughts:
Create a script onOpen to kill sheets if the file is wrong?
onOpen cannot post data anywhere without the new copy owner permission. It's not possible to kill sheets. But data can be erased.
/**
* Deletes all sheets on the copy, if a copy is made
*/
const onOpen = () => {
const ss = SpreadsheetApp.getActive();
const id = ss.getId();
const sheets = ss.getSheets();
ss.insertSheet(sheets.length);//insert a blank sheet at the end
if (id !== '###Original ID###') sheets.forEach(s => ss.deleteSheet(s));//will fail at the last sheet(doesn't matter)
};
But editor can modify the original script before making a copy. And a revision of the original spreadsheet will still be available. The new owner can revert to the original version, use api endpoints mentioned above to get the data. Also mobile apps don't support onOpen. New owners can simply use mobile versions to access data.
Use formula web-app to notify file owner, ?
Possible, but data is already copied and there's no specific information that can be used to accurately identify the new owner. You maybe able to get locale information though.

Permission to run a script created by another user

I am having a problem running a script that is set up by one person but I need to also be able to run and debug the script.
I am new to using Google Sheets scripting and do not understand the correct steps need to do to run a script setup by one person at a different location and I need to debug and run the same script on the same worksheet.
I have been given access to the worksheet and can edit the Google Sheet and edit the script but when I try to run the script using the interface run option or run the script on by using a button or the worksheet. It works fine in the original location, but does not work for me.
I am forced to give start to permission process but told that I need to contact the person that original created the worksheet it gives me his email address.

Sharing a Google Spreadsheet containing a script with a workgroup so they can use it, but not modify it

I have written a Google Spreadsheet script which reads data from a user provided CSV file, populates a sheet with the data, makes a copy of the spreadsheet with a different name, and provides a link for the user to click to see the new spreadsheet. After making the new copy, the original spreadsheet is then cleared of user data and restored to its original state so other users can use it.
I want to share this spreadsheet with the workgroup (several hundred users), but I don't want them to be able to modify either the sheet or the script. If I share it read-only the script won't run, but to get the script to run I have to allow users edit capability and that is a bad thing.
I have googled myself silly trying to find a direction in which to go, but I am still wandering in the wilderness.
Can any of you point me in the right direction? If I need to be more specific or provide more information I will be glad to do so.
Thanks,
Larry
P.S. Other questions of note:
o Is it possible for a app-script in a spreadsheet to make the new copy active and 'close' the original shared spreadsheet?
o Can the user be made the owner of the new copy?
There is the option to put the code that you don't want modified, into a Stand Alone Apps Script file, then use that code as a "Library" in your script bound to the sheet. You can set the permissions on the Stand Alone Apps Script to VIEW only. That will keep people from changing it. When you share the Apps Script file with the users, they will get an email notification. So, they'll have the URL to the file, and can view it, but they can't edit it. (If you set it to VIEW only)
So, you'll be using both your spreadsheet file, and a Apps Script file. Two files, and setting the sharing to VIEW only on the Apps Script file. You can still give people EDIT access to the spreadsheet.
You'll need to go through a process of making the function available to your spreadsheet. This is called a "Library", but don't pay much attention to that name when creating the file.
Create a Stand Alone Apps Script
Create the function you want to share.
Get the Project Key --> FILE, PROJECT PROPERTIES
Share the Apps Script file with users you want to give access to, but only give them VIEW access to the file. NOT Edit.
Give the Project Key to the user, (In this case that's just you.) and have them add the library, or if you have access to the spreadsheet, you can probably add the key yourself. So, in your case, you will not be sharing the Project Key with anyone. You don't need to.
In the script file that is bound to the spreadsheet, click the RESOURCES menu, and the LIBRARIES menu item.
Enter the Project Key
Click SELECT button, and turn the library ON.
Make sure to set the library Identifier to a key word you'd like to use.
Go to the code editor, create a function, and type the Library Identifier.
All the functions that are available from the Library will show up
Google Documentation - Gaining Access to a Library
Keep in mind, that creating a library is nothing more than writing code in an Apps Script in a stand alone Apps Script file. If you've done that, then all you need to share is the Project Key. The user of the Library won't see a list of all the available Libraries when Resources, Libraries is opened. You need the Key.

I need a script to monitor a specific Google Drive folder whenever there is a change and notify me by email

I have been trying all day and I found this:
http://www.jellybend.com/2012/12/19/monitor-google-drive-folders-with-google-apps-script/
The attached script worked only partially for me. It doesn't respond to change to the subfolders even there are files inside the subfolders (eg. rename/delete the subfolder). It also seems to have errors if I delete and re-add the same file to the folder again, it just doesn't email me for the newly added "old file".
I also found this:
https://developers.google.com/drive/v2/reference/changes/list#examples
but unfortunately I am not really sure what those parameters are and I am just inexperienced in writing something like that.
Any help will be greatly appreciated! Thanks!
The file monitoring code at that link, is an Apps Script bound to a Sheet. An Apps Script can be bound to a Sheet, Doc, Form or Site. An Apps Script can also be a stand alone application. So, any code you may want to write, does not need to be in a spreadsheet.
An Apps Script can be set up to have a Time-driven event trigger.
There is also a Script Service to build Clock Triggers.
ClockTriggerBuilder Class
Using Time Driven Event Trigger, or a Clock Trigger you could use the getSize() method to return the amount of disk space used by the item:
Class - Folder - getSize Method
// This example logs the first file's size in bytes
// Note: This can also be used on a folder to get the size of its contents
var file = DocsList.getAllFiles[0];
Logger.log(file.getSize());
Of course, you would need to know what the original size of the folder or file was, and so you would need to store the current size somewhere. You could create a file for storing that information, or use the built in database that Apps Script has.
For storing your historical folder or file information you could use ScriptDB.
ScriptDB
Quote:
ScriptDB is a JavaScript object database for Google Apps Script. Each script project gets a database, which the script can use to save, update, and search JavaScript object data.
You could write historical file and folder info to a spreadsheet or document also.
Depending on who owns the file, and who is accessing the file, permissions would need to be granted, or you'd need to use oAuth2 to authenticate who has access to the file and folder information.
If you can't write all the code yourself, you could set up a shared Apps Script file, or find some other way to have people collaborate on the project.
I've been researching this on my own for some time and came up with a script bound to a spreadsheet as well. Hope it can help someone, as it seems that a lot of people are looking for something similar. My script is monitoring a folder and sends notification to all the current viewers of the folder as soon as there is new file added. Trigger to run the script could be set depending on the needs of the user. In my case hourly worked just fine.
Spread Sheet with the script: https://docs.google.com/spreadsheets/d/1CzVADjUTT2d9Y5OGDOnv37mCaO49kPt4RmnyZgzjTKA/edit#gid=0
If you would like to try this script just make sure you are logged in with your google account when you open the link and you should be able to make a copy of the spreadsheet.
This Google Script will send an email notification to you or other email addresses when a file in a Google Drive folder has been added, renamed, changed, or modified. http://baumbach.com/google-script-2/

Add records to a google spreadsheet using google script without access to that sheet

I have created a spreadsheet that works as a form and allows users to enter information in another sheet that acts as database. I have total 110 users and all of them will have a separate spreadsheet for entering data. They wont have access to the spreadsheet that acts as database. I have written script to cut data from their sheet to master sheet and it works when I do it because I have access to both of the sheets. But whey they run the script it gives access denied error.
Is there a way to run that particular script or all scripts as me master user so I can use my access rights?
Please advise. Help will be really appreciated.
Thank you
Just make a webapp interface and publish it to run as you. Get each users spreadsheet from a config file, session.getActiveUser().getEmail tell you who is running it.
You will need to locks as well since users could run it simultaneously and all write to the same place.