You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何授权域内非管理员用户在Google Apps Script中运行Admin SDK代码

实现非管理员运行高权限Google Apps Script的方案

方案核心逻辑

  • 现有代码调用了Admin Directory API,必须要有Google Workspace管理员权限才能调用,普通用户直接运行自然无权限
  • 我们不需要给普通用户赋予管理员权限,只需要让代码以预先授权的管理员身份执行,操作权限和触发用户完全隔离即可

具体操作步骤

步骤1:管理员账号配置脚本基础环境

  • 用具有Google Workspace超级管理员/组管理权限的账号打开对应的Google Sheet,进入脚本编辑器(扩展程序 -> Apps Script)
  • 确认Admin Directory API已开启:点击编辑器左侧「服务」-> 找到「Admin Directory API」-> 添加,版本选择v1即可
  • 替换脚本里的域名占位符:把listAllGroups函数里的THEDOMAIN和YOURDOMAIN改成你司的实际域名

步骤2:把高权限逻辑封装为Web App(适配onEdit触发场景)

原有onEdit是简单触发器,只能以当前用户权限运行,且无法调用需要授权的API,因此需要改成通过Web App调用的模式:

第一步:新增Web App入口函数,粘贴到现有代码末尾

// Web App 入口函数,统一处理增删查请求,以部署者(管理员)权限运行
function doPost(e) {
  const params = JSON.parse(e.postData.contents);
  const action = params.action;
  try {
    if (action === 'add') {
      // 调用加人逻辑
      const newMember = {email: params.userEmail, role: "MEMBER"};
      AdminDirectory.Members.insert(newMember, params.groupId);
      // 更新表格数据
      const groupData = SpreadsheetApp.getActive().getSheetByName('GroupAddress');
      groupData.appendRow([params.userEmail, params.groupId]);
      return ContentService.createTextOutput(JSON.stringify({status: 'success'})).setMimeType(ContentService.MimeType.JSON);
    } else if (action === 'remove') {
      // 调用删人逻辑
      AdminDirectory.Members.remove(params.groupId, params.userEmail);
      // 更新表格数据
      const groupData = SpreadsheetApp.getActive().getSheetByName('GroupAddress');
      const groupDataValues = groupData.getDataRange().getValues();
      const resultArray = groupDataValues.filter(row => !(row[0] === params.userEmail && row[1] === params.groupId));
      const start = 2;
      if (groupData.getLastRow() >= start) {
        groupData.deleteRows(start, groupData.getLastRow() - start + 1);
      }
      if (resultArray.length > 1) {
        groupData.getRange(2, 1, resultArray.length - 1, resultArray[0].length).setValues(resultArray.slice(1));
      }
      return ContentService.createTextOutput(JSON.stringify({status: 'success'})).setMimeType(ContentService.MimeType.JSON);
    } else if (action === 'list') {
      // 调用列组逻辑
      listAllGroups();
      return ContentService.createTextOutput(JSON.stringify({status: 'success'})).setMimeType(ContentService.MimeType.JSON);
    }
  } catch (err) {
    return ContentService.createTextOutput(JSON.stringify({status: 'error', message: err.message})).setMimeType(ContentService.MimeType.JSON);
  }
}

第二步:替换原有的onEdit触发逻辑

把原来的addUsertoGroup和deleteGroupMember函数替换为以下版本,不再直接调用Admin API,改为调用后续部署的Web App:

// 替换原有addUsertoGroup函数
function addUsertoGroup(e) {
  const sheet = e.source.getActiveSheet();
  if (sheet.getName() !== 'AddUser') return;
  const userData = e.source.getSheetByName('AddUser');
  const userEmail = userData.getRange(2, 1).getValue().trim();
  const groupId = userData.getRange(2, 2).getValue().trim();
  if (!userEmail || !groupId) return;
  // 这里替换为后续部署Web App得到的URL
  const WEB_APP_URL = "你的Web App部署链接";
  const payload = JSON.stringify({
    action: 'add',
    userEmail: userEmail,
    groupId: groupId
  });
  const options = {
    method: 'POST',
    contentType: 'application/json',
    payload: payload,
    muteHttpExceptions: true
  };
  UrlFetchApp.fetch(WEB_APP_URL, options);
  // 重置表单
  const header = ['UserEmail', 'GroupID'];
  userData.clear();
  userData.appendRow(header).setFrozenRows(1);
}

// 替换原有deleteGroupMember函数
function deleteGroupMember(e) {
  const sheet = e.source.getActiveSheet();
  if (sheet.getName() !== 'RemoveUser') return;
  const removeUserData = e.source.getSheetByName('RemoveUser');
  const userEmail = removeUserData.getRange(2, 1).getValue().trim();
  const groupId = removeUserData.getRange(2, 2).getValue().trim();
  if (!userEmail || !groupId) return;
  // 替换为你的Web App部署链接
  const WEB_APP_URL = "你的Web App部署链接";
  const payload = JSON.stringify({
    action: 'remove',
    userEmail: userEmail,
    groupId: groupId
  });
  const options = {
    method: 'POST',
    contentType: 'application/json',
    payload: payload,
    muteHttpExceptions: true
  };
  UrlFetchApp.fetch(WEB_APP_URL, options);
  // 重置表单
  const header = ['UserEmail', 'GroupID'];
  removeUserData.clear();
  removeUserData.appendRow(header).setFrozenRows(1);
}

第三步:部署Web App

  • 脚本编辑器右上角点击「部署」->「新建部署」
  • 点击设置图标(齿轮)选择「Web应用」
  • 配置参数:
    • 说明可随意填写,例如「组管理工具接口」
    • 执行身份选择:我(即当前登录的管理员账号)
    • 有权访问的用户选择:你司域名内的所有人
  • 点击部署,完成权限授权后复制得到的Web App URL,替换上述两个函数里的WEB_APP_URL变量

步骤3:配置定时同步触发器

listAllGroups函数不需要用户触发,直接用管理员账号添加可安装触发器即可:

  • 脚本编辑器左侧点击「触发器」->「添加触发器」
  • 选择要运行的函数:listAllGroups
  • 选择事件源:「时间驱动」
  • 按需求设置运行频率,例如每天凌晨运行一次

步骤4:表格权限配置

把Google Sheet的编辑权限开放给你司需要使用该工具的非管理员用户即可

注意事项

  • Web App每次修改代码后都要重新部署新版本,否则修改不会生效
  • 可在代码中添加额外权限校验,例如只允许指定用户组的人员调用,避免功能滥用
  • 如果仅需要查看组列表,直接给普通用户开放GroupAddress工作表的只读权限即可
  • 如果普通用户编辑表格后没有生效,可删除原有简单触发器,用管理员账号新增2个可安装的「编辑时」触发器,分别绑定addUsertoGroup和deleteGroupMember函数即可

内容的提问来源于stack exchange,提问作者Riccardo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 21:48:02