DocumentApp导致从Javascript客户端执行的App脚本到401

时间:2016-11-28 18:45:30

标签: javascript google-apps-script

目前正在尝试从Javascript客户端执行GAS。 GAS脚本如下:

function findAndReplace() {
    var doc = DocumentApp.openById('ID_OMITTED');
}

这可以通过在GAS编辑器中按Play来执行,但是当我尝试从我的Javascript客户端执行时,我单击授权。

Authorisation

然后我收到401。

Error calling API: {
    "error": {
        "code": 401,
        "message": "ScriptError",
        "status": "UNAUTHENTICATED",
        "details": [{
            "@type": "type.googleapis.com/google.apps.script.v1.ExecutionError",
            "errorMessage": "Authorization is required to perform that action.",
            "errorType": "ScriptError"
        }]
    }
}

现在,当我在GAS编辑器中按Play时,出现Action not allowed错误。然后,我可以通过复制它来创建一个新脚本,按Play,它工作正常。从Javascript执行导致整个401,然后整个循环重复。

但是,如果我执行一个简单的:

function test() {
    return 'hello';
}

可行,并返回

Folders under your root folder:
    h (0)
    e (1)
    l (2)
    l (3)
    o (4)

(输出看起来像这样,因为程序需要一个数组,如下所示)。

这是Javascript客户端,基本上是Javascript快速入门的复制和粘贴。

var CLIENT_ID = 'CLIENT_ID_OMITTED';
var SCOPES = ['https://www.googleapis.com/auth/drive'];

function checkAuth() {
    gapi.auth.authorize(
        {
            'client_id': CLIENT_ID,
            'scope': SCOPES.join(' '),
            'immediate': true
        }, handleAuthResult
    );
}

function handleAuthResult(authResult) {
    var authorizeDiv = document.getElementById('authorize-div');
    if (authResult && !authResult.error) {
        authorizeDiv.style.display = 'none';
        callScriptFunction();
    } else {
        authorizeDiv.style.display = 'inline';
    }
}

function handleAuthClick(event) {
    gapi.auth.authorize(
        {client_id: CLIENT_ID, scope: SCOPES, immediate: false},
        handleAuthResult
    );
    return false;
}

function callScriptFunction() {
    var scriptId = "SCRIPT_ID_OMITTED";

    var request = {
        'function': 'findAndReplace'
    };

    var op = gapi.client.request({
        'root': 'https://script.googleapis.com',
        'path': 'v1/scripts/' + scriptId + ':run',
        'method': 'POST',
        'body': request
    });

    op.execute(function(resp) {
        if (resp.error && resp.error.status) {
            appendPre('Error calling API:');
            appendPre(JSON.stringify(resp, null, 2));
        } else if (resp.error) {
            var error = resp.error.details[0];
            appendPre('Script error message: ' + error.errorMessage);

            if (error.scriptStackTraceElements) {
                appendPre('Script error stacktrace:');
                for (var i = 0; i < error.scriptStackTraceElements.length; i++)         {
                    var trace = error.scriptStackTraceElements[i];
                    appendPre('\t' + trace.function + ':' + trace.lineNumber);
                }
            }
        } else {
            var folderSet = resp.response.result;
            if (Object.keys(folderSet).length === 0) {
                appendPre('No folders returned!');
            } else {
                appendPre('Folders under your root folder:');
                Object.keys(folderSet).forEach(function(id){
                    appendPre('\t' + folderSet[id] + ' (' + id  + ')');
                });
            }
        }
    });
}

function appendPre(message) {
    var pre = document.getElementById('output');
    var textContent = document.createTextNode(message + '\n');
    pre.appendChild(textContent);
}    

我确保通过复制DocumentApp来创建权限。在运行副本时,它会给我这个提示:

Permission request

我明显接受。

我每次都在脚本上创建一个新项目,启用Scripts API

Enabling API

然后创建OAuth2客户端

Creating client id

将客户端ID复制到脚本中。我还在脚本上Deploy as API Executable,并获取脚本ID。

我错过了什么?为什么代码产生401?那么为什么GAS脚本会在编辑器中神秘地返回Action now allowed,只有在复制后才能工作?

提前致谢。

1 个答案:

答案 0 :(得分:0)

在尝试做了几个晚上之后,我在发布到SO后直接解决了......典型的!

This post solved it

基本上,转到File > Project Properties并点击Scopes标签。从这里,您可以看到项目所需的所有范围。

然后必须将其添加到客户端javascript中的scopes数组中。

所以我的范围现在看起来像这样:

var SCOPES = ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/documents'];

为什么GAS脚本然后决定返回Action not allowed我永远不会知道,它真的让我离开了。

希望这有助于其他人。