Skip to content
8 changes: 8 additions & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,11 @@ kbd {
right: 0.15em;
};
}

.is-9-desktop-12-mobile {
width: 75%;

@media screen and (max-width:850px) {
width: 100%;
}
}
6 changes: 5 additions & 1 deletion app/assets/stylesheets/tabs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@

.tabs {
margin-bottom: 1em;
}

.tabs--push {
flex-grow: 1;
}
}
30 changes: 30 additions & 0 deletions app/assets/stylesheets/users.scss
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,33 @@ $sizes: (16, 32, 40, 48, 64, 128, 256);
}
}
}

.modtools--sidebar {
margin-right: 1rem;
}
.modtools--usercard {
padding: 0.5rem;
}
.modtools-tbl-noborder {
th {
border-bottom-width: 1px !important;
width: 150px;
}
}

.mod-warnings-clear-form { display: inline; }

.modtools--top-list {
display: none;
}


@media screen and (max-width: 850px) {
.modtools--top-list {
display: block;
}

.modtools--sidebar {
display: none;
}
}
8 changes: 5 additions & 3 deletions app/controllers/admin_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
class AdminController < ApplicationController
before_action :verify_admin, except: [:change_back, :verify_elevation]
before_action :verify_global_admin, only: [:admin_email, :send_admin_email, :new_site, :create_site, :setup,
:setup_save, :hellban, :all_email, :send_all_email]
:setup_save, :failban, :all_email, :send_all_email]
before_action :verify_developer, only: [:change_users, :impersonate]
before_action :set_user, only: [:change_users, :hellban, :impersonate]
before_action :set_user, only: [:change_users, :failban, :impersonate]

skip_before_action :check_if_warning_or_suspension_pending, only: [:change_back, :verify_elevation]

Expand Down Expand Up @@ -204,7 +204,7 @@ def setup_save
render
end

def hellban
def failban
@user.block("user manually blocked by admin ##{current_user.id}")
flash[:success] = t 'admin.user_fed_stat'
redirect_back fallback_location: admin_path
Expand All @@ -213,6 +213,8 @@ def hellban
def impersonate
if Rails.env.development?
change_users
else
render layout: 'without_sidebar'
end
end

Expand Down
1 change: 1 addition & 0 deletions app/controllers/moderator_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def user_vote_summary
total: Vote.for(@user).count
)
)
render layout: 'without_sidebar'
end

def spammy_users
Expand Down
42 changes: 13 additions & 29 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

# rubocop:disable Metrics/ClassLength
class UsersController < ApplicationController
layout 'without_sidebar'

include Devise::Controllers::Rememberable

before_action :authenticate_user!, only: [:edit_profile, :update_profile, :stack_redirect,
Expand All @@ -12,11 +14,12 @@ class UsersController < ApplicationController

before_action :redirect_to_sign_in, only: [:filters], unless: [:user_signed_in?, :json_request?]

before_action :verify_moderator, only: [:mod, :destroy, :soft_delete, :role_toggle, :full_log,
:annotate, :annotations, :mod_privileges, :mod_privilege_action]
before_action :set_user, only: [:show, :mod, :destroy, :soft_delete, :posts, :role_toggle, :full_log, :activity,
:annotate, :annotations, :mod_privileges, :mod_privilege_action,
:vote_summary, :network, :avatar]
before_action :verify_moderator, only: [:mod, :soft_delete, :role_toggle, :full_log,
:annotate, :annotations, :mod_privileges, :mod_privilege_action, :mod_delete]
before_action :verify_global_moderator, only: [:mod_failban, :mod_delete_network_account]
before_action :set_user, only: [:show, :mod, :mod_delete, :mod_failban, :mod_delete_network_account, :soft_delete,
:posts, :role_toggle, :full_log, :activity, :annotate, :annotations, :mod_privileges,
:mod_privilege_action, :vote_summary, :network, :avatar]
before_action :check_deleted, only: [:show, :posts, :activity]

def index
Expand All @@ -36,7 +39,9 @@ def index
@post_counts = Post.where(user_id: @users.pluck(:id).uniq).group(:user_id).count

respond_to do |format|
format.html
format.html do
render layout: 'application'
end
format.json do
render json: @users
end
Expand All @@ -60,7 +65,6 @@ def show
.count
end
@posts = @posts.first(@limit)
render layout: 'without_sidebar'
end

def me
Expand Down Expand Up @@ -92,7 +96,6 @@ def preferences
prefs = current_user.preferences
@preferences = prefs[:global]
@community_prefs = prefs[:community]
render layout: 'without_sidebar'
end
format.json do
render json: current_user.preferences
Expand Down Expand Up @@ -135,9 +138,7 @@ def filters_json

def filters
respond_to do |format|
format.html do
render layout: 'without_sidebar'
end
format.html
format.json do
render json: filters_json
end
Expand Down Expand Up @@ -225,7 +226,7 @@ def posts

respond_to do |format|
format.html do
render :posts
render :posts, layout: 'application'
end
format.json do
render json: @posts
Expand All @@ -239,7 +240,6 @@ def my_network

def network
@communities = Community.all
render layout: 'without_sidebar'
end

def my_activity
Expand Down Expand Up @@ -272,11 +272,8 @@ def activity
end

@items = items.sort_by(&:created_at).reverse.paginate(page: params[:page], per_page: 50)
render layout: 'without_sidebar'
end

def mod; end

def full_log
@posts = Post.by(@user).count
@comments = Comment.by(@user).count
Expand Down Expand Up @@ -315,8 +312,6 @@ def full_log
SuggestedEdit.by(@user).all + PostHistory.by(@user).all +
ModWarning.to(@user).all
end).sort_by(&:created_at).reverse.paginate(page: params[:page], per_page: 50)

render layout: 'without_sidebar'
end

def mod_privileges
Expand Down Expand Up @@ -349,10 +344,6 @@ def soft_delete
render json: { status: 'success', user: @user.id }
end

def edit_profile
render layout: 'without_sidebar'
end

def cleaned_profile_websites(profile_params)
sites = profile_params[:user_websites_attributes]

Expand Down Expand Up @@ -575,7 +566,6 @@ def annotations
@logs = AuditLog.where(log_type: 'user_annotation', related: @user)
.newest_first
.paginate(page: params[:page], per_page: 20)
render layout: 'without_sidebar'
end

def annotate
Expand Down Expand Up @@ -605,8 +595,6 @@ def vote_summary
[k, vl.group_by(&:post), vl.sum { |v| v.vote_type * v.vote_count }]
end
.paginate(page: params[:page], per_page: 15)

render layout: 'without_sidebar'
end

def avatar
Expand All @@ -628,10 +616,6 @@ def specific_avatar
end
end

def disconnect_sso
render layout: 'without_sidebar'
end

def confirm_disconnect_sso
if current_user.sso_profile.blank? || !helpers.devise_sign_in_enabled? || !SiteSetting['AllowSsoDisconnect']
flash[:danger] = 'You cannot disable Single Sign-On.'
Expand Down
62 changes: 37 additions & 25 deletions app/views/admin/impersonate.html.erb
Original file line number Diff line number Diff line change
@@ -1,31 +1,43 @@
<h1>Impersonate <%= @user.username %></h1>
<p>
As a developer, you have access to impersonate users to help in reproducing bug reports, among other things.
</p>
<% content_for :title, "Moderator Tools: #{rtl_safe_username(@user)}" %>

<div class="notice is-warning has-color-yellow-900">
<h3><i class="fas fa-exclamation-triangle"></i> Caution</h3>
<p>
Using this tool may give you access to a user's personally identifiable information (PII). You are reminded of your
obligations under data protection laws to protect this information and not to use or disclose it without permission
or reasonable justification. This impersonation will be logged.
</p>
</div>
<%= render 'users/tabs', user: @user %>

<div class="user-list">
<div class="user-list--user">
<%= render 'users/common_card', user: @user, ckb: false %>
</div>
</div>
<%= render 'shared/user_mod_mobile_list', user: @user %>

<div class="grid">
<%= render 'shared/user_mod_sidebar', user: @user %>

<%= form_tag impersonate_path(@user) do %>
<div class="flex-row ai-fe">
<div class="form-group primary">
<%= label_tag :comment, 'Why are you impersonating this user?', class: 'form-element' %>
<%= text_field_tag :comment, nil, class: 'form-element', required: true %>
<div class="grid--cell is-9-desktop-12-mobile">
<h1>Impersonate <%= @user.username %></h1>
<p>
As a developer, you have access to impersonate users to help in reproducing bug reports, among other things.
</p>

<div class="notice is-warning has-color-yellow-900">
<h3><i class="fas fa-exclamation-triangle"></i> Caution</h3>
<p>
Using this tool may give you access to a user's personally identifiable information (PII). You are reminded of your
obligations under data protection laws to protect this information and not to use or disclose it without permission
or reasonable justification. This impersonation will be logged.
</p>
</div>
<div class="actions">
<%= submit_tag 'Impersonate', class: 'button is-danger h-m-b-2' %>

<div class="user-list">
<div class="user-list--user">
<%= render 'users/common_card', user: @user, ckb: false %>
</div>
</div>

<%= form_tag impersonate_path(@user) do %>
<div class="flex-row ai-fe">
<div class="form-group primary">
<%= label_tag :comment, 'Why are you impersonating this user?', class: 'form-element' %>
<%= text_field_tag :comment, nil, class: 'form-element', required: true %>
</div>
<div class="actions">
<%= submit_tag 'Impersonate', class: 'button is-danger h-m-b-2' %>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
91 changes: 50 additions & 41 deletions app/views/mod_warning/log.html.erb
Original file line number Diff line number Diff line change
@@ -1,42 +1,51 @@
<h1>Warnings sent to <%= user_link @user %></h1>
<% content_for :title, "Moderator Tools: #{rtl_safe_username(@user)}" %>

<table class="table is-full-width is-with-hover">
<tr>
<th>Date</th>
<th>Type</th>
<th>From</th>
<th>Excerpt</th>
<th>Status</th>
</tr>
<% @warnings.each do |w| %>
<tr>
<td>
<span title="<%= w.created_at.iso8601 %>"><%= time_ago_in_words(w.created_at) %> ago</span>
</td>
<td>
<% if w.suspension? %>
<% diff = ((w.suspension_end - w.created_at) / (3600 * 24)).to_i %>
<span class="badge is-tag is-red is-filled nowrap">Suspension</span> (<%= diff %>d)
<% else %>
<span class="badge is-tag is-muted nowrap">Warning</span>
<% end %>
</td>
<td><%= user_link w.author %></td>
<td><%= raw(sanitize(render_markdown(w.body), scrubber: scrubber)) %></td>
<td class="wrap-word">
<% if w.suspension_active? %>
<strong>Current</strong>
<%= form_tag lift_mod_warning_url(@user.id), method: :post do %>
<%= submit_tag '(lift)', class: 'link is-red' %>
<% end %>
<% elsif w.active %>
<strong>Unread</strong>
<% elsif w.read %>
Read
<% else %>
<strong>Lifted</strong>
<% end %>
</td>
</tr>
<% end %>
</table>
<%= render 'users/tabs', user: @user %>

<%= render 'shared/user_mod_mobile_list', user: @user %>

<div class="grid">
<%= render 'shared/user_mod_sidebar', user: @user %>

<div class="grid--cell is-9-desktop-12-mobile">
<h1>Previously Sent Warnings</h1>

<% if @warnings.size == 0 %>
<p class="has-color-tertiary"><em>No warnings found for this user.</em></p>
<% end %>

<% @warnings.each do |w| %>
<div class="widget">
<div class="widget--header is-complex h-bg-tertiary-050">
<div class="has-float-right h-p-1 h-fs-caption">
<% if w.suspension_active? %>
<%= form_tag lift_mod_warning_url(@user.id), method: :post, class: 'mod-warnings-clear-form' do %>
<%= submit_tag '(lift)', class: 'link is-red' %>
<% end %> &middot;
<strong>Current <i class="fas fa-fw fa-clock"></i></strong>
<% elsif w.active %>
<strong>Unread <i class="fas fa-fw fa-eye-slash"></i></strong>
<% elsif w.read %>
Read <i class="fas fa-fw fa-eye"></i>
<% else %>
Lifted <i class="fas fa-fw fa-undo"></i>
<% end %>
</div>
<div>
<% if w.is_suspension %>
<% diff = ((w.suspension_end - w.created_at) / (3600 * 24)).to_i %>
<span class="badge is-tag is-red is-filled badge-nobreak"><i class="fas fa-user-slash fa-fw"></i> Suspension</span>
<span class="badge is-tag is-muted badge-nobreak">length: <%= diff %>d</span>
<% else %>
<span class="badge is-tag is-yellow is-filled badge-nobreak"><i class="fas fa-exclamation-triangle fa-fw"></i> Warning</span>
<% end %>
</div>
<div class="h-c-tertiary-700 h-fs-caption h-m-t-2"><span title="<%= w.created_at.iso8601 %>"><%= time_ago_in_words(w.created_at) %> ago</span> by <%= user_link w.author %></div>
</div>
<div class="widget--body">
<%= raw(sanitize(render_markdown(w.body), scrubber: scrubber)) %>
</div>
</div>
<% end %>
</div>
</div>
Loading