Code parsed under different levels of authorization

64 views
Skip to first unread message

Alan Wells

unread,
May 15, 2020, 4:54:56 PM5/15/20
to Google Apps Script Community
JavaScript is parsed and compiled at run time, immediately before your code runs.  That happens every time that your Apps Script code runs.  But depending upon the circumstances, your code can be parsed at different levels of authorization.  If you have simple triggers/functions in your code, then those triggers run under a restricted permission.  Simple triggers can't use services that require authorization. 

Google Services that are called in the global scope require authorization.  This creates a problem if you have global variables assigned to an Apps Script Class.

For example:

var MY_GLOBAL_SPREADSHEET = SpreadsheetApp.getActiveSpreadsheet();

Having a global variable for your active spreadsheet can save you lots of service calls to SpreadsheetApp, for example if you had 10 functions that all needed to access the active spreadsheet. 

And simple triggers avoid the need to install a trigger.  An Installed Trigger can use services that require authorization, but for something like an add-on, you would need to write code to create/install the trigger.  A simple trigger and a global variable that needs an authorized service call, don't mix.  That combination has caused a lot of frustration for many people, wondering why their menu created from a simple onOpen() function won't display.  It could be because there was an error when Apps Script parsed your code.  The code failed before your menu in the onOpen() function could be created.

The documentation warns about this situation in the quote below:

Warning: When your onOpen(e) function runs, the entire script is loaded and any global statements are executed. These statements execute under the same authorization mode as onOpen(e) and fail if the mode prohibits them. This prevents onOpen(e) from running. If your published add-on fails to add its menu items, look in the browser's JavaScript console to see if an error was thrown, then examine your script to see whether the onOpen(e) function or global variables call services that aren't allowed in AuthMode.NONE.

Michael O'Shaughnessy

unread,
May 15, 2020, 9:00:14 PM5/15/20
to google-apps-sc...@googlegroups.com
Allan - thank you for the post... it came at a good time because I am working on "re factoring" some old code to try to make it (trying to follow good coding practices).

So what do you suggest to fix the global variable issue?  I have read about using "namespaces" and using immediately invoked functions but would really like to hear what you (and others) think about this.

It does make sense that if I do have 10 functions that have as the first variable declaration as "var ss = SpreadsheetApp.getActiveSpreadsheet()" it would make sense to make "ss" a global variable.  BUT it would cause the issue you are describing... 

So, thoughts on a solution?

Thanks in advance for your help.




--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-apps-script-community/22420993-439c-4985-bc56-3f020f03dea5%40googlegroups.com.

Alan Wells

unread,
May 15, 2020, 10:15:17 PM5/15/20
to Google Apps Script Community
I use an assignment operator in a statement without a "var" keyword.

function define_My_Global_Vars_() {
  /*
    Sets global var names in the global space -
    Not using a var keyword puts the variable into the global scope -
    The statements are not in the global scope but the variables get put into the global scope
  */

  MY_ADD_ON_NAME = "Super Good Add-on";//No service call needed - assign a value now
  MY_GLOBAL_ONE = undefined;
  MY_GLOBAL_DOCUMENT = undefined;//Needs a service call to be assigned to an Apps Script Class

}

function set_My_Global_Doc_() {
  MY_GLOBAL_DOCUMENT = SpreadsheetApp.getActiveSpreadsheet;//Call a Google Service - Done inside of a fnk not in global space

}

define_My_Global_Vars_();//Call the fnk to define global var names in the global space - This statement is in the global scope

function getActiveDoc_() {
  try{
    if (MY_GLOBAL_DOCUMENT) {//If already assigned then this avoids additional service calls
      return MY_GLOBAL_DOCUMENT;
    };
  }catch(e){
    MY_GLOBAL_DOCUMENT = null;//If not already assigned then there must be an initial assignment
  }
  return set_My_Global_Doc_();//Assigns and returns the active document
};

Whenever your code needs to access the active spreadsheet, then simply use:
    getActiveDoc_()

You can either assign a var in the function or use it directly:

function myFunk_() {
  var ssID = getActiveDoc_().getId();

}

function my2_Fnk_() {
  var ss = getActiveDoc_();//Get the active spreadsheet
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-community+unsub...@googlegroups.com.

Michael O'Shaughnessy

unread,
May 15, 2020, 10:46:50 PM5/15/20
to google-apps-sc...@googlegroups.com
Awesome!  Thank you so much.  I really need to look at the code I have written... I really need to implement this code pattern!!

To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-apps-script-community/de6ba1e9-db18-4726-983a-8245b84e35e7%40googlegroups.com.

TIM “HANK” SHANK

unread,
Apr 2, 2024, 6:00:57 AMApr 2
to Google Apps Script Community
Reply all
Reply to author
Forward
0 new messages