使用Google Drive REST API的Web应用程序如何与使用同一应用程序的另一个用户共享文件? [英] How can a webapp using the Google Drive REST API share files with another user using the same app?

查看:85
本文介绍了使用Google Drive REST API的Web应用程序如何与使用同一应用程序的另一个用户共享文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的webapp是一个3D虚拟游戏桌面,没有后端服务器...而是使用Google云端硬盘存储用户数据和图像.我有一个特定的问题,但是如果问题上方有解决方案,我将更全面地描述我的情况.

My webapp is a 3D virtual gaming tabletop with no back-end server... instead, it uses Google Drive to store user data and images. I have a specific question, but I'll describe my situation more fully in case there's a solution somewhere above the level of my question.

使用案例

  1. 用户A,即游戏大师(GM),使用该应用上传了一张地图的图像以及一些怪物的图像.该应用程序将图像上传到它在用户A的Google云端硬盘中创建的文件夹结构中,并通过链接将其标记为可读.
  2. 用户A进行配置后,该应用将显示一个虚拟桌面,即一个3D空间,其中包含地图,上面有一些怪物.描述桌面的JSON数据也存储在Google云端硬盘中,并且该应用将其标记为可通过链接读取.
  3. 用户A与播放器用户B共享一个URL.链接指向我的应用程序,但是在用户A的驱动器中描述了桌面的JSON文件中包含了JSON文件的Google云端硬盘文件ID.
  4. 用户B访问该链接.该应用程序将加载,使用ID从用户A的驱动器读取JSON文件,然后呈现桌面,并根据需要从用户A的驱动器加载图像.

问题

Google云端硬盘的drive.files oAuth范围足以完成用例的第1-3步-该应用程序能够为用户A创建和读取Google云端硬盘文件.

Google Drive's drive.files oAuth scope is sufficient to do steps 1-3 of the use case - the app is able to create and read Google Drive files for User A.

但是,仅使用drive.files范围,似乎无法执行步骤4.

However, with just drive.files scope it does not appear to be possible to do step 4.

  • 用户B已授予应用drive.files对其云端硬盘的访问权限.
  • 文件是由应用创建的(在第1-2步中)
  • 用户B具有对文件的读取访问权限(在第1-2步中已授予)
  • Google云端硬盘不允许应用访问文件,因为用户B未授予应用访问文件的权限.
  • User B has granted the app drive.files access to their Drive.
  • The files were created by the app (in steps 1-2)
  • User B has read access to the files (granted in steps 1-2)
  • Google Drive does not allow the app to access the files, because User B has not granted the app permission to access the files.

drive.files的文档将其描述为对由应用程序创建或打开的文件的按文件访问.文件授权是按用户授予的,而在用户取消对应用程序的授权时将被撤消."但是,这似乎并不完全正确,因为云端硬盘"似乎没有记录应用是否创建了文件.似乎相反,当应用程序创建文件时,这些用户的隐式权限被授予当前用户对这些文件的访问权限,然后该文件是由应用程序创建的事实被忘记了.

The documentation for drive.files describes it as "Per-file access to files created or opened by the app. File authorization is granted on a per-user basis and is revoked when the user deauthorizes the app." However, this does not appear to be strictly true, because Drive does not appear to record whether a file is created by the app. It seems that instead, when the app creates files, access is implicitly granted to the app for the current user for those files, and then the fact that the file was created by the app is forgotten.

当前的解决方法是应用程序还需要drive.readonly oAuth范围.这是不合理的访问级别,据我所知,许多用户(相当合理地)决定不愿意授予我的应用对其整个云端硬盘的只读访问权限.这也是一个受限"的oAuth范围,但是我已经通过Google进行了应用验证过程.

The current workaround is for the app to also require drive.readonly oAuth scope. This is an unreasonable level of access, and I know of numerous users who have (quite reasonably) decided they're not willing to grant my app read-only access to their entire Drive. It is also a "restricted" oAuth scope, but I've gone through the app verification process with Google.

问题

是否可以让我的应用授予用户B对文件的读取访问权限,而无需使用受限级别的oAuth范围,不需要用户B进行过多工作,而仅保留客户端功能?如果可以,怎么办?

Is it possible to make my app grant User B read access to the files without using restricted-level oAuth scopes, without requiring too much work from User B, and while remaining purely client-side? If so, how?

问题解决方案

使用drive.readonly oAuth范围有效,但是如上所述,这是不合理的.

Using drive.readonly oAuth scope works, but is unreasonable, as discussed above.

我相信可以为我的应用程序创建云端硬盘集成,这将允许用户右键单击文件并打开"我的应用程序,这将授予应用程序对该文件的访问权限.但是,

I believe that it's possible to create Drive integrations for my app which would allow a user to right-click a file and "Open with" my app, which would grant the app access to the file. However,

  • 涉及许多文件-描述桌面的JSON文件,桌面上每个地图和生物的单个图像以及其他文件.此外,可以在游戏中期将新图像放置在桌面上.
  • 用户B是播放器,没有(也不应该)具有在Drive GUI中浏览GM的文件的权限,以便右键单击它们并打开"应用程序.他们应该看不到尚未添加到桌面的怪物或地图.为此,该应用通过链接授予对文件的读取访问权限,但不授予包含这些文件的目录的读取访问权限.

可能会有一个自定义服务器来提供来自Drive的内容,但是我试图将应用程序纯粹保留在客户端.

It would be possible to have a custom server which serves up the content from Drive, but I'm trying to keep the app purely client-side.

技术

如果相关,该应用程序是用Javascript(实际上是Typescript)编写的,并且Drive API的调用是通过Javascript Google Drive REST API完成的.

In case it's relevant, the app is written in Javascript (actually, Typescript), and Drive API calls are done via the Javascript Google Drive REST API.

推荐答案

我发现了一种解决方法,可以处理用例的所有四个步骤.解决方法仅适用,因为我要共享的文件可由具有链接的任何人读取"-如果仅与某些人共享文件,则不起作用.

I have found a workaround which allows all four steps of my use-case to be handled. The workaround only works because the files I want to share are "readable by anyone with the link" - it would not work if the files were shared only with certain people.

我在未验证的iframe中创建了第二个GAPI客户端(甚至没有使用oAuth客户端ID或范围进行配置).主要的GAPI客户端与以前一样用于登录用户(具有drive.file oAuth范围).

I create a second GAPI clients in an iframe, which is left unauthenticated (it isn't even configured with the oAuth client ID or the scope). The main GAPI client is used as before to log in the user (with drive.file oAuth scope).

function addGapiScript() {
    return new Promise((resolve, reject) => {
        const iframe = document.createElement('iframe');
        iframe.onload = () => {
            if (!iframe || !iframe.contentDocument || !iframe.contentWindow) {
                reject(new Error('Failed to add iframe'));
                return;
            }
            const script = iframe.contentDocument.createElement('script');
            script.onload = () => {
                resolve(iframe.contentWindow['gapi']);
            };
            script.onerror = reject;
            script.src = 'https://apis.google.com/js/api.js';
            iframe.contentDocument.head.appendChild(script);
        };
        iframe.onerror = reject;
        iframe.src = '/blank.html'; // A src is required because gapi refuses to init in an iframe with a location of about:blank.
        document.body.appendChild(iframe);
    });
}

// Discovery docs for the Google Drive API.
const DISCOVERY_DOCS = ['https://www.googleapis.com/discovery/v1/apis/drive/v3/rest'];
// Authorization scopes required by the API; multiple scopes can be included, separated by spaces.
const SCOPES = 'https://www.googleapis.com/auth/drive.file';

let anonymousGapi;

async function initialiseFileAPI(signInHandler, onerror) {
    // Jump through some hoops to get two gapi clients.
    // The first is "anonymous", i.e. does not log in
    anonymousGapi = window['anonymousGapi'] = await addGapiScript();
    anonymousGapi.load('client', {
        callback: async () => {
            await anonymousGapi.client.init({
                apiKey: API_KEY,
                discoveryDocs: DISCOVERY_DOCS
            });
        },
        onerror
    });
    // The second is the normal gapi that we log in.
    gapi.load('client:auth2', {
        callback: async () => {
            await gapi.client.init({
                apiKey: API_KEY,
                discoveryDocs: DISCOVERY_DOCS,
                clientId: CLIENT_ID,
                scope: SCOPES
            });
            // Listen for sign-in state changes.
            gapi.auth2.getAuthInstance().isSignedIn.listen(signInHandler);
            // Handle initial sign-in state.
            signInHandler(gapi.auth2.getAuthInstance().isSignedIn.get());
        },
        onerror
    });
}

如果经过身份验证的客户端无法读取文件,则代码将退回到未经身份验证的客户端,该客户端可以匿名读取文件.

If the authenticated client fails to read a file, the code falls back on the unauthenticated client, which is able to read the file anonymously.

async function driveFilesGet(params) {
    // Do a regular drive.files.get, but fall back to anonymous if it throws a 404 error
    try {
        return await gapi.client.drive.files.get(params);
    } catch (err) {
        if (err.status === 404) {
            // Attempt to get the file data anonymously
            return await anonymousGapi.client.drive.files.get(params);
        }
        throw err;
    }
}

不幸的是,尽管请求中存在应用程序的API_KEY,但响应匿名请求的云端硬盘文件元数据似乎将不包含该应用程序的任何appProperties数据.元数据可以包含properties.

Unfortunately, it appears that the Drive file metadata in response to an anonymous request will not contain any appProperties data for the app, despite the app's API_KEY being present in the request. The metadata can contain properties however.

这篇关于使用Google Drive REST API的Web应用程序如何与使用同一应用程序的另一个用户共享文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆