Users: add Contributor and Approver user levels

This commit is contained in:
nonamethanks
2022-10-21 14:59:15 +02:00
parent f092bc28ee
commit ca31e7a47c
29 changed files with 105 additions and 251 deletions

View File

@@ -10,10 +10,8 @@ module Admin
@user = authorize User.find(params[:id]), :promote? @user = authorize User.find(params[:id]), :promote?
@level = params.dig(:user, :level) @level = params.dig(:user, :level)
@can_upload_free = params.dig(:user, :can_upload_free)
@can_approve_posts = params.dig(:user, :can_approve_posts)
@user.promote_to!(@level, CurrentUser.user, can_upload_free: @can_upload_free, can_approve_posts: @can_approve_posts) @user.promote_to!(@level, CurrentUser.user)
redirect_to edit_admin_user_path(@user), :notice => "User updated" redirect_to edit_admin_user_path(@user), :notice => "User updated"
end end

View File

@@ -218,9 +218,7 @@ module ApplicationHelper
def link_to_user(user, text = nil, classes: nil, **options) def link_to_user(user, text = nil, classes: nil, **options)
return "anonymous" if user.blank? return "anonymous" if user.blank?
user_class = "user user-#{user.level_string.downcase} #{classes}" user_class = "user user-#{user.level_string.downcase} #{classes}".strip
user_class += " user-post-approver" if user.can_approve_posts?
user_class += " user-post-uploader" if user.can_upload_free?
user_class += " user-banned" if user.is_banned? user_class += " user-banned" if user.is_banned?
text = user.pretty_name if text.blank? text = user.pretty_name if text.blank?

View File

@@ -11,6 +11,14 @@ body {
color: var(--user-moderator-color); color: var(--user-moderator-color);
} }
a.user-approver {
color: var(--user-builder-color);
}
a.user-contributor {
color: var(--user-builder-color);
}
a.user-builder { a.user-builder {
color: var(--user-builder-color); color: var(--user-builder-color);
} }

View File

@@ -15,12 +15,10 @@ module ApproverPruner
# Get the list of inactive approvers. # Get the list of inactive approvers.
# @return [Array<User>] the list of inactive approvers # @return [Array<User>] the list of inactive approvers
def inactive_approvers def inactive_approvers
approvers = User.bit_prefs_match(:can_approve_posts, true) recently_promoted_approvers = UserFeedback.where("created_at >= ?", APPROVAL_PERIOD.ago).where_like(:body, "*You gained the ability to approve posts*").pluck(:user_id) # XXX remove in two months
approvers = approvers.where("level < ?", User::Levels::MODERATOR) recently_promoted_approvers += UserFeedback.where("created_at >= ?", APPROVAL_PERIOD.ago).where_like(:body, "*You have been promoted to an Approver*").pluck(:user_id)
recently_promoted_approvers = UserFeedback.where("created_at >= ?", APPROVAL_PERIOD.ago).where_like(:body, "*You gained the ability to approve posts*").select(:user_id)
approvers = approvers.where.not(id: recently_promoted_approvers)
approvers = User.where(level: User::Levels::APPROVER).where.not(id: recently_promoted_approvers)
approvers.select do |approver| approvers.select do |approver|
approver.post_approvals.where("created_at >= ?", APPROVAL_PERIOD.ago).count < MINIMUM_APPROVALS approver.post_approvals.where("created_at >= ?", APPROVAL_PERIOD.ago).count < MINIMUM_APPROVALS
end end
@@ -30,7 +28,7 @@ module ApproverPruner
def prune! def prune!
inactive_approvers.each do |user| inactive_approvers.each do |user|
CurrentUser.scoped(User.system) do CurrentUser.scoped(User.system) do
user.update!(can_approve_posts: false) user.update!(level: User::Levels::CONTRIBUTOR)
user.feedback.create(category: "neutral", body: "Lost approval privileges", creator: User.system) user.feedback.create(category: "neutral", body: "Lost approval privileges", creator: User.system)
Dmail.create_automated( Dmail.create_automated(

View File

@@ -470,7 +470,7 @@ class PostQueryBuilder
relation = relation.reorder(Arel.sql("log(3, posts.score) + (extract(epoch from posts.created_at) - extract(epoch from timestamp '2005-05-24')) / 35000 DESC")) relation = relation.reorder(Arel.sql("log(3, posts.score) + (extract(epoch from posts.created_at) - extract(epoch from timestamp '2005-05-24')) / 35000 DESC"))
when "curated" when "curated"
contributors = User.bit_prefs_match(:can_upload_free, true) contributors = User.where("level >= ?", User::Levels::CONTRIBUTOR)
relation = relation relation = relation
.joins(:favorites) .joins(:favorites)

View File

@@ -39,7 +39,7 @@ class UploadLimit
# @return [Boolean] true if the user can't upload because they're out of upload slots. # @return [Boolean] true if the user can't upload because they're out of upload slots.
def limited? def limited?
!user.can_upload_free? && used_upload_slots >= upload_slots !user.is_contributor? && used_upload_slots >= upload_slots
end end
# @return [Boolean] true if the user is at max level. # @return [Boolean] true if the user is at max level.
@@ -91,7 +91,7 @@ class UploadLimit
# @param is_approval [Boolean] true if the post is being approved or # @param is_approval [Boolean] true if the post is being approved or
# undeleted, false if the post is being deleted. # undeleted, false if the post is being deleted.
def update_limit!(is_pending, is_approval) def update_limit!(is_pending, is_approval)
return if user.can_upload_free? return if user.is_contributor?
user.with_lock do user.with_lock do
# If we're approving or deleting a pending post, we can simply increment # If we're approving or deleting a pending post, we can simply increment

View File

@@ -5,31 +5,22 @@
# user a feedback, sends them a notification dmail, and creates a mod action for # user a feedback, sends them a notification dmail, and creates a mod action for
# the promotion. # the promotion.
class UserPromotion class UserPromotion
attr_reader :user, :promoter, :new_level, :old_can_approve_posts, :old_can_upload_free, :can_upload_free, :can_approve_posts attr_reader :user, :promoter, :new_level
# Initialize a new promotion. # Initialize a new promotion.
# @param user [User] the user to promote # @param user [User] the user to promote
# @param promoter [User] the user doing the promotion # @param promoter [User] the user doing the promotion
# @param new_level [Integer] the new user level # @param new_level [Integer] the new user level
# @param can_upload_free [Boolean] whether the user should gain unlimited upload privileges def initialize(user, promoter, new_level)
# @param can_approve_posts [Boolean] whether the user should gain approval privileges
def initialize(user, promoter, new_level, can_upload_free: nil, can_approve_posts: nil)
@user = user @user = user
@promoter = promoter @promoter = promoter
@new_level = new_level.to_i @new_level = new_level.to_i
@can_upload_free = can_upload_free
@can_approve_posts = can_approve_posts
end end
def promote! def promote!
validate! validate!
@old_can_approve_posts = user.can_approve_posts?
@old_can_upload_free = user.can_upload_free?
user.level = new_level user.level = new_level
user.can_upload_free = can_upload_free unless can_upload_free.nil?
user.can_approve_posts = can_approve_posts unless can_approve_posts.nil?
create_user_feedback create_user_feedback
create_dmail create_dmail
@@ -41,18 +32,6 @@ class UserPromotion
private private
def create_mod_actions def create_mod_actions
if old_can_approve_posts == false && user.can_approve_posts? == true
ModAction.log("granted approval privileges to \"#{user.name}\":#{Routes.user_path(user)}", :user_approval_privilege, subject: user, user: promoter)
elsif old_can_approve_posts == true && user.can_approve_posts? == false
ModAction.log("removed approval privileges from \"#{user.name}\":#{Routes.user_path(user)}", :user_approval_privilege, subject: user, user: promoter)
end
if old_can_upload_free == false && user.can_upload_free? == true
ModAction.log("granted unlimited upload privileges to \"#{user.name}\":#{Routes.user_path(user)}", :user_upload_privilege, subject: user, user: promoter)
elsif old_can_upload_free == false && user.can_upload_free? == true
ModAction.log("removed unlimited upload privileges from \"#{user.name}\":#{Routes.user_path(user)}", :user_upload_privilege, subject: user, user: promoter)
end
if user.level_changed? && user.level >= user.level_was if user.level_changed? && user.level >= user.level_was
ModAction.log(%{promoted "#{user.name}":#{Routes.user_path(user)} from #{user.level_string_was} to #{user.level_string}}, :user_level_change, subject: user, user: promoter) ModAction.log(%{promoted "#{user.name}":#{Routes.user_path(user)} from #{user.level_string_was} to #{user.level_string}}, :user_level_change, subject: user, user: promoter)
elsif user.level_changed? && user.level < user.level_was elsif user.level_changed? && user.level < user.level_was
@@ -73,37 +52,20 @@ class UserPromotion
end end
# Build the dmail and user feedback message. # Build the dmail and user feedback message.
def build_messages def build_message
messages = [] level_string = (user.level == User::Levels::APPROVER) ? "an Approver" : "a #{user.level_string}"
if user.level > user.level_was
if user.level_changed? "You have been promoted to #{level_string} level account from #{user.level_string_was}."
if user.level > user.level_was elsif user.level < user.level_was
messages << "You have been promoted to a #{user.level_string} level account from #{user.level_string_was}." "You have been demoted to #{level_string} level account from #{user.level_string_was}."
elsif user.level < user.level_was
messages << "You have been demoted to a #{user.level_string} level account from #{user.level_string_was}."
end
end end
if user.can_approve_posts? && !old_can_approve_posts
messages << "You gained the ability to approve posts."
elsif !user.can_approve_posts? && old_can_approve_posts
messages << "You lost the ability to approve posts."
end
if user.can_upload_free? && !old_can_upload_free
messages << "You gained the ability to upload posts without limit."
elsif !user.can_upload_free? && old_can_upload_free
messages << "You lost the ability to upload posts without limit."
end
messages.join("\n")
end end
def create_dmail def create_dmail
Dmail.create_automated(to_id: user.id, title: "Your account has been updated", body: build_messages) Dmail.create_automated(to_id: user.id, title: "Your account has been updated", body: build_message)
end end
def create_user_feedback def create_user_feedback
UserFeedback.create(user: user, creator: promoter, category: "neutral", body: build_messages, disable_dmail_notification: true) UserFeedback.create(user: user, creator: promoter, category: "neutral", body: build_message, disable_dmail_notification: true)
end end
end end

View File

@@ -120,7 +120,7 @@ class Post < ApplicationRecord
tag_string: tag_string, tag_string: tag_string,
rating: rating, rating: rating,
parent_id: parent_id, parent_id: parent_id,
is_pending: !upload.uploader.can_upload_free? || is_pending.to_s.truthy?, is_pending: !upload.uploader.is_contributor? || is_pending.to_s.truthy?,
artist_commentary: (commentary if commentary.any_field_present?), artist_commentary: (commentary if commentary.any_field_present?),
) )
end end

View File

@@ -12,13 +12,15 @@ class User < ApplicationRecord
GOLD = 30 GOLD = 30
PLATINUM = 31 PLATINUM = 31
BUILDER = 32 BUILDER = 32
CONTRIBUTOR = 35
APPROVER = 37
MODERATOR = 40 MODERATOR = 40
ADMIN = 50 ADMIN = 50
OWNER = 60 OWNER = 60
end end
# Used for `before_action :<role>_only`. Must have a corresponding `is_<role>?` method. # Used for `before_action :<role>_only`. Must have a corresponding `is_<role>?` method.
Roles = Levels.constants.map(&:downcase) + %i[banned approver] Roles = Levels.constants.map(&:downcase) + %i[banned]
BOOLEAN_ATTRIBUTES = %w[ BOOLEAN_ATTRIBUTES = %w[
is_banned is_banned
@@ -34,8 +36,8 @@ class User < ApplicationRecord
_unused_enable_auto_complete _unused_enable_auto_complete
show_deleted_children show_deleted_children
_unused_has_saved_searches _unused_has_saved_searches
can_approve_posts _unused_can_approve_posts
can_upload_free _unused_can_upload_free
disable_categorized_saved_searches disable_categorized_saved_searches
_unused_is_super_voter _unused_is_super_voter
disable_tagged_filenames disable_tagged_filenames
@@ -261,6 +263,8 @@ class User < ApplicationRecord
"Gold" => Levels::GOLD, "Gold" => Levels::GOLD,
"Platinum" => Levels::PLATINUM, "Platinum" => Levels::PLATINUM,
"Builder" => Levels::BUILDER, "Builder" => Levels::BUILDER,
"Contributor" => Levels::CONTRIBUTOR,
"Approver" => Levels::APPROVER,
"Moderator" => Levels::MODERATOR, "Moderator" => Levels::MODERATOR,
"Admin" => Levels::ADMIN, "Admin" => Levels::ADMIN,
"Owner" => Levels::OWNER, "Owner" => Levels::OWNER,
@@ -268,42 +272,12 @@ class User < ApplicationRecord
end end
def level_string(value) def level_string(value)
case value level_hash.key(value)
when Levels::ANONYMOUS
"Anonymous"
when Levels::RESTRICTED
"Restricted"
when Levels::MEMBER
"Member"
when Levels::BUILDER
"Builder"
when Levels::GOLD
"Gold"
when Levels::PLATINUM
"Platinum"
when Levels::MODERATOR
"Moderator"
when Levels::ADMIN
"Admin"
when Levels::OWNER
"Owner"
else
""
end
end end
end end
def promote_to!(new_level, promoter = CurrentUser.user, **options) def promote_to!(new_level, promoter = CurrentUser.user)
UserPromotion.new(self, promoter, new_level, **options).promote! UserPromotion.new(self, promoter, new_level).promote!
end end
def promote_to_owner_if_first_user def promote_to_owner_if_first_user
@@ -311,8 +285,6 @@ class User < ApplicationRecord
if name != Danbooru.config.system_user && !User.exists?(level: Levels::OWNER) if name != Danbooru.config.system_user && !User.exists?(level: Levels::OWNER)
self.level = Levels::OWNER self.level = Levels::OWNER
self.can_approve_posts = true
self.can_upload_free = true
end end
end end
@@ -340,10 +312,6 @@ class User < ApplicationRecord
level >= Levels::MEMBER level >= Levels::MEMBER
end end
def is_builder?
level >= Levels::BUILDER
end
def is_gold? def is_gold?
level >= Levels::GOLD level >= Levels::GOLD
end end
@@ -352,6 +320,18 @@ class User < ApplicationRecord
level >= Levels::PLATINUM level >= Levels::PLATINUM
end end
def is_builder?
level >= Levels::BUILDER
end
def is_contributor?
level >= Levels::CONTRIBUTOR
end
def is_approver?
level >= Levels::APPROVER
end
def is_moderator? def is_moderator?
level >= Levels::MODERATOR level >= Levels::MODERATOR
end end
@@ -363,10 +343,6 @@ class User < ApplicationRecord
def is_owner? def is_owner?
level >= Levels::OWNER level >= Levels::OWNER
end end
def is_approver?
can_approve_posts?
end
end end
module EmailMethods module EmailMethods
@@ -484,7 +460,7 @@ class User < ApplicationRecord
end end
def is_appeal_limited? def is_appeal_limited?
return false if can_upload_free? return false if is_contributor?
upload_limit.free_upload_slots < UploadLimit::APPEAL_COST upload_limit.free_upload_slots < UploadLimit::APPEAL_COST
end end
@@ -496,7 +472,7 @@ class User < ApplicationRecord
# Flags are unlimited if you're an approver or you have at least 30 flags # Flags are unlimited if you're an approver or you have at least 30 flags
# in the last 3 months and have a 70% flag success rate. # in the last 3 months and have a 70% flag success rate.
def has_unlimited_flags? def has_unlimited_flags?
return true if can_approve_posts? return true if is_approver?
recent_flags = post_flags.where("created_at >= ?", 3.months.ago) recent_flags = post_flags.where("created_at >= ?", 3.months.ago)
flag_ratio = recent_flags.succeeded.count / recent_flags.count.to_f flag_ratio = recent_flags.succeeded.count / recent_flags.count.to_f
@@ -642,11 +618,11 @@ class User < ApplicationRecord
q = q.where("level <= ?", params[:max_level].to_i) q = q.where("level <= ?", params[:max_level].to_i)
end end
%w[can_approve_posts can_upload_free is_banned].each do |flag| if params[:is_banned].present?
if params[flag].to_s.truthy? if params[:is_banned].to_s.truthy?
q = q.bit_prefs_match(flag, true) q = q.bit_prefs_match(:is_banned, true)
elsif params[flag].to_s.falsy? elsif params[:is_banned].to_s.falsy?
q = q.bit_prefs_match(flag, false) q = q.bit_prefs_match(:is_banned, false)
end end
end end

View File

@@ -56,9 +56,8 @@ class UserPolicy < ApplicationPolicy
def api_attributes def api_attributes
attributes = %i[ attributes = %i[
id created_at name inviter_id level id created_at name inviter_id level level_string
post_upload_count post_update_count note_update_count is_banned post_upload_count post_update_count note_update_count is_banned
can_approve_posts can_upload_free level_string
] ]
if record.id == user.id if record.id == user.id

View File

@@ -15,20 +15,6 @@ class UserPresenter
user.created_at.strftime("%Y-%m-%d") user.created_at.strftime("%Y-%m-%d")
end end
def permissions
permissions = []
if user.can_approve_posts?
permissions << "approve posts"
end
if user.can_upload_free?
permissions << "unrestricted uploads"
end
permissions.join(", ")
end
def posts_for_saved_search_category(category) def posts_for_saved_search_category(category)
Post.user_tag_match("search:#{category}").limit(10) Post.user_tag_match("search:#{category}").limit(10)
end end

View File

@@ -7,8 +7,6 @@
<%= edit_form_for(@user, url: admin_user_path(@user)) do |f| %> <%= edit_form_for(@user, url: admin_user_path(@user)) do |f| %>
<%= f.input :level, collection: User.level_hash.to_a, selected: @user.level %> <%= f.input :level, collection: User.level_hash.to_a, selected: @user.level %>
<%= f.input :can_upload_free, label: "Unrestricted Uploads", as: :boolean, selected: @user.can_upload_free %>
<%= f.input :can_approve_posts, label: "Approve Posts", as: :boolean, selected: @user.can_approve_posts %>
<%= f.submit "Update" %> <%= f.submit "Update" %>
<% end %> <% end %>
</div> </div>

View File

@@ -1,4 +1,4 @@
<% if (CurrentUser.can_approve_posts? || post.created_at < Danbooru.config.moderation_period.ago) && disapprovals.length > 0 %> <% if (CurrentUser.is_approver? || post.created_at < Danbooru.config.moderation_period.ago) && disapprovals.length > 0 %>
<% if disapprovals.map(&:reason).grep("breaks_rules").count > 0 %> <% if disapprovals.map(&:reason).grep("breaks_rules").count > 0 %>
(breaks rules: <%= disapprovals.map(&:reason).grep("breaks_rules").count %>) (breaks rules: <%= disapprovals.map(&:reason).grep("breaks_rules").count %>)
<% end %> <% end %>

View File

@@ -1,4 +1,4 @@
<% if (CurrentUser.can_approve_posts? || post.created_at < Danbooru.config.moderation_period.ago) && disapprovals.length > 0 %> <% if (CurrentUser.is_approver? || post.created_at < Danbooru.config.moderation_period.ago) && disapprovals.length > 0 %>
<p> <p>
It has been reviewed by <%= pluralize disapprovals.length, "approver" %>. It has been reviewed by <%= pluralize disapprovals.length, "approver" %>.

View File

@@ -16,7 +16,7 @@
<%= embed_wiki("help:upload_notice", id: "upload-guide-notice") %> <%= embed_wiki("help:upload_notice", id: "upload-guide-notice") %>
<% unless CurrentUser.can_upload_free? %> <% unless CurrentUser.is_contributor? %>
<p id="upload-limit">Upload Limit: <%= render "users/upload_limit", user: CurrentUser.user %></p> <p id="upload-limit">Upload Limit: <%= render "users/upload_limit", user: CurrentUser.user %></p>
<% end %> <% end %>
@@ -88,7 +88,7 @@
<%= f.submit "Post" %> <%= f.submit "Post" %>
<% if CurrentUser.can_upload_free? %> <% if CurrentUser.is_contributor? %>
<%= f.input :is_pending, as: :boolean, label: "Upload for approval", wrapper_html: { class: "inline-block" }, input_html: { checked: post.is_pending? } %> <%= f.input :is_pending, as: :boolean, label: "Upload for approval", wrapper_html: { class: "inline-block" }, input_html: { checked: post.is_pending? } %>
<% end %> <% end %>

View File

@@ -94,11 +94,6 @@
</td> </td>
</tr> </tr>
<tr>
<th>Permissions</th>
<td><%= presenter.permissions %></td>
</tr>
<% if user.is_banned? && user.active_ban.present? %> <% if user.is_banned? && user.active_ban.present? %>
<tr> <tr>
<th>Ban reason</th> <th>Ban reason</th>

View File

@@ -1,6 +1,6 @@
<%# user %> <%# user %>
<% if user.can_upload_free? %> <% if user.is_contributor? %>
none none
<% else %> <% else %>
<%= link_to user.upload_limit.used_upload_slots, posts_path(tags: "user:#{user.name} status:pending") %> / <%= link_to user.upload_limit.used_upload_slots, posts_path(tags: "user:#{user.name} status:pending") %> /

View File

@@ -5,8 +5,6 @@
<%= search_form_for(users_path) do |f| %> <%= search_form_for(users_path) do |f| %>
<%= f.input :name_matches, label: "Name", input_html: { value: params[:search][:name_matches], data: { autocomplete: "user" } } %> <%= f.input :name_matches, label: "Name", input_html: { value: params[:search][:name_matches], data: { autocomplete: "user" } } %>
<%= f.input :level, collection: User.level_hash.to_a, include_blank: true, selected: params[:search][:level] %> <%= f.input :level, collection: User.level_hash.to_a, include_blank: true, selected: params[:search][:level] %>
<%= f.input :can_upload_free, label: "Contributor?", as: :select, include_blank: true, selected: params[:search][:can_upload_free] %>
<%= f.input :can_approve_posts, label: "Approver?", as: :select, include_blank: true, selected: params[:search][:can_approve_posts] %>
<%= f.input :order, collection: [["Joined", "date"], ["Name", "name"], ["Posts", "post_upload_count"], ["Edits", "post_update_count"], ["Notes", "note_count"]], include_blank: true, selected: params[:search][:order] %> <%= f.input :order, collection: [["Joined", "date"], ["Name", "name"], ["Posts", "post_upload_count"], ["Edits", "post_update_count"], ["Notes", "note_count"]], include_blank: true, selected: params[:search][:order] %>
<%= f.submit "Search" %> <%= f.submit "Search" %>
<% end %> <% end %>

View File

@@ -7,14 +7,6 @@
<% if @user.is_banned? %> <% if @user.is_banned? %>
<%= link_to "Banned", users_path(search: { is_banned: true }), class: "user-tooltip-badge user-tooltip-badge-banned" %> <%= link_to "Banned", users_path(search: { is_banned: true }), class: "user-tooltip-badge user-tooltip-badge-banned" %>
<% elsif @user.is_admin? %>
<%= link_to @user.level_string, users_path(search: { level: @user.level }), class: "user-tooltip-badge user-tooltip-badge-#{@user.level_string.downcase}" %>
<% elsif @user.is_moderator? %>
<%= link_to @user.level_string, users_path(search: { level: @user.level }), class: "user-tooltip-badge user-tooltip-badge-#{@user.level_string.downcase}" %>
<% elsif @user.can_approve_posts? %>
<%= link_to "Approver", users_path(search: { can_approve_posts: true }), class: "user-tooltip-badge user-tooltip-badge-approver" %>
<% elsif @user.can_upload_free? %>
<%= link_to "Contributor", users_path(search: { can_upload_free: true }), class: "user-tooltip-badge user-tooltip-badge-contributor" %>
<% else %> <% else %>
<%= link_to @user.level_string, users_path(search: { level: @user.level }), class: "user-tooltip-badge user-tooltip-badge-#{@user.level_string.downcase}" %> <%= link_to @user.level_string, users_path(search: { level: @user.level }), class: "user-tooltip-badge user-tooltip-badge-#{@user.level_string.downcase}" %>
<% end %> <% end %>

View File

@@ -33,12 +33,6 @@ def populate_users(n, password: DEFAULT_PASSWORD)
puts "Created user ##{user.id} (#{user.name})" puts "Created user ##{user.id} (#{user.name})"
end end
user = User.create(name: "contributor", password: password, password_confirmation: password, level: User::Levels::BUILDER, can_upload_free: true)
puts "Created user ##{user.id} (#{user.name})"
user = User.create(name: "approver", password: password, password_confirmation: password, level: User::Levels::BUILDER, can_upload_free: true, can_approve_posts: true)
puts "Created user ##{user.id} (#{user.name})"
n.times do |i| n.times do |i|
user = User.create(name: FFaker::Internet.user_name, password: password, password_confirmation: password, level: User::Levels::MEMBER) user = User.create(name: FFaker::Internet.user_name, password: password, password_confirmation: password, level: User::Levels::MEMBER)
puts "Created user ##{user.id}" puts "Created user ##{user.id}"

View File

@@ -0,0 +1,17 @@
#!/usr/bin/env ruby
require_relative "base"
with_confirmation do
User.where(level: User::Levels::BUILDER).bit_prefs_match(:_unused_can_upload_free, true).bit_prefs_match(:_unused_can_approve_posts, false).find_each do |contributor|
contributor.level = User::Levels::CONTRIBUTOR
contributor.save
puts "user ##{contributor.id} #{contributor.name} updated to contributor"
end
User.where(level: User::Levels::BUILDER).bit_prefs_match(:_unused_can_approve_posts, true).find_each do |approver|
approver.level = User::Levels::APPROVER
approver.save
puts "user ##{contributor.id} #{approver.name} updated to approver"
end
end

View File

@@ -12,64 +12,30 @@ FactoryBot.define do
end end
factory(:restricted_user) do factory(:restricted_user) do
level {10} level {User::Levels::RESTRICTED}
requires_verification { true } requires_verification { true }
is_verified { false } is_verified { false }
end end
factory(:member_user) do User.level_hash.each do |level_name, level_value|
level {20} # allows create(:moderator_user), create(:approver) etc
end next if level_name == "Restricted" # already defined above
factory(:gold_user) do factory(level_name.downcase) do
level {30} level {level_value}
end end
factory(:platinum_user) do factory("#{level_name.downcase}_user") do
level {31} level {level_value}
end end
factory(:builder_user) do
level {32}
end
factory(:contributor_user) do
level {32}
can_upload_free {true}
end
factory(:contrib_user) do
level {32}
can_upload_free {true}
end
factory(:moderator_user) do
level {40}
can_approve_posts {true}
end end
factory(:mod_user) do factory(:mod_user) do
level {40} level {User::Levels::MODERATOR}
can_approve_posts {true}
end
factory(:admin_user) do
level {50}
can_approve_posts {true}
end
factory(:owner_user) do
level { User::Levels::OWNER }
can_approve_posts {true}
end end
factory(:uploader) do factory(:uploader) do
created_at { 2.weeks.ago } created_at { 2.weeks.ago }
end end
factory(:approver) do
level {32}
can_approve_posts {true}
end
end end
end end

View File

@@ -22,37 +22,7 @@ class Admin::UsersControllerTest < ActionDispatch::IntegrationTest
assert_redirected_to(edit_admin_user_path(@user)) assert_redirected_to(edit_admin_user_path(@user))
assert_equal(30, @user.reload.level) assert_equal(30, @user.reload.level)
assert_match(/promoted "#{@user.name}":\/users\/#{@user.id} from Member to Gold/, ModAction.last.description) assert_match(%r{promoted "#{@user.name}":/users/#{@user.id} from Member to Gold}, ModAction.last.description)
assert_equal(@user, ModAction.last.subject)
assert_equal(@mod, ModAction.last.creator)
end
should "promote the user to unrestricted uploads" do
put_auth admin_user_path(@user), @mod, params: { user: { level: User::Levels::BUILDER, can_upload_free: true }}
assert_redirected_to(edit_admin_user_path(@user.reload))
assert_equal(true, @user.is_builder?)
assert_equal(true, @user.can_upload_free?)
assert_equal(false, @user.can_approve_posts?)
assert_match(/granted unlimited upload privileges to "#{@user.name}":\/users\/#{@user.id}/, ModAction.first.description)
assert_match(/promoted "#{@user.name}":\/users\/#{@user.id} from Member to Builder/, ModAction.last.description)
assert_equal(@user, ModAction.first.subject)
assert_equal(@mod, ModAction.first.creator)
assert_equal(@user, ModAction.last.subject)
assert_equal(@mod, ModAction.last.creator)
end
should "promote the user to approver" do
put_auth admin_user_path(@user), @mod, params: { user: { level: User::Levels::BUILDER, can_approve_posts: true }}
assert_redirected_to(edit_admin_user_path(@user.reload))
assert_equal(true, @user.is_builder?)
assert_equal(false, @user.can_upload_free?)
assert_equal(true, @user.can_approve_posts?)
assert_match(/granted approval privileges to "#{@user.name}":\/users\/#{@user.id}/, ModAction.first.description)
assert_match(/promoted "#{@user.name}":\/users\/#{@user.id} from Member to Builder/, ModAction.last.description)
assert_equal(@user, ModAction.first.subject)
assert_equal(@mod, ModAction.first.creator)
assert_equal(@user, ModAction.last.subject) assert_equal(@user, ModAction.last.subject)
assert_equal(@mod, ModAction.last.creator) assert_equal(@mod, ModAction.last.creator)
end end

View File

@@ -522,8 +522,8 @@ class PostsControllerTest < ActionDispatch::IntegrationTest
context "with everything" do context "with everything" do
setup do setup do
@admin = create(:admin_user, can_approve_posts: true) @admin = create(:admin_user)
@builder = create(:builder_user, can_approve_posts: true) @approver = create(:approver_user)
as(@user) do as(@user) do
@post.update!(tag_string: "1girl solo highres blah 2001") @post.update!(tag_string: "1girl solo highres blah 2001")
@@ -545,7 +545,7 @@ class PostsControllerTest < ActionDispatch::IntegrationTest
#create(:post_appeal, post: @post, creator: @user) #create(:post_appeal, post: @post, creator: @user)
create(:post_vote, post: @post, user: @user) create(:post_vote, post: @post, user: @user)
create(:favorite, post: @post, user: @user) create(:favorite, post: @post, user: @user)
create(:moderation_report, model: @comment, creator: @builder) create(:moderation_report, model: @comment, creator: @approver)
end end
end end
@@ -560,7 +560,7 @@ class PostsControllerTest < ActionDispatch::IntegrationTest
end end
should "render for a builder" do should "render for a builder" do
get_auth post_path(@post), @builder get_auth post_path(@post), @approver
assert_response :success assert_response :success
end end
@@ -570,7 +570,7 @@ class PostsControllerTest < ActionDispatch::IntegrationTest
end end
should "render for a builder with a search query" do should "render for a builder with a search query" do
get_auth post_path(@post, q: "tagme"), @builder get_auth post_path(@post, q: "tagme"), @approver
assert_response :success assert_response :success
end end

View File

@@ -9,7 +9,7 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
context "index action" do context "index action" do
setup do setup do
@mod_user = create(:moderator_user, name: "yukari") @mod_user = create(:moderator_user, name: "yukari")
@other_user = create(:builder_user, can_upload_free: true, inviter: @mod_user, created_at: 2.weeks.ago) @other_user = create(:contributor_user, inviter: @mod_user, created_at: 2.weeks.ago)
@uploader = create(:user, created_at: 2.weeks.ago) @uploader = create(:user, created_at: 2.weeks.ago)
end end
@@ -41,7 +41,6 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
should respond_to_search({}).with { [@uploader, @other_user, @mod_user, @user, User.system] } should respond_to_search({}).with { [@uploader, @other_user, @mod_user, @user, User.system] }
should respond_to_search(min_level: User::Levels::BUILDER).with { [@other_user, @mod_user, User.system] } should respond_to_search(min_level: User::Levels::BUILDER).with { [@other_user, @mod_user, User.system] }
should respond_to_search(can_upload_free: "true").with { @other_user }
should respond_to_search(name_matches: "yukari").with { @mod_user } should respond_to_search(name_matches: "yukari").with { @mod_user }
context "using includes" do context "using includes" do
@@ -114,7 +113,7 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
context "show action" do context "show action" do
setup do setup do
# flesh out profile to get more test coverage of user presenter. # flesh out profile to get more test coverage of user presenter.
@user = create(:user, can_approve_posts: true, created_at: 2.weeks.ago) @user = create(:approver, created_at: 2.weeks.ago)
as(@user) do as(@user) do
create(:saved_search, user: @user) create(:saved_search, user: @user)
create(:post, uploader: @user, tag_string: "fav:#{@user.name}") create(:post, uploader: @user, tag_string: "fav:#{@user.name}")

View File

@@ -3,13 +3,13 @@ require 'test_helper'
class ApproverPrunerTest < ActiveSupport::TestCase class ApproverPrunerTest < ActiveSupport::TestCase
context "ApproverPruner" do context "ApproverPruner" do
setup do setup do
@approver = create(:user, can_approve_posts: true) @approver = create(:approver)
end end
should "demote inactive approvers" do should "demote inactive approvers" do
assert_equal([@approver.id], ApproverPruner.inactive_approvers.map(&:id)) assert_equal([@approver.id], ApproverPruner.inactive_approvers.map(&:id))
assert_nothing_raised { ApproverPruner.prune! } assert_nothing_raised { ApproverPruner.prune! }
assert_equal(false, @approver.reload.can_approve_posts) assert_equal(User::Levels::CONTRIBUTOR, @approver.reload.level)
end end
should "not demote active approvers" do should "not demote active approvers" do
@@ -22,7 +22,7 @@ class ApproverPrunerTest < ActiveSupport::TestCase
should "not demote recently promoted approvers" do should "not demote recently promoted approvers" do
as(create(:admin_user)) do as(create(:admin_user)) do
@user = create(:user) @user = create(:user)
@user.promote_to!(User::Levels::BUILDER, can_approve_posts: true) @user.promote_to!(User::Levels::APPROVER)
end end
assert_not_includes(ApproverPruner.inactive_approvers.map(&:id), @user.id) assert_not_includes(ApproverPruner.inactive_approvers.map(&:id), @user.id)

View File

@@ -43,7 +43,7 @@ class PostAppealTest < ActiveSupport::TestCase
context "for users with unrestricted uploads" do context "for users with unrestricted uploads" do
should "should not have an appeal limit" do should "should not have an appeal limit" do
@user = create(:user, can_upload_free: true) @user = create(:contributor)
create_list(:post_appeal, 10, creator: @user) create_list(:post_appeal, 10, creator: @user)
assert_equal(15, @user.upload_limit.upload_slots) assert_equal(15, @user.upload_limit.upload_slots)

View File

@@ -5,7 +5,7 @@ class PostApprovalTest < ActiveSupport::TestCase
setup do setup do
@user = create(:user, created_at: 2.weeks.ago) @user = create(:user, created_at: 2.weeks.ago)
@post = create(:post, uploader: @user, is_pending: true) @post = create(:post, uploader: @user, is_pending: true)
@approver = create(:user, can_approve_posts: true) @approver = create(:approver)
end end
context "a pending post" do context "a pending post" do

View File

@@ -4,7 +4,7 @@ class PostFlagTest < ActiveSupport::TestCase
context "PostFlag: " do context "PostFlag: " do
context "an approver" do context "an approver" do
should "be able to flag an unlimited number of posts" do should "be able to flag an unlimited number of posts" do
@user = create(:user, can_approve_posts: true) @user = create(:approver)
assert_nothing_raised do assert_nothing_raised do
create_list(:post_flag, 6, creator: @user, status: :pending) create_list(:post_flag, 6, creator: @user, status: :pending)