Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion app/controllers/request_for_comments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

class RequestForCommentsController < ApplicationController
include CommonBehavior
before_action :set_request_for_comment, only: %i[show mark_as_solved set_thank_you_note clear_question]
before_action :set_request_for_comment, only: %i[show mark_as_solved set_thank_you_note clear_question report]
before_action :set_study_group_grouping,
only: %i[index my_comment_requests rfcs_with_my_comments rfcs_for_exercise]

Expand Down Expand Up @@ -162,6 +162,15 @@ def create
authorize!
end

# POST /request_for_comments/1/report
def report
authorize!

ReportMailer.with(reported_content: @request_for_comment).report_content.deliver_later

redirect_to(@request_for_comment, notice: t('.report.reported'))
Comment thread
nenock marked this conversation as resolved.
end

private

# Use callbacks to share common setup or constraints between actions.
Expand Down
11 changes: 11 additions & 0 deletions app/mailers/report_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class ReportMailer < ApplicationMailer
default to: CodeOcean::Config.new(:code_ocean).read.dig(:content_moderation, :report_emails)

def report_content
@reported_content = params.fetch(:reported_content)

mail(subject: I18n.t('report_mailer.report_content.subject', content_name: @reported_content.model_name.human))
end
end
8 changes: 8 additions & 0 deletions app/policies/request_for_comment_policy.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class RequestForCommentPolicy < ApplicationPolicy
REPORT_RECEIVER_CONFIGURED = CodeOcean::Config.new(:code_ocean).read.dig(:content_moderation, :report_emails).present?

def create?
everyone
end
Expand Down Expand Up @@ -41,6 +43,12 @@ def rfcs_with_my_comments?
everyone
end

def report?
REPORT_RECEIVER_CONFIGURED && show? && !author?
end

private

def rfc_visibility
# The consumer with the most restricted visibility determines the visibility of the RfC
case [@user.consumer.rfc_visibility, @record.author.consumer.rfc_visibility]
Expand Down
4 changes: 4 additions & 0 deletions app/views/report_mailer/report_content.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
h3 = t('.prolog')
blockquote style="white-space: pre-wrap;" = @reported_content.question
p = t('.take_action')
p = link_to(request_for_comment_url(@reported_content), request_for_comment_url(@reported_content))
7 changes: 7 additions & 0 deletions app/views/report_mailer/report_content.text.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
== t('.prolog')
== "\n\n"
== @reported_content.question.lines.map { "> #{it}" }.join
== "\n\n"
== t('.take_action')
== "\n\n"
== request_for_comment_url(@reported_content)
7 changes: 7 additions & 0 deletions app/views/request_for_comments/_report.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/# locals: (request_for_comment:)

- if policy(request_for_comment).report?
= button_to t('.report'), report_request_for_comment_path(request_for_comment),
data: {confirm: t('.confirm')},
class: 'btn btn-light btn-sm',
form: {class: 'd-inline float-end'}
1 change: 1 addition & 0 deletions app/views/request_for_comments/show.html.slim
Comment thread
MrSerth marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
.question
h5.mt-4
= RequestForComment.human_attribute_name('question')
= render('report', request_for_comment: @request_for_comment)
.text
- question = @request_for_comment.question
= question.presence || t('request_for_comments.no_question')
Expand Down
9 changes: 9 additions & 0 deletions config/code_ocean.yml.example
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,22 @@ default: &default
# be truly greater than any permitted execution time of an execution environment.
unused_runner_expiration_time: 180

content_moderation:
# Learners can report inappropriate content, such as offensive RfCs or comments.
# For each report, an email is sent to all addresses listed below. If no address is
# configured, learners cannot report user-generated content.
report_emails:
# - report@example.com

development:
<<: *default
flowr:
enabled: true
codeharbor:
enabled: true
content_moderation:
report_emails:
- report@example.com


production:
Expand Down
7 changes: 7 additions & 0 deletions config/locales/de/report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
de:
report_mailer:
report_content:
prolog: 'Die folgenden Inhalte wurden als unangemessen gemeldet:'
subject: 'Spam Report: Ein %{content_name} in CodeOcean wurde als unangemessen markiert.'
Comment thread
nenock marked this conversation as resolved.
take_action: Bitte ergreifen Sie gegebenenfalls Maßnahmen.
4 changes: 4 additions & 0 deletions config/locales/de/request_for_comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ de:
no_output: Keine Ausgabe.
no_question: Der/die Autor:in hat keine Frage zu dieser Anfrage gestellt.
passed: Erfolgreich
report:
confirm: Möchten Sie diesen Inhalt melden?
report: Melden
reported: Vielen Dank, dass Sie uns auf dieses Problem aufmerksam gemacht haben. Wir werden uns in Kürze darum kümmern.
runtime_output: Programmausgabe
send_thank_you_note: Senden
show_all: Alle Anfragen anzeigen
Expand Down
7 changes: 7 additions & 0 deletions config/locales/en/report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
en:
report_mailer:
report_content:
prolog: 'The following content has been reported as inappropriate:'
subject: 'Spam Report: A %{content_name} on CodeOcean has been marked as inappropriate.'
take_action: Please take action if required.
4 changes: 4 additions & 0 deletions config/locales/en/request_for_comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ en:
no_output: No output.
no_question: The author did not enter a question for this request.
passed: Passed
report:
confirm: Do you want to report this content?
report: Report
reported: Thank you for letting us know about this issue. We will look into the matter shortly.
runtime_output: Runtime Output
send_thank_you_note: Send
show_all: All requests
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
get :mark_as_solved, defaults: {format: :json}
post :set_thank_you_note, defaults: {format: :json}
post :clear_question
post :report
end
end
resources :comments, defaults: {format: :json}
Expand Down
4 changes: 2 additions & 2 deletions spec/controllers/comments_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
RSpec.describe CommentsController do
render_views

let(:user) { create(:learner) }
let(:rfc_with_comment) { create(:rfc_with_comment, user:) }
let(:user) { comment.user }
let(:rfc_with_comment) { create(:rfc_with_comment) }
Comment thread
nenock marked this conversation as resolved.
let(:comment) { rfc_with_comment.comments.first }
let(:updated_comment) { comment.reload }
let(:perform_request) { proc { put :update, format: :json, params: {id: comment.id, comment: comment_params} } }
Expand Down
10 changes: 10 additions & 0 deletions spec/factories/comment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

FactoryBot.define do
factory :comment do
file { create(:rfc).file }
user factory: :learner
Comment thread
arkirchner marked this conversation as resolved.
row { 1 }
text { "comment on file #{file.id} on #{row}" }
end
end
2 changes: 1 addition & 1 deletion spec/factories/request_for_comment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

factory :rfc_with_comment, class: 'RequestForComment' do
after(:create) do |rfc|
Comment.create(file: rfc.file, user: rfc.user, row: 1, text: "comment for rfc #{rfc.question}")
create(:comment, file: rfc.file)
end
end
end
Expand Down
9 changes: 9 additions & 0 deletions spec/mailers/previews/report_mailer_preview.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class ReportMailerPreview < ActionMailer::Preview
def report
rfc = FactoryBot.build_stubbed(:rfc)

ReportMailer.with(reported_content: rfc).report_content
end
end
27 changes: 27 additions & 0 deletions spec/mailers/report_mailer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe ReportMailer do
describe '#report_content' do
subject(:mail) { described_class.with(reported_content:).report_content }

context 'when an RfC is reported' do
let(:question) { 'Inappropriate content for RfC.' }
let(:reported_content) { create(:rfc, question:) }

it 'sets the correct sender' do
expect(mail.from).to include('codeocean@openhpi.de')
end

it 'sets the correct subject' do
expect(mail.subject).to eq(I18n.t('report_mailer.report_content.subject', content_name: RequestForComment.model_name.human))
end

it 'includes the reported content' do
expect(mail.text_part.body).to include(question)
expect(mail.html_part.body).to include(question)
end
end
end
end
Loading