LoginSignup
12
17

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-10-10

背景

社内で使用されている、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()
12
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
17