编辑器插件授权

在大多数情况下,您必须先授权某个插件,然后才能使用它。对许多 Apps 脚本项目(例如 Web 应用)来说,授权很简单:当您尝试使用该脚本项目时,脚本项目会请求它缺少任何所需权限。获得授权后,您可以随意使用该脚本项目。使用脚本项目的每个人都单独进行授权。

编辑器插件的授权模型较为复杂。由于这些插件适用于 Google 云端硬盘中的文件(可以与他人共享的文件),因此您在构建编辑器插件时必须考虑到不同的授权模式。Google 文档编辑器也会在其界面中提供插件菜单,即使您尚未授权这些插件,这些插件也可以填充。这会给授权模型增添一些额外的复杂性。

授权模式

编辑器插件的两个属性使其易于共享和使用:

  • 从商店获取编辑器插件后,您可以在打开或创建的每个文档、表单、演示文稿或电子表格的插件菜单中看到该插件。在实际使用文档、表单、演示文稿或电子表格的情况下,协作者看不到该插件。
  • 您在文档、表单、演示文稿或电子表格中使用编辑器插件后,您的协作者也会在插件菜单中看到该插件,但只会访问该文件(除非他们还安装了该插件)。

对于大多数用户来说,这种分享模式自然而然。不过,由于编辑器插件会在 Google 文档编辑器打开时自动运行其 onOpen(e) 函数来添加菜单项,因此上述行为会给 Apps 脚本的授权规则增加一些复杂性。毕竟,用户在每次打开文档、表单、演示文稿或电子表格时都会感到不自在。本指南可帮助您了解代码的用途和执行时间。

已安装与已启用

如果您在菜单中看到一个编辑器插件,则表示该插件处于两种状态之一(即已安装和已启用)。编辑器用户在商店中选择某个插件并授权该插件访问其 Google 数据后,系统就会安装该插件。相比之下,如果给定插件使用给定文档表单演示文稿电子表格中的某插件,系统就会启用该插件。如果两个人协作,而其中一位用户使用插件,则系统会为一位用户安装该插件,并允许该插件使用。

下表对这两种状态进行了总结。请注意,在将脚本作为插件进行测试时,您可以选择在这两种状态之一或同时在这两种状态下运行测试。

已安装 已启用
应用对象 用户 文档、表单、演示文稿或电子表格
原因 从商店中购买插件 在使用该文档、表单、演示文稿或电子表格时从商店获取插件,或者
在文档、表单、演示文稿或电子表格中使用之前安装的插件
菜单公开范围 只有该用户在其打开或创建的所有文档、表单、演示文稿或电子表格中 使用该文档、表单、演示文稿或电子表格的所有协作者
onOpen(e)”正在运行 AuthMode.NONE(除非也已启用,在这种情况下为 AuthMode.LIMITED) AuthMode.LIMITED

授权模式

编辑器插件在文档、表单、演示文稿或电子表格打开时,会自动运行其 onOpen(e) 函数来添加菜单项,但为了保护用户数据,Apps 脚本会限制 onOpen(e) 函数的用途。如果当前文档、表单、演示文稿或电子表格中尚未使用该插件,则这些限制会更加严格。

具体来说,已安装和已启用的状态决定了 onOpen(e) 函数会以哪种授权模式运行。Apps 脚本会将授权模式作为 Apps 脚本事件参数 eauthMode 属性传递;e.authMode 的值对应于 Apps 脚本 ScriptApp.AuthMode 枚举中的一个常量。

如果当前文档、表单、演示文稿或电子表格中启用了编辑器插件,则 onOpen(e) 会在 AuthMode.LIMITED 中运行。如果该插件未启用,但只安装了,onOpen(e) 会在 AuthMode.NONE 中运行。

授权模式的概念适用于所有 Apps 脚本的执行,例如从脚本编辑器、菜单项或 Apps 脚本 google.script.run 调用运行,但 e.authMode 属性只能在脚本作为 onOpen(e)onEdit(e)onInstall(e)触发器运行的情况下进行检查。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 的访问权限
能够访问“Jdbc”,UrlFetch
其他服务 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 中的菜单项对应的函数。文档、表单、演示文稿或电子表格中也会启用该插件(如果尚未启用)。