Google Apps Script API Authorizations สำหรับ DriveApp.getFileById

Oct 07 2020

ฉันมีโครงการ Google Cloud Platform (GCP) ที่เรียกใช้สคริปต์ / ฟังก์ชันเกือบทั้งหมดโดยตรง แต่มีสองสามรายการผ่าน API ทุกอย่างสามารถเข้าถึงได้ภายในโดเมน G Suite เท่านั้นและประเภทแอปพลิเคชันในหน้าจอคำยินยอม OAuth คือ "ภายใน"

ฉันมีสคริปต์ซึ่งไม่ได้เรียกผ่าน API แต่จะจับเวลาโดยตรงทุกๆ x นาที มันดำเนินการ

DriveApp.getFileByID(pictureID)

ใช้งานได้ดีมาก! ไม่มีปัญหา.

ฉันยังมีสคริปต์ที่แตกต่างกันในโครงการ GCP เดียวกันซึ่งแทนที่จะเรียกใช้โดยตัวจับเวลาจะทำงานโดยการเรียกผ่าน API นี่คือบรรทัดของรหัสที่เรียกมัน (ไม่สำคัญจริงๆ):

var result = UrlFetchApp.fetch(url, options);

สคริปต์ API ทำงานได้ดีมาก! จนกว่าจะถึงบรรทัดต่อไปนี้:

      try { var file = DriveApp.getFileById(pictureID); }
      catch (e) {
        Logger.log('e = ' + JSON.stringify(e));
        return;
      }

ผลลัพธ์ของบันทึกคือ

e = {"name":"Exception"}

ฉันตรวจสอบแล้วว่า pictureID นั้นเหมือนกับในสคริปต์ที่ไม่ใช่ API ที่ใช้งานได้ ฉันกำลังทำการ "ลอง" ในสคริปต์ที่เรียกใช้ API นี้เพื่อให้แน่ใจว่าซอฟต์แวร์สามารถเข้าถึงไฟล์ได้ไม่ใช่เพื่อเข้าถึงจริง

ฉันค่อนข้างมั่นใจว่านี่เป็นปัญหาการให้สิทธิ์ ฉันใช้ GCP มาระยะหนึ่งแล้วมีประสบการณ์เกี่ยวกับการให้สิทธิ์บ้าง แต่ก็ไม่มากนัก

นี่คือรายละเอียดบางส่วนเกี่ยวกับการอนุญาต ...

สคริปต์ของโปรเจ็กต์ Project Properties (File / Project Properties) แสดงว่าต้องการขอบเขต OAuth ต่อไปนี้:

ตามเอกสารของ Google ที่ https://developers.google.com/apps-script/reference/drive/drive-app#getfilebyidid,

Scripts that use this method require authorization with one or more of the following scopes: 

https://www.googleapis.com/auth/drive.readonly
https://www.googleapis.com/auth/drive

ขอบเขตที่ฉันได้กำหนดไว้ในหน้าจอคำยินยอม GCP Oauth มีดังนี้

อย่างที่คุณเห็นฉันได้เพิ่ม drive, drive.readonly และ drive.file (ซึ่งดูเหมือนจะไม่จำเป็นจริงๆ)

เหนือสิ่งอื่นใดไฟล์รูปภาพนี้จะถูกเก็บไว้ใน Google ไดรฟ์ของเจ้าของโครงการ GCP สคริปต์และผู้ดูแลระบบระดับบนสุดของโดเมน G Suite ซึ่งจะไม่เป็นเช่นนั้นเสมอไปเนื่องจากผู้ใช้จะแชร์รูปภาพจาก Google ไดรฟ์ของตนเองไปยังเจ้าของซอฟต์แวร์ / GCP อย่างไรก็ตามฉันมีความรู้สึกว่าแม้ตอนนี้สคริปต์ที่เรียกใช้โดยตัวจับเวลาจะทำงานกับไฟล์ที่ผู้ใช้แชร์เหล่านั้น แต่ไม่ใช่สคริปต์ที่เรียกผ่าน API

ฉันค่อนข้างมั่นใจว่านี่เป็นปัญหาเกี่ยวกับการตรวจสอบสิทธิ์ แต่ฉันพลาดบางอย่าง

ขอขอบคุณสำหรับความช่วยเหลือของคุณ!

อัปเดต:

นี่คือรหัสจากสคริปต์ที่เรียกสคริปต์ API (เปลี่ยนบางส่วนเพื่อการรักษาความลับ) เนื่องจากฉันสงสัยว่าบางทีปัญหาอาจไม่ได้อยู่ที่ฝั่งไคลเอ็นต์ / การโทร บางทีฉันอาจไม่ได้รับ OAuthToken อย่างถูกต้อง? หรือโทเค็นไม่มีสิทธิ์ที่ถูกต้อง?

  var token = ScriptApp.getOAuthToken();
  
  var header = {
    "Content-Type": "application/json",
    "Authorization": "Bearer " + token,
  };
  
  var parms = [id];
  
  var data = {
    "function": "updateSettings",
    "parameters": parms,
    "devMode": true,
  }
  
  var options = {
    "method":"POST",
    "headers": header,
    "muteHttpExceptions": true,
    "payload": JSON.stringify(data)
  };
  
  // Call the API
  var result = UrlFetchApp.fetch(url, options);

คำตอบ

Chris Oct 07 2020 at 22:27

ฉันคิดออกหลังจากติดต่อ Google แล้ว แต่น่าเสียดายที่ไม่ได้รับความช่วยเหลือมากนักและอีกไม่กี่ชั่วโมงในการลองค้นคว้า ...

สิ่งที่ฉันขาดหายไปคือการเพิ่ม "oathScopes" ลงในไฟล์ manifest / appsscript.json ฉันเล่นกับขอบเขตที่จำเป็นและลงเอยด้วยสองสิ่งต่อไปนี้ที่แสดงด้านล่าง ฉันคิดว่าการแก้ปัญหาโดยดูที่คำตอบนี้: การใช้ AuthToken ได้รับผ่านทาง ScriptApp.getAuthToken () เพื่อเรียกเว็บแอปใน GAS

ภายในโปรแกรมแก้ไขสคริปต์ไปที่ View / Show manifest file

นี่คือสิ่งที่ดูเหมือนก่อนหน้านี้:

{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "webapp": {
    "access": "MYSELF",
    "executeAs": "USER_DEPLOYING"
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

และนี่คือสิ่งที่ดูเหมือนตอนนี้ ...

{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "webapp": {
    "access": "MYSELF",
    "executeAs": "USER_DEPLOYING"
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/drive",
    "https://www.googleapis.com/auth/script.external_request"
    ]
}

หลังจากเพิ่มแล้วฉันบันทึก appsscript.json จากนั้นฉันไปที่ทริกเกอร์ runOnEdit ของฉัน (สคริปต์การโทร) ลบออกและเพิ่มเข้าไปใหม่ อย่างไรก็ตามนั่นทำให้เกิดข้อผิดพลาดในการมองที่น่ารังเกียจ:

ผมมองขึ้นไปที่และพบบทความนี้: รับข้อผิดพลาดเมื่อมีการสร้างทริกเกอร์ใหม่ในสคริปต์ของแอป ดังนั้นฉันจึงรันโค้ดในโปรแกรมแก้ไขสคริปต์และมันก็แสดงหน้าจอรับรองความถูกต้อง ฉันอนุมัติเพิ่มทริกเกอร์อีกครั้งและตอนนี้ทุกอย่างทำงานได้ดีในการเรียก API!