こんにちは。
Google Calendar APIを使うときにサービスアカウントをオーナーにしてカレンダーを作るといい感じだったので共有です。
よくあるフロー
ネットでよく見るやり方は主にこんな流れかと思います。
ここではカレンダーの更新権限が必要なアプリを想定しています。
- サービスアカウントを作成
- 自分のアカウントでカレンダーを作成
- 2で作ったカレンダーについて、1のサービスアカウントへ必要な権限付与
- カレンダーのAPIを使ってイベントを自動登録
これで問題ない場合はOKなんですが、会社なんかだとGoogle Workspace(旧 G Suite)の全体設定などでカレンダーの編集権限は社内のユーザーアカウントのみに制限、みたいなセキュリティポリシーにしている時があって、そのときは上記のやり方だとうまくいきません。
かといって、アプリのためにポリシー変える?みたいな話になって困っちゃいますよね。
もうひとつのフロー
ミソはサービスアカウントがオーナーのカレンダーを作ってしまうことです。
- サービスアカウントを作成
- サービスアカウントでCalendar APIを実行してカレンダーを作成
- 2で作ったカレンダーについて、共有が必要なユーザーをCalendar APIを使って追加
- カレンダーのAPIを使ってイベントを自動登録
この方法だと、アプリのために会社全体のセキュリティポリシーを変更しなくてすみます。
さらに、誰か人が作成したカレンダーに依存しないので、属人性が排除されるのもいいところですね。
サンプルコード
では、具体的なコードを見ていきましょう。
サンプルはRubyですが、他の言語でも同様にできると思います。
前提として、サービスアカウントを作成し、認証ファイル(json)は取得済みの状態から始めます。
APIの仕様は以下になります。
https://googleapis.dev/ruby/google-api-client/latest/Google/Apis/CalendarV3/CalendarService.html
初期化
このインスタンスから各種APIを実行していきます。
require 'google/apis/calendar_v3'
require 'googleauth'
require 'googleauth/stores/file_token_store'
# どこかクラスに以下のメソッドを書いている想定
def google_service
@google_service ||= Google::Apis::CalendarV3::CalendarService.new.tap do |service|
service.client_options.application_name = '素敵なアプリケーション'
sio = StringIO.new({client_email: ENV['GOOGLE_CALENDAR_CLIENT_ID'], private_key: ENV['GOOGLE_CALENDAR_CLIENT_PRIVATE_KEY'].gsub(/\\n/, "\n")}.to_json)
service.authorization = Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: sio, scope: Google::Apis::CalendarV3::AUTH_CALENDAR)
end
end
サービスアカウントでCalendar APIを実行してカレンダーを作成
最初にこれをバッチかなんかで実行してカレンダーを作ります。カレンダーのIDは後々使うので控えておきましょう。
calendar = Google::Apis::CalendarV3::Calendar.new(summary: 'カレンダーのタイトル', description: 'カレンダーの詳細')
result = google_service.insert_calendar(calendar)
result.id
共有が必要なユーザーをCalendar APIを使って追加
これをしないと、誰もサービスアカウントが作ったカレンダーを見ることができません。
権限付与したいユーザーを指定してあげましょう。
これも最初はバッチでやるとかになると思います。
これを実行すると、登録したメールアドレス宛に確認のメールが届きます。
その中にある「カレンダーを追加」を押すと、該当ユーザーはカレンダーを見ることが可能です。
scope = Google::Apis::CalendarV3::AclRule::Scope.new(type: 'user', value: 'account@example.com')
acl = Google::Apis::CalendarV3::AclRule.new(role: 'writer', scope: scope)
google_service.insert_acl(@calendar_id, acl)
Calendar APIを使ってイベントを登録
あとはイベントなどお好きなものをカレンダーに登録すれば、OKですね。
calendar_object = Google::Apis::CalendarV3::Event.new(
start: Google::Apis::CalendarV3::EventDateTime.new(date_time: @start_at.rfc3339),
end: Google::Apis::CalendarV3::EventDateTime.new(date_time: @end_at.rfc3339),
summary: 'イベントタイトル',
description: '詳細事項'
)
event = google_service.insert_event(@calendar_id, calendar_object)
event.html_link # ここにカレンダーのイベントごとのURLが入っている。(参考)
個人的には少しの違いですが、だいぶ楽になると思います。
Google Workspaceの設定の影響を受けないのがとてもよいと思いました。
サービスアカウントのこうした使い方については、プロジェクトや社内で相談した上で使っていくとよいでしょう。
参考文献