Luca Francis

GDrive Proxy mit der Google Drive API

Knowledge Base

Du möchtest Daten in Google Drive speichern, aber auch eigene Sicherheits- oder Usability Funktionen hinzufügen und eine allgemeine Verfügbarkeit gewährleisten? Dann kann es sinnvoll sein, eine eigene Softwarelösung mit der Google Drive zu verknüpfen. Zum Glück stellt Google mit der Google Drive API und der Developer Console die notwendigen Werkzeuge dafür bereit.

In diesem Blogpost wird untersucht, wie man einen NodeJs Service bauen kann, der Dateien mithilfe eines Service Accounts in eine TeamDrive hochladen kann, sodass eine Schnittstelle für erweiterte Funktionen geschaffen ist.

Was ist eine TeamDrive

Normale Google Drives sind immer an einen Nutzer gebunden, der Dateien dann für andere Nutzer teilen kann. Eine TeamDrive, oder auch Shared Drive genannt, zeichnet sich dadurch aus, dass sie nicht an einen Nutzer, sondern an eine Organisation gebunden ist. Dadurch kann sie auf einem Firmenlevel verwaltet werden und z.B. mithilfe der GSuite Zugriffsberechtigungen zugewiesen bekommen.

Was ist ein ServiceAccount

Ein ServiceAccount, zu Deutsch Dienstkonto, ist ein Google Nutzerkonto, hinter dem keine echte Person steht. Von der Google Drive Oberfläche wird ein ServiceAccount wie ein normaler Nutzer behandelt, der entsprechend seiner Berechtigungen in der Google Drive Umgebung Handlungen durchführen darf.
Im Hintergrund steht dabei aber eine Schnittstelle zur Google Drive API, welche wir mit unserem Programm ansprechen, um den ServiceAccount für uns z.B. Dateien hochladen zu lassen.

Schnittstelle

Bevor wir mit dem Bauen unserer Anwendung beginnen können, muss die Schnittstelle zur Google Drive vorbereitet werden. In der Developer Console erstellen wir zuerst ein neues Projekt, und aktivieren die Drive API. Über IAM & Verwaltung kann nun ein Service Account angelegt und dessen Anmeldedaten als JSON heruntergeladen werden.

In der heruntergeladenen JSON Datei findet sich die client_email, welcher die zu bearbeitende TeamDrive mit Bearbeitungsrechten geteilt wird.

Nun muss die JSON Datei noch in den Projektordner der Anwendung kopiert werden und schon sind wir bereit mit dem ServiceAccount Handlungen vorzubereiten.

Die hier erstellt Anwendung wird zwei Funktionen besitzten: 1. Datei hochladen 2. Ordner auflisten

Um uns die Arbeit mit der Google Drive API zu erleichtern, nutzen wir die googleapis package, sowie streamifier um die Dateien nicht lokal ablegen zu müssen.

const {google} = require('googleapis');
let streamifier = require('streamifier');
let credentials = require("../../credentials.json");
let fs = require('fs');

Für beide Funktionen ist es notwendig, das wir uns als der ServiceAccount authentifizieren. Dies geschiet entweder über eine OAuth2 oder eine JWT Authentifizierung:

// configure a JWT auth client
let jwtClient = new google.auth.JWT(
    credentials.client_email,
    credentials,
    credentials.private_key,
    ['https://www.googleapis.com/auth/drive']);
//authenticate request
jwtClient.authorize(function (err, tokens) {
    if (err) {
        console.log(err);
        return;
    } else {
        console.log("Successfully connected to GDrive!");
    }
});

Der Ausdruck

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

legt hierbei das Scope, also die Zugriffsrechte für die wir uns Authentifizieren wollen, fest. Die verschiedenen Möglichkeiten lassen sich hier nachlesen.

Mit der vorbereiteten Authentifizierung können wir uns nun bei Google Drive anmelden und z.B. die erste TeamDrive auswählen

let drive = google.drive({version: 'v3', auth: jwtClient});
let sharedDrive;
drive.drives.list().then(data => {
    sharedDrive = data.data.drives[0];
});

Ordner auflisten

exports.list = function () {
   return drive.files.list({
        "supportsAllDrives": true,
        "includeItemsFromAllDrives": true,
        "auth": jwtClient,
        "driveId": sharedDrive.id,
        "corpora": "drive",
        "q": "mimeType = 'application/vnd.google-apps.folder'"
    }).then((response)=>{
        // handle response
    });
  }

Datei hochladen

Nachdem der Nutzer über ein Frontend eine Datei und einen durch list() ausgewählten Zielordner zurückgibt, kann diese Datei in die Google Drive hochgeladen werden

exports.upload = function (file,Folder) {
    const date = new Date();
    let fileMetadata = {
        'name': date.getTime() + '_' + file.originalname,
        'teamDriveId': sharedDrive.id,
        "driveId": sharedDrive.id,
        "parents": [
            Folder
        ]
    };
    let media = {
        'body': streamifier.createReadStream(file.buffer)
    };
    drive.files.create({
        'requestBody': fileMetadata,
        'media': media,
        "supportsAllDrives": true,
        "includeItemsFromAllDrives": true,
        "auth": jwtClient,
        "driveId": sharedDrive.id,
        "corpora": "drive",
    }, function (err, file) {
        if (err) {
            // Handle error
            console.error(err);
        } else {
            console.log('\nCreated File ' +file.data.name+' with GDrive_Id: ' + file.data.id);
        }
    });
};

Um den Befehl drive.files.create() ausführen zu können, müssen zwei Attribute gesetzt werden: 1. Die Datei selbst als ReadableStream 2. Die Metadaten der Datei, mit Name und Speicherort

Außerdem müssen weiter Attribute gesetzt werden, um das Hochladen in eine TeamDrive zu ermöglichen

Folder entspricht der Order Id, die durch list() geholt und vom Nutzer als Zielortner ausgewählt wurde.

Mit dieser Grundlage können nun Dateien hochgeladen werden. Und es wurde mit diesem Service eine Schnittstelle zur Google Drive geschaffen, auf die weitere Anwendungen aufbauen können.

15 Jul 2019 #Google Drive #Service Account #GDrive #NodeJs