【问题标题】:Google Users: List users data of a specific groupGoogle 用户:列出特定组的用户数据
【发布时间】:2021-04-07 11:17:49
【问题描述】:

我需要列出属于组织内特定组的用户数据。 documentation 没有说明这是否可行。我真的希望有某种查询可以允许这样做。例如email in (1@domain.com,2@domain.com)。但是,我认为这是不可能的。我能想到的唯一方法是:

  1. 获取群组中所有成员的列表 (https://developers.google.com/admin-sdk/directory/reference/rest/v1/members/list)

  2. 通过电子邮件(https://developers.google.com/admin-sdk/directory/reference/rest/v1/users/get)获取每个用户数据

上述方法的问题在于,如果一个组包含 50 多个成员,这意味着我必须发出所有请求,这会适得其反。想象一下这需要多长时间。

有什么想法吗?非常感谢。

【问题讨论】:

    标签: google-api google-admin-sdk google-api-nodejs-client


    【解决方案1】:

    我在发布问题几个小时后考虑了批处理请求。 Node JS 的问题在于它没有内置对批处理请求的支持,这与 php 客户端库不同;因此,我不得不花一些时间自己实现对它的支持,因为我找不到任何示例。我会分享解决方案,以防它帮助其他人或供我将来参考。

    async function getGroupMembersData(){
      const groupEmail = "group@domain.com"; //google group email
      const groupMembers = await getGroupMembers(groupEmail).catch(error=>{
        console.error(`Error querying group members: ${error.toString()}`);
      });
      if(!groupMembers){ return; }
      const url = "https://www.googleapis.com/batch/admin/directory_v1";
      const scopes = ["https://www.googleapis.com/auth/admin.directory.user.readonly"];
      const requests = [];
      for(let i=0; i<groupMembers.length; ++i){
        const user = groupMembers[i];
        const request = {
          email: user,
          endpoint: `GET directory_v1/admin/directory/v1/users/${user}?fields=*`
        };
        requests.push(request);
      }
      const batchRequestData = await batchProcess(url, scopes, requests).catch(error=>{
        console.error(`Error processing batch request: ${error.toString()}`);
      });
      if(!batchRequestData){ return; }
      const usersList = batchRequestData.map(i=>{
        return i.responseBody;
      });
      console.log(usersList);
    }
    
    //get group members using group email address
    async function getGroupMembers(groupKey){
      const client = await getClient(scopes); //function to get an authorized client, you have to implement on your own
      const service = google.admin({version: "directory_v1", auth: client});
      const request = await service.members.list({
        groupKey,
        fields: "members(email)",
        maxResults: 200
      });
      const members = !!request.data.members ? request.data.members.map(i=>i.email) : [];
      return members;
    }
    
    //batch request processing in groups of 100
    async function batchProcess(batchUrl, scopes, requests){
      const client = await getClient(scopes); //function to get an authorized client, you have to implement on your own
      let results = [];
      const boundary = "foobar99998888"; //boundary line definition
      let batchBody = ""; const nl = "\n";
      const batchLimit = 100; //define batch limit (max supported = 100)
      const totalRounds = Math.ceil(requests.length / batchLimit);
      let batchRound = 1;
      let batchItem = 0;
      let roundLimit = batchLimit;
      do{
        roundLimit = roundLimit < requests.length ? roundLimit : requests.length;
        //build the batch request body
        for(batchItem; batchItem<roundLimit; batchItem++){
          const requestData = requests[batchItem];
          batchBody += `--${boundary}${nl}`;
          batchBody += `Content-Type: application/http${nl}`;
          batchBody += `Content-Id: <myapprequest-${requestData.email}>${nl}${nl}`;
          batchBody += `${requestData.endpoint}${nl}`;
        }
        batchBody += `--${boundary}--`;
        //send the batch request
        const batchRequest = await client.request({
          url: batchUrl,
          method: "POST",
          headers: {
            "Content-Type": `multipart/mixed; boundary=${boundary}`
          },
          body: batchBody
        }).catch(error=>{
          console.log("Error processing batch request: " + error);
        });
        //parse the batch request response
        if(!!batchRequest){
          const batchResponseData = batchRequest.data;
          const responseBoundary = batchRequest.headers["content-type"].split("; ")[1].replace("boundary=", "");
          const httpResponses = batchResponseParser(batchResponseData, responseBoundary);
          results.push(...httpResponses);
        }
        batchRound++;
        roundLimit += batchLimit;
      } while(batchRound <= totalRounds);
      return results;
    };
    
    //batch response parser
    function batchResponseParser(data, boundary){
      const nl = "\r\n";
      data = data.replace(`--${boundary}--`,"");
      const responses = data.split(`--${boundary}`);
      responses.shift();
      const formattedResponses = responses.map(i=>{
        const parts = i.split(`${nl}${nl}`);
        const responseMetaParts = (parts[0].replace(nl, "")).split(nl);
        let responseMeta = {};
        responseMetaParts.forEach(part=>{
          const objectParts = part.split(":");
          responseMeta[objectParts[0].trim()] = objectParts[1].trim();
        });
        const responseHeadersParts = parts[1].split(nl);
        let responseHeaders = {};
        responseHeadersParts.forEach(part=>{
          if(part.indexOf("HTTP/1.1") > -1){
            responseHeaders.status = part;
          } else {
            const objectParts = part.split(":");
            responseHeaders[objectParts[0].trim()] = objectParts[1].trim();
          }
        });
        const reg = new RegExp(`${nl}`, "g");
        const responseBody = JSON.parse(parts[2].replace(reg, ""));
        const formatted = {
          responseMeta: responseMeta,
          responseHeaders: responseHeaders,
          responseBody: responseBody
        };
        return formatted;
      });
      return formattedResponses;
    }
    

    【讨论】:

      【解决方案2】:

      很遗憾,我认为您不能跳过这两个步骤,但您可以使用 batch requests 加快速度。这 允许您在单个请求中请求多达 1000 个呼叫。步骤是:

      1. 发出批处理请求以获取您想要的所有组的所有成员(使用members.list)。
      2. 使用用户 ID(使用 user.get)发出批处理请求以获取您需要的所有用户信息。

      请注意,结果中的数据不会被排序,但它们会被标记为Content-ID

      参考文献

      【讨论】:

        猜你喜欢
        • 2011-07-14
        • 2016-11-28
        • 2014-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多