3
votes

Simple function here in Google Apps Script:

function driveSearch() {
  // Log the name of every file in the user's Drive whose visibility is anyonewithLink or anyonecanfind
  var files = DriveApp.searchFiles(
    'visibility = "anyoneWithLink" or visibility = "anyoneCanFind"');
  while (files.hasNext()) {
    var file = files.next();
    var owner = file.getOwner().getName();
    var sa = file.getSharingAccess();
    Logger.log(file.getName());
    Logger.log('Owner:'+owner);
    Logger.log("SharingAccess:"+sa);
  }
  }

It want to find shared files in my gsuite drive.

However, it says I don't have permissions to run DriveApp

My permissions are set and requested correctly, like so:

{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes": [
    "https://www.googleapis.com/auth/drive.readonly",
    "https://www.googleapis.com/auth/drive.metadata.readonly"
  ]
}

The error is

You do not have permission to call DriveApp.searchFiles. Required permissions: https://www.googleapis.com/auth/drive (line 3, file "Code")

Why does searchFiles require delete permissions? I am very worried about inadvertent deletion, I don't want the full scope. Is there something else I'm doing wrong?

Lastly, yes my Gsuite allows Google Apps Script.

1
Method of searchFiles() in Class DriveApp uses the scope of https://www.googleapis.com/auth/drive. It seems that this is the specification. If you don't want to use the scope of https://www.googleapis.com/auth/drive, how about this workaround? In this workaround, the endpoint of Drive API is directly requested by UrlFetchApp. But in this case, 2 scopes of https://www.googleapis.com/auth/drive.metadata.readonly and https://www.googleapis.com/auth/script.external_request are required. Because I'm not sure whether this is what you want, I posted it as a comment. - Tanaike
@Tanaike whatever works and allows me to search without granting unrestricted permissions - I'll take! Please elaborate in an answer, thank you! - Summer Developer
Thank you for replying. I posted a workaround as an answer. Could you please confirm it? - Tanaike
In addition, You can also whitelist the access point url. - TheMaster

1 Answers

3
votes

How about this workaround? In this workaround, the endpoint of Drive API is directly requested by UrlFetchApp, and the following 2 scopes are used.

  • https://www.googleapis.com/auth/drive.metadata.readonly
    • This is used to the access token which is used for using Drive API.
  • https://www.googleapis.com/auth/script.external_request
    • This is used for using UrlFetchApp.

Enable Drive API at API console

Before you use this script, please enable Drive API as follows.

  • On script editor
    • Resources -> Cloud Platform project
    • View API console
    • At Getting started, click "Explore and enable APIs".
    • At left side, click Library.
    • At "Search for APIs & services", input "Drive". And click Drive API.
    • Click Enable button.
    • If API has already been enabled, please don't turn off.

Sample script:

function myFunction() {
  var baseUrl = "https://www.googleapis.com/drive/v3/files";
  var q = 'visibility = "anyoneWithLink" or visibility = "anyoneCanFind"';
  var fields = "files(id,name,owners,permissions),nextPageToken";
  var pageToken = "";
  var results = [];
  var params = {headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}};
  do {
    var endpoint = baseUrl + "?pageSize=1000&q=" + encodeURIComponent(q) + "&fields=" +  encodeURIComponent(fields) + "&pageToken=" + pageToken;
    var res = UrlFetchApp.fetch(endpoint, params);
    res = JSON.parse(res.getContentText());
    Array.prototype.push.apply(results, res.files);
    pageToken = res.nextPageToken || "";
  } while (pageToken);
  results.forEach(function(e) {
    Logger.log(e.name);
    Logger.log('Owner: ' + e.owners.map(function(f) {return f.displayName}).join(","));
    Logger.log("SharingAccess: " + e.permissions.map(function(f) {return f.id}).join(","));
  });
}

Note:

  • In this sample script, the log is the same with your script.

References:

If this was not the result you want, I apologize.