feat(fraud): mark as sus#2080
Merged
NeonGamerBot-QK merged 6 commits intohackclub:mainfrom Apr 14, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a “suspicious user” flagging mechanism to User (tracking who flagged them), exposes mark/unmark actions via admin UI and webhook endpoints, and improves audit log rendering for these changes.
Changes:
- Add
users.marked_sus_by(string array) and a derivedUser#is_sus?helper. - Add admin UI controls + banner on the admin user page to mark/unmark a user as suspicious.
- Add webhook + admin routes/controllers for mark/unmark, and enhance audit log detail display for
marked_sus_bydiffs.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| db/schema.rb | Updates schema version and adds marked_sus_by array column to users. |
| db/migrate/20260407220819_add_marked_sus_by_to_users.rb | Migration introducing users.marked_sus_by. |
| config/routes.rb | Adds webhook endpoints and admin member routes for mark/unmark sus. |
| app/views/admin/users/show.html.erb | Shows “sus” banner and mark/unmark controls in admin UI. |
| app/views/admin/audit_logs/show.html.erb | Adds special-case display for sus events and a detailed diff UI. |
| app/models/user.rb | Adds is_sus? derived helper. |
| app/controllers/webhooks/mark_sus_controller.rb | Implements webhook mark/unmark sus endpoints. |
| app/controllers/admin/users_controller.rb | Implements admin mark/unmark sus actions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Member
|
Why is this required? Please fix your commit message
…On Wed, 8 Apr, 2026, 04:15 Copilot, ***@***.***> wrote:
***@***.**** commented on this pull request.
Pull request overview
Adds a “suspicious user” flagging mechanism to User (tracking who flagged
them), exposes mark/unmark actions via admin UI and webhook endpoints, and
improves audit log rendering for these changes.
*Changes:*
- Add users.marked_sus_by (string array) and a derived User#is_sus?
helper.
- Add admin UI controls + banner on the admin user page to mark/unmark
a user as suspicious.
- Add webhook + admin routes/controllers for mark/unmark, and enhance
audit log detail display for marked_sus_by diffs.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and
generated 6 comments.
Show a summary per file
File Description
db/schema.rb Updates schema version and adds marked_sus_by array column
to users.
db/migrate/20260407220819_add_marked_sus_by_to_users.rb Migration
introducing users.marked_sus_by.
config/routes.rb Adds webhook endpoints and admin member routes for
mark/unmark sus.
app/views/admin/users/show.html.erb Shows “sus” banner and mark/unmark
controls in admin UI.
app/views/admin/audit_logs/show.html.erb Adds special-case display for
sus events and a detailed diff UI.
app/models/user.rb Adds is_sus? derived helper.
app/controllers/webhooks/mark_sus_controller.rb Implements webhook
mark/unmark sus endpoints.
app/controllers/admin/users_controller.rb Implements admin mark/unmark
sus actions.
------------------------------
💡 Add Copilot custom instructions
<http:///hackclub/flavortown/new/main?filename=.github/instructions/*.instructions.md>
for smarter, more guided reviews. Learn how to get started
<https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot>
.
------------------------------
In app/controllers/webhooks/mark_sus_controller.rb
<#2080 (comment)>:
> +class Webhooks::MarkSusController < ApplicationController
+ skip_before_action :verify_authenticity_token
+ skip_before_action :enforce_ban
+ skip_before_action :refresh_identity_on_portal_return
+ before_action :load_users
+
Webhooks::ShipCertController protects its webhook with before_action
:verify_api_key, but this controller has no equivalent authentication. As
written, anyone who can guess an admin/fraud ft_user_id could call this
endpoint and mark arbitrary users as suspicious. Add API key (or signature)
verification consistent with the other webhook controllers and reject
unauthorized requests before load_users runs.
------------------------------
In app/controllers/webhooks/mark_sus_controller.rb
<#2080 (comment)>:
> + @marking_user = User.find_by(id: @ft_user_id)
+ unless @marking_user&.admin? || @marking_user&.has_role?(:fraud_dept)
+ render json: { error: "Forbidden: only admins and fraud department members can mark users as sus" }, status: :forbidden
+ return
+ end
Authorization here only allows admin or fraud_dept, but the linked issue
describes allowing shipwright/review roles (e.g. project_certifier /
ysws_reviewer) to mark users as sus. Consider introducing a dedicated
policy/role check for "mark sus" (instead of reusing ban/admin checks) and
aligning both this webhook and the admin UI with the intended roles.
------------------------------
In app/controllers/admin/users_controller.rb
<#2080 (comment)>:
> + def unmark_sus
+ authorize :admin, :ban_users?
+ @user = User.find(params[:id])
+
+ PaperTrail.request(whodunnit: current_user.id.to_s) do
+ @user.update!(marked_sus_by: @user.marked_sus_by - [ current_user.id.to_s ])
+ end
+
+ flash[:notice] = "Sus flag removed from ***@***.***_name}."
+ redirect_to ***@***.***)
+ end
unmark_sus always updates and flashes success, even if the current user
never marked this user as sus. This can lead to misleading UI and noisy
audit entries. Mirror mark_sus by checking include? first and showing a
"not marked by you" message (and skipping the update/version) when there’s
nothing to remove.
------------------------------
In app/views/admin/audit_logs/show.html.erb
<#2080 (comment)>:
> + <%
+ raw_changes = @version.object_changes
+ parsed_changes = raw_changes.is_a?(Hash) ? raw_changes : (JSON.parse(raw_changes) rescue {})
+ sus_change = parsed_changes["marked_sus_by"]
+ display_event = if sus_change.is_a?(Array) && sus_change.length == 2
+ before, after = sus_change
+ if Array(after).length > Array(before).length
+ "marked_sus"
+ elsif Array(after).length < Array(before).length
+ "unmarked_sus"
+ else
+ @version.event
+ end
+ else
+ @version.event
+ end
+ %>
+ <span class="badge badge-<%= display_event %>"><%= display_event.tr("_", " ") %></span>
This page infers a custom display_event for sus changes, but the audit
log index uses AuditLogsHelper#audit_event_display and will still show
these entries as a generic update (and filtering by event won’t include
them). Consider moving this inference into the shared helper (or creating
explicit PaperTrail events like marked_sus/unmarked_sus when updating the
user) so both index and show stay consistent.
------------------------------
In app/views/admin/audit_logs/show.html.erb
<#2080 (comment)>:
> + <% elsif field.to_s == "marked_sus_by" && values.is_a?(Array) && values.length == 2 %>
+ <%
+ before_ids = Array(values[0])
+ after_ids = Array(values[1])
+ added_ids = after_ids - before_ids
+ removed_ids = before_ids - after_ids
+ %>
+ <td colspan="2">
+ <div class="sus-diff">
+ <% if added_ids.any? %>
+ <% added_ids.each do |uid| %>
+ <% u = User.find_by(id: uid) %>
+ <span class="sus-diff__tag sus-diff__tag--added">
+ + flagged by <%= u ? link_to(u.display_name, admin_user_path(u)) : "user ##{uid}" %>
+ </span>
+ <% end %>
+ <% end %>
+ <% if removed_ids.any? %>
+ <% removed_ids.each do |uid| %>
+ <% u = User.find_by(id: uid) %>
+ <span class="sus-diff__tag sus-diff__tag--removed">
+ − unflagged by <%= u ? link_to(u.display_name, admin_user_path(u)) : "user ##{uid}" %>
+ </span>
+ <% end %>
Rendering the marked_sus_by diff performs a User.find_by query per
added/removed id. If multiple ids are present, this becomes an N+1 query
pattern on the audit log details page. Prefer batching (e.g., fetch all
relevant users in one query and index them by id) and render from that map.
------------------------------
In app/views/admin/users/show.html.erb
<#2080 (comment)>:
> +<% if @user.is_sus? && policy(:admin).ban_users? %>
+ <div style="margin-bottom: 1rem; background: #fef9c3; border: 1px solid #ca8a04; border-radius: 0.5rem; padding: 0.75rem 1rem; color: #713f12;">
+ <strong>
|
Member
Author
nothing else is changed besides adding the ability to mark people as sus..? |
Member
|
sus |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fixes #1652

This is a great feature which will help fraud dept diffrentiate between people