Merge pull request #18 from skiprope/temp-bans

Support for ban reasons and ban times.
This commit is contained in:
Georg G. 2015-05-05 16:54:23 +02:00
commit 9b39491d88
20 changed files with 263 additions and 21 deletions

View File

@ -33,6 +33,8 @@ gem 'font-awesome-rails', '~> 4.3.0.0'
gem 'rails-assets-growl' gem 'rails-assets-growl'
gem "paperclip", "~> 4.2" gem "paperclip", "~> 4.2"
gem 'delayed_paperclip' gem 'delayed_paperclip'
gem 'momentjs-rails', '>= 2.9.0'
gem 'bootstrap3-datetimepicker-rails', '~> 4.7.14'
gem 'ruby-progressbar' gem 'ruby-progressbar'
@ -78,4 +80,3 @@ group :development, :test do
gem 'simplecov-rcov', require: false gem 'simplecov-rcov', require: false
gem 'database_cleaner' gem 'database_cleaner'
end end

View File

@ -48,6 +48,8 @@ GEM
bcrypt (3.1.10) bcrypt (3.1.10)
bootstrap-sass (3.2.0.2) bootstrap-sass (3.2.0.2)
sass (~> 3.2) sass (~> 3.2)
bootstrap3-datetimepicker-rails (4.7.14)
momentjs-rails (>= 2.8.1)
bootstrap_form (2.3.0) bootstrap_form (2.3.0)
bootswatch-rails (3.2.4) bootswatch-rails (3.2.4)
railties (>= 3.1) railties (>= 3.1)
@ -149,6 +151,8 @@ GEM
mime-types (2.4.3) mime-types (2.4.3)
mini_portile (0.6.2) mini_portile (0.6.2)
minitest (5.6.0) minitest (5.6.0)
momentjs-rails (2.9.0)
railties (>= 3.1)
multi_json (1.11.0) multi_json (1.11.0)
multipart-post (2.0.0) multipart-post (2.0.0)
mysql2 (0.3.18) mysql2 (0.3.18)
@ -362,6 +366,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
bcrypt (~> 3.1.7) bcrypt (~> 3.1.7)
bootstrap-sass (~> 3.2.0.1) bootstrap-sass (~> 3.2.0.1)
bootstrap3-datetimepicker-rails (~> 4.7.14)
bootstrap_form bootstrap_form
bootswatch-rails bootswatch-rails
capybara capybara
@ -380,6 +385,7 @@ DEPENDENCIES
jbuilder (~> 2.2.4) jbuilder (~> 2.2.4)
jquery-rails jquery-rails
jquery-turbolinks jquery-turbolinks
momentjs-rails (>= 2.9.0)
mysql2 mysql2
nprogress-rails nprogress-rails
omniauth omniauth

View File

@ -94,11 +94,67 @@ namespace :justask do
end end
desc "Hits an user with the banhammer." desc "Hits an user with the banhammer."
task :ban, [:screen_name] => :environment do |t, args| task :permanently_ban, [:screen_name, :reason] => :environment do |t, args|
fail "screen name required" if args[:screen_name].nil? fail "screen name required" if args[:screen_name].nil?
user = User.find_by_screen_name(args[:screen_name]) user = User.find_by_screen_name(args[:screen_name])
fail "user #{args[:screen_name]} not found" if user.nil? fail "user #{args[:screen_name]} not found" if user.nil?
user.banned = true user.permanently_banned = true
user.ban_reason = args[:reason]
user.save!
puts "#{user.screen_name} got hit by\033[5m YE OLDE BANHAMMER\033[0m!!1!"
end
desc "Hits an user with the banhammer for one day."
task :ban, [:screen_name, :reason] => :environment do |t, args|
fail "screen name required" if args[:screen_name].nil?
user = User.find_by_screen_name(args[:screen_name])
user.permanently_banned = false
user.banned_until = DateTime.current + 1
user.ban_reason = args[:reason]
user.save!
puts "#{user.screen_name} got hit by\033[5m YE OLDE BANHAMMER\033[0m!!1!"
end
desc "Hits an user with the banhammer for one week."
task :week_ban, [:screen_name, :reason] => :environment do |t, args|
fail "screen name required" if args[:screen_name].nil?
user = User.find_by_screen_name(args[:screen_name])
user.permanently_banned = false
user.banned_until = DateTime.current + 7
user.ban_reason = args[:reason]
user.save!
puts "#{user.screen_name} got hit by\033[5m YE OLDE BANHAMMER\033[0m!!1!"
end
desc "Hits an user with the banhammer for one month."
task :month_ban, [:screen_name, :reason] => :environment do |t, args|
fail "screen name required" if args[:screen_name].nil?
user = User.find_by_screen_name(args[:screen_name])
user.permanently_banned = false
user.banned_until = DateTime.current + 30
user.ban_reason = args[:reason]
user.save!
puts "#{user.screen_name} got hit by\033[5m YE OLDE BANHAMMER\033[0m!!1!"
end
desc "Hits an user with the banhammer for one year."
task :year_ban, [:screen_name, :reason] => :environment do |t, args|
fail "screen name required" if args[:screen_name].nil?
user = User.find_by_screen_name(args[:screen_name])
user.permanently_banned = false
user.banned_until = DateTime.current + 365
user.ban_reason = args[:reason]
user.save!
puts "#{user.screen_name} got hit by\033[5m YE OLDE BANHAMMER\033[0m!!1!"
end
desc "Hits an user with the banhammer for one aeon."
task :aeon_ban, [:screen_name, :reason] => :environment do |t, args|
fail "screen name required" if args[:screen_name].nil?
user = User.find_by_screen_name(args[:screen_name])
user.permanently_banned = false
user.banned_until = DateTime.current + 365_000_000_000
user.ban_reason = args[:reason]
user.save! user.save!
puts "#{user.screen_name} got hit by\033[5m YE OLDE BANHAMMER\033[0m!!1!" puts "#{user.screen_name} got hit by\033[5m YE OLDE BANHAMMER\033[0m!!1!"
end end
@ -108,7 +164,9 @@ namespace :justask do
fail "screen name required" if args[:screen_name].nil? fail "screen name required" if args[:screen_name].nil?
user = User.find_by_screen_name(args[:screen_name]) user = User.find_by_screen_name(args[:screen_name])
fail "user #{args[:screen_name]} not found" if user.nil? fail "user #{args[:screen_name]} not found" if user.nil?
user.banned = false user.permanently_banned = false
user.banned_until = nil
user.ban_reason = nil
user.save! user.save!
puts "#{user.screen_name} is no longer banned." puts "#{user.screen_name} is no longer banned."
end end

View File

@ -41,7 +41,8 @@ $(document).on "click", "button#create-account", ->
Turbolinks.visit "/sign_up" Turbolinks.visit "/sign_up"
_ready = -> _ready = ->
sweetAlertInitialize() if typeof sweetAlertInitialize != "undefined"
sweetAlertInitialize()
$(document).ready _ready $(document).ready _ready
$(document).on 'page:load', _ready $(document).on 'page:load', _ready

View File

@ -1 +1,3 @@
#= require_tree ./moderation #= require moment
#= require bootstrap-datetimepicker
#= require_tree ./moderation

View File

@ -0,0 +1,58 @@
$(document).on "DOMContentLoaded", ->
parent = $ "#ban-control-super"
parent.find('#_ban').on "change", (event) ->
$t = $ this
if $t.is(":checked")
$("#ban-controls").show()
else
$("#ban-controls").hide()
parent.find('#_permaban').on "change", (event) ->
$t = $ this
if $t.is(":checked")
$("#ban-controls-time").hide()
else
$("#ban-controls-time").show()
parent.find("#until").datetimepicker
defaultDate: parent.find("#until").val()
sideBySide: true
icons:
time: "fa fa-clock-o"
date: "fa fa-calendar"
up: "fa fa-chevron-up"
down: "fa fa-chevron-down"
previous: "fa fa-chevron-left"
next: "fa fa-chevron-right"
today: "fa fa-home"
clear: "fa fa-trash-o"
close: "fa fa-times"
parent.parent()[0].addEventListener "submit", (event) ->
event.preventDefault();
$("#modal-ban").modal "hide"
checktostr = (selector) ->
if $(selector)[0].checked
"1"
else
"0"
data = {
ban: checktostr "#_ban"
permaban: checktostr "#_permaban"
until: $("#until")[0].value.trim()
reason: $("#reason")[0].value.trim()
user: $("#_user")[0].value
}
$.ajax
url: '/ajax/mod/ban'
type: 'POST'
data: data
success: (data, status, jqxhr) ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
complete: (jqxhr, status) ->

View File

@ -21,4 +21,4 @@
console.log jqxhr, status, error console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false showNotification "An error occurred, a developer should check the console for details", false
complete: (jqxhr, status) -> complete: (jqxhr, status) ->
box.removeAttr "disabled" box.removeAttr "disabled"

View File

@ -45,7 +45,14 @@ $navbar-inverse-toggle-border-color: #512da8;
@import "bootswatch/cosmo/variables"; @import "bootswatch/cosmo/variables";
@import "bootstrap"; @import "bootstrap";
body { padding-top: $navbar-height; } body { padding-top: $navbar-height; }
@import 'bootstrap-datetimepicker';
.remove-native-picker::-webkit-calendar-picker-indicator{
display: none
}
@import "bootswatch/cosmo/bootswatch"; @import "bootswatch/cosmo/bootswatch";
@import "base"; @import "base";

View File

@ -105,6 +105,46 @@ class Ajax::ModerationController < ApplicationController
@success = true @success = true
end end
def ban
@status = :err
@message = "Weird..."
@success = false
params.require :user
params.require :ban
params.require :permaban
reason = params[:reason]
target = User.find_by_screen_name(params[:user])
unban = params[:ban] == "0"
perma = params[:permaban] == "1"
buntil = DateTime.strptime params[:until], "%m/%d/%Y %I:%M %p" unless unban or perma
if not unban and target.admin?
@status = :nopriv
@message = "You cannot ban an administrator!"
@success = false
return
end
if unban
target.unban
@message = "Unbanned user."
@success = true
elsif perma
target.ban nil, reason
@message = "Permanently banned user."
else
target.ban buntil, reason
@message = "Banned user until #{buntil.to_s}"
end
target.save!
@status = :okay
@success = target.banned? == !unban
end
def privilege def privilege
@status = :err @status = :err
@success = false @success = false
@ -118,10 +158,9 @@ class Ajax::ModerationController < ApplicationController
target_user = User.find_by_screen_name(params[:user]) target_user = User.find_by_screen_name(params[:user])
@message = "nope!" @message = "nope!"
return unless %w(banned blogger supporter moderator admin contributor).include? params[:type].downcase return unless %w(blogger supporter moderator admin contributor).include? params[:type].downcase
if (%w(supporter moderator admin).include?(params[:type].downcase) and !current_user.admin?) or if %w(supporter moderator admin).include?(params[:type].downcase) and !current_user.admin?
(params[:type].downcase == 'banned' and target_user.admin?)
@status = :nopriv @status = :nopriv
@message = "You'd better check YOUR privileges first!" @message = "You'd better check YOUR privileges first!"
@success = false @success = false

View File

@ -12,6 +12,13 @@ class ApplicationController < ActionController::Base
name = current_user.screen_name name = current_user.screen_name
# obligatory '2001: A Space Odyssey' reference # obligatory '2001: A Space Odyssey' reference
flash[:notice] = "I'm sorry, #{name}, I'm afraid I can't do that." flash[:notice] = "I'm sorry, #{name}, I'm afraid I can't do that."
if current_user.ban_reason.nil?
flash[:notice] += "\nBan reason: #{current_user.ban_reason}"
end
if not current_user.permanently_banned?
# TODO format banned_until
flash[:notice] += "\nBanned until: #{current_user.banned_until}"
end
sign_out current_user sign_out current_user
redirect_to new_user_session_path redirect_to new_user_session_path
end end

View File

@ -224,4 +224,21 @@ class User < ActiveRecord::Base
def cropping? def cropping?
!crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank? !crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
end end
# forwards fill
def banned?
self.permanently_banned? or ((not self.banned_until.nil?) and self.banned_until >= DateTime.current)
end
def unban
self.update(permanently_banned: false, ban_reason: nil, banned_until: nil)
end
def ban(buntil=nil, reason=nil)
if buntil == nil
self.update(permanently_banned: true, ban_reason: reason)
else
self.update(permanently_banned: false, banned_until: buntil, ban_reason: reason)
end
end
end end

View File

@ -0,0 +1 @@
json.partial! 'ajax/shared/status'

View File

@ -27,6 +27,9 @@
%a.btn.btn-primary{href: content_url(report)} %a.btn.btn-primary{href: content_url(report)}
View reported View reported
= report.type.sub('Reports::', '') = report.type.sub('Reports::', '')
- if report.target.respond_to? :user and not report.target.user.nil?
%a.btn.btn-primary{href: show_user_profile_path(report.target.user.screen_name)}
View reported User
.col-md-6.col-sm-8.col-xs-6.text-right .col-md-6.col-sm-8.col-xs-6.text-right
%span.mod-count{id: "mod-count-#{report.id}"} %span.mod-count{id: "mod-count-#{report.id}"}
= report.votes = report.votes

View File

@ -35,4 +35,9 @@
Check Check
= succeed "'s" do = succeed "'s" do
= user.screen_name = user.screen_name
privileges privileges
- unless user.admin?
%li
%a{href: '#', data: { target: "#modal-ban", toggle: :modal }}
%i.fa.fa-ban
Ban Control

View File

@ -0,0 +1,21 @@
#modal-ban.modal.fade{"aria-hidden" => "true", "aria-labelledby" => "modal-ban-label", :role => "dialog", :tabindex => "-1"}
.modal-dialog
.modal-content
.modal-header
%button.close{"data-dismiss" => "modal", :type => "button"}
%span{"aria-hidden" => "true"} ×
%span.sr-only Close
%h4#modal-ban-label.modal-title
Ban Control Center
= bootstrap_form_tag(url: '/mod/ban', html: { method: :post, novalidate: "novalidate" }) do |f|
= f.hidden_field :user, value: @user.screen_name
#ban-control-super.modal-body
= f.check_box :ban, label: "Ban?", checked: @user.banned?
#ban-controls{style: "#{"display: none" unless @user.banned?}"}
= f.check_box :permaban, label: "Permanently?", checked: @user.permanently_banned?
#ban-controls-time{style: "#{"display: none" unless not @user.permanently_banned?}"}
= f.text_field :until, label: "", required: true, value: (@user.banned_until || DateTime.current).strftime("%m/%d/%Y %I:%M %p")
= f.text_field :reason, placeholder: "Reason", value: @user.ban_reason
.modal-footer
%button.btn.btn-default{name: 'stop-time', type: :button, data: { dismiss: :modal }} Close
= f.submit "Hammer Time", class: "btn btn-primary", name: 'hammer-time'

View File

@ -11,8 +11,6 @@
= @user.screen_name = @user.screen_name
privileges privileges
%ul.list-group.groups--list %ul.list-group.groups--list
- unless @user.admin?
= render 'user/modal_privileges_item', privilege: 'banned', description: 'Hit the user with ye olde banhammer', user: @user
= render 'user/modal_privileges_item', privilege: 'blogger', description: 'The user gets that privilege if they blogged something (nice) about Retrospring.', user: @user = render 'user/modal_privileges_item', privilege: 'blogger', description: 'The user gets that privilege if they blogged something (nice) about Retrospring.', user: @user
= render 'user/modal_privileges_item', privilege: 'contributor', description: "This user has contributed to justask#{" (the software behind #{APP_CONFIG['site_name']})" unless APP_CONFIG['site_name'] == 'justask'}.", user: @user = render 'user/modal_privileges_item', privilege: 'contributor', description: "This user has contributed to justask#{" (the software behind #{APP_CONFIG['site_name']})" unless APP_CONFIG['site_name'] == 'justask'}.", user: @user
- if current_user.admin? - if current_user.admin?

View File

@ -5,17 +5,19 @@
.hidden-xs= render 'shared/links' .hidden-xs= render 'shared/links'
.col-md-9.col-xs-12.col-sm-8.j2-col-reset .col-md-9.col-xs-12.col-sm-8.j2-col-reset
= render 'shared/questionbox' = render 'shared/questionbox'
#answers = unless @user.banned?
- @answers.each do |a| #answers
= render 'shared/answerbox', a: a - @answers.each do |a|
= render 'shared/answerbox', a: a
#pagination= will_paginate @answers, renderer: BootstrapPagination::Rails, page_links: false #pagination= will_paginate @answers, renderer: BootstrapPagination::Rails, page_links: false
- if @answers.next_page - if @answers.next_page
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @answers.current_page }} %button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @answers.current_page }}
Load more Load more
.visible-xs= render 'shared/links' .visible-xs= render 'shared/links'
- if user_signed_in? - if user_signed_in?
= render 'user/modal_group_memberships' = render 'user/modal_group_memberships'
- if current_user.mod? and @user != current_user - if current_user.mod? and @user != current_user
= render 'user/modal_privileges' = render 'user/modal_privileges'
= render 'user/modal_ban'

View File

@ -21,6 +21,7 @@ Rails.application.routes.draw do
match '/mod/create_vote', to: 'moderation#vote', via: :post, as: :mod_create_vote match '/mod/create_vote', to: 'moderation#vote', via: :post, as: :mod_create_vote
match '/mod/destroy_vote', to: 'moderation#destroy_vote', via: :post, as: :mod_destroy_vote match '/mod/destroy_vote', to: 'moderation#destroy_vote', via: :post, as: :mod_destroy_vote
match '/mod/privilege', to: 'moderation#privilege', via: :post, as: :mod_privilege match '/mod/privilege', to: 'moderation#privilege', via: :post, as: :mod_privilege
match '/mod/ban', to: 'moderation#ban', via: :post, as: :mod_ban
end end
end end

View File

@ -0,0 +1,9 @@
class RenameBannedToPermanentlyBannedInUsers < ActiveRecord::Migration
def up
rename_column :users, :banned, :permanently_banned
end
def down
rename_column :users, :permanently_banned, :banned
end
end

View File

@ -0,0 +1,6 @@
class AddBanReasonAndBannedUntilToUsers < ActiveRecord::Migration
def change
add_column :users, :ban_reason, :string, default: nil
add_column :users, :banned_until, :datetime, default: nil
end
end