首页 > 解决方案 > UrlFetchApp.fetch 由 Sheets 事件触发,因缺少权限而失败,但在直接运行时有效

问题描述

我有一个谷歌应用程序脚本托管在谷歌表格表中,它运行 UrlFetchApp.fetch,用于几件事(使用 GCP 服务帐户进行身份验证、调用 GCP api 等)。

问题是,如果我直接从脚本编辑器运行或调试它(菜单运行 -> 运行函数/调试函数),它工作正常,但是当我将它附加到像“onEdit”这样的事件处理程序时,它会失败,在“ Apps 脚本仪表板”我可以看到这个错误

您无权调用 UrlFetchApp.fetch。所需权限:https://www.googleapis.com/auth/script.external_request 在 getBearerToken(Code:24) at writeToBigquery(Code:40) at onEdit(Code:15) 的未知函数

但是,我有给定的范围https://www.googleapis.com/auth/script.external_request作为清单和脚本属性,以及脚本本身(即使直接启动时带有硬编码值的 onedit 也可以正常运行)。

遵循清单:

{
  "timeZone": "Europe/Paris",
  "dependencies": {
    ...
  },
  "oauthScopes": [
    "https://www.googleapis.com/auth/script.external_request"
  ],

  "exceptionLogging": "STACKDRIVER"
}

脚本文件提取如下:

function onEdit(e) {
  // var range = e.range;
  var range = SpreadsheetApp.getActiveSheet().getRange("A1");
  // var row = range.rowStart;
  var row = 2;
  var cols = ['C', 'K', 'L', 'M', 'O', 'P', 'Q', 'R'];
  var data = new Object();
  for (var ii = 0; ii < cols.length; ii++)
  {
     data[cols[ii]] = SpreadsheetApp.getActiveSheet().getRange(cols[ii] + row.toString()).getValue();
  }
  Logger.log('calling writeToBigquery');
  writeToBigquery(data);
}

// uses the wonderful library https://github.com/Spencer-Easton/Apps-Script-GSApp-Library to oauth against a GCP service account
function getBearerToken() {

  var jsonKey = JSON.parse(PropertiesService.getScriptProperties().getProperty("json_key"));
  var key = jsonKey.private_key;
  var clientEmail = jsonKey.client_email;
  var serverToken = new GSApp.init(key, ['https://www.googleapis.com/auth/bigquery.insertdata'], clientEmail);
  // requestToken invokes UrlFetchApp according to https://github.com/Spencer-Easton/Apps-Script-GSApp-Library/blob/master/GSApp.gs, line 120
  serverToken.addUser(clientEmail).requestToken();
  var token = serverToken.getToken(clientEmail);
  Logger.log(token);
  return token.token;
}

function uuidv4() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}

function writeToBigquery(obj)
{
  Logger.log('requesting bearer token');
  // fails in this line
  var token = getBearerToken();
  // lots of other irrelevant stuff
  // ...
}

如前所述,当直接从脚本编辑器运行时工作正常,它只是在通过谷歌表格中的用户交互触发它运行时失败。

此外,编辑 Google 表格的用户不一定是在 GCP 项目中拥有权限的用户(这就是使用服务帐户的原因)。

标签: google-apps-scripturlfetch

解决方案


推荐阅读