From 1958ac2b10a44aa63897cca6ce45f602ad35e9d0 Mon Sep 17 00:00:00 2001 From: Kushal SM Date: Sun, 15 Feb 2026 22:39:07 +0530 Subject: [PATCH] feat: Add public RSS feed for conferences Users currently have no way to be notified when new conferences are published on an OSEM instance. This adds an RSS 2.0 feed endpoint at /feed.rss that lists all conferences ordered by creation date. The feed action is excluded from CanCanCan authorization so it remains publicly accessible without authentication, similar to the existing calendar endpoint. Also adds an RSS subscribe link to the conferences index page and an auto-discovery tag in the application layout so RSS readers can detect the feed automatically. Fixes #3543 --- app/controllers/conferences_controller.rb | 10 +++++++++- app/views/conferences/feed.rss.builder | 18 ++++++++++++++++++ app/views/conferences/index.html.haml | 3 +++ app/views/layouts/application.html.haml | 1 + config/routes.rb | 1 + 5 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 app/views/conferences/feed.rss.builder diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index 43809551..0accb4ae 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -3,7 +3,8 @@ class ConferencesController < ApplicationController protect_from_forgery with: :null_session before_action :respond_to_options - load_and_authorize_resource find_by: :short_title, except: :show + load_and_authorize_resource find_by: :short_title, except: [:show, :feed] + skip_authorization_check only: :feed def index @current = Conference.upcoming.reorder(start_date: :asc) @@ -108,6 +109,13 @@ class ConferencesController < ApplicationController end end + def feed + @conferences = Conference.order(created_at: :desc) + respond_to do |format| + format.rss { render layout: false } + end + end + def code_of_conduct; end private diff --git a/app/views/conferences/feed.rss.builder b/app/views/conferences/feed.rss.builder new file mode 100644 index 00000000..7b7e7d3c --- /dev/null +++ b/app/views/conferences/feed.rss.builder @@ -0,0 +1,18 @@ +xml.instruct! :xml, version: "1.0" +xml.rss version: "2.0" do + xml.channel do + xml.title "#{ENV.fetch('OSEM_NAME', 'OSEM')} - Conferences" + xml.description "Conferences from #{ENV.fetch('OSEM_NAME', 'OSEM')}" + xml.link conferences_url + + @conferences.each do |conference| + xml.item do + xml.title conference.title + xml.description conference.description + xml.pubDate conference.created_at.to_fs(:rfc822) + xml.link conference_url(conference.short_title) + xml.guid conference_url(conference.short_title) + end + end + end +end diff --git a/app/views/conferences/index.html.haml b/app/views/conferences/index.html.haml index 720e1cdf..2cfeb6d3 100644 --- a/app/views/conferences/index.html.haml +++ b/app/views/conferences/index.html.haml @@ -23,6 +23,9 @@ %span.btn-group = link_to("Days only", calendar_url(protocol: 'webcal', format: 'ics'), class: 'btn btn-default') = link_to("Detailed", calendar_url(protocol: 'webcal', format: 'ics', full: true), class: 'btn btn-default') + %p + Subscribe to the RSS feed: + = link_to("RSS Feed", feed_url(format: :rss), class: 'btn btn-default') -content_for :script_body do :javascript diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 95fb77f1..d6ad6ae6 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -7,6 +7,7 @@ %meta{content: '', name: 'author'} = stylesheet_link_tag "application", media: 'all' = javascript_include_tag "application" + = auto_discovery_link_tag(:rss, feed_url(format: :rss), title: "#{ENV.fetch('OSEM_NAME', 'OSEM')} Conferences RSS Feed") = csrf_meta_tags = content_for(:script_head) diff --git a/config/routes.rb b/config/routes.rb index 730d43cf..2bc55e48 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -216,6 +216,7 @@ Osem::Application.routes.draw do get '/admin' => redirect('/admin/conferences') get '/calendar' => 'conferences#calendar' + get '/feed' => 'conferences#feed' if ENV.fetch('OSEM_ROOT_CONFERENCE', nil) root to: redirect("/conferences/#{ENV.fetch('OSEM_ROOT_CONFERENCE')}")