Class: Moderate::Appeal
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Moderate::Appeal
- Defined in:
- lib/moderate/models/appeal.rb
Overview
A DSA Art. 20 internal complaint against a moderation decision.
The Digital Services Act requires platforms to give affected users an “effective internal complaint-handling system” that is FREE, ELECTRONIC, open for AT LEAST SIX MONTHS after the decision, and decided by a HUMAN (not “solely on the basis of automated means”). This model encodes each of those:
- free + electronic: it's just a record + a queue (no payment path exists);
- six-month window: an appeal is refused once the report's appeal window has
closed (`report_must_still_be_appealable`);
- human-decided: there is no auto-decide path — uphold!/reject! (in a service)
require a moderator and a note;
- against a DECISION: an appeal can only be opened on an already-resolved
report (`report_must_be_closed`).
Source: eur-lex.europa.eu/eli/reg/2022/2065/oj (Art. 20)
Constant Summary collapse
- STATUSES =
Validated by the ‘validates :status, inclusion` below — NOT a DB constraint, so the vocabulary can grow without a host migration. `upheld` overturns the original decision; `rejected` confirms it.
%w[open upheld rejected].freeze
- SOURCES =
Who lodged the complaint. ‘notifier` = the person who filed the original notice; `affected_user` = the content owner whose content was actioned; the rest are operational. Validated by the model (inclusion), not a DB constraint.
%w[notifier affected_user admin other].freeze
Instance Method Summary collapse
- #closed? ⇒ Boolean
- #open? ⇒ Boolean
- #reject!(by:, note:) ⇒ Object
- #rejected? ⇒ Boolean
- #upheld? ⇒ Boolean
-
#uphold!(by:, note:) ⇒ Object
Decide this appeal — model-level sugar over Moderate::Services::ResolveAppeal, so a host can write ‘appeal.uphold!(by: moderator, note: “…”)` / `appeal.reject!(by: moderator, note: “…”)` instead of constructing the service.
Instance Method Details
#closed? ⇒ Boolean
72 73 74 |
# File 'lib/moderate/models/appeal.rb', line 72 def closed? status.in?(%w[upheld rejected]) end |
#open? ⇒ Boolean
68 69 70 |
# File 'lib/moderate/models/appeal.rb', line 68 def open? status == "open" end |
#reject!(by:, note:) ⇒ Object
93 94 95 |
# File 'lib/moderate/models/appeal.rb', line 93 def reject!(by:, note:) Moderate::Services::ResolveAppeal.new(self, by: by).reject!(note: note) end |
#rejected? ⇒ Boolean
80 81 82 |
# File 'lib/moderate/models/appeal.rb', line 80 def rejected? status == "rejected" end |
#upheld? ⇒ Boolean
76 77 78 |
# File 'lib/moderate/models/appeal.rb', line 76 def upheld? status == "upheld" end |
#uphold!(by:, note:) ⇒ Object
Decide this appeal — model-level sugar over Moderate::Services::ResolveAppeal, so a host can write ‘appeal.uphold!(by: moderator, note: “…”)` / `appeal.reject!(by: moderator, note: “…”)` instead of constructing the service. The service does the real work (audit, the appeal-decision notification, and —for an upheld appeal — reversing the original decision); these only forward.
89 90 91 |
# File 'lib/moderate/models/appeal.rb', line 89 def uphold!(by:, note:) Moderate::Services::ResolveAppeal.new(self, by: by).uphold!(note: note) end |