diff --git a/app/controllers/bans_controller.rb b/app/controllers/bans_controller.rb index 74b76372a..3d11efa10 100644 --- a/app/controllers/bans_controller.rb +++ b/app/controllers/bans_controller.rb @@ -1,5 +1,5 @@ class BansController < ApplicationController - respond_to :html, :xml, :json + respond_to :html, :xml, :json, :js def new @ban = authorize Ban.new(permitted_attributes(Ban)) diff --git a/app/logical/bigquery_export_service.rb b/app/logical/bigquery_export_service.rb index c8d5a957c..7320eb2c9 100644 --- a/app/logical/bigquery_export_service.rb +++ b/app/logical/bigquery_export_service.rb @@ -21,7 +21,7 @@ class BigqueryExportService Rails.application.eager_load! models = ApplicationRecord.descendants.sort_by(&:name) - models -= [Ban, Favorite, IpAddress, TagRelationship, ArtistVersion, ArtistCommentaryVersion, NoteVersion, PoolVersion, PostVersion, WikiPageVersion] + models -= [Favorite, IpAddress, TagRelationship, ArtistVersion, ArtistCommentaryVersion, NoteVersion, PoolVersion, PostVersion, WikiPageVersion] models end diff --git a/app/logical/concerns/searchable.rb b/app/logical/concerns/searchable.rb index 46b1682ee..7f5a3c5c6 100644 --- a/app/logical/concerns/searchable.rb +++ b/app/logical/concerns/searchable.rb @@ -212,7 +212,7 @@ module Searchable search_text_attribute(name, params) when :boolean search_boolean_attribute(name, params) - when :integer, :float, :datetime + when :integer, :float, :datetime, :interval search_numeric_attribute(name, params, type: type) when :inet search_inet_attribute(name, params) @@ -221,7 +221,7 @@ module Searchable when :array search_array_attribute(name, subtype, params) else - raise NotImplementedError, "unhandled attribute type: #{name}" + raise NotImplementedError, "unhandled attribute type: #{name} (#{type})" end end diff --git a/app/logical/post_query_builder.rb b/app/logical/post_query_builder.rb index 5c0b5f5e1..33c37ff07 100644 --- a/app/logical/post_query_builder.rb +++ b/app/logical/post_query_builder.rb @@ -740,6 +740,9 @@ class PostQueryBuilder when :age DurationParser.parse(object).ago + when :interval + DurationParser.parse(object) + when :ratio object =~ /\A(\d+(?:\.\d+)?):(\d+(?:\.\d+)?)\Z/i @@ -765,6 +768,9 @@ class PostQueryBuilder end (size * conversion_factor).to_i + + else + raise NotImplementedError, "unrecognized type #{type} for #{object}" end end diff --git a/app/models/ban.rb b/app/models/ban.rb index b1a23bf68..912f17619 100644 --- a/app/models/ban.rb +++ b/app/models/ban.rb @@ -1,4 +1,6 @@ class Ban < ApplicationRecord + attribute :duration, :interval + after_create :create_feedback after_create :update_user_on_create after_create :create_ban_mod_action @@ -7,20 +9,14 @@ class Ban < ApplicationRecord belongs_to :user belongs_to :banner, :class_name => "User" - validates_presence_of :reason, :duration + validates :reason, presence: true validate :user, :validate_user_is_bannable, on: :create - scope :unexpired, -> { where("bans.expires_at > ?", Time.now) } - scope :expired, -> { where("bans.expires_at <= ?", Time.now) } - - attr_reader :duration - - def self.is_banned?(user) - exists?(["user_id = ? AND expires_at > ?", user.id, Time.now]) - end + scope :unexpired, -> { where("bans.created_at + bans.duration > ?", Time.now) } + scope :expired, -> { where("bans.created_at + bans.duration <= ?", Time.now) } def self.search(params) - q = search_attributes(params, :id, :created_at, :updated_at, :expires_at, :reason, :user, :banner) + q = search_attributes(params, :id, :created_at, :updated_at, :duration, :reason, :user, :banner) q = q.text_attribute_matches(:reason, params[:reason_matches]) q = q.expired if params[:expired].to_s.truthy? @@ -28,7 +24,7 @@ class Ban < ApplicationRecord case params[:order] when "expires_at_desc" - q = q.order("bans.expires_at desc") + q = q.order(Arel.sql("bans.created_at + bans.duration DESC")) else q = q.apply_default_order(params) end @@ -62,9 +58,8 @@ class Ban < ApplicationRecord self.user = User.find_by_name(username) end - def duration=(dur) - self.expires_at = dur.to_i.days.from_now - @duration = dur + def expires_at + created_at + duration end def humanized_duration diff --git a/app/policies/ban_policy.rb b/app/policies/ban_policy.rb index 16606eb07..554e82c5b 100644 --- a/app/policies/ban_policy.rb +++ b/app/policies/ban_policy.rb @@ -9,11 +9,11 @@ class BanPolicy < ApplicationPolicy alias_method :destroy?, :bannable? def permitted_attributes_for_create - [:reason, :duration, :expires_at, :user_id, :user_name] + [:reason, :duration, :user_id, :user_name] end def permitted_attributes_for_update - [:reason, :duration, :expires_at] + [:reason, :duration] end def html_data_attributes diff --git a/app/views/bans/_form.html.erb b/app/views/bans/_form.html.erb index ec18d0df6..0c67491ca 100644 --- a/app/views/bans/_form.html.erb +++ b/app/views/bans/_form.html.erb @@ -1,6 +1,9 @@ <%= edit_form_for(ban) do |f| %> - <%= f.input :user_name, :as => :string, :input_html => { data: { autocomplete: "user" } } %> - <%= f.input :duration, :hint => "in days" %> + <% if ban.new_record? %> + <%= f.input :user_name, as: :string, input_html: { "data-autocomplete": "user" } %> + <% end %> + + <%= f.input :duration, collection: [["1 day", 1.day.iso8601], ["3 days", 3.days.iso8601], ["1 week", 1.week.iso8601], ["1 month", 1.month.iso8601], ["3 months", 3.months.iso8601], ["6 months", 6.months.iso8601], ["1 year", 1.year.iso8601], ["forever", 100.years.iso8601]] %> <%= f.input :reason %> - <%= f.button :submit, :value => "Ban" %> + <%= f.button :submit %> <% end %> diff --git a/app/views/bans/destroy.js.erb b/app/views/bans/destroy.js.erb index ba8a50f62..345366b9b 100644 --- a/app/views/bans/destroy.js.erb +++ b/app/views/bans/destroy.js.erb @@ -1 +1 @@ -$("#ban-<%= @ban.id %>").remove(); +location.reload(); diff --git a/app/views/bans/edit.html.erb b/app/views/bans/edit.html.erb index bb4ddefa2..9e969acc0 100644 --- a/app/views/bans/edit.html.erb +++ b/app/views/bans/edit.html.erb @@ -2,11 +2,7 @@