Feed ICS autenticati per eventi del calendario privato

L’esportazione pubblica ICS è stata recentemente reintrodotta tramite

GET /discourse-post-event/events.ics, che è un ottimo miglioramento a seguito del lavoro in

Re-Add full ICS export.

Al momento, questo endpoint sembra essere limitato agli eventi visibili agli utenti anonimi. Di conseguenza, gli eventi in categorie private o categorie limitate al gruppo predefinito everyone non possono essere sottoscritti in client di calendario esterni (ad esempio, Google Calendar, Outlook).

Sarebbe fattibile supportare l’accesso autenticato a questo endpoint, in modo simile a come Discourse gestisce i feed RSS/Atom privati (ad esempio, tramite un token per utente o una chiave API di sola lettura)?

Questo non cambierebbe alcuna regola di autorizzazione: consentirebbe semplicemente ai client di calendario di accedere agli eventi che l’utente è già autorizzato a vedere.

Sollevo questa richiesta separata e circoscritta a seguito della reintroduzione del feed ICS pubblico, come suggerito in precedenza.

1 Mi Piace

Dopo aver esaminato attentamente il codice, ho finito per scrivere un proxy molto semplice che gestisce vari ostacoli necessari per creare una chiave API utente e passarla all’API; genera anche un link che gli utenti devono incollare nelle loro applicazioni di calendario:

Spero che tutto questo un giorno arrivi al codice di Discourse e non sia più necessario; nel frattempo lo condivido nella speranza di rendere la vita più facile agli altri.

L’ho aggiunto all’inizio di questa settimana in questa PR. Tuttavia, l’ergonomia della generazione delle Chiavi API Utente non è ottimale per gli utenti non tecnici. Per rendere questo processo più fluido, sto dando seguito con:

Che cerca di renderlo il più semplice possibile

1 Mi Piace

Ho appena unito questa funzionalità, puoi provare tu, @Ethsim2?

1 Mi Piace

Grazie: posso confermare che anche il feed autenticato stesso viene ora generato correttamente da parte mia.
Il problema rimanente sembra essere la compatibilità client: né Google Calendar né Outlook sembrano gradire l’iscrizione diretta a un feed ICS autenticato in questa forma, quindi per ora ho intenzione di aggirarlo inserendo un proxy inverso Nginx a livello di host davanti alla mia installazione Discourse in un singolo container e servendo invece un file .ics semplice lì.

Poiché sono sulla configurazione standard a container singolo, penso che ciò significhi spostare le porte 80/443 fuori dal container, far sì che Discourse si metta in ascolto su una porta alta interna, e poi far sì che l’Nginx host inoltri il forum e serva anche un percorso di file statico per il calendario.

Approssimativamente, i comandi che prevedo di usare sono:

# 1. Installa nginx host + 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. Ferma il container Discourse in modo che le porte 80/443 possano essere liberate
cd /var/discourse
sudo ./launcher stop app

# 3. Modifica la configurazione del container in modo che Discourse non si colleghi più direttamente a 80/443
sudo nano /var/discourse/containers/app.yml

Quindi in app.yml cambia la sezione expose da:

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

a qualcosa come:

expose:
  - "127.0.0.1:8080:80"

e, se presente, rimuovi i template SSL/Let’s Encrypt del container in modo che la terminazione TLS avvenga invece sul proxy inverso dell’host.

Quindi ricostruisci:

cd /var/discourse
sudo ./launcher rebuild app

Quindi crea un sito Nginx a livello di host come:

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

con qualcosa di simile a:

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";
    }
}

Abilitalo e ricarica:

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

Quindi ottieni un certificato Let’s Encrypt con Certbot e lascia che aggiorni la configurazione Nginx:

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

Dopodiché, la configurazione Nginx includerà tipicamente anche un blocco server HTTPS, ad esempio:

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";
    }
}

A quel punto posso usare uno script/timer sull’host per recuperare l’ICS di Discourse autenticato e scrivere:

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

a cui Google Calendar/Outlook possono iscriversi come un normale URL ICS pubblico.
Quindi, dal mio punto di vista, il lato Discourse sembra risolto ora; il divario pratico rimanente è principalmente che i principali client di calendario non gestiscono particolarmente bene i feed ICS autenticati, motivo per cui sto ripiegando su un approccio di proxy pubblico/file statico per ora.

Sto anche supponendo che Certbot sia il percorso più semplice qui, poiché può gestire l’emissione/rinnovo di Let’s Encrypt direttamente contro Nginx host. Potrei anche usare acme.sh, ma la mia impressione è che sarebbe più una scelta manuale piuttosto che il percorso più diretto per questa specifica configurazione.

Aspetta cosa?

Lo sto usando con il mio Google Calendar senza problemi, così come alcuni dei miei colleghi.

Qual è la parte che è incompatibile con Google Calendar!?

Ah, grazie, questo aiuta a restringere il campo.

Da parte mia, Google Calendar accetta l’URL di sottoscrizione (tramite “Da URL”), ma il comportamento che riscontro è:

  • il calendario viene aggiunto con successo
  • tuttavia, non mostra alcun evento

Quindi non è un caso di rifiuto dell’URL, è più che il feed appare vuoto dal punto di vista di Google.

Dato che l’ICS grezzo contiene chiaramente voci VEVENT (ad esempio con UID, DTSTART, SUMMARY, ecc.), questo mi fa pensare che possa trattarsi di qualcosa come:

  • Google che filtra gli eventi passati (la maggior parte dei miei dati di prova è storica)
  • o qualcosa riguardo al modo in cui il feed viene interpretato (ad esempio, intervallo di tempo, memorizzazione nella cache o intestazioni)

Fammi sapere se c’è qualcosa di specifico che vorresti che controllassi nel feed stesso.

2 Mi Piace

Puoi controllare /logs per eventuali errori? Ho appena risolto un problema per cui i vecchi eventi ricorrenti causavano il fallimento del feed.

Se era lo stesso errore, devi aggiornare.

Dovrei scavare più indietro, prima delle 19:00, poiché ci sono molti avvisi/errori relativi a Discourse AI - limite di token.

1 Mi Piace
1 Mi Piace