Google Sheets Sheet Protection - google-apps-script

I have a spreadsheet with multiple sheets within. I have this spreadsheet shared with multiple users, and I need to protect the sheets so that certain users can only view and edit one sheet of this spreadsheet. As follows:
User 1 (one location manager) needs to view and edit Sheet 1 (that
location's payroll)
User 2 (another location manager) needs to view and edit Sheet 2
(that location's payroll), but NOT Sheet 1
User 3 (district manager) needs to view and edit both Sheet 1 AND
Sheet 2, but NOT Sheets 3 & 4.
User 4 (regional manager) needs to be able to view and edit Sheets 1,
2, 3, and 4.
Google Sheets only offers protection against editing, but I am wondering if there is any third-party app, script, or workaround that allows this functionality of protection against viewing?

Short answer = No. If you can't find this method via an API or script, there's no way a third party will offer it (They have access to the same APIs we do).
Slightly longer solution: You can create one master spreadsheet that contains all this data, then have 4 other spreadsheets (One for each user) that pulls the data from the correct sheet(s) into their personal spreadsheet.
For the slightly longer solution, you're looking at an 'onOpen' trigger in that specific users spreadsheet, so when they open the spreadsheet, it copies the right sheets from the Master spreadsheet to the spreadsheet they've just opened. Methods such as 'openByID' (To allow you to get another spreadsheet) and 'copyTo' (to copy another spreadsheets sheet to the current spreadsheet) are your friend here.
A very, very simple version of this might be:
var ss = SpreadsheetApp.openById("ID-FOR-MASTER-SHEET");
var sheet = ss.getSheets()
var destination = SpreadsheetApp.openById("ID-FOR-USERS-SHEET");
sheet[0].copyTo(destination);
Otherwise, if you have access to a Google Spreadsheet, you can always view all sheets within.

Idea
Split the tabs into separate sheets. Create a folder and place all documents in it. Share each sheet only with the owner that needs it and then share the folder with the regional manager.
Bonus
Try importrange command.
You can do: =IMPORTRANGE(A1,A2)
A1 = Sheet URL
A2 = Tab!Range ie Store1!A1:Q500
Use it to create a master sheet that pulls data from all of the individual stores, that can give the regional manger an easy snapshot. You can even mirror the original tab structure.

Comment on Separate Workbook architecture and ImportRange
I would caution against splitting the application into separate workbooks. Use of the ImportRange() requires you set sharing permissions to "Anyone with link" rather than the more secure "Only specific users".
I just re-architected an expense authorization application away from the separate (six) workbooks to a single master workbook because of this security issue.
Alternatives: Content Service
In my application, I use Content Service to do edit operations that only the owner of the database can do. The authorized users can only edit specific ranges in specific sheets. Then to do the magic, they execute macros using the content service that runs as the database owner.
Controlling Viewing
Conceivably you could program the workbook to hide sheets dependent on who the user is. This requires they authenticate themselves (you cannot do this in onOpen() for example. The problem with this is when you get collaborators viewing the workbook simultaneously. It would be interesting to see how Sheets would handle concurrent views of the same document. Knowing Google, I bet it would work.

Related

Clarification for Google Apps Script created by "Hyde" - Make some parts of sheet non-editable by code (and apply this to several tabs)

I need to use the script that "Hyde" created and provided as seen at https://support.google.com/docs/thread/149743347/script-make-some-parts-of-sheet-non-editable-by-code-and-apply-this-to-several-tabs?hl=en. Specifically, I need to use the "// copy sheets '1', '2' and '3' to another spreadsheet" and put them at the end of the tab bar" option in the script, but can't seem to sort out a) where to put what variables, and b) populate them, so the script does what I need it to do. Namely, take an exist Sheets file (will probably be a gallery template IF that would allow the script to work too) with RANGE protection in place on 7 tabs, and create a new Sheets file with the "same" protections. The goal is to allow our employees to make copies (by way of using template if possible) and use the Sheets file, but NOT edit the ranges we have protected. Only select accounts, excluding "you" in the permissions which is obviously relative, should be able to edit the protected ranges.
Hyde's script appears to have multiple uses as described in the comments, but it seems some of the variables listed in comments need to be moved out of the comment section and possibly replace other variables/options in place for the default way the script is built to run.
Looking at suggested questions for this post I've reviewed https://developers.google.com/apps-script/reference/spreadsheet/protection. It seems we may also need to be able to specify something (user or group) other than "me" in "protection.addEditor(me);". Is that possible?
The goal is to allow our employees to make copies (by way of using template if possible) and use the Sheets file, but NOT edit the ranges we have protected.
When a user starts a script function through a button, a custom menu item, or a sidebar, or directly through Run in the Script Editor, the function runs under the account of the user at the keyboard. This means that any spreadsheets created by the function will be owned by that user, and the user will thus have full access to any sheets and ranges protected by the function as well.
To do what you are asking, create a web app that runs under an admin account. Any spreadsheets and protections created by the web app will be owned by the account who deployed the web app and not by the account of the user who runs the web app.
An easier solution would be to protect the sheets and ranges with the Show warning when editing this range option. These protections are automatically inherited into copies of the spreadsheet. This way, you would not need a script at all — just tell the users to make a copy of the template, and it will automatically be protected. Those protections can be bypassed, but they still let users avoid unintentional changes to protected parts of the spreadsheet.

Google Sheets - Is there a way to toggle permissions between viewer and editor from one google sheets file on another/

I have two google sheet files:
1 - Manager
2 - Employee
I want to change the permissions for an employee on the Employee file, using a cell value on the Manager file.
So that the manager could enter his sheet, enter a "1" or a "0" in a specific cell, and toggle the employee permission on the Employee file on or off.
You can protect the sheet so the user can't make changes to it or you can hide the sheet but if the manager unhides the sheet the user can see it.
This two options are described on Protect, hide, and edit sheets but they should not be used as a security method.
As a security method you can create two different spreadsheets and give access to the specific users you want.
You can have all the data on the Manager spreadsheet and then by using IMPORTRANGE you can select what the Employee sees.

How to protect a range from creator / owner of Google Sheet using Google Apps Script?

I have developed a Google app script where I am generating new google sheet based on a template. After copying the Google sheet, we are changing the owner using setOwner method to specified email address. The requirement is to protect a range thus we use getRange method to select the range and then call protect() method and setDescription to show protect range description.
The issue is we don't want the person who run this script to have edit access. Because s/he is a creator, we tried to change the owner and used removeEditor as well, but it doesn't seem to work.
Thoughts: Is is possible to simuate the File copy run by another user such that the person who is running the script don't have access.
It's not possible to make a protection on such way that the spreadsheet owner will not be able to edit the protected sheet/range.
Bear in mind that only owners and editors are able to run scripts but they can't remove themselves as editors and and editor can't remove the owner.
From https://developers.google.com/apps-script/reference/spreadsheet/protection#removeeditoremailaddress
Neither the owner of the spreadsheet nor the current user can be removed

Google script: unprotect a sheet through function when user has no right to do so

I have a spreadsheet with different sheets in Google sheet, 3 users can edit each one a sheet (protections are set, each user can edit only one sheet). They all can execute a google script function that writes what they edited in a summary sheet. I don't want anyone to be abble to edit the summary sheet, so I set myself as the only available editor.
So my problem is to authorize the 3 users, only through the google script function, to write in the summary sheet. I tried to use the following function :
var unprotected = summarySheet.getRange('G3:G10');
protection.setUnprotectedRanges([unprotected]);
but since the users are not allowed to edit the summary sheet, and since the function is run with the active user, so they can't give themselves the right to unprotect a range in the summary sheet... Do you know how to workaround this problem?
Thanks a lot!
I see two script-based choices, one easy and one quite hard, and one sheet-based choice, that is easiest:
Easy:
You run the "summarize" script instead of them or, you set the summarize script run on a trigger out of your account. Then you actually leave protections alone. You could set the summarize script to run on open with error catching if the user doesn't have the necessary authority to unprotect the summary sheet and/or write to the summary sheet.
Hard:
When they run the "summarize" script it calls a published standalone script that has been given the authorization to make the necessary protection changes. I'll be honest, I wouldn't be able to code this but have seen/heard of similar implementations.
Easiest:
Finally, I want to make sure you've considered having the summary sheet itself contain the necessary formulas, parsing, etc. to summarize data from the other sheets without any need of scripts for this aspect of the sheet. The sheet could call custom functions as needed if the parsing or other summarization functionality is beyond built-in functions' capabilities. The sheet could stay fully protected and update itself in real time as users enter data (no need for users to trigger the summary creation, unless spreadsheet settings have auto-recalculate turned off).
Edited to add: put in A1 of Summary sheet something like:
=summarize()
And have that custom function return a 2-dimensional array of the summarized data.

web app : sharing settings

I have an apps script, a web app (within google site, share option: "Who has access to the app:anyone within mydomain" when publishing it) who make a forms using code as :
var app = UiApp.createApplication();
var panel = app.createVerticalPanel();
.....
When user press submit button the data are saved in a spreadsheet.
I have to give full access to an user group on this spreadsheet in order to make the forms works.
the problem, is that i don't want user1 (belonging to the user group) see what user2(belonging to the user group) has save in this spreadsheet.
At the moment, i share the spreadsheet without notifications but users are style able to access the spreadsheet using "shared with me" button on the drive.
Question:
Is that possible to hide share (like $ share on windows)?
Is that possible to let the script special grant option to read/write the spreadsheet without sharing it with the user group on run time.
or how the actual google forms (the one provide by google drive, not mine) handle this problem ?
Google API is not activate in my domain, i have a google education license and i am the admin of this domain.
hope it's clear enough.^^
thanks for hwelp
If you use Google Forms, you do not need to share your spreadsheet at all. You can distribute the URL for the live form, and from there users can only enter form data. Forms are static, though - you can edit the questions easily, and create logical flows between pages of questions based on previous answers, but you cannot dynamically include data. You're also very limited in your options for layout. But aside from that, the ease of use and information security make them a good option.
With Legacy Forms, collected data is stored in a spreadsheet. Since the introduction of the new Forms, you need to first create your spreadsheet, then select Forms - Create Legacy Form to start. The "Summary of Responses" report reflects what is in the form table in the spreadsheet. Any changes you make to the sheet affect this, for example row deletion, addition, or information edits.
With the new Forms, introduced in February 2013, the collected data is attached to the Form, not a Spreadsheet. You can choose to have it copied to a spreadsheet, but since that is a copy, any edits you make to it will not be reflected in the "Summary of Responses". You can create a new Form from the "Create" dialog in Drive, or from within a spreadsheet.
Your spreadsheet must be shared as 'anyone with the link can EDIT', as long as you don't publish this link no one will be able to find it and it will not appear in their 'shared with me' category.
Your webapp however will allow each user to fill the spreadsheet with their date by using the form.
see this other post that shows a practical example.