简体   繁体   English

如何获取使用 Google Apps 脚本的 G Suite 用户列表?

[英]How to get a list of G Suite users which are using Google Apps Script?

I would like to find out, is there any chance to get a list of G Suite users (of one domain) who are using Google Apps Script?我想知道,是否有机会获得使用 Google Apps 脚本的 G Suite 用户(一个域的)列表?

After you retrieve the list of script projects from Google Drives of your users, you will have to first request project metadata for them from the Apps Script API .从用户的 Google Drives 检索脚本项目列表后,您必须首先从Apps Script API请求项目元数据。 Presently, the only way to get a project is to go one by one, supplying requests with scriptId .目前,获得项目的唯一方法是 go 一个一个,提供带有scriptId的请求。

The trick is that the Id of the script project file happens to be the the same as script Id (if you look at the source code of the CLASP project's list command, you will see that they utilize this fact to display project Ids).诀窍是脚本项目文件的 Id 恰好与脚本 Id相同(如果您查看 CLASP 项目的list命令的源代码,您会发现他们利用这一事实来显示项目 Id)。

To acquire a Project resource, we need to call the get method :要获取Project资源,我们需要调用get 方法

GET https://script.googleapis.com/v1/projects/{scriptId}

Below is a simple utility for retrieving a single Project resource from the API.下面是一个简单的实用程序,用于从 API 中检索单个Project资源。 Note that your manifest file will have to include at least the https://www.googleapis.com/auth/script.projects.readonly scope, otherwise the API will return a 403 response code.请注意,您的清单文件必须至少包含https://www.googleapis.com/auth/script.projects.readonly scope,否则403将返回响应代码

/**
 * @typedef {{
 *  domain : string,
 *  email : string,
 *  name : string
 * }} GSuiteUser
 * 
 * @typedef {{
 *  scriptId : string,
 *  title : string,
 *  createTime : string,
 *  updateTime : string,
 *  creator : GSuiteUser,
 *  lastModifyUser : GSuiteUser
 * }} ScriptProject
 * 
 * @summary gets script project metadata
 * @param {{
 *  id : string,
 *  token : string
 * }}
 * @returns {ScriptProject}
 */
const getProject = ({
  id = ScriptApp.getScriptId(),
  token = ScriptApp.getOAuthToken()
}) => {

  const uri = `https://script.googleapis.com/v1/projects/${id}`;

  /** @type {GoogleAppsScript.URL_Fetch.URLFetchRequestOptions} */
  const params = {
    contentType : "application/json",
    headers : {
      Authorization: `Bearer ${token}`
    },
    muteHttpExceptions : true,
    method : "get"
  };

  const response = UrlFetchApp.fetch(uri, params);

  const successChecker = getSuccessChecker();

  const success = successChecker(response);

  if(!success) {
    return {};
  }

  return JSON.parse(response.getContentText());
};

Map it over the list of script files you obtained using ziganotschka's method, and you will get detailed info about the projects. Map 在您使用 ziganotschka 方法获得的脚本文件列表上,您将获得有关项目的详细信息。 Next, if by using you mean running projects, you can invoke the processes.list API method instead:接下来,如果您意思是运行项目,您可以调用processes.list API 方法

GET https://script.googleapis.com/v1/processes

Required OAuth scope is https://www.googleapis.com/auth/script.processes .必需的 OAuth scope 是https://www.googleapis.com/auth/script.processes

/**
 * @typedef {{
 *  projectName : string,
 *  functionName : string,
 *  processType : string,
 *  processStatus : string,
 *  userAccessLevel : string,
 *  startTime : string,
 *  duration : string
 * }} ScriptProcess
 * 
 * @summary lists script processes for a user
 * @param {{
 *  id : (string|"any"),
 *  pageSize : (number|50),
 *  token : string,
 *  start : (Date|undefined),
 *  end : (Date|undefined),
 *  statuses : string[],
 *  types : string[]
 * }} 
 * @returns {ScriptProcess[]}
 */
const listScriptProcesses = ({
  id = ScriptApp.getScriptId(),
  token = ScriptApp.getOAuthToken(),
  pageSize = 50,
  start, end,
  statuses = [],
  types = []
} = {}) => {

  const query = [
    `pageSize=${pageSize}`,
    `userProcessFilter.startTime=${toZuluTimestamp(start)}`,
    `userProcessFilter.endTime=${toZuluTimestamp(end)}`
  ];

  id !== "any" && query.push(`userProcessFilter.scriptId=${id}`);
  types.length && query.push(`userProcessFilter.types=${types.join(",")}`);
  statuses.length && query.push(`userProcessFilter.statuses=${statuses.join(",")}`);

  const uri = `https://script.googleapis.com/v1/processes?${query.join("&")}`;

  /** @type {GoogleAppsScript.URL_Fetch.URLFetchRequestOptions} */
  const params = {
    contentType: "application/json",
    headers: {
      Authorization: `Bearer ${token}`
    },
    muteHttpExceptions: true,
    method: "get"
  };

  const response = UrlFetchApp.fetch(uri, params);
  const content = response.getContentText();

  const successChecker = getSuccessChecker();
  const success = successChecker(response);

  if (!success) {
    console.warn(response.getResponseCode(), content);
    return [];
  }

  const { processes = [] } = JSON.parse(content);

  return processes;
};

In response, you will get metadata about script executions on behalf of the user whose credentials are passed with the bearer token (you will need a service account for each user).作为响应,您将代表用户获取有关脚本执行的元数据,其凭据与不记名令牌一起传递(您将需要每个用户的服务帐户)。

The rest is easy: if the response is not empty, then the user ran a script project at some point in time (note that the utility above defaults both start and end timestamp parameters to now ). rest 很简单:如果响应不为空,则用户在某个时间点运行脚本项目(请注意,上面的实用程序将startend时间戳参数都默认为now )。 If you supply any as the script Id, the request will return every execution made on behalf of the user.如果您提供any作为脚本 ID,则请求将返回代表用户执行的每次执行。

An added benefit of the approach is that every type of script project execution is returned, including Web Apps, Add-ons, and bound projects (see ProcessType enum for details).该方法的另一个好处是返回每种类型的脚本项目执行,包括 Web 应用程序、附加组件和绑定项目(有关详细信息,请参阅ProcessType枚举)。

The only difficulty with this approach is presented by Web Apps deployed to "execute as me" which will always run under the authority of the script project owner, so you will have to track the users of the Web App separately.这种方法的唯一困难是 Web 部署为“像我一样执行”的应用程序,该应用程序将始终在脚本项目所有者的权限下运行,因此您必须单独跟踪 Web 应用程序的用户。


Snippets above use the following utility scripts:上面的片段使用以下实用程序脚本:

/**
 * @summary checks HTTPResponse for being successful
 * @param {GoogleAppsScript.URL_Fetch.HTTPResponse} resp 
 * @returns {boolean}
 */
const getSuccessChecker = ({ successOn = [200] } = {}) => (resp) => {
    const code = resp.getResponseCode();
    return successOn.some(c => c === code);
}; 
/**
 * @summary converts input into RFC3339 UTC "Zulu" format
 * @param {Date|number|string} [date] 
 * @returns {string}
 */
const toZuluTimestamp = (date = Date.now()) => new Date(date).toISOString().replace('Z','000000Z');

You will need to enable V8 runtime enabled for the snippets above to work (or transpile them to ES5 syntax).您需要启用V8 运行时才能使上面的代码片段正常工作(或将它们转换为 ES5 语法)。

How to verify either domain users have Standalone Apps Script projects on their Google Drive如何验证任一域用户在其 Google 云端硬盘上是否拥有独立应用程序脚本项目

  1. In order to have as an admin access to your users' Drive, you need to set-up a service account in your GCP Console要以管理员身份访问用户的云端硬盘,您需要在GCP Console中设置服务帐号
  2. Make sure to enable domain-wide delegation - this allows oyu to authenticate as a domain user and list his Drive files确保启用域范围的委派- 这允许 oyu 以域用户身份进行身份验证并列出他的云端硬盘文件
  3. Go to your Admin console and got to Main menu menu> Security > API controls and add the necessary scopes for the freshly created service account - as described here Go 到您的管理控制台并进入Main menu menu> Security > API controls并为新创建的服务帐户添加必要的范围 - 如此所述
  4. Download the.json file with the service account credentials - it should contain a "private_key" field下载带有服务帐户凭据的 .json 文件 - 它应包含"private_key"字段
  5. The necessary scope in your case is https://www.googleapis.com/auth/drive.readonly在您的情况下,必要的 scope 是https://www.googleapis.com/auth/drive.readonly
  6. To use a service accounbt within Apps Script, you need to install the OAuth2 for Apps Script library from as described herehere要在 Apps 脚本中使用服务帐户,您需要安装 OAuth2 for Apps 脚本库,如此处所述
  7. For this, go to your Apps Script editor, "Resources > Libraries... > Find a library" and enter the code 1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF为此,go 到您的应用程序脚本编辑器, "Resources > Libraries... > Find a library"并输入代码1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF
  8. Chose a version (currently the newest is 38)选择一个版本(目前最新的是38)
  9. Now, the first thing you need to do programmaticallyis to enable the adminSDK to list all domain users - as suggested by @TheMaster现在,您需要以编程方式执行的第一件事是启用adminSDK列出所有域用户 - 正如@TheMaster 所建议的那样
  10. The second step is to loop through all users, and to create a service account token on their behalf (setting them as a subject )第二步是遍历所有用户,并代表他们创建一个服务帐户令牌(将他们设置为主题
  11. With the access token you can list the files with the query parameters q: 'mimeType="application/vnd.google-apps.script"' for each user to find out either the user has standaolone Apps Script files on his Drive使用访问令牌,您可以使用查询参数q: 'mimeType="application/vnd.google-apps.script"'每个用户的文件,以找出用户在他的驱动器上是否有独立的应用程序脚本文件

Code sample:代码示例:

function myFunction() {
  var users = AdminDirectory.Users.list({"domain":"PASTE HERE YOUR DOMAIN NAME"}).users;
  users.forEach(function(user){  
    user = user.primaryEmail;
    getService(user).reset();
    var service = getService(user);
    
    if (service.hasAccess()) {
      Logger.log("service has access");
      var url = "https://www.googleapis.com/drive/v3/files";
      var query = '?q=mimeType%3D%22application%2Fvnd.google-apps.script%22';
      var headers ={
        "Authorization": 'Bearer ' + service.getAccessToken()
      };       
      var options = {
        'headers': headers,
        'method' : 'get',
        'muteHttpExceptions': true    
      };      
      var response=UrlFetchApp.fetch(url+query, options).getContentText();
      if(JSON.parse(response).files.length==0){
        Logger.log("User " + user + " does not have any Standalone Apps Script projects on his Drive");
      }else{
        Logger.log("User " + user + " has Standalone Apps Script projects on his Drive");
      }
      
    }
    else {
      Logger.log(service.getLastError());
    }
  }
 )
}

var PRIVATE_KEY ="-----BEGIN PRIVATE KEY-----PASTE HERE YOUR PRIVATE KEY FROM THE JSON FILE-----END PRIVATE KEY-----\n";
var CLIENT_EMAIL = 'PASTE HERE THE EMAIL OF THE SERVICE ACCOUNT';

function getService(user) {
  return OAuth2.createService('List users')
  .setTokenUrl('https://accounts.google.com/o/oauth2/token')
  .setPrivateKey(PRIVATE_KEY)
  .setIssuer(CLIENT_EMAIL)
  .setSubject(user)
  .setPropertyStore(PropertiesService.getScriptProperties())
  .setParam('access_type', 'offline')
  .setScope("https://www.googleapis.com/auth/drive.readonly");
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 Google Apps 脚本从 G Suite 管理控制台中删除 web 应用程序 - Remove the web apps from the G Suite Admin Console by using Google Apps Script 是否可以将 Google Apps Script Web App 发布到 G Suite Marketplace? - Is it possible to publish a Google Apps Script Web App to G Suite Marketplace? 使用 Google Apps 脚本发送的 G Suite 电子邮件未发送“邮件已阻止” - G Suite Emails Sent with Google Apps Script Are Not Delivered "Message Blocked" 事件保存/更新时的 g-suite Google 日历应用程序脚本 - g-suite Google Calender Apps script On Event Save/Update 有G Suite / Google Apps API吗? - Is there a G Suite/Google Apps API? Google Apps脚本:获取“分配”给Google文档和评论的用户列表 - Google Apps Script: Get list of users “assigned” to a google doc and comments 如何将 Google Apps Script Web 应用程序发布到 G-Suite Marketplace? - How to publish a Google Apps Script web app to the G-Suite Marketplace? 如何在Google Apps域Apps脚本中获取“所有新用户” - How to get 'All new users' in the Google Apps domain Apps Script 如何使用 Google Apps 脚本获取列表项的价值 - How to get value of List Items using Google Apps Script 如何使用 Gmail API、OAuth2 for Apps 脚本和域范围委派为 G Suite 域中的用户设置电子邮件签名 - How to use the Gmail API, OAuth2 for Apps Script, and Domain-Wide Delegation to set email signatures for users in a G Suite domain
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM