在大多数情况下,您必须先授权插件,然后才能使用该插件。对于许多 Apps 脚本项目(例如 Web 应用),授权都很简单,即当您尝试使用脚本项目时,它需要获得所有缺少的权限。授权后,您可以自由使用脚本项目。使用此脚本项目的每个人都需单独进行授权。
编辑器插件的授权模型更为复杂。由于这些插件适用于 Google 云端硬盘中的文件(可以与他人共享的文件),因此在构建编辑器插件时必须考虑到不同的授权模式。Google Workspace 编辑器应用还会在其界面中提供插件菜单,即使您已经授权使用这些插件,这些插件也会填充这些插件。这会增加授权模型的复杂性。
授权模型
编辑器插件的两个属性使其特别易于共享和使用:
- 从商店获取编辑器插件后,您可以在打开或创建的每个文档的插件菜单中看到该插件。这些文档的协作者不会看到此插件,除非您实际使用该插件。
- 在文档中使用编辑器插件后,您的协作者也会在插件菜单中看到该插件,但仅限于此文档(除非他们还安装了该插件)。
对于大多数用户来说,这种共享模式是自然而然的。不过,由于编辑器插件会自动在文档打开时运行其 onOpen(e)
函数来添加菜单项,因此上述行为会增加 Apps 脚本授权规则的复杂性。毕竟,用户不愿意在每次打开文档时都要接受插件访问个人数据。本指南可帮助您了解代码的用途和时间。
已安装与已启用
如果您在菜单中看到编辑器插件,它处于以下两种状态之一(或两种):已安装且已启用。在特定插件存储区中选择特定用户插件并授权其访问其 Google 数据后,系统就会安装该插件,相比之下,当有人在给定文档中使用某个插件时,该插件会启用。如果两个人协同处理某个文档,并且其中一位用户使用插件,则系统会为一位用户安装该插件并为文档启用该插件。
下表总结了这两种状态。请注意,在以插件形式测试脚本时,您可以选择在上述两种状态中任一种或同时运行测试。
已安装 | 已启用 | |
---|---|---|
适用对象 | 用户 | 文档 |
原因 | 从商店获取插件 | 在使用该文档时从应用店获取插件,或者 使用该文档中之前安装的插件 |
菜单公开范围 | 仅该用户在打开或创建的所有文档中 | 该文档的所有协作者 |
onOpen(e) 运行 |
AuthMode.NONE (除非也已启用,在这种情况下为 AuthMode.LIMITED) ) |
AuthMode.LIMITED |
授权模式
编辑器插件会在文档打开时自动运行其 onOpen(e)
函数来添加菜单项,但为了保护用户数据,Apps 脚本会限制 onOpen(e)
函数可以执行的操作。如果当前文档中尚未使用此插件,则这些限制会变得更加严重。
具体而言,已安装和已启用的状态决定了 onOpen(e)
函数在哪个授权模式下运行。Apps 脚本会将授权模式作为 Apps 脚本事件参数 e
的 authMode
属性传递;e.authMode
的值对应于 Apps 脚本 ScriptApp.AuthMode
枚举中的一个常量。
如果当前文档中启用了某个编辑器插件,onOpen(e)
将在 AuthMode.LIMITED
中运行。如果未启用该插件,但只安装该插件,onOpen(e)
将在 AuthMode.NONE
中运行。
授权模式的概念适用于所有 Apps 脚本执行,例如从脚本编辑器、菜单项或 Apps 脚本 google.script.run
调用运行,但只有在脚本作为 onOpen(e)
、onEdit(e)
或 onInstall(e)
等触发器运行的情况下,才能检查 e.authMode
属性。Google 表格中的自定义函数使用自己的授权模式 AuthMode.CUSTOM_FUNCTION
,这与 LIMITED
类似,但限制略有不同。其余时间,这些脚本将在 AuthMode.FULL
中运行,如下表所示。
NONE |
LIMITED |
CUSTOM_FUNCTION |
FULL |
|
---|---|---|---|---|
出现次数 | onOpen(e) (如果用户安装了插件,但未在文档中启用它) |
onOpen(e) (所有其他时间)onEdit(e) (仅适用于 Google 表格) |
自定义函数 | 所有其他时间,包括: 可安装的触发器 onInstall(e) google.script.run |
访问用户数据 | 仅限语言区域 | 仅限语言区域 | 仅限语言区域 | 是 |
对文档的访问权限 | 否 | 是 | 是 - 只读 | 是 |
访问界面 | 添加菜单项 | 添加菜单项 | 否 | 是 |
对 Properties 的访问权限 |
否 | 是 | 是 | 是 |
对“UrlFetch ”Jdbc 的访问权限 |
否 | 否 | 是 | 是 |
其他服务 | Logger Utilities |
任何不会访问用户数据的服务 | 任何不会访问用户数据的服务 | 所有服务 |
完整的生命周期
如果已安装适用于当前用户的插件,或插件在当前文档中已启用,则系统会在文档中加载该插件,从而使该插件出现在插件菜单中,并开始监听简单触发器 onInstall(e)
、onOpen(e)
和 onEdit(e)
。如果用户点击某个插件的菜单项,该插件会运行。
正在安装
从商店中安装编辑器插件时,其 onInstall(e)
函数会在 AuthMode.FULL
中运行。这使得插件能够运行复杂的设置例程,但也务必使用 onInstall(e)
创建菜单项,因为文档已经打开,所以您的 onOpen(e)
函数尚未运行。为方便起见,您只需从 onInstall(e)
调用 onOpen(e)
,如以下示例所示:
function onInstall(e) {
onOpen(e);
// Perform additional setup as needed.
}
开场白
当某个文档打开时,它会加载当前用户已安装或任何协作者已在该文档中启用的每个编辑器插件,并调用其每个 onOpen(e)
函数。onOpen(e)
运行的授权模式取决于插件是否已安装或启用。
如果插件仅创建了基本菜单,那么模式就无关紧要。以下示例展示了一个简单的 onOpen(e)
:
function onOpen(e) {
SpreadsheetApp.getUi().createAddonMenu() // Or DocumentApp.
.addItem('Insert chart', 'insertChart')
.addItem('Update charts', 'updateCharts')
.addToUi();
}
但是,如果要根据存储的 Apps 脚本属性添加动态菜单项、读取当前文档的内容或执行其他高级任务,则需要检测授权模式并进行适当处理。以下示例展示了高级 onOpen(e)
函数是什么样的,它根据授权模式更改其行为:
function onOpen(e) {
var menu = SpreadsheetApp.getUi().createAddonMenu(); // Or DocumentApp.
if (e && e.authMode == ScriptApp.AuthMode.NONE) {
// Add a normal menu item (works in all authorization modes).
menu.addItem('Start workflow', 'startWorkflow');
} else {
// Add a menu item based on properties (doesn't work in AuthMode.NONE).
var properties = PropertiesService.getDocumentProperties();
var workflowStarted = properties.getProperty('workflowStarted');
if (workflowStarted) {
menu.addItem('Check workflow status', 'checkWorkflow');
} else {
menu.addItem('Start workflow', 'startWorkflow');
}
}
menu.addToUi();
}
正在运行
当用户点击某个插件的菜单项时,Apps 脚本会首先检查用户是否已安装该插件,并在没有安装时提示他们进行安装。如果用户已授权该插件,脚本会运行与 AuthMode.FULL
中的菜单项对应的函数。文档中也会启用该插件(如果尚未启用的话)。