尝试通过API在Google云端硬盘上创建文件夹时权限不足(v3)

时间:2018-03-10 01:00:17

标签: node.js google-api

我正在尝试通过API在Google云端硬盘上创建一个文件夹。我正在使用Node,并创建了一个脚本来获取每日报告,并希望通过API创建一个文件夹并每天将这些文件上传到它。

要进行设置,我已根据文档quick start guide创建了一个项目。我的设置看起来基本上与样板文件相同,减去了读取Drive中文件的功能。但是,在尝试上传using the example given in the docs时,我收到错误:Insufficient Permission

通过项目界面中的权限,有许多角色可供选择。目前我已将我的项目指定为文件夹管理员(以及其他几个角色),应该给我权限但我仍然面临此错误。也许我需要重新生成我的client_secret.json文件以反映我更新的权限,但我该怎么做?我一直在谷歌上搜索和浏览界面很长一段时间,但看不到再生这个文件的方法。

我用来创建文件夹的代码看起来像这样,非常接近文档中给出的样板 - 只是为了看它的工作原理:

const drive = google.drive('v3')    
function createFolder (auth) {
      console.log('auth:', auth)
      const fileMetadata = {
        'name': 'daily-report',
        'mimeType': 'application/vnd.google-apps.folder',
        'parents': ['1P924MEzU_1VoL6OOvWPHSo6vb1u9u0a9'],
      }

      drive.files.create({
        auth: auth,
        resource: fileMetadata,
        fields: 'id'
      }, function (err, file) {
        if (err) {
          // Handle error
          console.error(err.message);
        } else {
          console.log('Folder Id: ', file.id);
        }
      });
    }

感谢任何帮助。

更新错误:

    Token stored to /Users/sg/.credentials/
auth: OAuth2Client {
  transporter: DefaultTransporter {},
  _certificateCache: null,
  _certificateExpiry: null,
  _clientId: 'clientID093420402349.apps.googleusercontent.com',
  _clientSecret: 'totalsecret',
  _redirectUri: 'urn:ietf:wg:oauth:2.0:oob',
  _opts: {},
  credentials: 
   { access_token: 'xxxxxxxxxxxx',
     refresh_token: 'xxxxxxxxxxxx',
     token_type: 'Bearer',
     expiry_date: 1520651774212 } }
(node:76284) [DEP0013] DeprecationWarning: Calling an asynchronous function without callback is deprecated.
fs.js:106
        throw backtrace;
        ^

Error: EISDIR: illegal operation on a directory, open '/Users/sg/.credentials/'
    at rethrow (fs.js:101:21)
    at maybeCallback (fs.js:119:42)
    at Object.fs.writeFile (fs.js:1260:14)
    at storeToken (/Users/sg/R2-DS/src/middleware/aptlist-report-auth.js:104:6)
    at /Users/sg/R2-DS/src/middleware/aptlist-report-auth.js:85:7
    at /Users/sg/R2-DS/node_modules/google-auth-library/lib/auth/oauth2client.js:95:13
    at Request._callback (/Users/sg/R2-DS/node_modules/google-auth-library/lib/transporters.js:113:17)
    at Request.self.callback (/Users/sg/R2-DS/node_modules/request/request.js:186:22)
    at emitTwo (events.js:126:13)
    at Request.emit (events.js:214:7)

1 个答案:

答案 0 :(得分:3)

我认为你的脚本有效。那么你能再次确认以下几点吗?

  1. 关于范围。
    • 在Quickstart中,默认范围为var SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly'];。但是,为了使用drive.files.create,需要将https://www.googleapis.com/auth/drive添加到范围中。
    • 如果您修改了范围,请删除drive-nodejs-quickstart.json的文件。并运行脚本。这样,就会运行授权,并将添加的范围反映到刷新令牌和访问令牌。
  2. 关于googleapis的版本
    • 最近,据报道,对于v27.0.0,v26.0.1和v25.0.0的googleapis存在一些漏洞。所以请确认您的版本以防万一。我使用的是v24.0.0。
  3. 是否在API控制台上启用了Drive API。
    • 关于这一点,我认为您可能已经启用了它。
  4. 如果这些对你没用,我很抱歉。

    编辑:

    var fs = require('fs');
    var readline = require('readline');
    var google = require('googleapis');
    var googleAuth = require('google-auth-library');
    
    // If modifying these scopes, delete your previously saved credentials
    // at ~/.credentials/drive-nodejs-quickstart.json
    var SCOPES = ['https://www.googleapis.com/auth/drive'];
    var TOKEN_DIR = './';
    var TOKEN_PATH = 'drive-nodejs-quickstart.json';
    
    // Load client secrets from a local file.
    fs.readFile('client_secret.json', function processClientSecrets(err, content) {
      if (err) {
        console.log('Error loading client secret file: ' + err);
        return;
      }
      // Authorize a client with the loaded credentials, then call the
      // Drive API.
      authorize(JSON.parse(content), createFolder);
    });
    
    /**
     * Create an OAuth2 client with the given credentials, and then execute the
     * given callback function.
     *
     * @param {Object} credentials The authorization client credentials.
     * @param {function} callback The callback to call with the authorized client.
     */
    function authorize(credentials, callback) {
      var clientSecret = credentials.installed.client_secret;
      var clientId = credentials.installed.client_id;
      var redirectUrl = credentials.installed.redirect_uris[0];
      var auth = new googleAuth();
      var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
    
      // Check if we have previously stored a token.
      fs.readFile(TOKEN_PATH, function(err, token) {
        if (err) {
          getNewToken(oauth2Client, callback);
        } else {
          oauth2Client.credentials = JSON.parse(token);
          callback(oauth2Client);
        }
      });
    }
    
    /**
     * Get and store new token after prompting for user authorization, and then
     * execute the given callback with the authorized OAuth2 client.
     *
     * @param {google.auth.OAuth2} oauth2Client The OAuth2 client to get token for.
     * @param {getEventsCallback} callback The callback to call with the authorized
     *     client.
     */
    function getNewToken(oauth2Client, callback) {
      var authUrl = oauth2Client.generateAuthUrl({
        access_type: 'offline',
        scope: SCOPES
      });
      console.log('Authorize this app by visiting this url: ', authUrl);
      var rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
      });
      rl.question('Enter the code from that page here: ', function(code) {
        rl.close();
        oauth2Client.getToken(code, function(err, token) {
          if (err) {
            console.log('Error while trying to retrieve access token', err);
            return;
          }
          oauth2Client.credentials = token;
          storeToken(token);
          callback(oauth2Client);
        });
      });
    }
    
    /**
     * Store token to disk be used in later program executions.
     *
     * @param {Object} token The token to store to disk.
     */
    function storeToken(token) {
      fs.writeFile(TOKEN_PATH, JSON.stringify(token));
      console.log('Token stored to ' + TOKEN_PATH);
    }
    
    /**
     * Lists the names and IDs of up to 10 files.
     *
     * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
     */
    function createFolder(auth) {
          const drive = google.drive('v3');
          console.log('auth:', auth);
          const fileMetadata = {
            'name': 'daily-report',
            'mimeType': 'application/vnd.google-apps.folder',
            'parents': ['1P924MEzU_1VoL6OOvWPHSo6vb1u9u0a9'],
          };
    
          drive.files.create({
            auth: auth,
            resource: fileMetadata,
            fields: 'id',
          }, function(err, file) {
            if (err) {
              // Handle error
              console.error(err.message);
            } else {
              console.log('Folder Id: ', file.id);
            }
          });
        }