Add /user_actions page.
Add a /user_actions page. This page shows you a global timeline of (almost) all activity on the site, including uploads, comments, votes, edits, forum posts, and so on. The main things it doesn't include are post edits, pool edits, and favorites (posts and pools live in a separate database, and favorites don't have the timestamps we need for ordering). This page is useful for moderation purposes because it lets you see a history of almost all of a user's activity on a single page. Currently this page is mod-only. In the future it will be open to all users, so you can view the history of your own site activity, or the activity of others.
This commit is contained in:
23
app/controllers/user_actions_controller.rb
Normal file
23
app/controllers/user_actions_controller.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class UserActionsController < ApplicationController
|
||||
respond_to :html, :xml, :json
|
||||
|
||||
def index
|
||||
if user_id = params[:user_id] || params.dig(:search, :user_id)
|
||||
@user = User.find(user_id)
|
||||
elsif user_name = params.dig(:search, :user_name)
|
||||
@user = User.find_by_name(user_name)
|
||||
end
|
||||
|
||||
@user_actions = authorize UserAction.for_user(CurrentUser.user).paginated_search(params, count_pages: @user.present?)
|
||||
@user_actions = @user_actions.includes(:user, model: [:artist, :post, :note, :user, :creator, :banner, :bulk_update_request, :tag, :antecedent_tag, :consequent_tag, :model, :topic, :purchaser, :recipient, :forum_topic, forum_post: [:topic], comment: [:creator, :post]]) if request.format.html?
|
||||
|
||||
respond_with(@user_actions)
|
||||
end
|
||||
|
||||
def show
|
||||
@user_actions = authorize UserAction.find(params[:id])
|
||||
respond_with(@user_actions)
|
||||
end
|
||||
end
|
||||
@@ -199,7 +199,7 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def link_to_search(tag, **options)
|
||||
link_to tag.name, posts_path(tags: tag.name), class: tag_class(tag), **options
|
||||
link_to tag.pretty_name, posts_path(tags: tag.name), class: tag_class(tag), **options
|
||||
end
|
||||
|
||||
def link_to_wiki(text, title = text, **options)
|
||||
|
||||
@@ -234,6 +234,10 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def revised?
|
||||
updated_at > created_at
|
||||
end
|
||||
|
||||
def warnings
|
||||
@warnings ||= ActiveModel::Errors.new(self)
|
||||
end
|
||||
|
||||
@@ -69,6 +69,10 @@ class Ban < ApplicationRecord
|
||||
ApplicationController.helpers.humanized_duration(duration)
|
||||
end
|
||||
|
||||
def forever?
|
||||
duration.present? && duration >= 100.years
|
||||
end
|
||||
|
||||
def expired?
|
||||
persisted? && expires_at < Time.zone.now
|
||||
end
|
||||
|
||||
@@ -76,7 +76,11 @@ class Dmail < ApplicationRecord
|
||||
|
||||
module SearchMethods
|
||||
def visible(user)
|
||||
where(owner: user)
|
||||
if user.is_anonymous?
|
||||
none
|
||||
else
|
||||
where(owner: user)
|
||||
end
|
||||
end
|
||||
|
||||
def sent_by(user)
|
||||
|
||||
@@ -8,7 +8,7 @@ class Favorite < ApplicationRecord
|
||||
after_create :upvote_post_on_create
|
||||
after_destroy :unvote_post_on_destroy
|
||||
|
||||
scope :public_favorites, -> { where(user: User.has_public_favorites) }
|
||||
scope :public_favorites, -> { where.not(user: User.has_private_favorites) }
|
||||
|
||||
def self.visible(user)
|
||||
if user.is_admin?
|
||||
|
||||
@@ -17,6 +17,9 @@ class FavoriteGroup < ApplicationRecord
|
||||
|
||||
array_attribute :post_ids, parse: /\d+/, cast: :to_i
|
||||
|
||||
scope :is_public, -> { where(is_public: true) }
|
||||
scope :is_private, -> { where(is_public: false) }
|
||||
|
||||
module SearchMethods
|
||||
def for_post(post_id)
|
||||
where_array_includes_any(:post_ids, [post_id])
|
||||
@@ -29,7 +32,13 @@ class FavoriteGroup < ApplicationRecord
|
||||
end
|
||||
|
||||
def visible(user)
|
||||
where(is_public: true).or(where(creator_id: user.id))
|
||||
if user.is_owner?
|
||||
all
|
||||
elsif user.is_anonymous?
|
||||
is_public
|
||||
else
|
||||
is_public.or(where(creator: user))
|
||||
end
|
||||
end
|
||||
|
||||
def search(params)
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
class ForumPostVote < ApplicationRecord
|
||||
belongs_to :creator, class_name: "User"
|
||||
belongs_to :forum_post
|
||||
belongs_to :bulk_update_request, primary_key: :forum_post_id, foreign_key: :forum_post_id, optional: true
|
||||
|
||||
validates :creator_id, uniqueness: {scope: :forum_post_id}
|
||||
validates :score, inclusion: {in: [-1, 0, 1]}
|
||||
|
||||
|
||||
@@ -35,8 +35,10 @@ class ModerationReport < ApplicationRecord
|
||||
def self.visible(user)
|
||||
if user.is_moderator?
|
||||
all
|
||||
else
|
||||
elsif !user.is_anonymous?
|
||||
where(creator: user)
|
||||
else
|
||||
none
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class PostVote < ApplicationRecord
|
||||
|
||||
scope :positive, -> { where("post_votes.score > 0") }
|
||||
scope :negative, -> { where("post_votes.score < 0") }
|
||||
scope :public_votes, -> { active.positive.where(user: User.has_public_favorites) }
|
||||
scope :public_votes, -> { active.positive.where.not(user: User.has_private_favorites) }
|
||||
|
||||
deletable
|
||||
|
||||
|
||||
@@ -18,7 +18,11 @@ class SavedSearch < ApplicationRecord
|
||||
scope :has_tag, ->(name) { where_regex(:query, "(^| )[~-]?#{Regexp.escape(name)}( |$)", flags: "i") }
|
||||
|
||||
def self.visible(user)
|
||||
where(user: user)
|
||||
if user.is_anonymous?
|
||||
none
|
||||
else
|
||||
where(user: user)
|
||||
end
|
||||
end
|
||||
|
||||
concerning :Redis do
|
||||
|
||||
@@ -39,4 +39,8 @@ class TagVersion < ApplicationRecord
|
||||
def category_name
|
||||
TagCategory.reverse_mapping[category].capitalize
|
||||
end
|
||||
|
||||
def pretty_name
|
||||
name.tr("_", " ")
|
||||
end
|
||||
end
|
||||
|
||||
122
app/models/user_action.rb
Normal file
122
app/models/user_action.rb
Normal file
@@ -0,0 +1,122 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class UserAction < ApplicationRecord
|
||||
belongs_to :model, polymorphic: true
|
||||
belongs_to :user
|
||||
|
||||
attribute :model_type, :string
|
||||
attribute :model_id, :integer
|
||||
attribute :user_id, :integer
|
||||
attribute :event_type, :string
|
||||
attribute :event_at, :time
|
||||
|
||||
def self.model_types
|
||||
%w[ArtistVersion ArtistCommentaryVersion Ban BulkUpdateRequest Comment
|
||||
CommentVote Dmail FavoriteGroup ForumPost ForumPostVote ForumTopic
|
||||
ModAction ModerationReport NoteVersion Post PostAppeal PostApproval
|
||||
PostDisapproval PostFlag PostReplacement PostVote SavedSearch TagAlias
|
||||
TagImplication TagVersion Upload User UserEvent UserFeedback UserUpgrade
|
||||
UserNameChangeRequest WikiPageVersion]
|
||||
end
|
||||
|
||||
def self.for_user(user)
|
||||
sql = <<~SQL.squish
|
||||
(#{ArtistVersion.visible(user).select("'ArtistVersion'::character varying AS model_type, id AS model_id, updater_id AS user_id, 'create'::character varying AS event_type, created_at AS event_at").to_sql})
|
||||
UNION ALL
|
||||
(#{ArtistCommentaryVersion.visible(user).select("'ArtistCommentaryVersion', id, updater_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{Ban.visible(user).select("'Ban', id, user_id, 'subject', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{BulkUpdateRequest.visible(user).select("'BulkUpdateRequest', id, user_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{Comment.visible(user).select("'Comment', id, creator_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{CommentVote.visible(user).select("'CommentVote', id, user_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{Dmail.visible(user).sent.select("'Dmail', id, from_id, 'create', created_at").order(created_at: :desc).to_sql})
|
||||
UNION ALL
|
||||
(#{FavoriteGroup.visible(user).select("'FavoriteGroup', id, creator_id, 'create', created_at").order(created_at: :desc).to_sql})
|
||||
UNION ALL
|
||||
(#{ForumPost.visible(user).select("'ForumPost', id, creator_id, 'create', created_at").order(created_at: :desc).to_sql})
|
||||
UNION ALL
|
||||
(#{ForumPostVote.visible(user).select("'ForumPostVote', id, creator_id, 'create', created_at").order(created_at: :desc).to_sql})
|
||||
UNION ALL
|
||||
(#{ForumTopic.visible(user).select("'ForumTopic', id, creator_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{ModAction.visible(user).select("'ModAction', id, creator_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{ModerationReport.visible(user).select("'ModerationReport', id, creator_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{NoteVersion.visible(user).select("'NoteVersion', id, updater_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{Post.visible(user).select("'Post', id, uploader_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{PostAppeal.visible(user).select("'PostAppeal', id, creator_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{PostApproval.visible(user).select("'PostApproval', id, user_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{PostDisapproval.visible(user).select("'PostDisapproval', id, user_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{PostFlag.visible(user).select("'PostFlag', id, creator_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{PostReplacement.visible(user).select("'PostReplacement', id, creator_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{PostVote.visible(user).select("'PostVote', id, user_id, 'create', created_at").order(created_at: :desc).to_sql})
|
||||
UNION ALL
|
||||
(#{SavedSearch.visible(user).select("'SavedSearch', id, user_id, 'create', created_at").order(created_at: :desc).to_sql})
|
||||
UNION ALL
|
||||
(#{TagAlias.visible(user).select("'TagAlias', id, creator_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{TagImplication.visible(user).select("'TagImplication', id, creator_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{TagVersion.visible(user).select("'TagVersion', id, updater_id, 'create', created_at").where("updater_id IS NOT NULL").order(created_at: :desc).to_sql})
|
||||
UNION ALL
|
||||
(#{Upload.visible(user).select("'Upload', id, uploader_id, 'create', created_at").order(created_at: :desc).to_sql})
|
||||
UNION ALL
|
||||
(#{User.visible(user).select("'User', id, id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{UserEvent.visible(user).select("'UserEvent', id, user_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{UserFeedback.visible(user).select("'UserFeedback', id, creator_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{UserFeedback.visible(user).select("'UserFeedback', id, user_id, 'subject', created_at").to_sql})
|
||||
UNION ALL (
|
||||
(#{UserUpgrade.visible(user).select("'UserUpgrade', id, purchaser_id, 'create', created_at").where(status: [:complete, :refunded]).order(created_at: :desc).to_sql})
|
||||
) UNION ALL
|
||||
(#{UserNameChangeRequest.visible(user).select("'UserNameChangeRequest', id, user_id, 'create', created_at").to_sql})
|
||||
UNION ALL
|
||||
(#{WikiPageVersion.visible(user).select("'WikiPageVersion', id, updater_id, 'create', created_at").to_sql})
|
||||
SQL
|
||||
|
||||
from("(#{sql}) user_actions")
|
||||
end
|
||||
|
||||
def self.visible(user)
|
||||
all
|
||||
end
|
||||
|
||||
def self.search(params)
|
||||
q = search_attributes(params, :event_type, :user, :model)
|
||||
|
||||
case params[:order]
|
||||
when "event_at_asc"
|
||||
q = q.order(event_at: :asc, model_id: :asc)
|
||||
else
|
||||
q = q.apply_default_order(params)
|
||||
end
|
||||
|
||||
q
|
||||
end
|
||||
|
||||
def self.default_order
|
||||
order(event_at: :desc, model_id: :desc)
|
||||
end
|
||||
|
||||
def self.available_includes
|
||||
[:user, :model]
|
||||
end
|
||||
|
||||
def readonly?
|
||||
true
|
||||
end
|
||||
end
|
||||
@@ -21,6 +21,10 @@ class CommentPolicy < ApplicationPolicy
|
||||
user.is_moderator?
|
||||
end
|
||||
|
||||
def can_see_creator?
|
||||
!record.is_deleted? || can_see_deleted?
|
||||
end
|
||||
|
||||
def reply?
|
||||
!record.is_deleted?
|
||||
end
|
||||
|
||||
20
app/policies/user_action_policy.rb
Normal file
20
app/policies/user_action_policy.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class UserActionPolicy < ApplicationPolicy
|
||||
def index?
|
||||
user.is_moderator?
|
||||
end
|
||||
|
||||
def can_see_user?
|
||||
case record.model_type
|
||||
when "Comment"
|
||||
policy(record.model).can_see_creator?
|
||||
when "PostFlag"
|
||||
policy(record.model).can_view_flagger?
|
||||
when "PostDisapproval"
|
||||
policy(record.model).can_view_creator?
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -145,6 +145,11 @@
|
||||
<ul>
|
||||
<li><h2>Admin</h2></li>
|
||||
<li><%= link_to("Mod Actions", mod_actions_path) %></li>
|
||||
|
||||
<% if policy(UserAction).index? %>
|
||||
<li><%= link_to("User Actions", user_actions_path) %></li>
|
||||
<% end %>
|
||||
|
||||
<li><%= link_to("Bulk Update Requests", bulk_update_requests_path) %></li>
|
||||
|
||||
<% if policy(UserNameChangeRequest).index? %>
|
||||
|
||||
11
app/views/user_actions/_secondary_links.html.erb
Normal file
11
app/views/user_actions/_secondary_links.html.erb
Normal file
@@ -0,0 +1,11 @@
|
||||
<% content_for(:secondary_links) do %>
|
||||
<%= quick_search_form_for(:user_name, user_actions_path, "users", autocomplete: "user") %>
|
||||
<%= subnav_link_to "Mod Actions", mod_actions_path %>
|
||||
<%= subnav_link_to "User Actions", user_actions_path %>
|
||||
<%= subnav_link_to "User Events", user_events_path %>
|
||||
<%= subnav_link_to "Bans", bans_path %>
|
||||
<%= subnav_link_to "IP Bans", ip_bans_path %>
|
||||
<%= subnav_link_to "Feedbacks", user_feedbacks_path %>
|
||||
<%= subnav_link_to "Mod Reports", moderation_reports_path %>
|
||||
<%= subnav_link_to "Modqueue", modqueue_index_path %>
|
||||
<% end %>
|
||||
161
app/views/user_actions/index.html.erb
Normal file
161
app/views/user_actions/index.html.erb
Normal file
@@ -0,0 +1,161 @@
|
||||
<div id="c-user-actions">
|
||||
<div id="a-index">
|
||||
<% if @user %>
|
||||
<h1>User Actions: <%= link_to_user @user %></h1>
|
||||
<%= link_to "« Back", user_actions_path, class: "text-xs" %>
|
||||
<% else %>
|
||||
<h1>User Actions</h1>
|
||||
<% end %>
|
||||
|
||||
<%= search_form_for(user_actions_path) do |f| %>
|
||||
<%= f.input :user_name, label: "User", input_html: { value: @user&.name, "data-autocomplete": "user" } %>
|
||||
<%= f.input :model_type, label: "Category", collection: UserAction.model_types.map { |type| [type.delete_suffix("Version").titleize, type] }, include_blank: true, selected: params[:search][:model_type] %>
|
||||
<%= f.input :order, collection: [%w[Newest event_at], %w[Oldest event_at_asc]], include_blank: true, selected: params[:search][:order] %>
|
||||
<%= f.submit "Search" %>
|
||||
<% end %>
|
||||
|
||||
<div>
|
||||
<%= table_for @user_actions, class: "striped autofit", width: "100%" do |t| %>
|
||||
<% t.column "Event", td: { class: "col-expand" } do |user_action| %>
|
||||
<% model = user_action.model %>
|
||||
<% user = user_action.user %>
|
||||
<% event_type = user_action.event_type %>
|
||||
|
||||
<% case user_action.model_type %>
|
||||
<% when "ArtistVersion" %>
|
||||
<%= link_to_user user %> <%= link_to "updated", model %> the artist <%= link_to model.artist.pretty_name, model.artist, class: "tag-type-#{Tag.categories.artist}" %>.
|
||||
<% when "ArtistCommentaryVersion" %>
|
||||
<%= link_to_user user %> updated the <%= link_to "commentary", model %> for <%= link_to model.post.dtext_shortlink, model.post %>.
|
||||
<% when "NoteVersion" %>
|
||||
<%= link_to_user user %> <%= link_to "updated", model %> a <%= link_to "note", model.note %> on <%= link_to model.post.dtext_shortlink, model.post %>.
|
||||
<% when "TagVersion" %>
|
||||
<%= link_to_user user %> updated the tag <%= link_to model.tag.name, model, class: tag_class(model) %>.
|
||||
<% when "WikiPageVersion" %>
|
||||
<%= link_to_user user %> <%= link_to "updated", model %> the <%= link_to_wiki model.title %> wiki.
|
||||
<% when "Ban" %>
|
||||
<div class="prose">
|
||||
<%= link_to_user user %> was <%= link_to (model.forever? ? "banned forever" : "banned for #{model.humanized_duration}"), model %> by <%= link_to_user model.banner %> (<%= format_text(model.reason.chomp(".").strip, inline: true) %>).
|
||||
</div>
|
||||
<% when "BulkUpdateRequest" %>
|
||||
<%= link_to_user user %> created a <%= link_to "new BUR", model %> in <%= link_to model.forum_topic.title, model.forum_post %>.
|
||||
<% when "Comment" %>
|
||||
<% if model.is_deleted? && !policy(model).can_see_deleted? %>
|
||||
[deleted] posted a <%= link_to "deleted comment", model %> on <%= link_to model.post.dtext_shortlink, model.post %>.
|
||||
<% else %>
|
||||
<%= link_to_user user %> <%= link_to "commented", model %> on <%= link_to model.post.dtext_shortlink, model.post %>.
|
||||
<% end %>
|
||||
<% when "CommentVote" %>
|
||||
<%= link_to_user user %> <%= model.is_positive? ? "upvoted" : "downvoted" %> a <%= link_to "comment", model.comment %> by <%= link_to_user model.comment.creator %> on <%= link_to model.comment.post.dtext_shortlink, model.comment.post %>.
|
||||
<% when "Dmail" %>
|
||||
<%= link_to_user user %> sent a dmail to <%= link_to_user model.to %> (<%= link_to model.title.strip, model %>).
|
||||
<% when "FavoriteGroup" %>
|
||||
<%= link_to_user user %> create <%= model.is_public? ? "public" : "private" %> favgroup <%= link_to model.pretty_name, model %>.
|
||||
<% when "ForumPost" %>
|
||||
<%= link_to_user user %> <%= link_to "posted", model %> in topic <%= link_to model.topic.title.chomp(".").strip, model.topic %>.
|
||||
<% when "ForumTopic" %>
|
||||
<%= link_to_user user %> created topic "<%= link_to model.title.strip, model %>".
|
||||
<% when "ForumPostVote" %>
|
||||
<% if model&.bulk_update_request.present? %>
|
||||
<%= link_to_user user %> <%= model.vote_type %>voted a <%= link_to "BUR", model.bulk_update_request %> in topic <%= link_to model.forum_post.topic.title.strip, model.forum_post %>.
|
||||
<% else %>
|
||||
<%= link_to_user user %> <%= model.vote_type %>voted a <%= link_to "post", model.forum_post %> in topic <%= link_to model.forum_post.topic.title.strip, model.forum_post %>.
|
||||
<% end %>
|
||||
<% when "ModAction" %>
|
||||
<div class="prose">
|
||||
<%= link_to_user user %> <%= format_text(model.description, inline: true) %>.
|
||||
</div>
|
||||
<% when "ModerationReport" %>
|
||||
<div class="prose">
|
||||
<%= link_to_user user %> <%= link_to "reported", model %> a <%= link_to model.model.class.name.titleize.downcase, model.model %> by <%= link_to_user model.reported_user %> (<%= format_text(model.reason.chomp(".").strip, inline: true) %>).
|
||||
</div>
|
||||
<% when "TagAlias" %>
|
||||
<%= link_to_user user %> aliased <%= link_to_search model.antecedent_tag %> to <%= link_to_search model.consequent_tag %>.
|
||||
<% when "TagImplication" %>
|
||||
<%= link_to_user user %> implied <%= link_to_search model.antecedent_tag %> to <%= link_to_search model.consequent_tag %>.
|
||||
<% when "Post" %>
|
||||
<%= link_to_user user %> created <%= link_to model.dtext_shortlink, model %>.
|
||||
<% when "PostAppeal" %>
|
||||
<%= link_to_user user %> appealed <%= link_to model.post.dtext_shortlink, model.post %>.
|
||||
<% when "PostApproval" %>
|
||||
<%= link_to_user user %> approved <%= link_to model.post.dtext_shortlink, model.post %>.
|
||||
<% when "PostDisapproval" %>
|
||||
<div class="prose">
|
||||
<% if policy(model).can_view_creator? %>
|
||||
<%= link_to_user user %> disapproved <%= link_to model.post.dtext_shortlink, model.post %> (<%= model.reason.titleize.downcase %><%= ": ".html_safe + format_text(model.message.chomp(".").strip, inline: true) if model.message.present? %>).
|
||||
<% else %>
|
||||
<%= link_to model.post.dtext_shortlink, model.post %> was disapproved (<%= model.reason.titleize.downcase %><%= ": ".html_safe + format_text(model.message.chomp(".").strip, inline: true) if model.message.present? %>).
|
||||
<% end %>
|
||||
</div>
|
||||
<% when "PostFlag" %>
|
||||
<div class="prose">
|
||||
<% if policy(model).can_view_flagger? %>
|
||||
<%= link_to_user user %> flagged <%= link_to model.post.dtext_shortlink, model.post %> (<%= format_text(model.reason.chomp(".").strip, inline: true) %>).
|
||||
<% else %>
|
||||
<%= link_to model.post.dtext_shortlink, model.post %> was flagged (<%= format_text(model.reason.chomp(".").strip, inline: true) %>).
|
||||
<% end %>
|
||||
</div>
|
||||
<% when "PostReplacement" %>
|
||||
<%= link_to_user user %> replaced <%= link_to model.post.dtext_shortlink, model.post %> with <%= external_link_to Source::URL.page_url(model.replacement_url) || model.replacement_url %>.
|
||||
<% when "PostVote" %>
|
||||
<%= link_to_user user %> <%= model.is_positive? ? "upvoted" : "downvoted" %> <%= link_to model.post.dtext_shortlink, model.post %>.
|
||||
<% when "SavedSearch" %>
|
||||
<%= link_to_user user %> saved search <%= link_to model.query, posts_path(tag: model.query) %>.
|
||||
<% when "Upload" %>
|
||||
<%= link_to_user user %> created <%= link_to model.dtext_shortlink, model %>.
|
||||
<% when "User" %>
|
||||
<%= link_to_user user %> created their account.
|
||||
<% when "UserEvent" %>
|
||||
<% case model.category %>
|
||||
<% when "login" %>
|
||||
<%= link_to_user user %> logged in.
|
||||
<% when "failed_login" %>
|
||||
Failed login attempt for <%= link_to_user user %>.
|
||||
<% when "logout" %>
|
||||
<%= link_to_user user %> logged out.
|
||||
<% when "user_creation" %>
|
||||
<%= link_to_user user %> created their account.
|
||||
<% when "user_deletion" %>
|
||||
<%= link_to_user user %> deleted their account.
|
||||
<% when "password_reset" %>
|
||||
<%= link_to_user user %> reset their password.
|
||||
<% when "password_reset" %>
|
||||
<%= link_to_user user %> changed their password.
|
||||
<% when "email_change" %>
|
||||
<%= link_to_user user %> changed their email address.
|
||||
<% end %>
|
||||
<% when "UserFeedback" %>
|
||||
<% case event_type %>
|
||||
<% when "create" %>
|
||||
<%= link_to_user model.creator %> created a <%= link_to "#{model.category} feedback", model %> for <%= link_to_user model.user %>.
|
||||
<% when "subject" %>
|
||||
<%= link_to_user model.user %> received a <%= link_to "#{model.category} feedback", model %> from <%= link_to_user model.creator %>.
|
||||
<% end %>
|
||||
<% when "UserNameChangeRequest" %>
|
||||
<%= link_to_user model.user %> <%= link_to "changed their name", model %> from <%= model.original_name %> to <%= model.desired_name %>.
|
||||
<% when "UserUpgrade" %>
|
||||
<% if model.complete? %>
|
||||
<%= link_to_user model.purchaser %> <%= link_to "upgraded", model %> <%= link_to_user model.recipient if model.is_gift? %> to <%= model.level_string %>.
|
||||
<% elsif model.refunded? %>
|
||||
<%= link_to_user model.purchaser %> <%= link_to "upgraded", model %> <%= link_to_user model.recipient if model.is_gift? %> to <%= model.level_string %> (refunded).
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% t.column "Category" do |user_action| %>
|
||||
<%= link_to user_action.model_type.delete_suffix("Version").titleize, user_actions_path(search: { model_type: user_action.model_type }) %>
|
||||
<% end %>
|
||||
|
||||
<% t.column "Date" do |user_action| %>
|
||||
<% if policy(user_action).can_see_user? %>
|
||||
<%= link_to_user user_action.user %> <%= link_to "»", user_actions_path(search: { **search_params, user_id: user_action.user_id }) %>
|
||||
<% end %>
|
||||
<div><%= time_ago_in_words_tagged(user_action.event_at) %></div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= numbered_paginator(@user_actions) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "secondary_links" %>
|
||||
@@ -261,7 +261,9 @@ Rails.application.routes.draw do
|
||||
resources :upload_media_assets, only: [:show, :index], path: "assets"
|
||||
end
|
||||
resources :upload_media_assets, only: [:show, :index]
|
||||
resources :user_actions, only: [:index, :show]
|
||||
resources :users do
|
||||
resources :actions, only: [:index]
|
||||
resources :favorites, only: [:index, :create, :destroy]
|
||||
resources :favorite_groups, controller: "favorite_groups", only: [:index], as: "favorite_groups"
|
||||
resource :email, only: [:show, :edit, :update] do
|
||||
|
||||
@@ -3,5 +3,6 @@ FactoryBot.define do
|
||||
creator
|
||||
reason {"xxx"}
|
||||
status { :pending }
|
||||
model { build(:comment) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,5 +2,6 @@ FactoryBot.define do
|
||||
factory(:user_event) do
|
||||
user
|
||||
user_session
|
||||
category { :login }
|
||||
end
|
||||
end
|
||||
|
||||
72
test/functional/user_actions_controller_test.rb
Normal file
72
test/functional/user_actions_controller_test.rb
Normal file
@@ -0,0 +1,72 @@
|
||||
require 'test_helper'
|
||||
|
||||
class UserActionsControllerTest < ActionDispatch::IntegrationTest
|
||||
context "The user actions controller" do
|
||||
context "index action" do
|
||||
setup do
|
||||
@user = create(:user)
|
||||
|
||||
as(@user) do
|
||||
create(:artist)
|
||||
create(:artist_commentary)
|
||||
create(:ban)
|
||||
create(:bulk_update_request)
|
||||
create(:comment)
|
||||
create(:comment_vote)
|
||||
create(:dmail)
|
||||
create(:favorite_group)
|
||||
create(:forum_post)
|
||||
create(:forum_post_vote)
|
||||
create(:forum_topic)
|
||||
create(:mod_action)
|
||||
create(:moderation_report)
|
||||
create(:note)
|
||||
create(:post)
|
||||
create(:post_appeal)
|
||||
create(:post_approval)
|
||||
create(:post_disapproval)
|
||||
create(:post_flag)
|
||||
create(:post_replacement)
|
||||
create(:post_vote)
|
||||
create(:wiki_page)
|
||||
create(:saved_search)
|
||||
create(:tag)
|
||||
create(:tag_alias)
|
||||
create(:tag_implication)
|
||||
create(:upload)
|
||||
create(:user_event)
|
||||
create(:user_feedback)
|
||||
create(:user_name_change_request)
|
||||
create(:user_upgrade)
|
||||
create(:wiki_page)
|
||||
end
|
||||
end
|
||||
|
||||
should "render for the owner" do
|
||||
get_auth user_events_path(limit: 1000), create(:admin_user)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
should "render for an admin" do
|
||||
get_auth user_events_path(limit: 1000), create(:admin_user)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
should "render for a mod" do
|
||||
get_auth user_events_path(limit: 1000), create(:moderator_user)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
should "fail for a normal user" do
|
||||
get_auth user_actions_path(limit: 1000), create(:user)
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
should "render when filtering on a single user" do
|
||||
get_auth user_events_path(user_id: @user.id, limit: 1000), create(:owner_user)
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user