FEATURE: per-topic unsubscribe option in emails#2
Conversation
|
Claude finished @ShashankFC's task in 2m 26s —— View job Code Review CompleteI've reviewed this PR which adds a per-topic unsubscribe option to email notifications. Here's my analysis: OverviewThis feature allows users to unsubscribe from notifications for specific topics directly from email links, rather than having to visit their user preferences page. The implementation includes both frontend (Ember.js) and backend (Ruby) changes. Issues Found1. Typo in Controller Property Name - app/assets/javascripts/discourse/controllers/topic-unsubscribe.js.es6:5stopNotificiationsText: function() {Issue: "Notificiations" should be "Notifications" 2. Missing Nil Check in Unsubscribe Action - app/controllers/topics_controller.rb:105-114tu = TopicUser.find_by(user_id: current_user.id, topic_id: params[:topic_id])
if tu.notification_level > TopicUser.notification_levels[:regular]
tu.notification_level = TopicUser.notification_levels[:regular]
else
tu.notification_level = TopicUser.notification_levels[:muted]
end
tu.save!Issue: If no Recommendation: Handle the case where no TopicUser record exists: tu = TopicUser.find_by(user_id: current_user.id, topic_id: params[:topic_id])
if tu
if tu.notification_level > TopicUser.notification_levels[:regular]
tu.notification_level = TopicUser.notification_levels[:regular]
else
tu.notification_level = TopicUser.notification_levels[:muted]
end
tu.save!
else
# Create a new TopicUser record with muted notifications
TopicUser.create!(
user_id: current_user.id,
topic_id: params[:topic_id],
notification_level: TopicUser.notification_levels[:muted]
)
end3. Missing First/Last Visited Timestamps - app/controllers/topics_controller.rb:105-114Even if we add the nil check above, the manual creation doesn't set tu = TopicUser.get(post.topic_id, user)
if tu && tu.notification_level > TopicUser.notification_levels[:regular]
TopicUser.change(current_user.id, params[:topic_id],
notification_level: TopicUser.notification_levels[:regular])
else
TopicUser.change(current_user.id, params[:topic_id],
notification_level: TopicUser.notification_levels[:muted])
endThe 4. Inconsistent List-Unsubscribe Header - lib/email/message_builder.rb:107result['List-Unsubscribe'] = "<#{template_args[:user_preferences_url]}>" if @opts[:add_unsubscribe_link]Issue: The Recommendation: if @opts[:add_unsubscribe_link]
unsubscribe_urls = ["<#{template_args[:user_preferences_url]}>"]
unsubscribe_urls << "<#{template_args[:unsubscribe_url]}>" if template_args[:unsubscribe_url].present?
result['List-Unsubscribe'] = unsubscribe_urls.join(', ')
endSuggestions for Improvement5. Route Definition Redundancy - config/routes.rbThe routes include both slug and non-slug versions: get "t/:slug/:topic_id/unsubscribe" => "topics#unsubscribe"
get "t/:topic_id/unsubscribe" => "topics#unsubscribe"This is consistent with existing patterns in the codebase, but the controller already handles redirecting to the correct URL with slug (lines 101-103). Good pattern! 6. Consider Flash Message After Unsubscribe - app/controllers/topics_controller.rb:98-116The unsubscribe action modifies notification settings but doesn't provide explicit feedback. Consider adding a flash message: flash[:notice] = I18n.t('topic.unsubscribed_successfully')7. Template Variable Escaping - app/views/email/notification.html.erb:20The template uses Positive Aspects✅ Good security: The unsubscribe action requires authentication ( ✅ Proper slug handling: Redirects to canonical URL if slug is missing or doesn't match (lines 101-103) ✅ Internationalization: All user-facing strings use I18n ✅ Consistent patterns: Follows existing Discourse conventions for routes, controllers, and Ember.js structure ✅ Database efficiency: Uses existing ✅ Email template updates: Properly adds the unsubscribe link to both text and HTML email formats Test CoverageThe spec file
Consider adding integration tests for the full unsubscribe flow. SummaryThis is a well-structured feature implementation that follows Discourse conventions. The main concerns are:
The security model is sound, and the feature integrates well with the existing notification system. |
Test 2nn---nReplicated from ai-code-review-evaluation/discourse-greptile#2