コンテンツにスキップ

Google Calendar を接続

このガイドでは、Google Calendar をワークスペースに接続する方法を説明します。接続はワークスペース単位で、そのワークスペースの予定を読み取り専用で Control Center に同期します。全体像はカレンダーとスケジュールを参照してください。

  1. サイドバーでカレンダーを開きます。
  2. カレンダーのサイドバーでカレンダーアカウントを追加をクリックします。(同じセクションは設定 → ワークスペース → プロフィールと識別情報のGoogle Calendarの下にもあります。)
  3. 認可の方法を選びます:
    • Control CenterのGoogleアプリを使用 — 設定は何も要りません。ビルドにこれが同梱されている場合の既定です。
    • 自分のGoogle Cloudクライアントを使用 — 自分のプロジェクトのクライアント ID とシークレットを貼り付けます(独自の Google クライアントを持ち込むを参照)。
  4. Googleカレンダーを接続をクリックします。ダイアログには短いコードと Google のデバイスページへのリンクが表示されます。
  5. 任意のデバイスでそのページを開き、コードを入力して、要求されたアクセスを承認します。ダイアログは自動的に閉じ、予定の同期が始まります。

このやり取りを実行し、そこで得られるリフレッシュトークンを保持するのは、あなたのデバイスではなくサーバーです。だからこそコードは、このアプリ上ではなく「任意のデバイス」で承認するのです。

アカウントが接続されるのはアクティブなワークスペースだけです。ワークスペースを切り替えると、そのワークスペースのカレンダーが表示されます。

接続フローが要求するのは calendar.readonly とあなたのメールアドレスで、組み込みアプリでも貼り付けたクライアントでもスコープは同じです。Control Center は予定を読み取るだけで、Google 側で予定を作成、編集、削除したり、招待に返信したりすることはありません。

スケジュールを所有するのはサーバーです。2 分ごとに各ワークスペースの接続済みアカウントをスイープし、予定をそのワークスペースのデータベースに書き込みます。クライアントが Google と通信することは決してなく、サーバーが書き込んだ内容を読み取るだけです。

スイープは増分式です。カレンダーごとの最初のパスでローリングウィンドウ(60 日前から 90 日先まで)を取得し、Google の同期トークンを取り込みます。以降のパスはそのトークンを提示し、変更された分だけを受け取ります。これが 2 分間隔を許容できるようにしています。ウィンドウは 24 時間ごと、および Google がトークンを無効化するたびに、完全同期によって基準を取り直します。

リフレッシュトークンは、サーバーのデータディレクトリ配下にある secrets.json にサーバー側で保存され、所有者のみが読める権限(0600)で書き込まれます。OS のキーチェーンには置かれず、クライアントデバイス上に置かれることもありません。

1 つのワークスペースには複数の Google アカウントを接続できます(たとえば仕事用と個人用)。それぞれについて接続の手順を繰り返します。予定は同じ月 / 週 / アジェンダの各ビューにマージされます。各アカウントは独立して同期・更新され、個別に切断できます。

Google がアカウントのトークンを恒久的に無効化した場合(セッションが取り消されたか、長期間失効した場合)、同期が停止し、Control Center はカレンダーに再接続バナーとデスクトップ通知を表示します。再接続をクリックして新しいコードを承認すると、次に同期が成功した時点でバナーが消えます。

カレンダーのサイドバー(または設定 → ワークスペース → プロフィールと識別情報)で、そのアカウントの切断をクリックします。これにより、同期済みの予定が削除され、サーバーに保存されたトークンが消去されます。

GUI が接続されていないサーバーでは、同じアカウントをサーバー自身のターミナルから接続します:

ターミナルウィンドウ
GOOGLE_OAUTH_CLIENT_ID=<id> GOOGLE_OAUTH_CLIENT_SECRET=<secret> \
cc_server calendar connect --data-dir <dir> --workspace <workspace-id>

コードと URL を表示し、承認を待ってからトークンを保存し、次のスイープで同期します。

ソースからのビルドには Google クライアントが同梱されていません。そのため ID とシークレットが必須です — GOOGLE_OAUTH_CLIENT_ID と GOOGLE_OAUTH_CLIENT_SECRET を設定してください。--google-client-id フラグはありません(不明なフラグは無視されます)。この環境変数のペアがないと、コマンドはクライアントが見つからないというエラーで終了します。

独自の Google クライアントを持ち込む(フォークとセルフホスティング)

「独自の Google クライアントを持ち込む(フォークとセルフホスティング)」というセクション

リリースビルドには Google クライアントが同梱されているため、ほとんどの人はこれに触れることはありません。ソースからビルドする場合、自分のサーバーを運用する場合、または同意画面に自分のプロジェクトの名前を出したい場合には、独自のクライアントを持ち込みます。

  1. Google Cloud ConsoleでGoogle Calendar APIを有効にし、OAuth 同意画面を構成して、calendar.readonly、openid、email の各スコープを追加します。アプリが未確認の間は、自分をテストユーザーとして追加します。同意画面で calendar.events を追加しても RSVP は有効になりません — Control Center がこのスコープを要求することは決してありません。
  2. アプリケーションの種類がTVs and limited input devicesのOAuth クライアント IDを作成し、クライアント ID とクライアントシークレットの両方をコピーします。
  3. 接続ごとに指定するか(ダイアログで自分のGoogle Cloudクライアントを使用を選びます)、サーバー全体に対して GOOGLE_OAUTH_CLIENT_ID と GOOGLE_OAUTH_CLIENT_SECRET で指定します。

サーバー全体のペアは、組み込みのペアをあらゆる場所で置き換えます。それは「Control CenterのGoogleアプリを使用」オプションの背後でも同じなので、自分のサーバーではそのオプションは自分のアプリを指します。

クライアントシークレットがサーバーから外に出ることはありません。どの RPC 応答にも含まれず、サーバー自身のクライアントを通じて接続したアカウントが保存するのはペアのコピーではなくマーカーなので、ローテーションは新しい値で再起動するだけで済みます。

症状 考えられる原因
ダイアログに組み込みのオプションが表示されない このビルドには Google クライアントが同梱されていない(ソースビルド)か、サーバーがペアの片方だけで起動されています。ID とシークレットの両方が必要です
フローの開始時に invalid_scope が出る その Cloud プロジェクトでは、デバイスコードクライアントに Calendar が許可されていません。代わりにループバックまたは Web クライアントのプロジェクトを使用してください
Google から invalid_client が返る クライアントがTVs and limited input devicesクライアントではないか、ID とシークレットが別々のクライアントのものです
承認は成功するが同期が空になる 同意画面で自分のアカウントがテストユーザーになっていないか、calendar.readonly が付与されていません
承認する前にコードが期限切れになる デバイスコードの有効期間は短いものです。接続をやり直して新しいコードを取得してください
RSVP で「回答を更新できませんでした」と表示される 想定どおりです。接続フローは calendar.events を要求しません
サーバーログのリフレッシュ警告とともに同期が停止する そのアカウントは、現在は構成されていないクライアントで接続されています。アカウントを再接続するか、そのクライアント ID とシークレットを復元してください