プライベートカレンダーイベントの認証済みICSフィード

公開ICSエクスポートは、最近、

GET /discourse-post-event/events.ics

によって再導入されました。これは、

Re-Add full ICS export

での作業に続く素晴らしい改善です。

現時点では、このエンドポイントは匿名ユーザーに表示されるイベントに限定されているようです。その結果、プライベートカテゴリやデフォルトの everyone グループから制限されているカテゴリのイベントは、外部カレンダークライアント(例:Googleカレンダー、Outlook)で購読することができません。

DiscourseがプライベートなRSS/Atomフィードを処理する方法(例えば、ユーザーごとのトークンや読み取り専用APIキーを介した方法)と同様に、このエンドポイントへの認証済みアクセスをサポートすることは可能でしょうか?

これは、以前提案された公開ICSフィードの再導入に続く、分離された範囲を限定したリクエストとして提起するものです。許可されるのは、ユーザーがすでに表示を許可されているイベントにカレンダークライアントがアクセスできるようにすることだけであり、権限ルールを変更するものではありません。

「いいね!」 1

コードを精査した結果、ユーザーAPIキーの作成とAPIへの受け渡しに必要な様々な障害を処理する非常にシンプルなプロキシをコーディングし、さらにユーザーがカレンダーアプリに貼り付ける必要があるリンクも生成しました。

これがいつかDiscourseのコードに組み込まれ、不要になることを願っています。それまでの間、他の人の生活を楽にするために、これを共有します。

私は今週初めにこのPRでそれを追加しました。しかし、非技術系のユーザーにとってユーザーAPIキーを生成する操作性はあまり良くありません。これをシームレスにするために、以下の対応を進めています。

これは可能な限り使いやすくしようとするものです。

「いいね!」 1

この機能をマージしました。試してもらえますか @Ethsim2

「いいね!」 1

ありがとうございます。認証済みのフィード自体は、私の側で正しく生成されていることを確認できました。

残りの問題はクライアントの互換性のようです。GoogleカレンダーもOutlookも、認証されたICSフィードに直接サブスクライブすることに難色を示しているようです。そのため、当面はホストレベルのNginxリバースプロキシを単一コンテナのDiscourseインストール(Discourse install)の前に配置し、代わりにプレーンな.icsファイルをそこで提供することで回避する予定です。

標準の単一コンテナ設定を使用しているため、これはコンテナからポート80/443を解放し、Discourseに内部のハイポートでリッスンさせ、その後ホストのNginxにフォーラムをプロキシさせ、静的カレンダーフィードパスも提供させることを意味すると思われます。

およそ、使用を想定しているコマンドは次のとおりです。

# 1. ホストのnginxとcertbotをインストール
sudo apt update
sudo apt install -y nginx snapd
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -sf /snap/bin/certbot /usr/bin/certbot

# 2. Discourseコンテナを停止して、ポート80/443を解放
cd /var/discourse
sudo ./launcher stop app

# 3. コンテナの設定を編集して、Discourseが直接80/443にバインドしないようにする
sudo nano /var/discourse/containers/app.yml

app.yml内で、exposeセクションを次のように変更します。

expose:
  - "80:80"
  - "443:443"

から、次のようなものに:

expose:
  - "127.0.0.1:8080:80"

そして、存在する場合は、TLSがホストのリバースプロキシで終了するように、コンテナのSSL/Let’s Encryptテンプレートを削除します。

その後、再ビルドします。

cd /var/discourse
sudo ./launcher rebuild app

次に、次のようなホストレベルのNginxサイトを作成します。

sudo nano /etc/nginx/sites-available/discourse

以下のような内容で設定します。

server {
    listen 80;
    listen [::]:80;
    server_name forum.example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /private-calendar/ethan.ics {
        alias /var/www/private-calendar/ethan.ics;
        default_type text/calendar;
        add_header Content-Type "text/calendar; charset=utf-8";
    }
}

有効化してリロードします。

sudo mkdir -p /var/www/private-calendar
sudo mkdir -p /var/www/certbot
sudo ln -s /etc/nginx/sites-available/discourse /etc/nginx/sites-enabled/discourse
sudo nginx -t
sudo systemctl reload nginx

その後、Certbotを使用してLet’s Encrypt証明書を取得し、Nginx設定を更新させます。

sudo certbot --nginx -d forum.example.com
sudo nginx -t
sudo systemctl reload nginx

その後、Nginx設定には通常、HTTPSサーバーブロックも含まれます。例えば次のようになります。

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name forum.example.com;

    ssl_certificate /etc/letsencrypt/live/forum.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/forum.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /private-calendar/ethan.ics {
        alias /var/www/private-calendar/ethan.ics;
        default_type text/calendar;
        add_header Content-Type "text/calendar; charset=utf-8";
    }
}

その時点で、ホスト上でスクリプト/タイマーを使用して、認証されたDiscourse ICSを取得し、次のように書き出すことができます。

/var/www/private-calendar/ethan.ics

これにより、Googleカレンダー/Outlookは通常の公開ICS URLとしてサブスクライブできるようになります。

したがって、私の見解では、Discourse側はこれで解決したと思われます。残りの実際的なギャップは、主に主要なカレンダークライアントが認証されたICSフィードをあまりうまく処理しないという点であり、そのため現時点では公開プロキシ/静的ファイルアプローチにフォールバックしているわけです。

また、CertbotがホストのNginxに対してLet’s Encryptの発行/更新を直接管理できるため、これが最も簡単なルートであると想定しています。acme.shを使用することもできますが、この特定のセットアップでは最も簡単なパスというよりは手動での選択になるという印象です。

え、何が?

私はそれをGoogleカレンダーで何の問題もなく使用していますし、同僚の中にも使用している者がいます。

Googleカレンダーと互換性がないのはどの部分なのですか!?

ああ、ありがとうございます、それで絞り込めました。

私の方では、Google カレンダーはサブスクリプション URL を受け付けます(「URL から」経由で)。ただし、表示される動作は次のとおりです。

  • カレンダーは正常に追加される
  • しかし、イベントが全く表示されない

したがって、URL が拒否されているケースではなく、Google から見るとフィードが空であるように見える、という状況です。

生の ICS には明らかに VEVENT エントリ(例: UIDDTSTARTSUMMARY などを含む)が含まれているため、これは次のようなものである可能性があります。

  • Google が過去のイベントをフィルタリングしている(私のテストデータの大半は履歴データです)
  • フィードの解釈方法に関する何らかの問題(例: 時間範囲、キャッシング、またはヘッダー)

フィード自体で確認してほしい具体的な事項があればお知らせください。

「いいね!」 2

エラーがないか /logs を確認していただけますか?古い定期イベントが原因でフィードが失敗する問題を修正したばかりです。

もし同じエラーだった場合、アップデートが必要です。

午後7時より前に遡って確認する必要があります。なぜなら、Discourse AI - トークン制限に関連する警告やエラーが多くあるからです。

「いいね!」 1
「いいね!」 1