Как веб-приложение, использующее Google Drive REST API, может обмениваться файлами с другим пользователем, использующим то же приложение? - PullRequest
0 голосов
/ 16 марта 2020

Мое веб-приложение представляет собой настольную виртуальную трехмерную игру без внутреннего сервера ... вместо этого оно использует Google Drive для хранения пользовательских данных и изображений. У меня есть конкретный c вопрос, но я опишу свою ситуацию более подробно, если есть решение где-то выше уровня моего вопроса.

Вариант использования

  1. Пользователь A, Game Master (GM), использует приложение для загрузки изображения карты и некоторых изображений некоторых монстров. Приложение загружает изображения в структуру папок, созданную на Google Диске пользователя А., и приложение помечает их как доступные для чтения по ссылке.
  2. После настройки пользователем приложения А приложение отображает виртуальную настольную поверхность в трехмерном пространстве. содержащий карту с несколькими монстрами на нем. JSON данные, описывающие столешницу, также хранятся в Google Диске, и приложение помечает их как читаемые по ссылке.
  3. Пользователь A делит URL-адрес с пользователем B, игроком. Ссылка на мое приложение, но содержит идентификатор файла Google Drive для файла JSON на диске пользователя А., описывающего настольную поверхность.
  4. Пользователь Б обращается к ссылке. Приложение загружается, использует идентификатор для чтения файла JSON с диска пользователя А, а затем визуализирует настольную панель, загружая изображения с диска пользователя А. по мере необходимости.

Проблема

Область Google Drive drive.files oAuth достаточна для выполнения шагов 1-3 варианта использования - приложение может создавать и читать файлы Google Диска для пользователя A.

Однако при использовании только области действия drive.files выполнение шага 4 не представляется возможным.

  • Пользователь B предоставил приложению drive.files доступ к своему диску.
  • файлы были созданы приложением (в шагах 1-2)
  • Пользователь B имеет доступ на чтение к файлам (предоставляется в шагах 1-2)
  • Google Диск не разрешает приложению доступ файлы, потому что пользователь B не предоставил приложению разрешение на доступ к файлам.

Документация для drive.files описывает его как "доступ к файлам для файлов, созданных или открытых приложением. Файл авторизация предоставляется для каждого пользователя и отменяется, когда пользователь деавторизует приложение. " Тем не менее, это не является строго правдой, потому что Drive, кажется, не записывает, был ли файл создан приложением. Кажется, что вместо этого, когда приложение создает файлы, доступ к приложению неявным образом предоставляется текущему пользователю для этих файлов, а затем тот факт, что файл был создан приложением, забывается.

Текущий обходной путь для приложения также требуется drive.readonly oAuth объем. Это необоснованный уровень доступа, и я знаю многих пользователей, которые (вполне разумно) решили, что не хотят предоставлять моему приложению доступ только для чтения ко всему диску. Это также «ограниченная» область действия oAuth, но я прошел процесс проверки приложения в Google.

Вопрос

Возможно ли сделать мое приложение предоставить пользователю B доступ на чтение к файлам, не используя oAuth-области ограниченного уровня, не требуя слишком много работы от пользователя B и оставаясь при этом чисто клиентской стороной? Если да, то как?

Проблема c Решения

Использование drive.readonly oAuth scope работает, но нецелесообразно, как обсуждалось выше.

Я считаю, что для моего приложения можно создать интеграцию Drive, которая позволила бы пользователю щелкнуть правой кнопкой мыши файл и «Открыть с помощью» моего приложения, что предоставило бы приложению доступ к файлу. Тем не менее,

  • Имеется множество файлов - файл JSON, описывающий столешницу, отдельные изображения для каждой карты и существа на столешнице, а также другие файлы. Кроме того, новые изображения могут быть добавлены в настольную игру.
  • Пользователь B является игроком и не имеет (и не должен иметь) разрешения просматривать файлы GM на диске GUI, чтобы щелкнуть их правой кнопкой мыши и «Открыть с помощью» приложения. Они не должны видеть монстров или карты, которые еще не были добавлены к столу. Для этого приложение предоставляет доступ для чтения по ссылке для файлов, но не для каталогов, содержащих эти файлы.

Было бы возможно иметь собственный сервер, который обслуживает содержимое с диска, но я пытаюсь сохранить приложение чисто на стороне клиента.

Технология

В случае необходимости, приложение написано в Javascript Typescript) и вызовы Drive API выполняются с помощью Javascript Google Drive REST API.

Ответы [ 2 ]

0 голосов
/ 15 апреля 2020

Я нашел обходной путь, который позволяет обрабатывать все четыре шага моего варианта использования. Обходной путь работает только потому, что файлы, которыми я хочу поделиться, «доступны для чтения любому, у кого есть ссылка» - он не будет работать, если файлы будут доступны только определенным людям.

Я создаю второго клиента GAPI в iframe , который остается не прошедшим проверку подлинности (он даже не настроен с идентификатором клиента oAuth или областью действия). Основной GAPI-клиент, как и прежде, используется для входа в систему пользователя (с областью drive.file oAuth).

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
    });
}

Если аутентифицированному клиенту не удается прочитать файл, код возвращается к неаутентифицированному клиенту, который может читать файл анонимно.

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;
    }
}

К сожалению, похоже, что метаданные файла Drive в ответ на анонимный запрос не будут содержать никаких данных appProperties для приложения, несмотря на то, что API_KEY приложения является присутствует в запросе. Однако метаданные могут содержать properties.

0 голосов
/ 16 марта 2020

Как вы можете видеть в официальной документации , drive.files позволяет вам:

Просмотр и управление файлами и папками на Google Диске, которые у вас есть открытые или созданные с помощью этого приложения

Поскольку файлы не были созданы от имени User B, приложение не имеет прав доступа к ним.

Боюсь, что там нет неограниченной области, которая предоставит это разрешение, поэтому вы должны использовать drive.readonly или полностью изменить процесс совместного использования.

Ссылка:

...