Search code examples
google-apps-scriptgoogle-formsgoogle-apps-script-api

Trying to set permissions for "anyone with link can view" on file uploaded via form "file upload" section


A "File upload" section is used in a form: I need the form user (not owner) to be able to share the file with someone other than the owner of the form.

It appears the results of the file-upload in the form puts the file into the current form user's Drive and provides a URL that the owner of the form can view. I need that URL to be sharable with others (via the script, not manual intervention).

Triggered by the form input, my script runs:

DriveApp.getFileById(id).setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.NONE);

... where id is derived from the URL provided from the form (see Easiest way to get file ID from URL on Google Apps Script ... as I know I'm getting the ID right).

As just user with a link to the form, I get no errors... nor do I see errors entering in the form as the owner.

But, the URL cannot be seen by anybody but the spreadsheet owner (not even the user who entered and owns the file can view the link)... so DriveApp.Access.ANYONE_WITH_LINK is not working. Non-owners of the form will be running this. I'm guessing setSharing is being run as the owner of the form, not the user, and therefore can't set it to be sharable? Is there a way for the script to make the file/link viewable?

But, even if the form owner runs the form, the URL can't be viewed by others. I don't think the ID changes once the file becomes sharable? So I must be calling setSharing incorrectly?

Maybe the ID in the URL provided by the form is n some "no-mans-land" where it's not the true ID of the file?

Example routine that just goes down column 4 of a spreadsheet with these URLs and makes them sharable:

`

function SetPermissions() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var maintsheet = ss.getSheetByName('Maintenance');
  var lastmr = maintsheet.getLastRow();
  for (var i = 2; i <= lastmr; i++) {
    var fileURL = maintsheet.getRange(i,4).getValue();
    Logger.log(fileURL);
    for (var j in fileURL.split(",")) {
      Logger.log(j);
      Logger.log(fileURL.split(",")[j]);
      var fileID = fileURL.split(",")[j].match(/[-\w]{25,}/)[0]
      Logger.log(fileID);
      DriveApp.getFileById(fileID).setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.NONE);
    }
  }
}

`

... run by the owner of the form/spreadsheet, no errors, and the logged data looks correct. But, give the URL to another user, and they get a permissions error.


Solution

  • This fixed it:

       function SetPermissions() {
          var ss = SpreadsheetApp.getActiveSpreadsheet();
          var maintsheet = ss.getSheetByName('Maintenance');
          var lastmr = maintsheet.getLastRow();
          for (var i = 2; i <= lastmr; i++) {
            var fileURL = maintsheet.getRange(i,4).getValue();
            Logger.log(fileURL);
            for (var j in fileURL.split(",")) {
              Logger.log(fileURL.split(",")[j]);
              var fileID = fileURL.split(",")[j].match(/[-\w]{25,}/)[0]
              Logger.log(fileID);
              var file = DriveApp.getFileById(fileID);
              file.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
              var newURL = file.getUrl();
              maintsheet.getRange(i, 4).setValue(newURL);
            }
          }
        }
    

    Doh: https://developers.google.com/apps-script/reference/drive/permission

    ... I was telling it: no permissions to anybody with the link! VIEW, is the right option!

    Here's a function that given the sort of list of URLs the form will stick in the cell (the form can be setup to allow multiple pics per cell), set the permissions, and return the list of URLs back, this time as Google formats the URL in getURL():

    function AnyoneWithLinkCanView(urls) {
      var newURLs = "";
      if ( urls.length > 0 ) {
        for each (var j in urls.split(",")) {
          var fileid = j.match(/[-\w]{25,}/)[0];
          var file = DriveApp.getFileById(fileid);
          file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
          if ( newURLs.length > 0 ) {
            newURLs += ", ";
          }
          newURLs += file.getUrl();
        }
      }
      return newURLs;
    }
    

    In my case, as the URLs will form the message body of an email, my call looks like:

    var message = AnyoneWithLinkCanView(dataSheet.getRange(lastr,i).getValue());