Help us understand the problem. What is going on with this article?

Google Drive で 全公開されているドキュメントを一覧化する

More than 1 year has passed since last update.

背景

社内で使用されている、Google Drive のドキュメントで、共有設定が「リンクを知っている全員が編集可」になっているファイルが無いか確認する必要がありました。

GSuiteの管理コンソールから「レポート」->「セキュリティ」で、外部とリンク共有中のファイルを下記方法で確認できます。
しかし、レポートの内容では「誰が」「外部リンク中のファイルを何個もっているか」しか表示されません。

Google API を利用して取得したファイルをスプレッドシートにリストする方法を記載します。
「Admin SDK」を有効にする方法はこちらを参照してください。

  • 有効にするAPI
    • Google Drive API
    • Google Sheets API

コードの仕様

  • 誰でもアクセスできるファイルをスプレッドシートにリスト保存する
    • 画像や動画は対象に含めない
    • 最終更新日から100日を超えているものは、共有範囲をドメイン内に設定する
  • 何かしらの理由で権限を取得できなかった場合は、別リストに保存する

実際のコード

list.py
# -*- coding: utf-8 -*-
from __future__ import print_function
import httplib2
import sys, os, time
from datetime import *
from apiclient import discovery
from apiclient import errors
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage

try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

CLIENT_SECRET_FILE = 'hoge.json'
CREDENTIAL_FILE = 'fuga.json'
APPLICATION_NAME = 'Drive Get Public Files'
SCOPES = 'https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/spreadsheets'
SPREADSHEET_ID = '保存するスプレッドシートのID'

"""
有効な証明書をストレージから取得
"""
def get_credentials():
    #認証情報を格納するディレクトリの作成
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)

    #OSにパスを通す
    credential_path = os.path.join(credential_dir, CREDENTIAL_FILE)

    store = Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        #認証処理を行うクラスのインスタンスを生成
        flow = client.flow_from_clientsecrets(
            os.path.join(home_dir, '.credentials', 'client_secrets', CLIENT_SECRET_FILE), SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else: # Python 2.6 互換用処理
            credentials = tools.run(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials

def main():
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    discovery_url = ('https://sheets.googleapis.com/$discovery/rest?' 'version=v4')
    drive_service = discovery.build('drive', 'v3', http=http)

    # スプレットシートサービスオブジェクトのビルド
    ss_service = discovery.build('sheets', 'v4', http=http, discoveryServiceUrl=discovery_url)

    page_token = None
    public_permissions = []
    unknown_permissions = []

    putblic_last_row = 2
    unknown_last_row = 2

    now_datetime = datetime.now()

    while True:
        response = drive_service.files().list(
                q="mimeType!='application/vnd.google-apps.folder' and mimeType!='image/jpeg' and mimeType!='video/quicktime' ",
                spaces='drive', 
                fields='nextPageToken, files(id, name, webViewLink, modifiedTime)',
                pageToken=page_token
            ).execute()

        for file in response.get('files', []):
            try:
                file_id = file.get('id', None)
                memo = '' #備考

                # ファイルの権限を取得
                permissions = drive_service.permissions().list(fileId=file_id).execute()
                permission_items = permissions.get('permissions', [])

                # ドキュメントに設定されている権限リストをループする
                for item in permission_items:
                    permission_id = item.get('id', '')
                    permission_type = item.get('type', '')
                    # 誰でもアクセスできる場合、配列に保存
                    if (permission_id == 'anyoneWithLink'):

                        # 最終更新日が3ヶ月以上前の場合は、共有設定を変更
                        last_update_str = file.get('modifiedTime', None)
                        last_update_datetime = datetime.strptime(last_update_str[:-1], '%Y-%m-%dT%H:%M:%S.%f')
                        diff_hour = (now_datetime - last_update_datetime).total_seconds() / (3600 * 24)

                        if(diff_hour > 100):
                            print('100日より前です')

                            # 誰でもアクセスできる権限を削除
                            drive_service.permissions().delete(fileId=file_id, permissionId='anyoneWithLink').execute()

                            # ドメインメンバーがアクセスできる権限を追加
                            batch = drive_service.new_batch_http_request(callback=callback)
                            batch.add(drive_service.permissions().create(
                                    fileId=file_id,
                                    body={
                                        'role': 'writer',
                                        'type': 'domain',
                                        'allowFileDiscovery': False,
                                        'domain': 'aaaaa.jp',
                                        'kind': 'drive#permission'
                                    },
                                    fields='id'
                            ))
                            batch.execute()
                            memo = '100日経過したので共有設定しなおしました'

                        # 配列に保存
                        public_permissions.append([file.get('webViewLink', None), file.get('name', None), memo])
                        print('#', end='', flush=True)

                # 10個ごとにシートに反映する
                if((len(public_permissions) > 0) and (len(public_permissions) % 10 == 0)):
                    # ワークシート情報を設定
                    range_name = 'file list' + '!A' + str(putblic_last_row)
                    body = {'values': public_permissions}

                    print('シートに反映')
                    result = ss_service.spreadsheets().values().update(
                        spreadsheetId=SPREADSHEET_ID, 
                        range=range_name, valueInputOption='USER_ENTERED', body=body).execute()

                    public_permissions = []
                    putblic_last_row += 10

            # 使用中もしくは読み込めずにエラーになった場合
            except:
                unknown_permissions.append([file.get('webViewLink', None), file.get('name', None)])
                print('%', end='', flush=True)

                # 10個ごとにシートに反映する
                if((len(unknown_permissions) > 0) and (len(unknown_permissions) % 10 == 0)):
                    range_name = 'file list' + '!E' + str(unknown_last_row)
                    body = {'values': unknown_permissions}

                    print('シートに反映')
                    result = ss_service.spreadsheets().values().update(
                        spreadsheetId=SPREADSHEET_ID, 
                        range=range_name, valueInputOption='USER_ENTERED', body=body).execute()

                    unknown_permissions = []
                    unknown_last_row += 10

                continue

        page_token = response.get('nextPageToken', None)
        if page_token is None:
            break;


def callback(request_id, response, exception):
    if exception:
        # Handle error
        print(exception)
    else:
        print("Permission Id: %s" % response.get('id'))

if __name__ == '__main__':
    main()
gaiax
人と人をつなげる Empowering the people to connect.
http://www.gaiax.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした