Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
af09b95
fixed incorrect check for whether the post has reactions leading to e…
Oaphi Sep 9, 2025
2435968
switched post close notice checks to proper predicates
Oaphi Sep 9, 2025
557f474
fixed invalid HTML markup of post closed guidance
Oaphi Sep 9, 2025
377d3c3
added ability_link abilities helper
Oaphi Sep 9, 2025
ac1c676
abstracted post closed notice into posts/_closed_notice & ensured abi…
Oaphi Sep 9, 2025
bad688c
abstracted post deleted notice into posts/_deleted_notice & ensured a…
Oaphi Sep 9, 2025
7f169a8
minor cleanup of post closed & deleted notices
Oaphi Sep 9, 2025
7433858
abstracted post locked notice into posts/_locked_notice
Oaphi Sep 9, 2025
f0f16c9
abstracted post flagged notice into posts/_flagged_notice
Oaphi Sep 9, 2025
11a3bc1
a couple more minor cleanups of post notice partials
Oaphi Sep 9, 2025
ae333c5
abstracted notice for post suggested edit into posts/_suggested_edit_…
Oaphi Sep 9, 2025
2264a50
aligned post reactions check code style with the other checks
Oaphi Sep 9, 2025
a35e2a7
moved post notice partials to posts/notices for better organization
Oaphi Sep 9, 2025
79e84be
cleaned up indentation in posts/_expanded partial
Oaphi Sep 9, 2025
3327a95
abstracted post meta into posts/_meta partial
Oaphi Sep 9, 2025
990a2ab
abstracted post votes into posts/_votes partial
Oaphi Sep 9, 2025
dcd5c9c
removed no longer user variables from posts/_expanded
Oaphi Sep 9, 2025
f92ba3e
fixed inability to upload images to tag wikis (runtime error)
Oaphi Sep 9, 2025
d6efe0d
fixed deleted posts leaking by the related posts widget if the user c…
Oaphi Sep 9, 2025
ed31200
fixed error reports spacing
Oaphi Sep 10, 2025
7e8af97
don't show empty backtrace in error reports
Oaphi Sep 10, 2025
e337269
added CommentThread#last_activity_at for caching purposes
Oaphi Sep 10, 2025
445833c
ensured thread_content sends Last-Modified header based on the thread…
Oaphi Sep 10, 2025
bf33c7f
include Cache-Control in /users/me requests
Oaphi Sep 11, 2025
8b33e3c
fixed remember_me_token not being generated for 2FA users
Oaphi Sep 11, 2025
7212378
posts/notices/suggested_edit requires a guarantee that the user is no…
Oaphi Sep 11, 2025
d6738d8
added tests for the thread_content action of comments controller
Oaphi Sep 11, 2025
8710a2d
added test for remember_me functionality on 2FA users
Oaphi Sep 11, 2025
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
5 changes: 4 additions & 1 deletion app/assets/javascripts/qpixel_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ window.QPixel = {
}

const myselfPromise = QPixel.fetch('/users/me', {
headers: { 'Accept': 'application/json' }
headers: {
'Accept': 'application/json',
'Cache-Control': 'no-cache',
}
});

QPixel._pendingUserResponse = myselfPromise;
Expand Down
3 changes: 2 additions & 1 deletion app/assets/stylesheets/errors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
.error-report-summary {
display: flex;
align-items: center;
gap: 0.15em;

.details {
flex: 1;
}
}
}
2 changes: 2 additions & 0 deletions app/controllers/comments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ def thread
end

def thread_content
fresh_when last_modified: @comment_thread.last_activity_at.utc, etag: @comment_thread

render partial: 'comment_threads/expanded', locals: { inline: params[:inline] == 'true',
show_deleted: params[:show_deleted_comments] == '1',
thread: @comment_thread }
Expand Down
23 changes: 16 additions & 7 deletions app/controllers/users/sessions_controller.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
class Users::SessionsController < Devise::SessionsController
include Devise::Controllers::Rememberable

protect_from_forgery except: [:create]

mattr_accessor :first_factor, default: [], instance_writer: false, instance_reader: false

# Any changes made here may also require changes to Users::SamlSessionsController#create.
def create
super do |user|
return unless post_sign_in(user)
remember_me = remember_me_is_active?(user)
return unless post_sign_in(user, remember_me)
end
end

Expand All @@ -29,10 +32,15 @@ def verify_code
'a backup code. Please re-configure two-factor authentication via your profile.'
end

if params[:remember_me] == 'true'
remember_me(target_user)
end

AuditLog.user_history(event_type: 'two_factor_success', related: target_user)
@@first_factor.delete params[:uid].to_i

flash[:info] = 'Signed in successfully.'
sign_in_and_redirect target_user
sign_in_and_redirect(target_user)
else
AuditLog.user_history(event_type: 'two_factor_fail', related: target_user, comment: 'first factor not present')
flash[:danger] = "You haven't entered your password yet."
Expand All @@ -56,9 +64,10 @@ def verify_code
#
# In general, this method should have similar behavior to the Users::SamlSessionsController#post_sign_in method.
# If you make changes here, you may also have to update that method.
# @param user [User]
# @param user [User] currently signed in user
# @param remember_me [Boolean] whether the user should be remembered after special conditions
# @return [Boolean] false if the handling by the calling method should be stopped
def post_sign_in(user)
def post_sign_in(user, remember_me = false)
# For a deleted user (banished), tell them non-specifically that there was a mistake with their credentials.
if user.deleted?
sign_out user
Expand Down Expand Up @@ -88,20 +97,20 @@ def post_sign_in(user)

# Enforce 2FA
if user.enabled_2fa
handle_2fa_login(user)
handle_2fa_login(user, remember_me)
return false
end

true
end

def handle_2fa_login(user)
def handle_2fa_login(user, remember_me = false)
sign_out user
case user.two_factor_method
when 'app'
id = user.id
@@first_factor << id
redirect_to login_verify_2fa_path(uid: id)
redirect_to login_verify_2fa_path(uid: id, remember_me: remember_me)
when 'email'
TwoFactorMailer.with(user: user, host: request.hostname).login_email.deliver_now
flash[:notice] = nil
Expand Down
12 changes: 10 additions & 2 deletions app/helpers/abilities_helper.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
module AbilitiesHelper
##
# Gets a maybe_ability to the specified ability
# @param ability [Ability, String] ability or its internal id to link to
# @return [ActiveSupport::SafeBuffer]
def ability_link(maybe_ability)
ability = maybe_ability.is_a?(String) ? Ability.find_by(internal_id: maybe_ability) : maybe_ability

link_to ability.name,
ability_url(ability.internal_id, host: ability.community.host)
end

# Linearizes the Wilson-score progress used by ability calculations. For example, 0.98 and 0.99 are not far away on a
# linear scale, but mean a change of about 2x for the actual limit used by the algorithm. This method takes that into
# account and provides an indicator of progress on a linear scale, for use in progress bars.
Expand All @@ -10,7 +19,6 @@ def linearize_progress(score)
[0, linear_score].max.to_f
end

##
# Provides an error message for when a user is unable to complete an ability-restricted action, either because the
# user doesn't have the ability or because it has been suspended.
# @param internal_id [String] The +internal_id+ attribute of the ability in question.
Expand Down
6 changes: 6 additions & 0 deletions app/models/comment_thread.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ def can_access?(user)
post.can_access?(user)
end

# Gets last activity date and time on the thread
# @return [DateTime] last activity date and time
def last_activity_at
[created_at, locked_at, updated_at].compact.max
end

# Gets a list of user IDs who should be pingable in the thread.
# @return [Array<Integer>]
def pingable
Expand Down
18 changes: 18 additions & 0 deletions app/models/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,24 @@ def reaction_list
.to_h { |_k, v| [v.first.reaction_type, v] }
end

# Gets a list of related posts scoped for a given user
# @param user [User, nil] user to check access for
# @return [ActiveRecord::Relation<Post>]
def related_posts_for(user)
if user&.can_see_deleted_posts?
inbound_duplicates
else
inbound_duplicates.undeleted
end
end

# Checks if the post has related posts (scoped for a given user)
# @param user [User, nil] user to check access for
# @return [Boolean] check result
def related_posts_for?(user)
related_posts_for(user).any?
end

# Are new threads on this post followed by a given user?
# @param post [Post] post to check
# @param user [User] user to check
Expand Down
9 changes: 6 additions & 3 deletions app/views/admin/_error_report.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<strong><%= report.klass %></strong><br/>
<span class="has-font-size-caption has-color-tertiary-600"><%= t('g.at') %> <%= report.request_uri %></span>
</span>
<span class="has-float-right has-color-tertiary-600">
<span class="has-padding-right-2 has-float-right has-color-tertiary-600">
<%= report.created_at.iso8601 %>
</span>
</summary>
Expand All @@ -26,5 +26,8 @@
<span class="raw-markdown"><%= report.uuid %></span>
</p>

<pre class="error-trace raw-markdown"><%= report.backtrace.split("\n").select { |l| l.include? Rails.root.to_s }.join("\n") %></pre>
</details>
<% backtrace_lines = report.backtrace.split("\n").select { |l| l.include? Rails.root.to_s } %>
<% if backtrace_lines.any? %>
<pre class="error-trace raw-markdown"><%= backtrace_lines.join("\n") %></pre>
<% end %>
</details>
6 changes: 3 additions & 3 deletions app/views/layouts/_sidebar.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@
<% end %>

<%# Related Posts widget %>
<% if defined?(@post) && @post.inbound_duplicates.any? %>
<% if defined?(@post) && @post.related_posts_for?(current_user) %>
<% collapse_related = user_preference('collapse_related_posts') == 'true' %>
<% cache [@post, @post.inbound_duplicates] do %>
<% cache [@post, @post.related_posts_for(current_user)] do %>
<div class="widget has-margin-4 is-green" data-collapsed="<%= user_preference('collapse_related_posts') %>">
<div class="widget--header">
Related Posts
Expand All @@ -60,7 +60,7 @@
<i class="fas <%= collapse_related ? 'fa-chevron-down' : 'fa-chevron-up' %>"></i>
</button>
</div>
<% @post.inbound_duplicates.each do |dp| %>
<% @post.related_posts_for(current_user).each do |dp| %>
<div class="widget--body <%= 'hidden' if collapse_related %>">
<% unless dp.category.nil? %>
<%= dp.category.name %>
Expand Down
Loading