0

I am trying to extract the details of all suspended users in G-Suite Admin SDK, for which I wrote a query in Google Apps script:

function fetchUser(){           
    var pageToken;
    var membersList = AdminDirectory.Users.list({
      domain: 'xyz.com',
      orderBy: 'email',
      query: isSuspended=true,
      maxResults: 100,
      pageToken: pageToken
    });  
    Logger.log('membersList:' +membersList);
}

The result that I am getting in the logs is:

[18-06-20 16:32:15:413 EDT] membersList:{"kind":"admin#directory#users","etag":"\"npJcgeAc7XbfkhvPm3glLSpkcPU/HMFwD2wLX237BRmKZQUJYB5ZE7U\""}

I am not able to see the users list in the response as mentioned in G-suite-admin-SDK, which says the response should be something like:

{
  "kind": "admin#directory#users",
  "etag": etag,
  "users": [
    users Resource
  ],
  "nextPageToken": string
}

I used the search-users documentation for the search-query which says to use isSuspended=true, may I know what am I doing wrong?

tehhowch
  • 9,645
  • 4
  • 24
  • 42
merilstack
  • 703
  • 9
  • 29
  • I notice you don't specify any requested fields. Is there a reason why you don't supply a `fields` parameter? All Google APIs recommend using the "fields" parameter to reduce bandwidth for you and your users. Also - your query looks wrong. Queries are usually a string, while yours is the result of an assignment expression. – tehhowch Jun 20 '18 at 21:14
  • I have not seen `fields` in the [user-list](https://developers.google.com/admin-sdk/directory/v1/reference/users/list), hence I didn't use it. As far as the assignment expression is concerned it's not throwing up an error in the script, just to make sure it's not because of that I declared `var isSuspended = true` and then used `query: isSuspended` in the code which is generating the same output. – merilstack Jun 20 '18 at 21:37
  • `isSuspended=true` is a Javascript statement. `"isSuspended=true"` is a string. You can review the "fields" parameter in every Google API, under "Standard Query Parameters" – tehhowch Jun 20 '18 at 21:38
  • I meant it as a Javascript statement, not as a string – merilstack Jun 20 '18 at 21:40
  • 1
    Per the description of the parameters that you link, the format for the `query` parameter is `string`. So supplying a statement likely means you gave it a random value (such as `true` or `undefined`, meaning you sent the following: `var options = {query: true}` or `var options = {query: undefined}` which will most certainly not give the same result as `var options = {query: "isSuspended=true"}` – tehhowch Jun 20 '18 at 21:42

2 Answers2

2

Per the API documentation you link, the query parameter is required to be a string. You supply an invalid query - query: isSuspended=true - and thus no query is performed.

You may be confused by the examples in the "Search for Users" API documentation that use seemingly "raw" variables and parameters - this is because the examples it gives still need to be URL-encoded:

Examples

All queries use the users.list method, which has an HTTP request similar to the following (line breaks included for readability):

GET https://www.googleapis.com/admin/directory/v1/users
?domain=primary domain
&query=query parameters

The query parameters must be URL encoded. For example, the query query=givenName:Jane* is URL encoded as query=givenName%3AJane*. All examples on this page show unencoded query parameters. Client libraries handle this URL encoding automatically.

You can help yourself and improve your code by re-using an options variable, e.g:

function getAllSuspended() {
  // Set the constant options only once.
  const options = {
    domain: 'xyz.com',
    orderBy: 'email',
    query: 'isSuspended=true',
    maxResults: 100,
    fields: "nextPageToken,users"
  };
  // Could log the options here to ensure they are valid and in the right format.

  const results = [];
  do {
    var search = AdminDirectory.Users.list(options);
    // Update the page token in case we have more than 1 page of results.
    options.pageToken = search.nextPageToken;
    // Append this page of results to our collected results.
    if(search.users && search.users.length)
      Array.prototype.push.apply(results, search.users);
  } while (options.pageToken);

  return results;
}

Client Libraries & Apps Script

The "advanced services" in Apps Script are Google API client libraries that wrap the underlying REST API, so you do not need to perform the URL encoding on parameters you pass to their methods. If you decided you didn't want to use the client library, preferring to query the URL with UrlFetchApp, then you would need to URL encode the querystring. (You might do this if you wanted to make a lot of simple, quick, unrelated requests and the client library does not offer a BatchHttpRequest method: you could use UrlFetchApp.fetchAll for better performance.)

tehhowch
  • 9,645
  • 4
  • 24
  • 42
  • Is it mandatory to URL encode the query parameters, since Client libraries handle this automatically? Is it necessary to manually update the pageToken, since that too is automatically taken care of? – merilstack Jun 20 '18 at 23:10
  • 1
    @JijoJohny changing the page token is not automatically handled - you must pass in the token of the page you want. On the first call, you don't have a token, so it is `undefined` and you get the first page. If `nextPageToken` is not present in the response from the API (and you either did not limit `fields`, or explicitly requested the `nextPageToken` field), then that means there are no more pages available. The Apps Script "advanced service" `AdminDirectory` class is a client library that handles URL encoding - note that you do not have to explicitly specify urls, etc, in order to use it. – tehhowch Jun 21 '18 at 00:38
  • but I am still able to retrieve all the suspended user's account details using my script in alphabetical order of the email id and it's not using `nextPageToken` – merilstack Jun 21 '18 at 02:08
  • @JijoJohny And how many suspended users are there? less than 100? See what happens when you change your `maxResults` parameter from 100 to 1. – tehhowch Jun 21 '18 at 02:09
  • it just shows one user, but this time it also shows the `nextPageToken` for the last record – merilstack Jun 21 '18 at 02:16
0

It was a simple error:

function fetchUser(){           
        var pageToken;
        var membersList = AdminDirectory.Users.list({
          domain: 'xyz.com',
          orderBy: 'email',
          query: "isSuspended=true",
          maxResults: 100,
          pageToken: pageToken
        });  
        Logger.log('membersList:' +membersList);
    }

Thanks @tehhowch for helping me out.

merilstack
  • 703
  • 9
  • 29