GASでGoogleWorkspaceの共有ドライブ内ファイルの権限チェック

GASでGoogleWorkspaceの共有ドライブ内ファイルの権限チェック

Gsuite改め、Google Workspaceの共有ドライブ利用して社内のファイルを管理していますが、アルバイトや業務委託の方など関係者が増えてくると権限の管理が煩雑になってきますよね。

弊社アンチパターンでも、権限の設定は共有ドライブのルートフォルダでのみ行い、共有ドライブ内のフォルダやファイルには個別に権限を設定しないというルールはつくったものの、すでに設定されている権限を可視化したり、今後個別設定された権限を検知できないためにGASでチェックできる仕組みを作成しました。

const SHEET = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('filelist')
const DRIVE_NAME = SHEET.getRange('A1').getValue()

const getFilesAuth = () => {
  // 共有ドライブを取得
  const drive = DriveApp.getFolderById(getDriveId(DRIVE_NAME))
  // デフォルト以外で権限付与されているフォルダとファイルをシートに記録
  getAuthorizedItems(drive, DRIVE_NAME)
}

/**
 * ファイルオブジェクトもしくはフォルダオブジェクトから権限保有者名を取得
 * @param {Folder} folder - フォルダ
 * @param {string} path - パス名
 */
const getAuthorizedItems = (folder,path) => {  
  // フォルダ内のファイルを取得
  const files = folder.getFiles()
  while (files.hasNext()) {
    const file = files.next()
    // ファイルに権限付与されたユーザーを取得
    const authorizers = getAuthorizers(file)
    // デフォルト以外で権限付与されていない場合はスキップ
    if (authorizers === '') continue
    // シートに記録。空白, ファイル名, 権限付与者, ファイルURL
    SHEET.appendRow(['', path + ' / ' + file.getName(), authorizers, file.getUrl()])
  }
  // folder内のフォルダを取得
  const folders = folder.getFolders()
  while (folders.hasNext()) {
    const folder = folders.next()
    const path_name = path + ' / ' + folder.getName()
    // フォルダ内を再帰的に検出
    getAuthorizedItems(folder, path_name)
    // フォルダに権限付与されたユーザーを取得
    const authorizers = getAuthorizers(folder)
    if (authorizers === '') continue
    // シートに記録。d(ディレクトリを表す), ディレクトリ名, 権限付与者, URL
    SHEET.appendRow(['d', path + ' / ' + folder.getName(), authorizers, folder.getUrl()])
  }
}

/**
 * ファイルオブジェクトもしくはフォルダオブジェクトから権限保有者名を取得
 * @param {object} item - ファイルオブジェクトもしくはフォルダオブジェクト
 * @return {string} - 権限保有者名
 */
const getAuthorizers = (item) => {
  const editors = item.getEditors()
  const viewers = item.getViewers()
  const authorize_users = editors.concat(viewers)
  let authorizers = ''
  authorize_users.forEach(user => {
    authorizers += user.getName()+ ' '
  })
  return authorizers
}

/**
 * 共有ドライブ名から共有ドライブを取得
 * @param {string} teamDriveName - 共有ドライブ名
 * @return {int} - 共有ドライブID
 */
const getDriveId = (drive_name) => {
  // シートA1セルに記載のドライブ名を取得
  const team_drives = Drive.Teamdrives.list().items
  Logger.log(team_drives)
  let id = 0
  team_drives.forEach(team_drive => {  
      if (team_drive.name === drive_name) {
        Logger.log(team_drive.getId())
       id = team_drive.getId()
    }
  })
  return id
}

実行すると、このような具合に個別に権限付与されたファイル・フォルダの一覧を取得することができます

共有ドライブ内のファイル数が多いと実行に時間がかかり、GASの実行時間上限に引っかかってしまう場合があるので、スプレッドシートへの記録を一回で済むようにしたり、複数回実行しても大丈夫なように工夫する必要がありそうです。