diff --git a/app/controllers/forum_categories_controller.rb b/app/controllers/forum_categories_controller.rb new file mode 100644 index 000000000..42a0f8d5f --- /dev/null +++ b/app/controllers/forum_categories_controller.rb @@ -0,0 +1,47 @@ +class ForumCategoriesController < ApplicationController + respond_to :html + before_action :admin_only + + def index + @forum_cats = ForumCategory.paginate(params[:page], limit: 50, order: "forum_categories.order ASC, forum_categories.id ASC") + @new_cat = ForumCategory.new + @user_levels = [['Anyone', 0]] + User.level_hash.to_a + end + + def create + @cat = ForumCategory.create(category_params) + if @cat.valid? + ModAction.log(:forum_category_create, {forum_category_id: @cat.id}) + flash[:notice] = "Category created" + else + flash[:notice] = @cat.errors.full_messages.join('; ') + end + redirect_to forum_categories_path + end + + def destroy + @cat = ForumCategory.find(params[:id]) + @cat.destroy + ModAction.log(:forum_category_delete, {forum_category_id: @cat.id}) + respond_with(@cat) + end + + def update + @cat = ForumCategory.find(params[:id]) + @cat.update(category_params) + + if @cat.valid? + ModAction.log(:forum_category_update, {forum_category_id: @cat.id}) + flash[:notice] = "Category updated" + else + flash[:notice] = @cat.errors.full_messages.join('; ') + end + redirect_to forum_categories_path + end + + private + + def category_params + params.require(:forum_category).permit([:name, :description, :can_create, :can_reply, :can_view, :order]) + end +end diff --git a/app/controllers/forum_posts_controller.rb b/app/controllers/forum_posts_controller.rb index fd9a48f35..6188551cd 100644 --- a/app/controllers/forum_posts_controller.rb +++ b/app/controllers/forum_posts_controller.rb @@ -8,11 +8,11 @@ class ForumPostsController < ApplicationController def new if params[:topic_id] @forum_topic = ForumTopic.find(params[:topic_id]) - raise User::PrivilegeError.new unless @forum_topic.visible?(CurrentUser.user) + raise User::PrivilegeError.new unless @forum_topic.visible?(CurrentUser.user) && @forum_topic.can_reply?(CurrentUser.user) end if params[:post_id] quoted_post = ForumPost.find(params[:post_id]) - raise User::PrivilegeError.new unless quoted_post.topic.visible?(CurrentUser.user) + raise User::PrivilegeError.new unless quoted_post.topic.visible?(CurrentUser.user) && quoted_post.topic.can_reply?(CurrentUser.user) end @forum_post = ForumPost.new_reply(params) respond_with(@forum_post) diff --git a/app/helpers/forum_topics_helper.rb b/app/helpers/forum_topics_helper.rb index 2fc818be6..c4cc9186d 100644 --- a/app/helpers/forum_topics_helper.rb +++ b/app/helpers/forum_topics_helper.rb @@ -1,6 +1,6 @@ module ForumTopicsHelper def forum_topic_category_select(object, field) - select(object, field, ForumTopic.reverse_category_mapping.to_a) + select(object, field, ForumCategory.reverse_mapping) end def available_min_user_levels diff --git a/app/models/forum_category.rb b/app/models/forum_category.rb new file mode 100644 index 000000000..722d5ceb9 --- /dev/null +++ b/app/models/forum_category.rb @@ -0,0 +1,22 @@ +class ForumCategory < ApplicationRecord + has_many :forum_topics, -> { order(id: :desc) } + validates_uniqueness_of :name, case_sensitive: false + + after_destroy :reassign_topics + + def reassign_topics + ForumTopic.where(category: @cat.id).update_all(category_id: 0) + end + + def can_create_within?(user = CurrentUser.user) + user.level >= can_create + end + + def self.reverse_mapping + order(:cat_order).all.map { |rec| [rec.name, rec.id] } + end + + def self.ordered_categories + order(:cat_order) + end +end \ No newline at end of file diff --git a/app/models/forum_post.rb b/app/models/forum_post.rb index ead618b2c..a7a301491 100644 --- a/app/models/forum_post.rb +++ b/app/models/forum_post.rb @@ -17,6 +17,7 @@ class ForumPost < ApplicationRecord validate :validate_topic_is_unlocked validate :topic_id_not_invalid validate :topic_is_not_restricted, :on => :create + validate :category_allows_replies, on: :create before_destroy :validate_topic_is_unlocked after_save :delete_topic_if_original_post after_update(:if => ->(rec) {rec.updater_id != rec.creator_id}) do |rec| @@ -158,6 +159,13 @@ class ForumPost < ApplicationRecord end end + def category_allows_replies + if topic && !topic.can_rely?(creator) + errors[:topic] << "does not allow replies" + return false + end + end + def editable_by?(user) (creator_id == user.id || user.is_moderator?) && visible?(user) end diff --git a/app/models/forum_topic.rb b/app/models/forum_topic.rb index 0ebd67aeb..cda86f210 100644 --- a/app/models/forum_topic.rb +++ b/app/models/forum_topic.rb @@ -13,15 +13,17 @@ class ForumTopic < ApplicationRecord belongs_to_creator belongs_to_updater + belongs_to :category, class_name: "ForumCategory", foreign_key: :category_id has_many :posts, -> {order("forum_posts.id asc")}, :class_name => "ForumPost", :foreign_key => "topic_id", :dependent => :destroy has_one :original_post, -> {order("forum_posts.id asc")}, class_name: "ForumPost", foreign_key: "topic_id", inverse_of: :topic has_many :subscriptions, :class_name => "ForumSubscription" before_validation :initialize_is_deleted, :on => :create validates_presence_of :title, :creator_id validates_associated :original_post - validates_inclusion_of :category_id, :in => CATEGORIES.keys + validates_associated :category validates_inclusion_of :min_level, :in => MIN_LEVELS.values validates :title, :length => {:maximum => 255} + validate :category_allows_creation, on: :create accepts_nested_attributes_for :original_post after_update :update_orignal_post after_save(:if => ->(rec) {rec.is_locked? && rec.saved_change_to_is_locked?}) do |rec| @@ -32,21 +34,21 @@ class ForumTopic < ApplicationRecord extend ActiveSupport::Concern module ClassMethods - def categories - CATEGORIES.values - end - - def reverse_category_mapping - @reverse_category_mapping ||= CATEGORIES.invert - end - def for_category_id(cid) where(:category_id => cid) end end def category_name - CATEGORIES[category_id] + return '(Unknown)' unless category + category.name + end + + def category_allows_creation + if category && !category.can_create_within?(creator) + errors[:category] << "doesn't allow new topics" + return false + end end end @@ -56,7 +58,7 @@ class ForumTopic < ApplicationRecord end def permitted - where("min_level <= ?", CurrentUser.level) + where("min_level <= ?", CurrentUser.level).joins(:category).where('forum_categories.can_view <= ?', CurrentUser.level) end def sticky_first @@ -148,7 +150,11 @@ class ForumTopic < ApplicationRecord end def visible?(user) - user.level >= min_level + user.level >= min_level && user.level >= category.can_view + end + + def can_reply?(user = CurrentUser.user) + user.level >= category.can_reply end def create_mod_action_for_delete diff --git a/app/views/forum_categories/index.html.erb b/app/views/forum_categories/index.html.erb new file mode 100644 index 000000000..d187704da --- /dev/null +++ b/app/views/forum_categories/index.html.erb @@ -0,0 +1,44 @@ +
Note: If any levels are set to "Member", logged-out users will not be able to use that category. Use "Anyone" as + the default.
+