Skip to content

Commit

Permalink
Merge pull request #1519 from codidact/art/1419-ability-notifications
Browse files Browse the repository at this point in the history
Notify user on ability grant
  • Loading branch information
Oaphi authored Jan 17, 2025
2 parents bb38485 + 36f9dfd commit e14b2a0
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 12 deletions.
4 changes: 2 additions & 2 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ def role_toggle

# Set/update ability
if new_value
@user.community_user.grant_privilege 'mod'
@user.community_user.grant_privilege! 'mod'
else
@user.community_user.privilege('mod').destroy
end
Expand Down Expand Up @@ -448,7 +448,7 @@ def mod_privilege_action
case params[:do]
when 'grant'
if ua.nil?
@user.community_user.grant_privilege(ability.internal_id)
@user.community_user.grant_privilege!(ability.internal_id)
AuditLog.admin_audit(event_type: 'ability_grant', related: @user, user: current_user,
comment: ability.internal_id.to_s)
elsif ua.is_suspended
Expand Down
33 changes: 29 additions & 4 deletions app/models/community_user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class CommunityUser < ApplicationRecord

after_create :prevent_ulysses_case

delegate :url_helpers, to: 'Rails.application.routes'

def system?
user_id == -1
end
Expand Down Expand Up @@ -58,8 +60,6 @@ def flag_score
end
end

## Privilege functions

def privilege?(internal_id, ignore_suspension: false, ignore_mod: false)
if internal_id != 'mod' && !ignore_mod && user.is_moderator
return true # includes: privilege? 'mod'
Expand All @@ -77,11 +77,26 @@ def privilege(internal_id)
UserAbility.joins(:ability).where(community_user_id: id, abilities: { internal_id: internal_id }).first
end

def grant_privilege(internal_id)
##
# Grant a specified ability to this CommunityUser.
# @param internal_id [String] The +internal_id+ of the ability to grant.
# @param notify [Boolean] Whether to send a notification to the user.
def grant_privilege!(internal_id, notify: true)
priv = Ability.where(internal_id: internal_id).first
UserAbility.create community_user_id: id, ability: priv
if notify
community_host = priv.community.host
user.create_notification("You've earned the #{priv.name} ability! Learn more.",
url_helpers.ability_url(priv.internal_id, host: community_host))
end
end

##
# Recalculate a specified ability for this CommunityUser. Will not revoke abilities that have already been granted.
# @param internal_id [String] The +internal_id+ of the ability to be recalculated.
# @param sandbox [Boolean] Whether to run in sandbox mode - if sandboxed, the ability will not be granted but the
# return value indicates whether it would have been.
# @return [Boolean] Whether or not the ability was granted.
def recalc_privilege(internal_id, sandbox: false)
# Do not recalculate privileges already granted
return true if privilege?(internal_id, ignore_suspension: true, ignore_mod: false)
Expand All @@ -100,17 +115,27 @@ def recalc_privilege(internal_id, sandbox: false)
end

# If not sandbox mode, create new privilege entry
grant_privilege(internal_id) unless sandbox
grant_privilege!(internal_id) unless sandbox
recalc_trust_level unless sandbox
true
end

##
# Recalculate a list of standard abilities for this CommunityUser.
# @param sandbox [Boolean] Whether to run in sandbox mode - see {#recalc_privilege}.
# @return [Array<Boolean>]
def recalc_privileges(sandbox: false)
[:everyone, :unrestricted, :edit_posts, :edit_tags, :flag_close, :flag_curate].map do |ability|
recalc_privilege(ability, sandbox: sandbox)
end
end

alias ability? privilege?
alias ability privilege
alias grant_ability! grant_privilege!
alias recalc_ability recalc_privilege
alias recalc_abilities recalc_privileges

# This check makes sure that every user gets the
# 'everyone' permission upon creation. We do not want
# to create a no permissions user by accident.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class EnforceConcurrenceOfIsModeratorAndModAbility < ActiveRecord::Migration[5.2
def up
CommunityUser.unscoped.where(is_moderator: true).all.map do |cu|
RequestContext.community = cu.community
cu.grant_privilege 'mod'
cu.grant_privilege! 'mod'
end
end

Expand Down
6 changes: 3 additions & 3 deletions scripts/recalc_abilities.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
puts "Scope: CommunityUser : #{cu.id}"
end

cu.recalc_privileges
cu.recalc_abilities

# Grant mod ability if mod status is given
if (cu.is_moderator || cu.is_admin || u.is_global_moderator || u.is_global_admin) && !cu.privilege?('mod')
cu.grant_privilege('mod')
if (cu.is_moderator || cu.is_admin || u.is_global_moderator || u.is_global_admin) && !cu.ability?('mod')
cu.grant_ability!('mod')
end

resolved << q.id
Expand Down
2 changes: 1 addition & 1 deletion scripts/recalc_abilities_upon_first_migration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
cu.recalc_privileges

if (cu.is_moderator || cu.is_admin || u.is_global_moderator || u.is_global_admin) && !cu.privilege?('mod')
cu.grant_privilege('mod')
cu.grant_privilege!('mod')
end
rescue
puts " !!! Error recalcing for CommunityUser.Id=#{cu.id}"
Expand Down
2 changes: 1 addition & 1 deletion test/models/user_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class UserTest < ActiveSupport::TestCase
assert_equal true, users(:moderator).can_update(post, post_type)
assert_equal true, users(:editor).can_update(post, post_type)

basic_user.community_user.grant_privilege('unrestricted')
basic_user.community_user.grant_privilege!('unrestricted')
assert_equal false, basic_user.can_update(post, post_type)
assert_equal true, basic_user.can_update(post, post_types(:free_edit))
end
Expand Down

0 comments on commit e14b2a0

Please sign in to comment.