Skip to content

Enhance embed URL handling and validation system - #7

Open
ShashankFC wants to merge 1 commit into
embed-url-handling-prefrom
embed-url-handling-post
Open

Enhance embed URL handling and validation system#7
ShashankFC wants to merge 1 commit into
embed-url-handling-prefrom
embed-url-handling-post

Conversation

@ShashankFC

@ShashankFC ShashankFC commented Feb 4, 2026

Copy link
Copy Markdown

Test 4

Summary by CodeRabbit

  • New Features

    • Added embedding functionality to display external website content in responsive iframes
    • Introduced RSS/ATOM feed polling to automatically create and update posts from external feeds
    • Added embed interface displaying top posts with dynamic height adjustment
  • Tests

    • Added comprehensive test coverage for embed functionality and feed polling
  • Chores

    • Added required dependencies and database schema updates to support embedding

✏️ Tip: You can customize this high-level summary in your review settings.


Replicated from ai-code-review-evaluation/discourse-coderabbit#4


EntelligenceAI PR Summary

This PR implements a complete embedding and RSS/ATOM feed import system for Discourse forums.

  • Enables external sites to embed Discourse discussions via iframes with dynamic height adjustment using postMessage API
  • Adds RSS/ATOM feed polling job that runs hourly to automatically import feed items as forum topics
  • Introduces TopicEmbed model with SHA1-based content change detection and URL absolutization
  • Implements EmbedController with host validation, rate limiting (60-second throttle), and 1-minute response caching
  • Adds cook_method enum to Post model supporting raw HTML rendering for imported content
  • Creates background jobs for topic retrieval (RetrieveTopic) and feed polling (PollFeed)
  • Adds four new site settings: embeddable_host, feed_polling_enabled, feed_polling_url, embed_by_username
  • Includes dedicated embed layout, stylesheets, and JavaScript for iframe communication
  • Provides TopicRetriever class with multi-stage retrieval strategy and Redis-based rate limiting
  • Refactors Disqus import to use new TopicEmbed.import_remote API
  • Adds complete test coverage for all new components and full i18n support

@entelligence-ai-pr-reviews entelligence-ai-pr-reviews Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough

This PR implements a comprehensive embedding and feed import system for Discourse. It enables external websites to embed Discourse discussions via iframes with dynamic height adjustment through postMessage API. The feature includes RSS/ATOM feed polling to automatically import content as forum topics, with support for raw HTML rendering and content change detection via SHA1 hashing. New models, controllers, background jobs, and views support the embedding workflow, including topic retrieval with rate limiting and host validation. Configuration is managed through four new site settings for embeddable hosts, feed polling, and user attribution. The implementation includes full test coverage and internationalization support.

Changes

File(s) Summary
Gemfile
Gemfile_rails4.lock
Added ruby-readability (v0.5.7) and simple-rss (v1.3.1) gem dependencies with their transitive dependencies for feed importing and content extraction functionality.
app/controllers/embed_controller.rb Introduced new controller to handle embedded content with best action that retrieves/enqueues topic fetching, validates embeddable host against referer, sets X-Frame-Options to ALLOWALL, and caches responses for 1 minute.
app/models/topic_embed.rb Added ActiveRecord model managing embedded content with associations to Topic/Post, SHA1-based change detection, and methods for importing/updating topics from external URLs with content parsing and URL absolutization.
app/models/post.rb Added cook_methods enum (:regular, :raw_html) and modified cook method to conditionally skip rendering pipeline for raw HTML posts imported from external sources.
app/jobs/regular/retrieve_topic.rb Created background job for asynchronous topic retrieval from embedded sites with parameter validation and staff user throttling bypass.
app/jobs/scheduled/poll_feed.rb Implemented hourly scheduled job to fetch RSS/ATOM feeds and import items as topics using SimpleRSS parsing with SHA1-based feed key generation and content sanitization.
lib/topic_retriever.rb Introduced class encapsulating topic retrieval logic with host validation, Redis-based rate limiting (60-second throttle), and multi-stage retrieval strategy (existing embeds, RSS polling, HTTP fetch).
lib/post_creator.rb
lib/post_revisor.rb
Enhanced to support custom cook_method assignment during post creation and added skip_validations option to bypass validation during post save operations.
app/assets/javascripts/embed.js
app/views/layouts/embed.html.erb
Implemented bidirectional postMessage communication for dynamic iframe height adjustment, with embed.js creating iframe and layout sending height updates to parent frame.
app/assets/stylesheets/embed.css.scss Added stylesheet for embedded content with author section layout, post date styling, header/footer borders, and floating logo component.
app/views/embed/best.html.erb
app/views/embed/loading.html.erb
Created view templates for displaying best posts with author avatars and content, and loading state with 30-second auto-refresh mechanism.
db/migrate/20131217174004_create_topic_embeds.rb Created topic_embeds table with foreign keys to topics/posts, unique indexed embed_url, and content_sha1 field for change tracking.
db/migrate/20131219203905_add_cook_method_to_posts.rb Added cook_method integer column to posts table with default value of 1 and NOT NULL constraint.
config/site_settings.yml
config/locales/server.en.yml
config/locales/client.en.yml
Added 'embedding' configuration section with four settings (embeddable_host, feed_polling_enabled, feed_polling_url, embed_by_username) and corresponding i18n strings.
config/routes.rb Added GET route /embed/best mapping to EmbedController#best action.
lib/tasks/disqus.thor Refactored to use TopicEmbed.import_remote instead of direct PostCreator calls, removing category assignment logic.
db/migrate/20131210181901_migrate_word_counts.rb
db/migrate/20131223171005_create_top_topics.rb
Whitespace cleanup and added force: true option to ensure table recreation on migration re-runs.
spec/components/topic_retriever_spec.rb
spec/controllers/embed_controller_spec.rb
spec/jobs/poll_feed_spec.rb
spec/models/topic_embed_spec.rb
Added comprehensive test coverage for TopicRetriever validation/rate-limiting, EmbedController behavior, PollFeed preconditions, and TopicEmbed import functionality.

Sequence Diagram

This diagram shows the interactions between components:

sequenceDiagram
    actor User
    participant Controller
    participant FeedImporter
    participant SimpleRSS as SimpleRSS Gem
    participant Readability as Ruby-Readability Gem
    participant Database

    User->>Controller: Request to import feed URL
    Controller->>FeedImporter: import_feed(url)
    activate FeedImporter
    
    FeedImporter->>SimpleRSS: parse(feed_url)
    activate SimpleRSS
    SimpleRSS-->>FeedImporter: feed items (title, link, content)
    deactivate SimpleRSS
    
    loop For each feed item
        FeedImporter->>Readability: parse(item.link)
        activate Readability
        Readability-->>FeedImporter: cleaned content & metadata
        deactivate Readability
        
        FeedImporter->>Database: save_post(content, metadata)
        Database-->>FeedImporter: confirmation
    end
    
    FeedImporter-->>Controller: import complete
    deactivate FeedImporter
    Controller-->>User: Display imported posts
Loading

🔗 Cross-Repository Impact Analysis

Enable automatic detection of breaking changes across your dependent repositories. → Set up now

Learn more about Cross-Repository Analysis

What It Does

  • Automatically identifies repositories that depend on this code
  • Analyzes potential breaking changes across your entire codebase
  • Provides risk assessment before merging to prevent cross-repo issues

How to Enable

  1. Visit Settings → Code Management
  2. Configure repository dependencies
  3. Future PRs will automatically include cross-repo impact analysis!

Benefits

  • 🛡️ Prevent breaking changes across repositories
  • 🔍 Catch integration issues before they reach production
  • 📊 Better visibility into your multi-repo architecture

▶️AI Code Reviews for VS Code, Cursor, Windsurf
Install the extension

Note for Windsurf Please change the default marketplace provider to the following in the windsurf settings:

Marketplace Extension Gallery Service URL: https://marketplace.visualstudio.com/_apis/public/gallery

Marketplace Gallery Item URL: https://marketplace.visualstudio.com/items

Entelligence.ai can learn from your feedback. Simply add 👍 / 👎 emojis to teach it your preferences. More shortcuts below

Emoji Descriptions:

  • ⚠️ Potential Issue - May require further investigation.
  • 🔒 Security Vulnerability - Fix to ensure system safety.
  • 💻 Code Improvement - Suggestions to enhance code quality.
  • 🔨 Refactor Suggestion - Recommendations for restructuring code.
  • ℹ️ Others - General comments and information.

Interact with the Bot:

  • Send a message or request using the format:
    @entelligenceai + *your message*
Example: @entelligenceai Can you suggest improvements for this code?
  • Help the Bot learn by providing feedback on its responses.
    @entelligenceai + *feedback*
Example: @entelligenceai Do not comment on `save_auth` function !

Also you can trigger various commands with the bot by doing
@entelligenceai command

The current supported commands are

  1. config - shows the current config
  2. retrigger_review - retriggers the review

More commands to be added soon.

url = i.link
url = i.id if url.blank? || url !~ /^https?\:\/\//

content = CGI.unescapeHTML(i.content.scrub)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: Calling i.content.scrub will raise a NoMethodError and abort the job if an RSS item lacks a content tag (returning nil). Use i.content.to_s.scrub or provide a fallback like i.description to ensure the job handles items with missing content.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In `app/jobs/scheduled/poll_feed.rb` at the line where `content` is built from `i.content`, make the call nil-safe so RSS items without content don't raise. Change `i.content.scrub` to `i.content.to_s.scrub` (or fallback to `description` if preferred) while preserving existing behavior.

Comment thread app/models/topic_embed.rb
Comment on lines +44 to +48
def self.import_remote(user, url, opts=nil)
require 'ruby-readability'

opts = opts || {}
doc = Readability::Document.new(open(url).read,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: ⚠️ import_remote calls open(url) before any scheme validation, so a non-HTTP URL (e.g., file:// or a local path) can be read from the server. This bypasses the safety check in import and enables SSRF/local file reads. Add the same http/https guard here before open is called.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In app/models/topic_embed.rb lines 44-48, add a guard in import_remote to ensure the URL is http/https before calling open(url). This prevents SSRF/local file reads. Insert `return unless url =~ /^https?:\/\//` immediately after the require statement.

window.onload = function() {
if (parent) {
// Send a post message with our loaded height
parent.postMessage({type: 'discourse-resize', height: document['body'].offsetHeight}, '<%= request.referer %>');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: parent.postMessage will throw a SyntaxError DOMException if request.referer is blank (e.g., due to Referrer-Policy), as an empty string is an invalid targetOrigin. Provide a fallback origin or use '*' to prevent the script from crashing when the referrer header is missing.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

File: app/views/layouts/embed.html.erb (line 11). Problem: request.referer can be blank, producing an empty targetOrigin that throws a DOMException in postMessage. Fix: introduce a targetOrigin variable and only call parent.postMessage when it is non-empty (or use a safe fallback if required).

Comment thread lib/tasks/disqus.thor
if options[:dry_run].blank?
creator = PostCreator.new(user, title: t[:title], raw: "\[[Permalink](#{t[:link]})\]", created_at: Date.parse(t[:created_at]), category: category_id)
post = creator.create

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: The call to TopicEmbed.import_remote on this line omits the created_at timestamp previously passed to PostCreator. This causes the topic to be created with the current timestamp while subsequent replies use historical dates, breaking the thread timeline. Ensure the topic and its first post use Date.parse(t[:created_at]).

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

File: lib/tasks/disqus.thor. At the `TopicEmbed.import_remote` call (around line 147), ensure the imported topic/post preserves the Disqus thread’s `created_at`. Either pass `created_at: Date.parse(t[:created_at])` if supported, or update the created post/topic timestamps immediately after import. Keep replies’ timestamps intact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants