编辑器插件授权

许多 Google Apps 脚本应用的授权过程都很简单。当有人尝试使用脚本项目时,该项目会请求所需的任何缺失权限。

由于以下几个原因,编辑器插件的授权模型较为复杂

  • 当用户创建文件时,即使尚未授权,用户安装的所有插件也会列在扩展程序 菜单中。

  • 这些插件适用于 Google 云端硬盘中可与协作者共享的文件。未安装编辑器插件的协作者会在文件创建者使用该插件的文档中看到该插件。

  • 当文档打开时,编辑器插件会自动运行其 onOpen 函数。

为了保护用户数据,系统会应用授权模式,使某些服务无法用于 onOpen。本指南介绍了您的代码可以执行的操作以及执行时间。

授权模型

编辑器插件的授权模式取决于其状态,而其状态取决于使用该插件的用户:安装该插件的用户或协作者。

编辑器插件状态

扩展程序 菜单中的编辑器插件处于已安装、已启用状态,或同时处于这两种状态:

  • 当用户或其管理员可从 Google Workspace Marketplace 获取插件并授权其访问用户的 Google 数据后,该插件即为特定用户 已安装
  • 当有人在文档、表单、演示文稿或电子表格中使用插件时,该插件即在其中 已启用
  • 当用户协作处理文件且其中一人使用插件时,该插件即为该用户 已安装 ,并为该文件 已启用

下表总结了已安装和已启用之间的区别。 当您 将脚本作为插件进行测试时, 可以在任一状态或两种状态下运行测试。

已安装 已启用
适用对象 用户 文档、表单、演示文稿或电子表格
原因 从商店获取插件 在使用文档、表单、演示文稿或电子表格时从商店获取插件,或者在该文档、表单、演示文稿或电子表格中使用之前安装的插件
可见菜单 仅该用户,在其打开或创建的所有文档、表单、演示文稿、 或电子表格中 该文档、表单、演示文稿、 或电子表格的所有协作者
onOpen 的授权模式 AuthMode.NONE
(除非它也已启用,在这种情况下为 AuthMode.LIMITED)
AuthMode.LIMITED

授权模式

当用户打开文档、表单、演示文稿或电子表格时,编辑器插件的 onOpen 函数会自动运行。为了保护用户的数据,Apps 脚本会限制 onOpen 函数可以执行的操作。编辑器插件的状态决定了 onOpen 函数在哪个授权模式下运行。

如果编辑器插件在文件、表单、演示文稿或电子表格中 已启用 ,则 onOpenAuthMode.LIMITED 中运行。如果 插件未启用,仅 已安装,则 onOpenAuthMode.NONE 中运行。

AuthMode.NONE 中,插件无法运行某些服务,除非用户通过点击或运行自定义函数与插件互动。如果您的插件尝试在 onOpenonInstall 或全局范围内使用这些服务,权限会失败,并且其他调用(例如填写菜单)会停止 。帮助是唯一受支持的选项。

如需运行受限的服务调用,您必须使用 AuthMode.FULL 授权模式。用户互动函数(例如点击菜单选项)仅在此模式下运行。在 AuthMode.FULL 模式下运行代码后,插件可以使用所有已授权的范围。

只有已发布的 编辑器插件才能处于 AuthMode.NONE 状态; 未发布的 编辑器插件会在 AuthMode.LIMITED 中运行 onOpen。不过,无论采用哪种授权模式,都应如此。为此, 请测试编辑器插件

Apps 脚本会将授权模式 作为 Apps 脚本 事件参数 eauthMode 属性传递; e.authMode 的值对应于 Apps 脚本 ScriptApp.AuthMode 枚举中的常量。

授权模式适用于所有 Apps 脚本执行方法, 包括从脚本编辑器、菜单项或 Apps 脚本 google.script.run 调用运行。不过, 只有当脚本因触发器(例如 onOpenonEditonInstall)而运行时,才能检查 e.authMode 属性。Google 表格中的 自定义函数 使用自己的授权模式 AuthMode.CUSTOM_FUNCTION,该模式与 LIMITED 类似,但限制略有不同。对于所有其他情况,脚本都在 AuthMode.FULL 中运行,如下表所述。

NONE LIMITED CUSTOM_FUNCTION FULL
发生于 onOpen(如果用户已安装插件,但未在文档、表单、演示文稿或电子表格中启用该插件) onOpen(所有其他时间)
onEdit(仅在表格中)
自定义函数 所有其他时间,包括:
可安装的触发器
onInstall
google.script.run
访问用户数据 仅限语言区域 仅限语言区域 仅限语言区域 支持
访问文档、表单、演示文稿或电子表格 不支持 支持 支持 - 只读 支持
访问界面 添加菜单项 添加菜单项 不支持 支持
访问 Properties 不支持 支持
访问 JdbcUrlFetch 不支持 支持
其他服务 Logger
Utilities
任何不访问用户数据的服务 任何不访问用户数据的服务 所有服务

编辑器插件的授权生命周期

当为当前用户安装插件或在当前文件中启用插件时,该插件会在打开文档、表单、演示文稿或电子表格时为该文件 加载 。该插件会列在扩展程序 菜单中,并 开始监听简单触发器 onInstallonOpenonEdit。如果用户点击扩展程序 菜单项,该菜单项就会运行。

编辑器插件已安装

当从商店安装编辑器插件时,其 onInstall 函数会在 AuthMode.FULL 中运行。在此授权模式下,插件可以运行复杂的设置例程。您还应使用 onInstall 创建菜单项,因为文档、表单、演示文稿或电子表格已打开,而 onOpen 函数尚未运行。以下示例展示了如何从 onInstall 函数调用 onOpen 函数:

function onInstall(e) {
  onOpen(e);
  // Perform additional setup as needed.
}

编辑器插件已打开

当文档、表单、演示文稿或电子表格打开时,它会加载当前用户已安装或任何协作者已在该文件中启用的每个编辑器插件,并调用每个插件的 onOpen 函数。onOpen 运行的授权模式取决于插件是已安装还是已启用。

如果插件仅创建基本菜单,则模式无关紧要。以下示例展示了一个基本的 onOpen 函数:

function onOpen(e) {
  SpreadsheetApp.getUi().createAddonMenu() // Or DocumentApp.
      .addItem('Insert chart', 'insertChart')
      .addItem('Update charts', 'updateCharts')
      .addToUi();
}

如需根据存储的 Apps 脚本 属性添加动态菜单项、读取 当前文件的内容或执行其他高级任务,您 必须识别授权模式并对其进行适当处理。

以下示例展示了一个高级 onOpen 函数,该函数会根据授权模式更改其操作:

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();
}

onOpen 函数运行时,整个脚本会加载,并且全局语句会在与 onOpen 相同的授权模式下运行。如果授权模式禁止全局语句,则全局语句和 onOpen 都无法运行。如果已发布的插件无法添加其菜单项,请查看浏览器控制台以查看是否返回了错误。然后,检查您的脚本,看看 onOpen 函数或全局变量是否调用了 AuthMode.NONE 中不允许的服务。

插件在 AuthMode.LIMITED 中执行时无法打开边栏或对话框。您可以使用菜单项 打开边栏和对话框,因为这些菜单项在AuthMode.FULL中运行。

用户运行编辑器插件

当用户点击扩展程序 菜单项时,Apps 脚本会先检查用户是否已安装该插件,如果未安装,则会提示用户安装。如果用户已授权该插件,脚本会在 AuthMode.FULL 中运行与该菜单项对应的函数。如果插件尚未在文档、表单、演示文稿或电子表格中启用,则会在其中启用。

排查插件菜单未呈现的问题

如果您的代码未正确管理授权模式,则插件菜单可能无法呈现。例如:

  • 插件尝试运行当前授权模式不支持的 Apps 脚本服务。

  • 插件尝试在用户与其互动之前运行服务调用。

如需移除或重新排列导致 AuthMode.NONE 中出现权限错误的服务调用,请尝试以下操作:

  1. 打开插件的 Apps 脚本项目,找到 onOpen 函数。
  2. onOpen 函数中搜索提及 Apps 脚本服务或与其关联的对象(例如 PropertiesServiceSpreadsheetAppGmailApp)的内容。
  3. 如果服务用于创建界面元素以外的任何用途,请将其移除或将其封装在注释块中。仅保留以下方法:.getUi.createMenu.addItem.addToUi。 另请查找并移除函数之外的任何服务。
  4. 找出可能包含在上一步中注释或移除的代码行的函数,尤其是使用其生成的信息的函数,并将服务调用移至需要这些信息的函数。重新排列或重写代码库,以适应在上一步中所做的更改。
  5. 保存代码并创建测试部署。 创建测试部署时,请确保配置字段为 为当前用户安装,并且“配置”框下方的文本显示 AuthMode.NONE 中进行测试
  6. 启动测试部署并打开扩展程序 菜单。
  7. 如果显示所有菜单项,则问题已解决。如果您只看到帮助 菜单,请返回到第 1 步。 您可能遗漏了某个服务调用。