Merge branch 'master' into fix-mention-dmails
This commit is contained in:
1
Gemfile
1
Gemfile
@@ -59,6 +59,7 @@ gem 'google-api-client'
|
|||||||
gem 'cityhash'
|
gem 'cityhash'
|
||||||
gem 'bigquery', :git => "https://github.com/abronte/BigQuery.git", :ref => "b92b4e0b54574e3fde7ad910f39a67538ed387ad"
|
gem 'bigquery', :git => "https://github.com/abronte/BigQuery.git", :ref => "b92b4e0b54574e3fde7ad910f39a67538ed387ad"
|
||||||
gem 'memcache_mock'
|
gem 'memcache_mock'
|
||||||
|
gem 'memoist'
|
||||||
|
|
||||||
# needed for looser jpeg header compat
|
# needed for looser jpeg header compat
|
||||||
gem 'ruby-imagespec', :require => "image_spec", :git => "https://github.com/r888888888/ruby-imagespec.git", :branch => "exif-fixes"
|
gem 'ruby-imagespec', :require => "image_spec", :git => "https://github.com/r888888888/ruby-imagespec.git", :branch => "exif-fixes"
|
||||||
|
|||||||
@@ -405,6 +405,7 @@ DEPENDENCIES
|
|||||||
mechanize
|
mechanize
|
||||||
memcache-client
|
memcache-client
|
||||||
memcache_mock
|
memcache_mock
|
||||||
|
memoist
|
||||||
mocha
|
mocha
|
||||||
net-sftp
|
net-sftp
|
||||||
net-ssh
|
net-ssh
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ div.list-of-forum-posts {
|
|||||||
margin-bottom: 3em;
|
margin-bottom: 3em;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
||||||
|
&:target {
|
||||||
|
background-color: #FFC;
|
||||||
|
}
|
||||||
|
|
||||||
div.author {
|
div.author {
|
||||||
width: 12em;
|
width: 12em;
|
||||||
float: left;
|
float: left;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
module Admin
|
module Admin
|
||||||
class UsersController < ApplicationController
|
class UsersController < ApplicationController
|
||||||
before_filter :moderator_only
|
before_filter :moderator_only
|
||||||
rescue_from User::PrivilegeError, :with => :access_denied
|
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@user = User.find(params[:id])
|
@user = User.find(params[:id])
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
class CommentsController < ApplicationController
|
class CommentsController < ApplicationController
|
||||||
respond_to :html, :xml, :json
|
respond_to :html, :xml, :json
|
||||||
before_filter :member_only, :except => [:index, :search, :show]
|
before_filter :member_only, :except => [:index, :search, :show]
|
||||||
rescue_from ActiveRecord::StatementInvalid, :with => :rescue_exception
|
|
||||||
skip_before_filter :api_check
|
skip_before_filter :api_check
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
class DmailsController < ApplicationController
|
class DmailsController < ApplicationController
|
||||||
respond_to :html, :xml, :json
|
respond_to :html, :xml, :json
|
||||||
before_filter :member_only
|
before_filter :member_only
|
||||||
rescue_from User::PrivilegeError, :with => :access_denied
|
|
||||||
|
|
||||||
def new
|
def new
|
||||||
if params[:respond_to_id]
|
if params[:respond_to_id]
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
class LegacyController < ApplicationController
|
class LegacyController < ApplicationController
|
||||||
before_filter :member_only, :only => [:create_post]
|
before_filter :member_only, :only => [:create_post]
|
||||||
rescue_from PostSets::SearchError, :with => :rescue_exception
|
|
||||||
|
|
||||||
def posts
|
def posts
|
||||||
@post_set = PostSets::Post.new(tag_query, params[:page], params[:limit], format: "json")
|
@post_set = PostSets::Post.new(tag_query, params[:page], params[:limit], format: "json")
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
module Maintenance
|
module Maintenance
|
||||||
module User
|
module User
|
||||||
class DeletionsController < ApplicationController
|
class DeletionsController < ApplicationController
|
||||||
rescue_from UserDeletion::ValidationError, :with => :rescue_exception
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ module Moderator
|
|||||||
class PostsController < ApplicationController
|
class PostsController < ApplicationController
|
||||||
before_filter :approver_only, :only => [:delete, :undelete, :move_favorites, :ban, :unban, :confirm_delete, :confirm_move_favorites, :confirm_ban]
|
before_filter :approver_only, :only => [:delete, :undelete, :move_favorites, :ban, :unban, :confirm_delete, :confirm_move_favorites, :confirm_ban]
|
||||||
before_filter :admin_only, :only => [:expunge]
|
before_filter :admin_only, :only => [:expunge]
|
||||||
rescue_from ::PostFlag::Error, ::Post::ApprovalError, :with => :rescue_exception
|
|
||||||
skip_before_filter :api_check
|
skip_before_filter :api_check
|
||||||
|
|
||||||
def confirm_delete
|
def confirm_delete
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module Moderator
|
|||||||
end
|
end
|
||||||
|
|
||||||
::Post.without_timeout do
|
::Post.without_timeout do
|
||||||
@posts = ::Post.order("posts.id asc").pending_or_flagged.available_for_moderation(params[:hidden]).tag_match(params[:query]).paginate(params[:page], :limit => per_page)
|
@posts = ::Post.includes(:disapprovals, :uploader).order("posts.id asc").pending_or_flagged.available_for_moderation(params[:hidden]).tag_match(params[:query]).paginate(params[:page], :limit => per_page)
|
||||||
@posts.each # hack to force rails to eager load
|
@posts.each # hack to force rails to eager load
|
||||||
end
|
end
|
||||||
respond_with(@posts)
|
respond_with(@posts)
|
||||||
@@ -25,7 +25,7 @@ module Moderator
|
|||||||
cookies.permanent[:moderated] = Time.now.to_i
|
cookies.permanent[:moderated] = Time.now.to_i
|
||||||
|
|
||||||
::Post.without_timeout do
|
::Post.without_timeout do
|
||||||
@posts = ::Post.order("posts.id asc").pending_or_flagged.available_for_moderation(false).reorder("random()").limit(RANDOM_COUNT)
|
@posts = ::Post.includes(:disapprovals, :uploader).order("posts.id asc").pending_or_flagged.available_for_moderation(false).reorder("random()").limit(RANDOM_COUNT)
|
||||||
@posts.each # hack to force rails to eager load
|
@posts.each # hack to force rails to eager load
|
||||||
|
|
||||||
if @posts.empty?
|
if @posts.empty?
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
class PostVersionsController < ApplicationController
|
class PostVersionsController < ApplicationController
|
||||||
respond_to :html, :xml, :json
|
respond_to :html, :xml, :json
|
||||||
rescue_from ActiveRecord::StatementInvalid, :with => :rescue_exception
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@post_versions = PostVersion.search(params[:search]).order("updated_at desc, id desc").paginate(params[:page], :limit => params[:limit], :search_count => params[:search])
|
@post_versions = PostArchive.search(params[:search]).order("updated_at desc, id desc").paginate(params[:page], :limit => params[:limit], :search_count => params[:search])
|
||||||
respond_with(@post_versions) do |format|
|
respond_with(@post_versions) do |format|
|
||||||
format.xml do
|
format.xml do
|
||||||
render :xml => @post_versions.to_xml(:root => "post-versions")
|
render :xml => @post_versions.to_xml(:root => "post-versions")
|
||||||
@@ -15,7 +14,7 @@ class PostVersionsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def undo
|
def undo
|
||||||
@post_version = PostVersion.find(params[:id])
|
@post_version = PostArchive.find(params[:id])
|
||||||
|
|
||||||
if @post_version.post.visible?
|
if @post_version.post.visible?
|
||||||
@post_version.undo!
|
@post_version.undo!
|
||||||
|
|||||||
@@ -3,10 +3,6 @@ class PostsController < ApplicationController
|
|||||||
before_filter :builder_only, :only => [:copy_notes]
|
before_filter :builder_only, :only => [:copy_notes]
|
||||||
before_filter :enable_cors, :only => [:index, :show]
|
before_filter :enable_cors, :only => [:index, :show]
|
||||||
respond_to :html, :xml, :json
|
respond_to :html, :xml, :json
|
||||||
rescue_from PostSets::SearchError, :with => :rescue_exception
|
|
||||||
rescue_from Post::SearchError, :with => :rescue_exception
|
|
||||||
rescue_from ActiveRecord::StatementInvalid, :with => :rescue_exception
|
|
||||||
rescue_from ActiveRecord::RecordNotFound, :with => :rescue_exception
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
if params[:md5].present?
|
if params[:md5].present?
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
class UploadsController < ApplicationController
|
class UploadsController < ApplicationController
|
||||||
before_filter :member_only
|
before_filter :member_only
|
||||||
respond_to :html, :xml, :json, :js
|
respond_to :html, :xml, :json, :js
|
||||||
rescue_from Upload::Error, :with => :rescue_exception
|
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@upload = Upload.new
|
@upload = Upload.new
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ class UserNameChangeRequestsController < ApplicationController
|
|||||||
before_filter :member_only, :only => [:index, :show]
|
before_filter :member_only, :only => [:index, :show]
|
||||||
before_filter :gold_only, :only => [:new, :create]
|
before_filter :gold_only, :only => [:new, :create]
|
||||||
before_filter :admin_only, :only => [:approve, :reject]
|
before_filter :admin_only, :only => [:approve, :reject]
|
||||||
rescue_from User::PrivilegeError, :with => :access_denied
|
|
||||||
respond_to :html, :json, :xml
|
respond_to :html, :json, :xml
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
class UsersController < ApplicationController
|
class UsersController < ApplicationController
|
||||||
respond_to :html, :xml, :json
|
respond_to :html, :xml, :json
|
||||||
before_filter :member_only, :only => [:edit, :update, :upgrade]
|
before_filter :member_only, :only => [:edit, :update, :upgrade]
|
||||||
rescue_from User::PrivilegeError, :with => :access_denied
|
|
||||||
skip_before_filter :api_check
|
skip_before_filter :api_check
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ class WikiPagesController < ApplicationController
|
|||||||
before_filter :member_only, :except => [:index, :show, :show_or_new]
|
before_filter :member_only, :except => [:index, :show, :show_or_new]
|
||||||
before_filter :builder_only, :only => [:destroy]
|
before_filter :builder_only, :only => [:destroy]
|
||||||
before_filter :normalize_search_params, :only => [:index]
|
before_filter :normalize_search_params, :only => [:index]
|
||||||
rescue_from ActiveRecord::StatementInvalid, :with => :rescue_exception
|
|
||||||
rescue_from ActiveRecord::RecordNotFound, :with => :rescue_exception
|
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@wiki_page = WikiPage.new(params[:wiki_page])
|
@wiki_page = WikiPage.new(params[:wiki_page])
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class ApproverPruner
|
|||||||
Dmail.create_automated(
|
Dmail.create_automated(
|
||||||
:to_id => user.id,
|
:to_id => user.id,
|
||||||
:title => "Approver inactivity",
|
:title => "Approver inactivity",
|
||||||
:body => "You haven't approved a post in the past three months. In order to make sure the list of active approvers is up-to-date, you have lost your approver privileges. Please reply to this message if you want to be reinstated."
|
:body => "You haven't approved a post in the past three months. In order to make sure the list of active approvers is up-to-date, you have lost your approver privileges."
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class BulkRevert
|
|||||||
end
|
end
|
||||||
|
|
||||||
def find_post_versions
|
def find_post_versions
|
||||||
q = PostVersion.where("true")
|
q = PostArchive.where("true")
|
||||||
|
|
||||||
if constraints[:user_name]
|
if constraints[:user_name]
|
||||||
constraints[:user_id] = User.find_by_name(constraints[:user_name]).try(:id)
|
constraints[:user_id] = User.find_by_name(constraints[:user_name]).try(:id)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ module Moderator
|
|||||||
add_row(sums, Hash[User.where(last_ip_addr: ip_addrs).collect { |user| [user, 1] }])
|
add_row(sums, Hash[User.where(last_ip_addr: ip_addrs).collect { |user| [user, 1] }])
|
||||||
|
|
||||||
add_row_id(sums, PoolArchive.where(updater_ip_addr: ip_addrs).group(:updater_id).count) if PoolArchive.enabled?
|
add_row_id(sums, PoolArchive.where(updater_ip_addr: ip_addrs).group(:updater_id).count) if PoolArchive.enabled?
|
||||||
add_row_id(sums, PostVersion.where(updater_ip_addr: ip_addrs).group(:updater_id).count)
|
add_row_id(sums, PostArchive.where(updater_ip_addr: ip_addrs).group(:updater_id).count) if PostArchive.enabled?
|
||||||
|
|
||||||
sums
|
sums
|
||||||
end
|
end
|
||||||
@@ -52,7 +52,7 @@ module Moderator
|
|||||||
add_row(sums, ArtistVersion.where(updater: users).group(:updater_ip_addr).count)
|
add_row(sums, ArtistVersion.where(updater: users).group(:updater_ip_addr).count)
|
||||||
add_row(sums, NoteVersion.where(updater: users).group(:updater_ip_addr).count)
|
add_row(sums, NoteVersion.where(updater: users).group(:updater_ip_addr).count)
|
||||||
add_row(sums, PoolArchive.where(updater_id: users.map(&:id)).group(:updater_ip_addr).count) if PoolArchive.enabled?
|
add_row(sums, PoolArchive.where(updater_id: users.map(&:id)).group(:updater_ip_addr).count) if PoolArchive.enabled?
|
||||||
add_row(sums, PostVersion.where(updater_id: users.map(&:id)).group(:updater_ip_addr).count)
|
add_row(sums, PostArchive.where(updater_id: users.map(&:id)).group(:updater_ip_addr).count) if PostArchive.enabled?
|
||||||
add_row(sums, WikiPageVersion.where(updater: users).group(:updater_ip_addr).count)
|
add_row(sums, WikiPageVersion.where(updater: users).group(:updater_ip_addr).count)
|
||||||
add_row(sums, Comment.where(creator: users).group(:ip_addr).count)
|
add_row(sums, Comment.where(creator: users).group(:ip_addr).count)
|
||||||
add_row(sums, Dmail.where(from: users).group(:creator_ip_addr).count)
|
add_row(sums, Dmail.where(from: users).group(:creator_ip_addr).count)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ module Reports
|
|||||||
end
|
end
|
||||||
|
|
||||||
def mock_version(row)
|
def mock_version(row)
|
||||||
PostVersion.new.tap do |x|
|
PostArchive.new.tap do |x|
|
||||||
x.id = row["f"][0]["v"]
|
x.id = row["f"][0]["v"]
|
||||||
x.post_id = row["f"][1]["v"]
|
x.post_id = row["f"][1]["v"]
|
||||||
x.updated_at = Time.at(row["f"][2]["v"].to_f)
|
x.updated_at = Time.at(row["f"][2]["v"].to_f)
|
||||||
|
|||||||
10
app/logical/user_name_validator.rb
Normal file
10
app/logical/user_name_validator.rb
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
class UserNameValidator < ActiveModel::EachValidator
|
||||||
|
def validate_each(rec, attr, value)
|
||||||
|
name = User.normalize_name(value)
|
||||||
|
|
||||||
|
rec.errors[attr] << "already exists" if User.find_by_name(name).present?
|
||||||
|
rec.errors[attr] << "must be 2 to 100 characters long" if !name.length.between?(2, 100)
|
||||||
|
rec.errors[attr] << "cannot have whitespace or colons" if name =~ /[[:space:]]|:/
|
||||||
|
rec.errors[attr] << "cannot begin or end with an underscore" if name =~ /\A_|_\z/
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -15,13 +15,13 @@ class UserRevert
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate!
|
def validate!
|
||||||
if PostVersion.where(updater_id: user_id).count > THRESHOLD
|
if PostArchive.where(updater_id: user_id).count > THRESHOLD
|
||||||
raise TooManyChangesError.new("This user has too many changes to be reverted")
|
raise TooManyChangesError.new("This user has too many changes to be reverted")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def revert_post_changes
|
def revert_post_changes
|
||||||
PostVersion.where(updater_id: user_id).find_each do |x|
|
PostArchive.where(updater_id: user_id).find_each do |x|
|
||||||
x.undo!
|
x.undo!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -12,6 +12,112 @@ class AmazonBackup < ActiveRecord::Base
|
|||||||
first.update_column(:last_id, new_id)
|
first.update_column(:last_id, new_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.restore_from_glacier(min_id, max_id)
|
||||||
|
credentials = Aws::Credentials.new(Danbooru.config.aws_access_key_id, Danbooru.config.aws_secret_access_key)
|
||||||
|
Aws.config.update({
|
||||||
|
region: "us-east-1",
|
||||||
|
credentials: credentials
|
||||||
|
})
|
||||||
|
client = Aws::S3::Client.new
|
||||||
|
bucket = Danbooru.config.aws_s3_bucket_name
|
||||||
|
|
||||||
|
f = lambda do |key|
|
||||||
|
begin
|
||||||
|
client.restore_object(
|
||||||
|
bucket: bucket,
|
||||||
|
key: key,
|
||||||
|
restore_request: {
|
||||||
|
days: 7,
|
||||||
|
glacier_job_parameters: {
|
||||||
|
tier: "Bulk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
rescue Aws::S3::Errors::InternalError
|
||||||
|
puts " internal error...retrying"
|
||||||
|
sleep 30
|
||||||
|
retry
|
||||||
|
rescue Aws::S3::Errors::InvalidObjectState
|
||||||
|
puts " already restored #{key}"
|
||||||
|
rescue Aws::S3::Errors::NoSuchKey
|
||||||
|
puts " missing #{key}"
|
||||||
|
file_path = "/var/www/danbooru2/shared/data/#{key}"
|
||||||
|
|
||||||
|
if File.exists?(file_path)
|
||||||
|
base64_md5 = Digest::MD5.base64digest(File.read(file_path))
|
||||||
|
body = open(file_path, "rb")
|
||||||
|
client.put_object(bucket: bucket, key: key, body: body, content_md5: base64_md5, acl: "public-read")
|
||||||
|
puts " uploaded"
|
||||||
|
end
|
||||||
|
rescue Aws::S3::Errors::RestoreAlreadyInProgress
|
||||||
|
puts " already restoring #{key}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Post.where("id >= ? and id <= ?", min_id, max_id).find_each do |post|
|
||||||
|
if post.has_large?
|
||||||
|
puts "large:#{post.id}"
|
||||||
|
key = "sample/" + File.basename(post.large_file_path)
|
||||||
|
f.call(key)
|
||||||
|
end
|
||||||
|
|
||||||
|
if post.has_preview?
|
||||||
|
puts "preview:#{post.id}"
|
||||||
|
key = "preview/" + File.basename(post.preview_file_path)
|
||||||
|
f.call(key)
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "#{post.id}"
|
||||||
|
key = File.basename(post.file_path)
|
||||||
|
f.call(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.copy_to_standard(min_id, max_id)
|
||||||
|
credentials = Aws::Credentials.new(Danbooru.config.aws_access_key_id, Danbooru.config.aws_secret_access_key)
|
||||||
|
Aws.config.update({
|
||||||
|
region: "us-east-1",
|
||||||
|
credentials: credentials
|
||||||
|
})
|
||||||
|
client = Aws::S3::Client.new
|
||||||
|
bucket = Danbooru.config.aws_s3_bucket_name
|
||||||
|
|
||||||
|
f = lambda do |key|
|
||||||
|
begin
|
||||||
|
client.copy_object(bucket: bucket, key: key, acl: "public-read", storage_class: "STANDARD", copy_source: "/#{bucket}/#{key}", metadata_directive: "COPY")
|
||||||
|
puts " copied #{key}"
|
||||||
|
rescue Aws::S3::Errors::InternalError
|
||||||
|
puts " internal error...retrying"
|
||||||
|
sleep 30
|
||||||
|
retry
|
||||||
|
rescue Aws::S3::Errors::InvalidObjectState
|
||||||
|
puts " invalid state #{key}"
|
||||||
|
rescue Aws::S3::Errors::NoSuchKey
|
||||||
|
puts " missing #{key}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Post.where("id >= ? and id <= ?", min_id, max_id).find_each do |post|
|
||||||
|
next unless post.has_preview?
|
||||||
|
|
||||||
|
if post.has_preview?
|
||||||
|
puts "preview:#{post.id}"
|
||||||
|
key = "preview/" + File.basename(post.preview_file_path)
|
||||||
|
f.call(key)
|
||||||
|
end
|
||||||
|
|
||||||
|
if post.has_large?
|
||||||
|
puts "large:#{post.id}"
|
||||||
|
key = "sample/" + File.basename(post.large_file_path)
|
||||||
|
f.call(key)
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "#{post.id}"
|
||||||
|
key = File.basename(post.file_path)
|
||||||
|
f.call(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.execute
|
def self.execute
|
||||||
return false unless Danbooru.config.aws_s3_enabled?
|
return false unless Danbooru.config.aws_s3_enabled?
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ class Comment < ActiveRecord::Base
|
|||||||
after_update(:if => lambda {|rec| CurrentUser.id != rec.creator_id}) do |rec|
|
after_update(:if => lambda {|rec| CurrentUser.id != rec.creator_id}) do |rec|
|
||||||
ModAction.log("comment ##{rec.id} updated by #{CurrentUser.name}")
|
ModAction.log("comment ##{rec.id} updated by #{CurrentUser.name}")
|
||||||
end
|
end
|
||||||
after_destroy :update_last_commented_at_on_destroy
|
after_update :update_last_commented_at_on_destroy, :if => lambda {|rec| rec.is_deleted? && rec.is_deleted_changed?}
|
||||||
after_destroy(:if => lambda {|rec| CurrentUser.id != rec.creator_id}) do |rec|
|
after_update(:if => lambda {|rec| rec.is_deleted? && rec.is_deleted_changed? && CurrentUser.id != rec.creator_id}) do |rec|
|
||||||
ModAction.log("comment ##{rec.id} deleted by #{CurrentUser.name}")
|
ModAction.log("comment ##{rec.id} deleted by #{CurrentUser.name}")
|
||||||
end
|
end
|
||||||
attr_accessible :body, :post_id, :do_not_bump_post, :is_deleted, :as => [:member, :gold, :platinum, :builder, :janitor, :moderator, :admin]
|
attr_accessible :body, :post_id, :do_not_bump_post, :is_deleted, :as => [:member, :gold, :platinum, :builder, :janitor, :moderator, :admin]
|
||||||
|
|||||||
@@ -154,6 +154,10 @@ class ForumTopic < ActiveRecord::Base
|
|||||||
self.updater_id = CurrentUser.id
|
self.updater_id = CurrentUser.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def page_for(post_id)
|
||||||
|
(posts.where("id < ?", post_id).count / Danbooru.config.posts_per_page.to_f).ceil
|
||||||
|
end
|
||||||
|
|
||||||
def last_page
|
def last_page
|
||||||
(response_count / Danbooru.config.posts_per_page.to_f).ceil
|
(response_count / Danbooru.config.posts_per_page.to_f).ceil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class JanitorTrial < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def send_dmail
|
def send_dmail
|
||||||
body = "You have been selected as a test janitor. You can now approve pending posts and have access to the moderation interface. You should reacquaint yourself with the [[howto:upload]] guide to make sure you understand the site rules.\n\nOver the next several weeks your approvals will be monitored. If the majority of them are not quality uploads you will fail the trial period and lose your approval privileges. You will also receive a negative user record indicating you previously attempted and failed a test janitor trial.\n\nThere is a minimum quota of 1 approval a month to indicate that you are being active. Remember, the goal isn't to approve as much as possible. It's to filter out borderline-quality art.\n\nIf you have any questions please respond to this message."
|
body = "You have been selected as a test janitor. You can now approve pending posts and have access to the moderation interface. You should reacquaint yourself with the [[howto:upload]] guide to make sure you understand the site rules.\n\nOver the next several weeks your approvals will be monitored. If the majority of them are not quality uploads you will fail the trial period and lose your approval privileges. You will also receive a negative user record indicating you previously attempted and failed a test janitor trial.\n\nThere is a minimum quota of 1 approval a month to indicate that you are being active. Remember, the goal isn't to approve as much as possible. It's to filter out borderline-quality art."
|
||||||
|
|
||||||
Dmail.create_automated(:title => "Test Janitor Trial Period", :body => body, :to_id => user_id)
|
Dmail.create_automated(:title => "Test Janitor Trial Period", :body => body, :to_id => user_id)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ class Post < ActiveRecord::Base
|
|||||||
has_one :pixiv_ugoira_frame_data, :class_name => "PixivUgoiraFrameData", :dependent => :destroy
|
has_one :pixiv_ugoira_frame_data, :class_name => "PixivUgoiraFrameData", :dependent => :destroy
|
||||||
has_many :flags, :class_name => "PostFlag", :dependent => :destroy
|
has_many :flags, :class_name => "PostFlag", :dependent => :destroy
|
||||||
has_many :appeals, :class_name => "PostAppeal", :dependent => :destroy
|
has_many :appeals, :class_name => "PostAppeal", :dependent => :destroy
|
||||||
has_many :versions, lambda {order("post_versions.updated_at ASC, post_versions.id ASC")}, :class_name => "PostVersion", :dependent => :destroy
|
|
||||||
has_many :votes, :class_name => "PostVote", :dependent => :destroy
|
has_many :votes, :class_name => "PostVote", :dependent => :destroy
|
||||||
has_many :notes, :dependent => :destroy
|
has_many :notes, :dependent => :destroy
|
||||||
has_many :comments, lambda {includes(:creator, :updater).order("comments.id")}, :dependent => :destroy
|
has_many :comments, lambda {includes(:creator, :updater).order("comments.id")}, :dependent => :destroy
|
||||||
@@ -1414,12 +1413,16 @@ class Post < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
module VersionMethods
|
module VersionMethods
|
||||||
def create_version(force = false)
|
def versions
|
||||||
if new_record? || rating_changed? || source_changed? || parent_id_changed? || tag_string_changed? || force
|
if PostArchive.enabled?
|
||||||
if merge_version?
|
PostArchive.where(post_id: id).order("updated_at ASC, id asc")
|
||||||
delete_previous_version
|
else
|
||||||
|
raise "Archive service not configured"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_version(force = false)
|
||||||
|
if new_record? || rating_changed? || source_changed? || parent_id_changed? || tag_string_changed? || force
|
||||||
create_new_version
|
create_new_version
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1431,19 +1434,7 @@ class Post < ActiveRecord::Base
|
|||||||
|
|
||||||
def create_new_version
|
def create_new_version
|
||||||
User.where(id: CurrentUser.id).update_all("post_update_count = post_update_count + 1")
|
User.where(id: CurrentUser.id).update_all("post_update_count = post_update_count + 1")
|
||||||
CurrentUser.reload
|
PostArchive.queue(self) if PostArchive.enabled?
|
||||||
|
|
||||||
versions.create(
|
|
||||||
:rating => rating,
|
|
||||||
:source => source,
|
|
||||||
:tags => tag_string,
|
|
||||||
:parent_id => parent_id
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete_previous_version
|
|
||||||
prev = versions.last
|
|
||||||
prev.destroy
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def revert_to(target)
|
def revert_to(target)
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
class PostArchive < ActiveRecord::Base
|
class PostArchive < ActiveRecord::Base
|
||||||
|
extend Memoist
|
||||||
|
|
||||||
def self.enabled?
|
def self.enabled?
|
||||||
Danbooru.config.aws_sqs_archives_url.present?
|
Danbooru.config.aws_sqs_archives_url.present?
|
||||||
end
|
end
|
||||||
@@ -6,32 +8,95 @@ class PostArchive < ActiveRecord::Base
|
|||||||
establish_connection (ENV["ARCHIVE_DATABASE_URL"] || "archive_#{Rails.env}".to_sym) if enabled?
|
establish_connection (ENV["ARCHIVE_DATABASE_URL"] || "archive_#{Rails.env}".to_sym) if enabled?
|
||||||
self.table_name = "post_versions"
|
self.table_name = "post_versions"
|
||||||
|
|
||||||
def self.calculate_version(post_id, updated_at, version_id)
|
module SearchMethods
|
||||||
if updated_at.to_i == Time.zone.parse("2007-03-14T19:38:12Z").to_i
|
def for_user(user_id)
|
||||||
# Old post versions which didn't have updated_at set correctly
|
if user_id
|
||||||
1 + PostVersion.where("post_id = ? and updated_at = ? and id < ?", post_id, updated_at, version_id).count
|
where("updater_id = ?", user_id)
|
||||||
else
|
else
|
||||||
1 + PostVersion.where("post_id = ? and updated_at < ?", post_id, updated_at).count
|
where("false")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.export(version_id = 9096768)
|
def for_user_name(name)
|
||||||
|
user_id = User.name_to_id(name)
|
||||||
|
for_user(user_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def search(params)
|
||||||
|
q = where("true")
|
||||||
|
params = {} if params.blank?
|
||||||
|
|
||||||
|
if params[:updater_name].present?
|
||||||
|
q = q.for_user_name(params[:updater_name])
|
||||||
|
end
|
||||||
|
|
||||||
|
if params[:updater_id].present?
|
||||||
|
q = q.where("updater_id = ?", params[:updater_id].to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
if params[:post_id].present?
|
||||||
|
q = q.where("post_id = ?", params[:post_id].to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
if params[:start_id].present?
|
||||||
|
q = q.where("id <= ?", params[:start_id].to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
q
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module ArchiveServiceMethods
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
class_methods do
|
||||||
|
def sqs_service
|
||||||
|
SqsService.new(Danbooru.config.aws_sqs_archives_url)
|
||||||
|
end
|
||||||
|
|
||||||
|
def queue(post)
|
||||||
|
# queue updates to sqs so that if archives goes down for whatever reason it won't
|
||||||
|
# block post updates
|
||||||
|
raise "Archive service is not configured" if !enabled?
|
||||||
|
|
||||||
|
json = {
|
||||||
|
"post_id" => post.id,
|
||||||
|
"rating" => post.rating,
|
||||||
|
"parent_id" => post.parent_id,
|
||||||
|
"source" => post.source,
|
||||||
|
"updater_id" => CurrentUser.id,
|
||||||
|
"updater_ip_addr" => CurrentUser.ip_addr.to_s,
|
||||||
|
"updated_at" => post.updated_at.try(:iso8601),
|
||||||
|
"created_at" => post.created_at.try(:iso8601),
|
||||||
|
"tags" => post.tag_string
|
||||||
|
}
|
||||||
|
msg = "add post version\n#{json.to_json}"
|
||||||
|
sqs_service.send_message(msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
def export_to_archives(version_id = 4394763)
|
||||||
PostVersion.where("id > ?", version_id).find_each do |version|
|
PostVersion.where("id > ?", version_id).find_each do |version|
|
||||||
previous = version.previous
|
previous = version.previous
|
||||||
tags = version.tags.scan(/\S+/)
|
tags = version.tags.scan(/\S+/)
|
||||||
|
version_number = if version.updated_at.to_i == Time.zone.parse("2007-03-14T19:38:12Z").to_i
|
||||||
|
# Old post versions which didn't have updated_at set correctly
|
||||||
|
1 + PostVersion.where("post_id = ? and updated_at = ? and id < ?", version.post_id, version.updated_at, version.id).count
|
||||||
|
else
|
||||||
|
1 + PostVersion.where("post_id = ? and updated_at < ?", version.post_id, version.updated_at).count
|
||||||
|
end
|
||||||
|
|
||||||
if previous
|
if previous
|
||||||
prev_tags = previous.tags.scan(/\S+/)
|
prev_tags = previous.tags.scan(/\S+/)
|
||||||
added_tags = tags - previous.tags.scan(/\S+/)
|
added_tags = tags - prev_tags
|
||||||
removed_tags = previous.tags.scan(/\S+/) - tags
|
removed_tags = prev_tags - tags
|
||||||
else
|
else
|
||||||
added_tags = tags
|
added_tags = tags
|
||||||
removed_tags = []
|
removed_tags = []
|
||||||
end
|
end
|
||||||
|
|
||||||
rating_changed = previous.nil? || version.rating != previous.try(:rating)
|
rating_changed = previous.nil? || version.rating != previous.rating
|
||||||
parent_changed = previous.nil? || version.parent_id != previous.try(:parent_id)
|
parent_changed = previous.nil? || version.parent_id != previous.parent_id
|
||||||
source_changed = previous.nil? || version.source != previous.try(:source)
|
source_changed = previous.nil? || version.source != previous.source
|
||||||
create(
|
create(
|
||||||
post_id: version.post_id,
|
post_id: version.post_id,
|
||||||
tags: version.tags,
|
tags: version.tags,
|
||||||
@@ -40,7 +105,7 @@ class PostArchive < ActiveRecord::Base
|
|||||||
updater_id: version.updater_id,
|
updater_id: version.updater_id,
|
||||||
updater_ip_addr: version.updater_ip_addr.to_s,
|
updater_ip_addr: version.updater_ip_addr.to_s,
|
||||||
updated_at: version.updated_at,
|
updated_at: version.updated_at,
|
||||||
version: calculate_version(version.post_id, version.updated_at, version.id),
|
version: version_number,
|
||||||
rating: version.rating,
|
rating: version.rating,
|
||||||
rating_changed: rating_changed,
|
rating_changed: rating_changed,
|
||||||
parent_id: version.parent_id,
|
parent_id: version.parent_id,
|
||||||
@@ -52,3 +117,176 @@ class PostArchive < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
extend SearchMethods
|
||||||
|
include ArchiveServiceMethods
|
||||||
|
|
||||||
|
def tag_array
|
||||||
|
tags.scan(/\S+/)
|
||||||
|
end
|
||||||
|
|
||||||
|
def presenter
|
||||||
|
PostVersionPresenter.new(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reload
|
||||||
|
flush_cache
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def post
|
||||||
|
Post.where(id: post_id).first
|
||||||
|
end
|
||||||
|
|
||||||
|
def previous
|
||||||
|
PostArchive.where("post_id = ? and version < ?", post_id, version).order("version desc").first
|
||||||
|
end
|
||||||
|
|
||||||
|
def updater
|
||||||
|
User.find(updater_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def diff(version = nil)
|
||||||
|
if post.nil?
|
||||||
|
latest_tags = tag_array
|
||||||
|
else
|
||||||
|
latest_tags = post.tag_array
|
||||||
|
latest_tags << "rating:#{post.rating}" if post.rating.present?
|
||||||
|
latest_tags << "parent:#{post.parent_id}" if post.parent_id.present?
|
||||||
|
latest_tags << "source:#{post.source}" if post.source.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
new_tags = tag_array
|
||||||
|
new_tags << "rating:#{rating}" if rating.present?
|
||||||
|
new_tags << "parent:#{parent_id}" if parent_id.present?
|
||||||
|
new_tags << "source:#{source}" if source.present?
|
||||||
|
|
||||||
|
old_tags = version.present? ? version.tag_array : []
|
||||||
|
if version.present?
|
||||||
|
old_tags << "rating:#{version.rating}" if version.rating.present?
|
||||||
|
old_tags << "parent:#{version.parent_id}" if version.parent_id.present?
|
||||||
|
old_tags << "source:#{version.source}" if version.source.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
added_tags = new_tags - old_tags
|
||||||
|
removed_tags = old_tags - new_tags
|
||||||
|
|
||||||
|
return {
|
||||||
|
:added_tags => added_tags,
|
||||||
|
:removed_tags => removed_tags,
|
||||||
|
:obsolete_added_tags => added_tags - latest_tags,
|
||||||
|
:obsolete_removed_tags => removed_tags & latest_tags,
|
||||||
|
:unchanged_tags => new_tags & old_tags,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def changes
|
||||||
|
delta = {
|
||||||
|
:added_tags => added_tags,
|
||||||
|
:removed_tags => removed_tags
|
||||||
|
}
|
||||||
|
|
||||||
|
latest_tags = post.tag_array
|
||||||
|
latest_tags << "rating:#{post.rating}" if post.rating.present?
|
||||||
|
latest_tags << "parent:#{post.parent_id}" if post.parent_id.present?
|
||||||
|
latest_tags << "source:#{post.source}" if post.source.present?
|
||||||
|
|
||||||
|
if parent_changed
|
||||||
|
delta[:added_tags] << "parent:#{parent_id}"
|
||||||
|
|
||||||
|
if previous
|
||||||
|
delta[:removed_tags] << "parent:#{previous.parent_id}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if rating_changed
|
||||||
|
delta[:added_tags] << "rating:#{rating}"
|
||||||
|
|
||||||
|
if previous
|
||||||
|
delta[:removed_tags] << "rating:#{previous.rating}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if source_changed
|
||||||
|
delta[:added_tags] << "source:#{source}"
|
||||||
|
|
||||||
|
if previous
|
||||||
|
delta[:removed_tags] << "source:#{previous.source}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
delta[:obsolete_added_tags] = delta[:added_tags] - latest_tags
|
||||||
|
delta[:obsolete_removed_tags] = delta[:removed_tags] & latest_tags
|
||||||
|
|
||||||
|
if previous
|
||||||
|
delta[:unchanged_tags] = tag_array & previous.tag_array
|
||||||
|
else
|
||||||
|
delta[:unchanged_tags] = []
|
||||||
|
end
|
||||||
|
|
||||||
|
delta
|
||||||
|
end
|
||||||
|
|
||||||
|
def added_tags_with_fields
|
||||||
|
changes[:added_tags].join(" ")
|
||||||
|
end
|
||||||
|
|
||||||
|
def removed_tags_with_fields
|
||||||
|
changes[:removed_tags].join(" ")
|
||||||
|
end
|
||||||
|
|
||||||
|
def obsolete_added_tags
|
||||||
|
changes[:obsolete_added_tags].join(" ")
|
||||||
|
end
|
||||||
|
|
||||||
|
def obsolete_removed_tags
|
||||||
|
changes[:obsolete_removed_tags].join(" ")
|
||||||
|
end
|
||||||
|
|
||||||
|
def unchanged_tags
|
||||||
|
changes[:unchanged_tags].join(" ")
|
||||||
|
end
|
||||||
|
|
||||||
|
def truncated_source
|
||||||
|
source.gsub(/^http:\/\//, "").sub(/\/.+/, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
def undo
|
||||||
|
added = changes[:added_tags_with_fields] - changes[:obsolete_added_tags]
|
||||||
|
removed = changes[:removed_tags_with_fields] - changes[:obsolete_removed_tags]
|
||||||
|
|
||||||
|
added.each do |tag|
|
||||||
|
if tag =~ /^source:/
|
||||||
|
post.source = ""
|
||||||
|
elsif tag =~ /^parent:/
|
||||||
|
post.parent_id = nil
|
||||||
|
else
|
||||||
|
escaped_tag = Regexp.escape(tag)
|
||||||
|
post.tag_string = post.tag_string.sub(/(?:\A| )#{escaped_tag}(?:\Z| )/, " ").strip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
removed.each do |tag|
|
||||||
|
if tag =~ /^source:(.+)$/
|
||||||
|
post.source = $1
|
||||||
|
else
|
||||||
|
post.tag_string = "#{post.tag_string} #{tag}".strip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def undo!
|
||||||
|
undo
|
||||||
|
post.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
def updater
|
||||||
|
User.find_by_id(updater_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def method_attributes
|
||||||
|
super + [:obsolete_added_tags, :obsolete_removed_tags, :unchanged_tags, :updater_name]
|
||||||
|
end
|
||||||
|
|
||||||
|
memoize :previous, :post, :tag_array, :changes, :added_tags_with_fields, :removed_tags_with_fields, :obsolete_removed_tags, :obsolete_added_tags, :unchanged_tags
|
||||||
|
end
|
||||||
|
|||||||
@@ -61,17 +61,6 @@ class PostVersion < ActiveRecord::Base
|
|||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def sequence_for_post
|
|
||||||
versions = PostVersion.where(:post_id => post_id).order("updated_at desc, id desc")
|
|
||||||
diffs = []
|
|
||||||
versions.each_index do |i|
|
|
||||||
if i < versions.size - 1
|
|
||||||
diffs << versions[i].diff(versions[i + 1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return diffs
|
|
||||||
end
|
|
||||||
|
|
||||||
def diff(version)
|
def diff(version)
|
||||||
latest_tags = post.tag_array
|
latest_tags = post.tag_array
|
||||||
latest_tags << "rating:#{post.rating}" if post.rating.present?
|
latest_tags << "rating:#{post.rating}" if post.rating.present?
|
||||||
|
|||||||
@@ -54,10 +54,8 @@ class User < ActiveRecord::Base
|
|||||||
attr_accessor :password, :old_password
|
attr_accessor :password, :old_password
|
||||||
attr_accessible :dmail_filter_attributes, :enable_privacy_mode, :enable_post_navigation, :new_post_navigation_layout, :password, :old_password, :password_confirmation, :password_hash, :email, :last_logged_in_at, :last_forum_read_at, :has_mail, :receive_email_notifications, :comment_threshold, :always_resize_images, :favorite_tags, :blacklisted_tags, :name, :ip_addr, :time_zone, :default_image_size, :enable_sequential_post_navigation, :per_page, :hide_deleted_posts, :style_usernames, :enable_auto_complete, :custom_style, :show_deleted_children, :disable_categorized_saved_searches, :disable_tagged_filenames, :enable_recent_searches, :as => [:moderator, :janitor, :gold, :platinum, :member, :anonymous, :default, :builder, :admin]
|
attr_accessible :dmail_filter_attributes, :enable_privacy_mode, :enable_post_navigation, :new_post_navigation_layout, :password, :old_password, :password_confirmation, :password_hash, :email, :last_logged_in_at, :last_forum_read_at, :has_mail, :receive_email_notifications, :comment_threshold, :always_resize_images, :favorite_tags, :blacklisted_tags, :name, :ip_addr, :time_zone, :default_image_size, :enable_sequential_post_navigation, :per_page, :hide_deleted_posts, :style_usernames, :enable_auto_complete, :custom_style, :show_deleted_children, :disable_categorized_saved_searches, :disable_tagged_filenames, :enable_recent_searches, :as => [:moderator, :janitor, :gold, :platinum, :member, :anonymous, :default, :builder, :admin]
|
||||||
attr_accessible :level, :as => :admin
|
attr_accessible :level, :as => :admin
|
||||||
validates_length_of :name, :within => 2..100, :on => :create
|
|
||||||
validates_format_of :name, :with => /\A[^\s:]+\Z/, :on => :create, :message => "cannot have whitespace or colons"
|
validates :name, user_name: true, on: :create
|
||||||
validates_format_of :name, :with => /\A[^_].*[^_]\Z/, :on => :create, :message => "cannot begin or end with an underscore"
|
|
||||||
validates_uniqueness_of :name, :case_sensitive => false
|
|
||||||
validates_uniqueness_of :email, :case_sensitive => false, :if => lambda {|rec| rec.email.present? && rec.email_changed? }
|
validates_uniqueness_of :email, :case_sensitive => false, :if => lambda {|rec| rec.email.present? && rec.email_changed? }
|
||||||
validates_length_of :password, :minimum => 5, :if => lambda {|rec| rec.new_record? || rec.password.present?}
|
validates_length_of :password, :minimum => 5, :if => lambda {|rec| rec.new_record? || rec.password.present?}
|
||||||
validates_inclusion_of :default_image_size, :in => %w(large original)
|
validates_inclusion_of :default_image_size, :in => %w(large original)
|
||||||
@@ -153,6 +151,10 @@ class User < ActiveRecord::Base
|
|||||||
def id_to_pretty_name(user_id)
|
def id_to_pretty_name(user_id)
|
||||||
id_to_name(user_id).gsub(/([^_])_+(?=[^_])/, "\\1 \\2")
|
id_to_name(user_id).gsub(/([^_])_+(?=[^_])/, "\\1 \\2")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def normalize_name(name)
|
||||||
|
name.to_s.mb_chars.downcase.strip.tr(" ", "_").to_s
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def pretty_name
|
def pretty_name
|
||||||
|
|||||||
@@ -3,11 +3,8 @@ class UserNameChangeRequest < ActiveRecord::Base
|
|||||||
validates_inclusion_of :status, :in => %w(pending approved rejected)
|
validates_inclusion_of :status, :in => %w(pending approved rejected)
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :approver, :class_name => "User"
|
belongs_to :approver, :class_name => "User"
|
||||||
validate :uniqueness_of_desired_name
|
|
||||||
validate :not_limited, :on => :create
|
validate :not_limited, :on => :create
|
||||||
validates_length_of :desired_name, :within => 2..100, :on => :create
|
validates :desired_name, user_name: true
|
||||||
validates_format_of :desired_name, :with => /\A[^\s:]+\Z/, :on => :create, :message => "cannot have whitespace or colons"
|
|
||||||
before_validation :normalize_name
|
|
||||||
attr_accessible :status, :user_id, :original_name, :desired_name, :change_reason, :rejection_reason, :approver_id
|
attr_accessible :status, :user_id, :original_name, :desired_name, :change_reason, :rejection_reason, :approver_id
|
||||||
|
|
||||||
def self.pending
|
def self.pending
|
||||||
@@ -40,8 +37,8 @@ class UserNameChangeRequest < ActiveRecord::Base
|
|||||||
status == "pending"
|
status == "pending"
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalize_name
|
def desired_name=(name)
|
||||||
self.desired_name = desired_name.strip.gsub(/ /, "_")
|
super(User.normalize_name(name))
|
||||||
end
|
end
|
||||||
|
|
||||||
def feedback
|
def feedback
|
||||||
@@ -72,15 +69,6 @@ class UserNameChangeRequest < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def uniqueness_of_desired_name
|
|
||||||
if User.find_by_name(desired_name)
|
|
||||||
errors.add(:desired_name, "already exists")
|
|
||||||
return false
|
|
||||||
else
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def hidden_attributes
|
def hidden_attributes
|
||||||
if CurrentUser.is_admin? || user == CurrentUser.user
|
if CurrentUser.is_admin? || user == CurrentUser.user
|
||||||
[]
|
[]
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ class WikiPage < ActiveRecord::Base
|
|||||||
:title => title,
|
:title => title,
|
||||||
:body => body,
|
:body => body,
|
||||||
:is_locked => is_locked,
|
:is_locked => is_locked,
|
||||||
|
:is_deleted => is_deleted,
|
||||||
:other_names => other_names
|
:other_names => other_names
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ class WikiPageVersion < ActiveRecord::Base
|
|||||||
belongs_to :wiki_page
|
belongs_to :wiki_page
|
||||||
belongs_to :updater, :class_name => "User"
|
belongs_to :updater, :class_name => "User"
|
||||||
belongs_to :artist
|
belongs_to :artist
|
||||||
attr_accessible :wiki_page_id, :title, :body, :is_locked, :updater_id, :updater_ip_addr, :version, :other_names
|
attr_accessible :wiki_page_id, :title, :body, :is_locked, :is_deleted, :updater_id, :updater_ip_addr, :version, :other_names
|
||||||
delegate :visible?, :to => :wiki_page
|
delegate :visible?, :to => :wiki_page
|
||||||
|
|
||||||
module SearchMethods
|
module SearchMethods
|
||||||
|
|||||||
@@ -95,6 +95,10 @@ class PostPresenter < Presenter
|
|||||||
@post = post
|
@post = post
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def tag_set_presenter
|
||||||
|
@tag_set_presenter ||= TagSetPresenter.new(@post.tag_array)
|
||||||
|
end
|
||||||
|
|
||||||
def preview_html
|
def preview_html
|
||||||
PostPresenter.preview(@post)
|
PostPresenter.preview(@post)
|
||||||
end
|
end
|
||||||
@@ -170,13 +174,15 @@ class PostPresenter < Presenter
|
|||||||
end
|
end
|
||||||
|
|
||||||
def tag_list_html(template, options = {})
|
def tag_list_html(template, options = {})
|
||||||
@tag_set_presenter ||= TagSetPresenter.new(@post.tag_array)
|
tag_set_presenter.tag_list_html(template, options.merge(:show_extra_links => CurrentUser.user.is_gold?))
|
||||||
@tag_set_presenter.tag_list_html(template, options.merge(:show_extra_links => CurrentUser.user.is_gold?))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def split_tag_list_html(template, options = {})
|
def split_tag_list_html(template, options = {})
|
||||||
@tag_set_presenter ||= TagSetPresenter.new(@post.tag_array)
|
tag_set_presenter.split_tag_list_html(template, options.merge(:show_extra_links => CurrentUser.user.is_gold?))
|
||||||
@tag_set_presenter.split_tag_list_html(template, options.merge(:show_extra_links => CurrentUser.user.is_gold?))
|
end
|
||||||
|
|
||||||
|
def inline_tag_list_html(template)
|
||||||
|
tag_set_presenter.inline_tag_list(template)
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_nav_links?(template)
|
def has_nav_links?(template)
|
||||||
|
|||||||
@@ -64,6 +64,17 @@ class TagSetPresenter < Presenter
|
|||||||
html.html_safe
|
html.html_safe
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# compact (horizontal) list, as seen in the /comments index.
|
||||||
|
def inline_tag_list(template)
|
||||||
|
@tags.map do |tag_name|
|
||||||
|
<<-EOS
|
||||||
|
<span class="category-#{Tag.category_for(tag_name)}">
|
||||||
|
#{template.link_to(tag_name.tr("_", " "), template.posts_path(tags: tag_name))}
|
||||||
|
</span>
|
||||||
|
EOS
|
||||||
|
end.join.html_safe
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def general_tags
|
def general_tags
|
||||||
@general_tags ||= categories.select {|k, v| v == Tag.categories.general}
|
@general_tags ||= categories.select {|k, v| v == Tag.categories.general}
|
||||||
|
|||||||
@@ -24,11 +24,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row list-of-tags">
|
<div class="row list-of-tags">
|
||||||
<strong>Tags</strong>
|
<strong>Tags</strong>
|
||||||
<% post.tag_array.each do |tag_name| %>
|
<%= post.presenter.inline_tag_list_html(self) %>
|
||||||
<span class="category-<%= Tag.category_for(tag_name) %>">
|
|
||||||
<%= link_to(tag_name.tr("_", " "), posts_path(:tags => tag_name)) %>
|
|
||||||
</span>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
<% if @dmail.is_automated? %>
|
<% if @dmail.is_automated? %>
|
||||||
<p class="tn">
|
<p class="tn">
|
||||||
This is an automated message. Post in the forums if you have any questions.
|
This is an automated message. Responses will not be seen. If you have any questions either message a moderator or ask in the forum.
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
<strong>Hidden</strong>: <%= render "post_disapprovals/compact_counts", :disapprovals => post.disapprovals, :post => post %>
|
<strong>Hidden</strong>: <%= render "post_disapprovals/compact_counts", :disapprovals => post.disapprovals, :post => post %>
|
||||||
</li>
|
</li>
|
||||||
<li><strong>Source</strong>: <%= post.source %></li>
|
<li><strong>Source</strong>: <%= post.source %></li>
|
||||||
<li><strong>Tags</strong>: <%= post.tag_string %></li>
|
<li><strong>Tags</strong>: <%= post.presenter.inline_tag_list_html(self) %></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<% if disapprovals.count > 0 && (CurrentUser.can_approve_posts? || post.created_at < 3.days.ago) %>
|
<% if CurrentUser.can_approve_posts? || post.created_at < 3.days.ago %>
|
||||||
<% if disapprovals.breaks_rules.count > 0 %>
|
<% if disapprovals.map(&:reason).grep("breaks_rules").count > 0 %>
|
||||||
(breaks rules: <%= disapprovals.breaks_rules.count %>)
|
(breaks rules: <%= disapprovals.map(&:reason).grep("breaks_rules").count %>)
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if disapprovals.poor_quality.count > 0 %>
|
<% if disapprovals.map(&:reason).grep("poor_quality").count > 0 %>
|
||||||
(poor quality: <%= disapprovals.poor_quality.count %>)
|
(poor quality: <%= disapprovals.map(&:reason).grep("poor_quality").count %>)
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if disapprovals.disinterest.count > 0 %>
|
<% if disapprovals.map(&:reason).grep(/disinterest|legacy/).count > 0 %>
|
||||||
(no interest: <%= disapprovals.disinterest.count %>)
|
(no interest: <%= disapprovals.map(&:reason).grep(/disinterest|legacy/).count %>)
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if disapprovals.with_message.any? %>
|
<% if disapprovals.map(&:message).any?(&:present?) %>
|
||||||
(messages: <%= disapprovals.disinterest.with_message.map(&:message).to_sentence %>)
|
(messages: <%= disapprovals.map(&:message).select(&:present?).map { |msg| format_text(msg, ragel: true, inline: true) }.to_sentence.html_safe %>)
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
<% if disapprovals.count > 0 && (CurrentUser.can_approve_posts? || post.created_at < 3.days.ago) %>
|
<% if CurrentUser.can_approve_posts? || post.created_at < 3.days.ago %>
|
||||||
<p>
|
<p>
|
||||||
It has been reviewed by <%= pluralize disapprovals.count, "moderator" %>.
|
It has been reviewed by <%= pluralize disapprovals.length, "moderator" %>.
|
||||||
|
|
||||||
<% if disapprovals.breaks_rules.count > 0 %>
|
<% if disapprovals.map(&:reason).grep("breaks_rules").count > 0 %>
|
||||||
<%= disapprovals.breaks_rules.count %> believe it breaks the rules.
|
<%= disapprovals.map(&:reason).grep("breaks_rules").count %> believe it breaks the rules.
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if disapprovals.poor_quality.count > 0 %>
|
<% if disapprovals.map(&:reason).grep("poor_quality").count > 0 %>
|
||||||
<%= disapprovals.poor_quality.count %> believe it has poor quality.
|
<%= disapprovals.map(&:reason).grep("poor_quality").count %> believe it has poor quality.
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if disapprovals.disinterest.count > 0 %>
|
<% if disapprovals.map(&:reason).grep(/disinterest|legacy/).count > 0 %>
|
||||||
<%= disapprovals.disinterest.count %> did not like the post enough to approve it.
|
<%= disapprovals.map(&:reason).grep(/disinterest|legacy/).count %> did not like the post enough to approve it.
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if disapprovals.with_message.any? %>
|
<% if disapprovals.map(&:message).any?(&:present?) %>
|
||||||
Messages: <%= disapprovals.with_message.map(&:message).to_sentence %>
|
Messages: <%= disapprovals.map(&:message).select(&:present?).map { |msg| format_text(msg, ragel: true, inline: true) }.to_sentence.html_safe %>.
|
||||||
<% end %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -53,7 +53,7 @@ module Moderator
|
|||||||
end
|
end
|
||||||
|
|
||||||
should "render" do
|
should "render" do
|
||||||
assert_equal(1, PostVersion.count)
|
assert_equal(1, PostArchive.count)
|
||||||
get :show, {}, {:user_id => @admin.id}
|
get :show, {}, {:user_id => @admin.id}
|
||||||
assert_response :success
|
assert_response :success
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -144,12 +144,12 @@ class PostsControllerTest < ActionController::TestCase
|
|||||||
|
|
||||||
context "revert action" do
|
context "revert action" do
|
||||||
setup do
|
setup do
|
||||||
@post.stubs(:merge_version?).returns(false)
|
PostArchive.sqs_service.stubs(:merge?).returns(false)
|
||||||
@post.update_attributes(:tag_string => "zzz")
|
@post.update_attributes(:tag_string => "zzz")
|
||||||
end
|
end
|
||||||
|
|
||||||
should "work" do
|
should "work" do
|
||||||
@version = @post.versions(true).first
|
@version = @post.versions.first
|
||||||
assert_equal("aaaa", @version.tags)
|
assert_equal("aaaa", @version.tags)
|
||||||
post :revert, {:id => @post.id, :version_id => @version.id}, {:user_id => @user.id}
|
post :revert, {:id => @post.id, :version_id => @version.id}, {:user_id => @user.id}
|
||||||
assert_redirected_to post_path(@post)
|
assert_redirected_to post_path(@post)
|
||||||
|
|||||||
45
test/helpers/post_archive_test_helper.rb
Normal file
45
test/helpers/post_archive_test_helper.rb
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
module PostArchiveTestHelper
|
||||||
|
def setup
|
||||||
|
super
|
||||||
|
|
||||||
|
mock_post_archive_service!
|
||||||
|
start_post_archive_transaction
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
super
|
||||||
|
|
||||||
|
rollback_post_archive_transaction
|
||||||
|
end
|
||||||
|
|
||||||
|
def mock_post_archive_service!
|
||||||
|
mock_sqs_service = Class.new do
|
||||||
|
def send_message(msg)
|
||||||
|
_, json = msg.split(/\n/)
|
||||||
|
json = JSON.parse(json)
|
||||||
|
json.delete("created_at")
|
||||||
|
json["version"] = 1 + PostArchive.where(post_id: json["post_id"]).count
|
||||||
|
prev = PostArchive.where(post_id: json["post_id"]).order("id desc").first
|
||||||
|
if merge?(prev, json)
|
||||||
|
prev.update_columns(json)
|
||||||
|
else
|
||||||
|
PostArchive.create(json)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge?(prev, json)
|
||||||
|
prev && (prev.updater_id == json["updater_id"]) && (prev.updated_at >= 1.hour.ago)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
PostArchive.stubs(:sqs_service).returns(mock_sqs_service.new)
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_post_archive_transaction
|
||||||
|
PostArchive.connection.begin_transaction joinable: false
|
||||||
|
end
|
||||||
|
|
||||||
|
def rollback_post_archive_transaction
|
||||||
|
PostArchive.connection.rollback_transaction
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -11,6 +11,7 @@ end
|
|||||||
require File.expand_path('../../config/environment', __FILE__)
|
require File.expand_path('../../config/environment', __FILE__)
|
||||||
require 'rails/test_help'
|
require 'rails/test_help'
|
||||||
require 'cache'
|
require 'cache'
|
||||||
|
require 'helpers/post_archive_test_helper'
|
||||||
|
|
||||||
Dir[File.expand_path(File.dirname(__FILE__) + "/factories/*.rb")].each {|file| require file}
|
Dir[File.expand_path(File.dirname(__FILE__) + "/factories/*.rb")].each {|file| require file}
|
||||||
|
|
||||||
@@ -24,6 +25,24 @@ if defined?(MEMCACHE)
|
|||||||
Object.send(:remove_const, :MEMCACHE)
|
Object.send(:remove_const, :MEMCACHE)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class ActiveSupport::TestCase
|
||||||
|
include PostArchiveTestHelper
|
||||||
|
end
|
||||||
|
|
||||||
|
class ActionController::TestCase
|
||||||
|
include PostArchiveTestHelper
|
||||||
|
|
||||||
|
def assert_authentication_passes(action, http_method, role, params, session)
|
||||||
|
__send__(http_method, action, params, session.merge(:user_id => @users[role].id))
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
def assert_authentication_fails(action, http_method, role)
|
||||||
|
__send__(http_method, action, params, session.merge(:user_id => @users[role].id))
|
||||||
|
assert_redirected_to(new_sessions_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
MEMCACHE = MemcacheMock.new
|
MEMCACHE = MemcacheMock.new
|
||||||
Delayed::Worker.delay_jobs = false
|
Delayed::Worker.delay_jobs = false
|
||||||
|
|
||||||
|
|||||||
@@ -107,11 +107,14 @@ class NoteTest < ActiveSupport::TestCase
|
|||||||
setup do
|
setup do
|
||||||
@post = FactoryGirl.create(:post, :image_width => 1000, :image_height => 1000)
|
@post = FactoryGirl.create(:post, :image_width => 1000, :image_height => 1000)
|
||||||
@note = FactoryGirl.create(:note, :post => @post)
|
@note = FactoryGirl.create(:note, :post => @post)
|
||||||
|
@note.stubs(:merge_version?).returns(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "increment the updater's note_update_count" do
|
should "increment the updater's note_update_count" do
|
||||||
assert_difference("CurrentUser.note_update_count", 1) do
|
@user.reload
|
||||||
|
assert_difference("@user.note_update_count", 1) do
|
||||||
@note.update_attributes(:body => "zzz")
|
@note.update_attributes(:body => "zzz")
|
||||||
|
@user.reload
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ class PostTest < ActiveSupport::TestCase
|
|||||||
assert_equal(posts.map(&:id), Post.tag_match(query).pluck(:id))
|
assert_equal(posts.map(&:id), Post.tag_match(query).pluck(:id))
|
||||||
end
|
end
|
||||||
|
|
||||||
setup do
|
def setup
|
||||||
|
super
|
||||||
|
|
||||||
Timecop.travel(2.weeks.ago) do
|
Timecop.travel(2.weeks.ago) do
|
||||||
@user = FactoryGirl.create(:user)
|
@user = FactoryGirl.create(:user)
|
||||||
end
|
end
|
||||||
@@ -20,7 +22,9 @@ class PostTest < ActiveSupport::TestCase
|
|||||||
mock_saved_search_service!
|
mock_saved_search_service!
|
||||||
end
|
end
|
||||||
|
|
||||||
teardown do
|
def teardown
|
||||||
|
super
|
||||||
|
|
||||||
CurrentUser.user = nil
|
CurrentUser.user = nil
|
||||||
CurrentUser.ip_addr = nil
|
CurrentUser.ip_addr = nil
|
||||||
end
|
end
|
||||||
@@ -1055,7 +1059,7 @@ class PostTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
context "that has been updated" do
|
context "that has been updated" do
|
||||||
should "create a new version if it's the first version" do
|
should "create a new version if it's the first version" do
|
||||||
assert_difference("PostVersion.count", 1) do
|
assert_difference("PostArchive.count", 1) do
|
||||||
post = FactoryGirl.create(:post)
|
post = FactoryGirl.create(:post)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1063,7 +1067,7 @@ class PostTest < ActiveSupport::TestCase
|
|||||||
should "create a new version if it's been over an hour since the last update" do
|
should "create a new version if it's been over an hour since the last update" do
|
||||||
post = FactoryGirl.create(:post)
|
post = FactoryGirl.create(:post)
|
||||||
Timecop.travel(6.hours.from_now) do
|
Timecop.travel(6.hours.from_now) do
|
||||||
assert_difference("PostVersion.count", 1) do
|
assert_difference("PostArchive.count", 1) do
|
||||||
post.update_attributes(:tag_string => "zzz")
|
post.update_attributes(:tag_string => "zzz")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1071,15 +1075,16 @@ class PostTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
should "merge with the previous version if the updater is the same user and it's been less than an hour" do
|
should "merge with the previous version if the updater is the same user and it's been less than an hour" do
|
||||||
post = FactoryGirl.create(:post)
|
post = FactoryGirl.create(:post)
|
||||||
assert_difference("PostVersion.count", 0) do
|
assert_difference("PostArchive.count", 0) do
|
||||||
post.update_attributes(:tag_string => "zzz")
|
post.update_attributes(:tag_string => "zzz")
|
||||||
end
|
end
|
||||||
assert_equal("zzz", post.versions.last.tags)
|
assert_equal("zzz", post.versions.last.tags)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "increment the updater's post_update_count" do
|
should "increment the updater's post_update_count" do
|
||||||
|
PostArchive.sqs_service.stubs(:merge?).returns(false)
|
||||||
post = FactoryGirl.create(:post, :tag_string => "aaa bbb ccc")
|
post = FactoryGirl.create(:post, :tag_string => "aaa bbb ccc")
|
||||||
post.stubs(:merge_version?).returns(false)
|
CurrentUser.reload
|
||||||
|
|
||||||
assert_difference("CurrentUser.post_update_count", 1) do
|
assert_difference("CurrentUser.post_update_count", 1) do
|
||||||
post.update_attributes(:tag_string => "zzz")
|
post.update_attributes(:tag_string => "zzz")
|
||||||
@@ -2289,8 +2294,8 @@ class PostTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
context "a post that has been updated" do
|
context "a post that has been updated" do
|
||||||
setup do
|
setup do
|
||||||
|
PostArchive.sqs_service.stubs(:merge?).returns(false)
|
||||||
@post = FactoryGirl.create(:post, :rating => "q", :tag_string => "aaa", :source => nil)
|
@post = FactoryGirl.create(:post, :rating => "q", :tag_string => "aaa", :source => nil)
|
||||||
@post.stubs(:merge_version?).returns(false)
|
|
||||||
@post.update_attributes(:tag_string => "aaa bbb ccc ddd")
|
@post.update_attributes(:tag_string => "aaa bbb ccc ddd")
|
||||||
@post.update_attributes(:tag_string => "bbb xxx yyy", :source => "xyz")
|
@post.update_attributes(:tag_string => "bbb xxx yyy", :source => "xyz")
|
||||||
@post.update_attributes(:tag_string => "bbb mmm yyy", :source => "abc")
|
@post.update_attributes(:tag_string => "bbb mmm yyy", :source => "abc")
|
||||||
|
|||||||
@@ -18,28 +18,21 @@ class PostVersionTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
context "that has multiple versions: " do
|
context "that has multiple versions: " do
|
||||||
setup do
|
setup do
|
||||||
|
PostArchive.sqs_service.stubs(:merge?).returns(false)
|
||||||
@post = FactoryGirl.create(:post, :tag_string => "1")
|
@post = FactoryGirl.create(:post, :tag_string => "1")
|
||||||
@post.stubs(:merge_version?).returns(false)
|
|
||||||
@post.stubs(:tag_string_changed?).returns(true)
|
|
||||||
@post.update_attributes(:tag_string => "1 2")
|
@post.update_attributes(:tag_string => "1 2")
|
||||||
@post.update_attributes(:tag_string => "2 3")
|
@post.update_attributes(:tag_string => "2 3")
|
||||||
end
|
end
|
||||||
|
|
||||||
context "a version record" do
|
context "a version record" do
|
||||||
setup do
|
setup do
|
||||||
@version = PostVersion.last
|
@version = PostArchive.last
|
||||||
end
|
end
|
||||||
|
|
||||||
should "know its previous version" do
|
should "know its previous version" do
|
||||||
assert_not_nil(@version.previous)
|
assert_not_nil(@version.previous)
|
||||||
assert_equal("1 2", @version.previous.tags)
|
assert_equal("1 2", @version.previous.tags)
|
||||||
end
|
end
|
||||||
|
|
||||||
should "know the seuqence of all versions for the post" do
|
|
||||||
assert_equal(2, @version.sequence_for_post.size)
|
|
||||||
assert_equal(%w(3), @version.sequence_for_post[0][:added_tags])
|
|
||||||
assert_equal(%w(2), @version.sequence_for_post[1][:added_tags])
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -75,9 +68,8 @@ class PostVersionTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
context "that has been updated" do
|
context "that has been updated" do
|
||||||
setup do
|
setup do
|
||||||
@parent = FactoryGirl.create(:post)
|
PostArchive.sqs_service.stubs(:merge?).returns(false)
|
||||||
@post = FactoryGirl.create(:post, :tag_string => "aaa bbb ccc", :rating => "q", :source => "xyz")
|
@post = FactoryGirl.create(:post, :tag_string => "aaa bbb ccc", :rating => "q", :source => "xyz")
|
||||||
@post.stubs(:merge_version?).returns(false)
|
|
||||||
@post.update_attributes(:tag_string => "bbb ccc xxx", :source => "")
|
@post.update_attributes(:tag_string => "bbb ccc xxx", :source => "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class PostVoteTest < ActiveSupport::TestCase
|
class PostVoteTest < ActiveSupport::TestCase
|
||||||
setup do
|
def setup
|
||||||
|
super
|
||||||
|
|
||||||
user = FactoryGirl.create(:user)
|
user = FactoryGirl.create(:user)
|
||||||
CurrentUser.user = user
|
CurrentUser.user = user
|
||||||
CurrentUser.ip_addr = "127.0.0.1"
|
CurrentUser.ip_addr = "127.0.0.1"
|
||||||
|
|||||||
@@ -186,6 +186,13 @@ class UserTest < ActiveSupport::TestCase
|
|||||||
assert_equal(Danbooru.config.default_guest_name, User.id_to_name(-1))
|
assert_equal(Danbooru.config.default_guest_name, User.id_to_name(-1))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
should "not contain whitespace" do
|
||||||
|
# U+2007: https://en.wikipedia.org/wiki/Figure_space
|
||||||
|
user = FactoryGirl.build(:user, :name => "foo\u2007bar")
|
||||||
|
user.save
|
||||||
|
assert_equal(["Name cannot have whitespace or colons"], user.errors.full_messages)
|
||||||
|
end
|
||||||
|
|
||||||
should "not contain a colon" do
|
should "not contain a colon" do
|
||||||
user = FactoryGirl.build(:user, :name => "a:b")
|
user = FactoryGirl.build(:user, :name => "a:b")
|
||||||
user.save
|
user.save
|
||||||
|
|||||||
Reference in New Issue
Block a user