fixing tests

This commit is contained in:
albert
2011-07-16 19:20:02 -04:00
parent 7d80057e20
commit 58c3d2af13
49 changed files with 896 additions and 488 deletions

View File

@@ -1,8 +1,8 @@
GIT GIT
remote: git://github.com/ernie/meta_search.git remote: git://github.com/ernie/meta_search.git
revision: 79806e6a9db5dc4eedbd45bccc5929cf6fbf3593 revision: dfdd9c3a9956c4a2ad96724e2a801ad77a962b70
specs: specs:
meta_search (1.1.0.pre) meta_search (1.1.0.pre2)
actionpack (~> 3.1.0.alpha) actionpack (~> 3.1.0.alpha)
activerecord (~> 3.1.0.alpha) activerecord (~> 3.1.0.alpha)
activesupport (~> 3.1.0.alpha) activesupport (~> 3.1.0.alpha)
@@ -46,33 +46,38 @@ GEM
activesupport (= 3.1.0.rc1) activesupport (= 3.1.0.rc1)
activesupport (3.1.0.rc1) activesupport (3.1.0.rc1)
multi_json (~> 1.0) multi_json (~> 1.0)
arel (2.1.1) arel (2.1.3)
bcrypt-ruby (2.1.4) bcrypt-ruby (2.1.4)
builder (3.0.0) builder (3.0.0)
daemons (1.1.3) daemons (1.1.4)
delayed_job (2.1.4) delayed_job (2.1.4)
activesupport (~> 3.0) activesupport (~> 3.0)
daemons daemons
erubis (2.7.0) erubis (2.7.0)
factory_girl (1.3.3) factory_girl (1.3.3)
haml (3.1.1) haml (3.1.2)
hike (1.0.0) hike (1.1.0)
i18n (0.6.0) i18n (0.6.0)
imagesize (0.1.1) imagesize (0.1.1)
mail (2.3.0) mail (2.3.0)
i18n (>= 0.4.0) i18n (>= 0.4.0)
mime-types (~> 1.16) mime-types (~> 1.16)
treetop (~> 1.4.8) treetop (~> 1.4.8)
mechanize (1.0.0) mechanize (2.0.1)
nokogiri (>= 1.2.1) net-http-digest_auth (~> 1.1, >= 1.1.1)
net-http-persistent (~> 1.8)
nokogiri (~> 1.4)
webrobots (~> 0.0, >= 0.0.9)
memcache-client (1.8.5) memcache-client (1.8.5)
mime-types (1.16) mime-types (1.16)
mocha (0.9.12) mocha (0.9.12)
multi_json (1.0.3) multi_json (1.0.3)
nokogiri (1.4.4) net-http-digest_auth (1.1.1)
net-http-persistent (1.8)
nokogiri (1.5.0)
pg (0.11.0) pg (0.11.0)
polyglot (0.3.1) polyglot (0.3.1)
rack (1.3.0) rack (1.3.1)
rack-cache (1.0.2) rack-cache (1.0.2)
rack (>= 0.4) rack (>= 0.4)
rack-mount (0.8.1) rack-mount (0.8.1)
@@ -98,7 +103,9 @@ GEM
rake (0.9.2) rake (0.9.2)
shoulda (2.11.3) shoulda (2.11.3)
silent-postgres (0.0.8) silent-postgres (0.0.8)
simple_form (1.4.0) simple_form (1.4.2)
actionpack (~> 3.0)
activemodel (~> 3.0)
simplecov (0.4.2) simplecov (0.4.2)
simplecov-html (~> 0.4.4) simplecov-html (~> 0.4.4)
simplecov-html (0.4.5) simplecov-html (0.4.5)
@@ -113,7 +120,9 @@ GEM
tilt (1.3.2) tilt (1.3.2)
treetop (1.4.9) treetop (1.4.9)
polyglot (>= 0.3.1) polyglot (>= 0.3.1)
tzinfo (0.3.27) tzinfo (0.3.29)
webrobots (0.0.10)
nokogiri (>= 1.4.4)
PLATFORMS PLATFORMS
ruby ruby

View File

@@ -1006,3 +1006,36 @@ div#c-static {
} }
} }
} }
/*** moderator dashboard ***/
div#moderator-dashboard {
div#comment-activity {
width: 45%;
float: left;
}
div#post-activity {
width: 45%;
float: left;
margin-left: 2em;
}
div#ip-addr-search {
margin-bottom: 2em;
}
div#activity-search {
margin-bottom: 2em;
}
table {
margin-bottom: 2em;
}
caption {
font-weight: bold;
font-size: 1.5em;
}
}

View File

@@ -1,5 +1,5 @@
class IpBansController < ApplicationController class IpBansController < ApplicationController
before_filter :admin_only before_filter :janitor_only
def new def new
@ip_ban = IpBan.new @ip_ban = IpBan.new

View File

@@ -0,0 +1,9 @@
module Moderator
class DashboardsController < ApplicationController
before_filter :janitor_only
def show
@dashboard = ModeratorDashboard.new(params[:min_date] || 2.days.ago.to_date, params[:max_level] || 20)
end
end
end

View File

@@ -37,7 +37,7 @@ class NotesController < ApplicationController
def destroy def destroy
@note = Note.find(params[:id]) @note = Note.find(params[:id])
@note.update_attribute(:is_active, false) @note.update_column(:is_active, false)
respond_with(@note) respond_with(@note)
end end

View File

@@ -0,0 +1,17 @@
module Moderator
module DashboardsHelper
def user_level_select_tag(name, options = {})
choices = [
["", ""],
["Member", 0],
["Privileged", 100],
["Contributor", 200],
["Janitor", 300],
["Moderator", 400],
["Admin", 500]
]
select_tag(name, options_for_select(choices, params[name].to_i), options)
end
end
end

View File

@@ -0,0 +1,14 @@
module Moderator
module Dashboard
module Queries
class Comment
attr_reader :comment, :count
def initialize(hash)
@comment = Comment.find(hash["comment_id"])
@count = hash["count"]
end
end
end
end
end

View File

@@ -0,0 +1,14 @@
module Moderator
module Dashboard
module Queries
class Post
attr_reader :post, :count
def initialize(hash)
@post = Post.find(hash["post_id"])
@count = hash["count"]
end
end
end
end
end

View File

@@ -0,0 +1,30 @@
module Moderator
module Dashboard
module Queries
class PostAppeal
attr_reader :post, :reason
def self.all(min_date)
sql = <<-EOS
SELECT post_appeals.post_id, count(*)
FROM post_appeals
JOIN posts ON posts.id = post_appeals.post_id
WHERE
post_appeals.created_at > ?
and posts.status <> ?
GROUP BY post_appeals.post_id
ORDER BY count(*) DESC
LIMIT 10
EOS
ActiveRecord::Base.select_all_sql(sql, min_date).map {|x| new(x)}
end
def initialize(hash)
@post = Post.find(hash["post_id"])
@reason = hash["reason"]
end
end
end
end
end

View File

@@ -0,0 +1,31 @@
module Moderator
module Dashboard
module Queries
class PostFlag
attr_reader :post, :count
def self.all(min_date)
sql = <<-EOS
SELECT post_flags.post_id, count(*)
FROM post_flags
JOIN posts ON posts.id = post_flags.post_id
WHERE
post_flags.created_at > ?
AND post_flags.reason <> ?
AND posts.status <> 'deleted'
GROUP BY post_flags.post_id
ORDER BY count(*) DESC
LIMIT 10
EOS
ActiveRecord::Base.select_all_sql(sql, min_date, "Unapproved in three days").map {|x| new(x)}
end
def initialize(hash)
@post = Post.find(hash["post_id"])
@count = hash["count"]
end
end
end
end
end

View File

@@ -0,0 +1,13 @@
module Moderator
module Dashboard
module Queries
class Upload
def self.all(min_date)
ActiveRecord::Base.without_timeout do
@upload_activity = ActiveRecord::Base.select_all_sql("select posts.uploader_string, count(*) from posts join users on posts.user_id = users.id where posts.created_at > ? and users.level <= ? group by posts.user_id order by count(*) desc limit 10", min_date, max_level).map {|x| UserActivity.new(x)}
end
end
end
end
end
end

View File

@@ -0,0 +1,14 @@
module Moderator
module Dashboard
module Queries
class User
attr_reader :user, :count
def initialize(hash)
@user = User.find(hash["user_id"])
@count = hash["count"]
end
end
end
end
end

View File

@@ -0,0 +1,6 @@
module Moderator
module Dashboard
class Report
end
end
end

View File

@@ -0,0 +1,54 @@
class ModeratorDashboard
attr_reader :min_date, :max_level
def initialize(min_date, max_level)
@min_date = min_date
@max_level = max_level
end
def upload_activity
@upload_activity
end
def comment_activity(positive = false)
if positive
ActiveRecord::Base.select_all_sql("SELECT comment_votes.comment_id, count(*) FROM comment_votes JOIN comments ON comments.id = comment_votes.comment_id JOIN users ON users.id = comments.user_id WHERE comment_votes.created_at > ? AND comments.score > 0 AND users.level <= ? GROUP BY comment_votes.comment_id HAVING count(*) >= 3 ORDER BY count(*) DESC LIMIT 10", min_date, max_level).map {|x| CommentActivity.new(x)}
else
ActiveRecord::Base.select_all_sql("SELECT comment_votes.comment_id, count(*) FROM comment_votes JOIN comments ON comments.id = comment_votes.comment_id JOIN users ON users.id = comments.user_id WHERE comment_votes.created_at > ? AND comments.score < 0 AND users.level <= ? GROUP BY comment_votes.comment_id HAVING count(*) >= 3 ORDER BY count(*) DESC LIMIT 10", min_date, max_level).map {|x| CommentActivity.new(x)}
end
end
def post_activity(positive = false)
ActiveRecord::Base.without_timeout do
if positive
@post_activity = ActiveRecord::Base.select_all_sql("SELECT post_votes.post_id, count(*) FROM post_votes JOIN posts ON posts.id = post_votes.post_id JOIN users ON users.id = posts.user_id WHERE post_votes.created_at > ? AND posts.score > 0 AND users.level <= ? GROUP BY post_votes.post_id HAVING count(*) >= 3 ORDER BY count(*) DESC LIMIT 10", min_date, max_level).map {|x| PostActivity.new(x)}
else
@post_activity = ActiveRecord::Base.select_all_sql("SELECT post_votes.post_id, count(*) FROM post_votes JOIN posts ON posts.id = post_votes.post_id JOIN users ON users.id = posts.user_id WHERE post_votes.created_at > ? AND posts.score < 0 AND users.level <= ? AND posts.status <> 'deleted' GROUP BY post_votes.post_id HAVING count(*) >= 3 ORDER BY count(*) DESC LIMIT 10", min_date, max_level).map {|x| PostActivity.new(x)}
end
end
@post_activity
end
def tag_activity
ActiveRecord::Base.without_timeout do
@tag_activity = ActiveRecord::Base.select_all_sql("SELECT post_tag_histories.user_id, count(*) FROM post_tag_histories JOIN users ON users.id = post_tag_histories.user_id WHERE post_tag_histories.created_at > ? AND users.level <= ? GROUP BY post_tag_histories.user_id ORDER BY count(*) DESC LIMIT 10", min_date, max_level).map {|x| UserActivity.new(x)}
end
@tag_activity
end
def note_activity
ActiveRecord::Base.select_all_sql("SELECT note_versions.user_id, count(*) FROM note_versions JOIN users ON users.id = note_versions.user_id WHERE note_versions.created_at > ? AND users.level <= ? GROUP BY note_versions.user_id ORDER BY count(*) DESC LIMIT 10", min_date, max_level).map {|x| UserActivity.new(x)}
end
def wiki_page_activity
ActiveRecord::Base.select_all_sql("SELECT wiki_page_versions.user_id, count(*) FROM wiki_page_versions JOIN users ON users.id = wiki_page_versions.user_id WHERE wiki_page_versions.created_at > ? AND users.level <= ? GROUP BY wiki_page_versions.user_id ORDER BY count(*) DESC LIMIT 10", min_date, max_level).map {|x| UserActivity.new(x)}
end
def artist_activity
ActiveRecord::Base.select_all_sql("SELECT artist_versions.updater_id AS user_id, count(*) FROM artist_versions JOIN users ON users.id = artist_versions.updater_id WHERE artist_versions.created_at > ? AND users.level <= ? GROUP BY artist_versions.updater_id ORDER BY count(*) DESC LIMIT 10", min_date, max_level).map {|x| UserActivity.new(x)}
end
end

View File

@@ -2,7 +2,7 @@ module PostSets
class Favorite < Base class Favorite < Base
attr_reader :user, :page, :favorites attr_reader :user, :page, :favorites
def initialize(user_id, page) def initialize(user_id, page = 1)
@user = ::User.find(user_id) @user = ::User.find(user_id)
@favorites = ::Favorite.model_for(user.id).for_user(user.id).paginate(page) @favorites = ::Favorite.model_for(user.id).for_user(user.id).paginate(page)
end end

View File

@@ -4,15 +4,11 @@ module PostSets
attr_accessor :total_pages, :current_page attr_accessor :total_pages, :current_page
end end
attr_reader :pool, :page, :posts attr_reader :pool, :page
def initialize(pool, page) def initialize(pool, page = 1)
@pool = pool @pool = pool
@page = page @page = page
@posts = pool.posts(:offset => offset, :limit => limit)
@posts.extend(ActiveRecordExtension)
@posts.total_pages = total_pages
@posts.current_page = current_page
end end
def offset def offset
@@ -27,6 +23,16 @@ module PostSets
["pool:#{pool.id}"] ["pool:#{pool.id}"]
end end
def posts
@posts ||= begin
x = pool.posts(:offset => offset, :limit => limit)
x.extend(ActiveRecordExtension)
x.total_pages = total_pages
x.current_page = current_page
x
end
end
def tag_string def tag_string
tag_array.join("") tag_array.join("")
end end

View File

@@ -1,11 +1,13 @@
module PostSets module PostSets
class SearchError < Exception
end
class Post < Base class Post < Base
attr_reader :tag_array, :page, :posts attr_reader :tag_array, :page
def initialize(params) def initialize(tags, page = 1)
@tag_array = Tag.scan_query(params[:tags]) @tag_array = Tag.scan_query(tags)
@page = params[:page] @page = page
@posts = ::Post.tag_match(tag_string).paginate(page)
end end
def tag_string def tag_string
@@ -24,6 +26,14 @@ module PostSets
end end
end end
def posts
if tag_array.size > 2 && !CurrentUser.is_privileged?
raise SearchError
end
@posts ||= ::Post.tag_match(tag_string).paginate(page)
end
def has_artist? def has_artist?
tag_array.any? && ::Artist.name_equals(tag_string).exists? tag_array.any? && ::Artist.name_equals(tag_string).exists?
end end
@@ -36,6 +46,10 @@ module PostSets
tag_array.size == 1 tag_array.size == 1
end end
def current_page
[page.to_i, 1].max
end
def presenter def presenter
@presenter ||= ::PostSetPresenters::Post.new(self) @presenter ||= ::PostSetPresenters::Post.new(self)
end end

View File

@@ -14,6 +14,7 @@ class Artist < ActiveRecord::Base
attr_accessible :name, :url_string, :other_names, :group_name, :wiki_page_attributes, :notes attr_accessible :name, :url_string, :other_names, :group_name, :wiki_page_attributes, :notes
scope :url_match, lambda {|string| where(["id in (?)", Artist.find_all_by_url(string).map(&:id)])} scope :url_match, lambda {|string| where(["id in (?)", Artist.find_all_by_url(string).map(&:id)])}
scope :other_names_match, lambda {|string| where(["other_names_index @@ to_tsquery('danbooru', ?)", Artist.normalize_name(string)])} scope :other_names_match, lambda {|string| where(["other_names_index @@ to_tsquery('danbooru', ?)", Artist.normalize_name(string)])}
scope :name_equals, lambda {|string| where("name = ?", string)}
search_methods :url_match, :other_names_match search_methods :url_match, :other_names_match
module UrlMethods module UrlMethods

View File

@@ -89,15 +89,15 @@ class Dmail < ActiveRecord::Base
end end
def mark_as_read! def mark_as_read!
update_attribute(:is_read, true) update_column(:is_read, true)
unless Dmail.exists?(["to_id = ? AND is_read = false", to_id]) unless Dmail.exists?(["to_id = ? AND is_read = false", to_id])
to.update_attribute(:has_mail, false) to.update_column(:has_mail, false)
end end
end end
def update_recipient def update_recipient
to.update_attribute(:has_mail, true) to.update_column(:has_mail, true)
end end
def visible_to?(user) def visible_to?(user)

View File

@@ -39,7 +39,7 @@ class ForumPost < ActiveRecord::Base
def update_topic_updated_at def update_topic_updated_at
if topic if topic
topic.update_attribute(:updater_id, CurrentUser.id) topic.update_column(:updater_id, CurrentUser.id)
topic.touch topic.touch
end end
end end

View File

@@ -5,11 +5,16 @@ class JanitorTrial < ActiveRecord::Base
after_destroy :create_feedback after_destroy :create_feedback
validates_presence_of :user validates_presence_of :user
before_validation :initialize_creator before_validation :initialize_creator
before_validation :initialize_original_level
def initialize_creator def initialize_creator
self.creator_id = CurrentUser.id self.creator_id = CurrentUser.id
end end
def initialize_original_level
self.original_level = user.level
end
def user_name=(name) def user_name=(name)
self.user_id = User.name_to_id(name) self.user_id = User.name_to_id(name)
end end
@@ -21,7 +26,7 @@ class JanitorTrial < ActiveRecord::Base
end end
def promote_user def promote_user
user.update_attribute(:is_janitor, true) user.update_column(:level, User::Levels::JANITOR)
end end
def create_feedback def create_feedback
@@ -36,7 +41,7 @@ class JanitorTrial < ActiveRecord::Base
end end
def demote! def demote!
user.update_attribute(:is_janitor, false) user.update_column(:level, original_level)
destroy destroy
end end
end end

View File

@@ -6,7 +6,7 @@ module Jobs
CONFIG["tag_types"].values.uniq.each do |tag_type| CONFIG["tag_types"].values.uniq.each do |tag_type|
tags += user.calculate_uploaded_tags(tag_type) tags += user.calculate_uploaded_tags(tag_type)
end end
user.update_attribute(:uploaded_tags, tags.join("\n")) user.update_column(:uploaded_tags, tags.join("\n"))
end end
end end
end end

View File

@@ -91,7 +91,6 @@ class Pool < ActiveRecord::Base
offset = options[:offset] || 0 offset = options[:offset] || 0
limit = options[:limit] || Danbooru.config.posts_per_page limit = options[:limit] || Danbooru.config.posts_per_page
slice = post_id_array.slice(offset, limit) slice = post_id_array.slice(offset, limit)
puts slice.inspect
if slice && slice.any? if slice && slice.any?
Post.where("id in (?)", slice).order(arbitrary_sql_order_clause(slice, "posts")) Post.where("id in (?)", slice).order(arbitrary_sql_order_clause(slice, "posts"))
else else
@@ -150,7 +149,7 @@ class Pool < ActiveRecord::Base
last_version = versions.last last_version = versions.last
if last_version && CurrentUser.ip_addr == last_version.updater_ip_addr && CurrentUser.id == last_version.updater_id if last_version && CurrentUser.ip_addr == last_version.updater_ip_addr && CurrentUser.id == last_version.updater_id
last_version.update_attribute(:post_ids, post_ids) last_version.update_column(:post_ids, post_ids)
else else
versions.create(:post_ids => post_ids) versions.create(:post_ids => post_ids)
end end

View File

@@ -15,6 +15,7 @@ class Post < ActiveRecord::Base
before_validation :initialize_uploader, :on => :create before_validation :initialize_uploader, :on => :create
belongs_to :updater, :class_name => "User" belongs_to :updater, :class_name => "User"
belongs_to :approver, :class_name => "User" belongs_to :approver, :class_name => "User"
belongs_to :uploader, :class_name => "User"
belongs_to :parent, :class_name => "Post" belongs_to :parent, :class_name => "Post"
has_one :upload, :dependent => :destroy has_one :upload, :dependent => :destroy
has_many :flags, :class_name => "PostFlag", :dependent => :destroy has_many :flags, :class_name => "PostFlag", :dependent => :destroy
@@ -36,7 +37,7 @@ class Post < ActiveRecord::Base
scope :visible, lambda {|user| Danbooru.config.can_user_see_post_conditions(user)} scope :visible, lambda {|user| Danbooru.config.can_user_see_post_conditions(user)}
scope :commented_before, lambda {|date| where("last_commented_at < ?", date).order("last_commented_at DESC")} scope :commented_before, lambda {|date| where("last_commented_at < ?", date).order("last_commented_at DESC")}
scope :has_notes, where("last_noted_at is not null") scope :has_notes, where("last_noted_at is not null")
scope :for_user, lambda {|user_id| where(["uploader_string = ?", "uploader:#{user_id}"])} scope :for_user, lambda {|user_id| where(["uploader_id = ?", user_id])}
scope :available_for_moderation, lambda {where(["id NOT IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])} scope :available_for_moderation, lambda {where(["id NOT IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])}
scope :hidden_from_moderation, lambda {where(["id IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])} scope :hidden_from_moderation, lambda {where(["id IN (SELECT pd.post_id FROM post_disapprovals pd WHERE pd.user_id = ?)", CurrentUser.id])}
scope :tag_match, lambda {|query| Post.tag_match_helper(query)} scope :tag_match, lambda {|query| Post.tag_match_helper(query)}
@@ -233,7 +234,7 @@ class Post < ActiveRecord::Base
module ApprovalMethods module ApprovalMethods
def is_approvable? def is_approvable?
(is_pending? || is_flagged? || is_deleted?) && approver_string != "approver:#{CurrentUser.name}" (is_pending? || is_flagged? || is_deleted?) && approver_id != CurrentUser.id
end end
def flag!(reason) def flag!(reason)
@@ -243,7 +244,7 @@ class Post < ActiveRecord::Base
raise PostFlag::Error.new(flag.errors.full_messages.join("; ")) raise PostFlag::Error.new(flag.errors.full_messages.join("; "))
end end
update_attribute(:is_flagged, true) update_column(:is_flagged, true)
end end
def appeal!(reason) def appeal!(reason)
@@ -255,13 +256,13 @@ class Post < ActiveRecord::Base
end end
def approve! def approve!
raise ApprovalError.new("You have previously approved this post and cannot approve it again") if approver_string == "approver:#{CurrentUser.name}" raise ApprovalError.new("You have previously approved this post and cannot approve it again") if approver_id == CurrentUser.id
flags.each {|x| x.resolve!} flags.each {|x| x.resolve!}
self.is_flagged = false self.is_flagged = false
self.is_pending = false self.is_pending = false
self.is_deleted = false self.is_deleted = false
self.approver_string = "approver:#{CurrentUser.name}" self.approver_id = CurrentUser.id
save! save!
end end
end end
@@ -295,7 +296,7 @@ class Post < ActiveRecord::Base
end end
def create_tags def create_tags
set_tag_string(tag_array.map {|x| Tag.find_or_create_by_name(x).name}.join(" ")) set_tag_string(tag_array.map {|x| Tag.find_or_create_by_name(x).name}.uniq.join(" "))
end end
def increment_tag_post_counts def increment_tag_post_counts
@@ -373,11 +374,12 @@ class Post < ActiveRecord::Base
normalized_tags = TagAlias.to_aliased(normalized_tags) normalized_tags = TagAlias.to_aliased(normalized_tags)
normalized_tags = TagImplication.with_descendants(normalized_tags) normalized_tags = TagImplication.with_descendants(normalized_tags)
normalized_tags = filter_metatags(normalized_tags) normalized_tags = filter_metatags(normalized_tags)
normalized_tags = %w(tagme) if normalized_tags.empty?
set_tag_string(normalized_tags.uniq.join(" ")) set_tag_string(normalized_tags.uniq.join(" "))
end end
def filter_metatags(tags) def filter_metatags(tags)
tags.reject {|tag| tag =~ /\A(?:pool|rating|fav|approver|uploader):/} tags.reject {|tag| tag =~ /\A(?:pool|rating|fav):/}
end end
def has_tag?(tag) def has_tag?(tag)
@@ -395,7 +397,7 @@ class Post < ActiveRecord::Base
end end
def append_user_to_fav_string(user_id) def append_user_to_fav_string(user_id)
update_attribute(:fav_string, (fav_string + " fav:#{user_id}").strip) update_column(:fav_string, (fav_string + " fav:#{user_id}").strip)
end end
def add_favorite!(user) def add_favorite!(user)
@@ -405,7 +407,7 @@ class Post < ActiveRecord::Base
end end
def delete_user_from_fav_string(user_id) def delete_user_from_fav_string(user_id)
update_attribute(:fav_string, fav_string.gsub(/(?:\A| )fav:#{user_id}(?:\Z| )/, " ").strip) update_column(:fav_string, fav_string.gsub(/(?:\A| )fav:#{user_id}(?:\Z| )/, " ").strip)
end end
def remove_favorite!(user) def remove_favorite!(user)
@@ -542,6 +544,22 @@ class Post < ActiveRecord::Base
relation = add_tag_string_search_relation(q[:tags], relation) relation = add_tag_string_search_relation(q[:tags], relation)
if q[:uploader_id_neg]
relation = relation.where("posts.uploader_id not in (?)", q[:uploader_id_neg])
end
if q[:uploader_id]
relation = relation.where("posts.uploader_id = ?", q[:uploader_id])
end
if q[:approver_id_neg]
relation = relation.where("posts.approver_id not in (?)", q[:approver_id_neg])
end
if q[:approver_id]
relation = relation.where("posts.approver_id = ?", q[:approver_id])
end
if q[:rating] == "q" if q[:rating] == "q"
relation = relation.where("posts.rating = 'q'") relation = relation.where("posts.rating = 'q'")
elsif q[:rating] == "s" elsif q[:rating] == "s"
@@ -601,29 +619,15 @@ class Post < ActiveRecord::Base
module UploaderMethods module UploaderMethods
def initialize_uploader def initialize_uploader
self.uploader = CurrentUser.user if uploader_id.blank?
self.uploader_ip_addr = CurrentUser.ip_addr self.uploader_id = CurrentUser.id
end self.uploader_ip_addr = CurrentUser.ip_addr
end
def uploader_id=(user_id)
self.uploader = User.find(user_id)
end
def uploader_id
uploader_string[9..-1].to_i
end end
def uploader_name def uploader_name
User.id_to_name(uploader_id) User.id_to_name(uploader_id)
end end
def uploader
User.find(uploader_id)
end
def uploader=(user)
self.uploader_string = "uploader:#{user.id}"
end
end end
module PoolMethods module PoolMethods
@@ -640,13 +644,15 @@ class Post < ActiveRecord::Base
def add_pool!(pool) def add_pool!(pool)
return if belongs_to_pool?(pool) return if belongs_to_pool?(pool)
update_attribute(:pool_string, "#{pool_string} pool:#{pool.id}".strip) self.pool_string = "#{pool_string} pool:#{pool.id}".strip
update_column(:pool_string, pool_string)
pool.add!(self) pool.add!(self)
end end
def remove_pool!(pool) def remove_pool!(pool)
return unless belongs_to_pool?(pool) return unless belongs_to_pool?(pool)
update_attribute(:pool_string, pool_string.gsub(/(?:\A| )pool:#{pool.id}(?:\Z| )/, " ").strip) self.pool_string = pool_string.gsub(/(?:\A| )pool:#{pool.id}(?:\Z| )/, " ").strip
update_column(:pool_string, pool_string)
pool.remove!(self) pool.remove!(self)
end end
end end
@@ -762,13 +768,11 @@ class Post < ActiveRecord::Base
if children.size == 0 if children.size == 0
# do nothing # do nothing
elsif children.size == 1 elsif children.size == 1
children.first.update_attribute(:parent_id, nil) children.first.update_column(:parent_id, nil)
else else
cached_children = children cached_children = children
cached_children[1..-1].each do |child| Post.update_all({:parent_id => cached_children[0].id}, :id => cached_children[1..-1].map(&:id))
child.update_attribute(:parent_id, cached_children[0].id) cached_children[0].update_column(:parent_id, nil)
end
cached_children[0].update_attribute(:parent_id, nil)
end end
end end
@@ -800,14 +804,14 @@ class Post < ActiveRecord::Base
update_children_on_destroy update_children_on_destroy
delete_favorites delete_favorites
decrement_tag_post_counts decrement_tag_post_counts
update_attribute(:is_deleted, true) update_column(:is_deleted, true)
update_parent_on_destroy update_parent_on_destroy
tag_array.each {|x| expire_cache(x)} tag_array.each {|x| expire_cache(x)}
end end
end end
def undelete! def undelete!
update_attribute(:is_deleted, false) update_column(:is_deleted, false)
tag_array.each {|x| expire_cache(x)} tag_array.each {|x| expire_cache(x)}
update_parent_on_save update_parent_on_save
end end
@@ -822,7 +826,7 @@ class Post < ActiveRecord::Base
:add_tags => tag_string, :add_tags => tag_string,
:parent_id => parent_id :parent_id => parent_id
) )
else elsif rating_changed? || source_changed? || parent_id_changed? || tag_string_changed?
versions.create( versions.create(
:rating => rating_changed? ? rating : nil, :rating => rating_changed? ? rating : nil,
:source => source_changed? ? source : nil, :source => source_changed? ? source : nil,

View File

@@ -13,7 +13,7 @@ class PostFlag < ActiveRecord::Base
scope :unresolved, where(["is_resolved = ?", false]) scope :unresolved, where(["is_resolved = ?", false])
def update_post def update_post
post.update_attribute(:is_flagged, true) post.update_column(:is_flagged, true)
end end
def validate_creator_is_not_limited def validate_creator_is_not_limited
@@ -40,7 +40,7 @@ class PostFlag < ActiveRecord::Base
end end
def resolve! def resolve!
update_attribute(:is_resolved, true) update_column(:is_resolved, true)
end end
def flag_count_for_creator def flag_count_for_creator

View File

@@ -88,15 +88,15 @@ class Tag < ActiveRecord::Base
if tag if tag
if category > 0 && !(options[:user] && !options[:user].is_privileged? && tag.post_count > 10) if category > 0 && !(options[:user] && !options[:user].is_privileged? && tag.post_count > 10)
tag.update_attribute(:category, category) tag.update_column(:category, category)
end end
tag tag
else else
Tag.new.tap do |tag| Tag.new.tap do |t|
tag.name = name t.name = name
tag.category = category t.category = category
tag.save t.save
end end
end end
end end
@@ -216,13 +216,21 @@ class Tag < ActiveRecord::Base
} }
scan_query(query).each do |token| scan_query(query).each do |token|
if token =~ /\A(-uploader|uploader|-pool|pool|-fav|fav|sub|md5|-rating|rating|width|height|mpixels|score|filesize|source|id|date|order|status|tagcount|gentags|arttags|chartags|copytags):(.+)\Z/ if token =~ /\A(-uploader|uploader|-approver|approver|-pool|pool|-fav|fav|sub|md5|-rating|rating|width|height|mpixels|score|filesize|source|id|date|order|status|tagcount|gentags|arttags|chartags|copytags):(.+)\Z/
case $1 case $1
when "-uploader" when "-uploader"
q[:tags][:exclude] << "uploader:#{User.name_to_id($2)}" q[:uploader_id_neg] ||= []
q[:uploader_id_neg] << User.name_to_id($2)
when "uploader" when "uploader"
q[:tags][:related] << "uploader:#{User.name_to_id($2)}" q[:uploader_id] = User.name_to_id($2)
when "-approver"
q[:approver_id_neg] ||= []
q[:approver_id_neg] << User.name.to_id($2)
when "approver"
q[:approver_id] = User.name.to_id($2)
when "-pool" when "-pool"
q[:tags][:exclude] << "pool:#{Pool.name_to_id($2)}" q[:tags][:exclude] << "pool:#{Pool.name_to_id($2)}"

View File

@@ -17,7 +17,7 @@ class Upload < ActiveRecord::Base
module ValidationMethods module ValidationMethods
def uploader_is_not_limited def uploader_is_not_limited
if !uploader.can_upload? if !uploader.can_upload?
update_attribute(:status, "error: uploader has reached their daily limit") update_column(:status, "error: uploader has reached their daily limit")
end end
end end
@@ -29,19 +29,19 @@ class Upload < ActiveRecord::Base
def validate_file_exists def validate_file_exists
unless File.exists?(file_path) unless File.exists?(file_path)
update_attribute(:status, "error: file does not exist") update_column(:status, "error: file does not exist")
end end
end end
def validate_file_content_type def validate_file_content_type
unless is_valid_content_type? unless is_valid_content_type?
update_attribute(:status, "error: invalid content type (#{file_ext} not allowed)") update_column(:status, "error: invalid content type (#{file_ext} not allowed)")
end end
end end
def validate_md5_confirmation def validate_md5_confirmation
if !md5_confirmation.blank? && md5_confirmation != md5 if !md5_confirmation.blank? && md5_confirmation != md5
update_attribute(:status, "error: md5 mismatch") update_column(:status, "error: md5 mismatch")
end end
end end
end end
@@ -49,7 +49,7 @@ class Upload < ActiveRecord::Base
module ConversionMethods module ConversionMethods
def process! def process!
CurrentUser.scoped(uploader, uploader_ip_addr) do CurrentUser.scoped(uploader, uploader_ip_addr) do
update_attribute(:status, "processing") update_column(:status, "processing")
if is_downloadable? if is_downloadable?
download_from_source(temp_file_path) download_from_source(temp_file_path)
end end
@@ -67,12 +67,12 @@ class Upload < ActiveRecord::Base
if post.save if post.save
update_attributes(:status => "completed", :post_id => post.id) update_attributes(:status => "completed", :post_id => post.id)
else else
update_attribute(:status, "error: " + post.errors.full_messages.join(", ")) update_column(:status, "error: " + post.errors.full_messages.join(", "))
end end
end end
rescue Exception => x rescue Exception => x
raise raise
update_attribute(:status, "error: #{x} - #{x.message}") update_column(:status, "error: #{x} - #{x.message}")
ensure ensure
delete_temp_file delete_temp_file
end end
@@ -87,6 +87,8 @@ class Upload < ActiveRecord::Base
p.rating = rating p.rating = rating
p.source = source p.source = source
p.file_size = file_size p.file_size = file_size
p.uploader_id = uploader_id
p.uploader_ip_addr = uploader_ip_addr
unless uploader.is_contributor? unless uploader.is_contributor?
p.is_pending = true p.is_pending = true
@@ -97,7 +99,7 @@ class Upload < ActiveRecord::Base
def merge_tags(post) def merge_tags(post)
post.tag_string += " #{tag_string}" post.tag_string += " #{tag_string}"
post.save post.save
update_attribute(:status, "duplicate: #{post.id}") update_column(:status, "duplicate: #{post.id}")
end end
end end

View File

@@ -28,6 +28,7 @@ class User < ActiveRecord::Base
after_save :update_cache after_save :update_cache
before_create :promote_to_admin_if_first_user before_create :promote_to_admin_if_first_user
has_many :feedback, :class_name => "UserFeedback", :dependent => :destroy has_many :feedback, :class_name => "UserFeedback", :dependent => :destroy
has_many :posts, :foreign_key => "uploader_id"
has_one :ban has_one :ban
has_many :subscriptions, :class_name => "TagSubscription" has_many :subscriptions, :class_name => "TagSubscription"
has_many :note_versions, :foreign_key => "updater_id" has_many :note_versions, :foreign_key => "updater_id"
@@ -46,7 +47,7 @@ class User < ActiveRecord::Base
end end
def unban! def unban!
update_attribute(:is_banned, false) update_column(:is_banned, false)
ban.destroy ban.destroy
end end
end end
@@ -218,7 +219,7 @@ class User < ActiveRecord::Base
def verify!(key) def verify!(key)
if email_verification_key == key if email_verification_key == key
self.update_attribute(:email_verification_key, nil) self.update_column(:email_verification_key, nil)
else else
raise User::Error.new("Verification key does not match") raise User::Error.new("Verification key does not match")
end end
@@ -293,12 +294,6 @@ class User < ActiveRecord::Base
end end
end end
module PostMethods
def posts
Post.where("uploader_string = ?", "uploader:#{id}")
end
end
include BanMethods include BanMethods
include NameMethods include NameMethods
include PasswordMethods include PasswordMethods
@@ -309,7 +304,6 @@ class User < ActiveRecord::Base
include BlacklistMethods include BlacklistMethods
include ForumMethods include ForumMethods
include LimitMethods include LimitMethods
include PostMethods
def initialize_default_image_size def initialize_default_image_size
self.default_image_size = "Medium" self.default_image_size = "Medium"

View File

@@ -42,6 +42,9 @@
<%= nav_link_to("Pools", pools_path) %> <%= nav_link_to("Pools", pools_path) %>
<%= nav_link_to("Wiki", wiki_pages_path(:title => "help:home")) %> <%= nav_link_to("Wiki", wiki_pages_path(:title => "help:home")) %>
<%= nav_link_to("Forum", forum_topics_path, :class => (CurrentUser.user.has_forum_been_updated? ? "forum-updated" : nil)) %> <%= nav_link_to("Forum", forum_topics_path, :class => (CurrentUser.user.has_forum_been_updated? ? "forum-updated" : nil)) %>
<% if CurrentUser.is_moderator? %>
<%= nav_link_to("Dashboard", moderator_dashboard_path) %>
<% end %>
<%= nav_link_to("&raquo;".html_safe, site_map_path) %> <%= nav_link_to("&raquo;".html_safe, site_map_path) %>
</menu> </menu>
<%= yield :secondary_links %> <%= yield :secondary_links %>

View File

@@ -0,0 +1,222 @@
<div id="moderator-dashboard">
<h1>Moderator Dashboard</h1>
<div id="ip-addr-search">
<% form_tag(moderator_ip_addrs_path, :method => :get) do %>
<label for="user_ids">Search IPs</label>
<%= text_field_tag "search[ip_addr_eq]", params[:ip_addrs] %>
<%= submit_tag "Search" %>
<% end %>
<% form_tag(moderator_ip_addrs_path, :method => :get) do %>
<label for="user_ids">Search User IDs</label>
<%= text_field_tag "search[user_id_eq]", params[:user_ids] %>
<%= submit_tag "Search" %>
<% end %>
</div>
<div id="activity-search">
<% form_tag(moderator_dashboard_path, :method => :get) do %>
<label for="min_date">Minimum Date</label>
<%= text_field_tag :min_date, @dashboard.min_date %><br>
<label for="max_level">Max Level</label>
<%= user_level_select_tag(:max_level) %><br>
<%= submit_tag "Search" %>
<% end %>
</div>
<div id="comment-activity">
<table width="100%" class="striped">
<caption>Uploads</caption>
<thead>
<tr>
<th>User</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<% @dashboard.upload_activity.each do |activity| %>
<tr>
<td><%= admin_link_to_user(activity.user, :positive) %></td>
<td><%= link_to activity.count, {:controller => "post", :action => "index", :tags => "user:#{activity.user.name}"} %></td>
</tr>
<% end %>
</tbody>
</table>
<table width="100%" class="striped">
<caption>Note Updates</caption>
<thead>
<tr>
<th>User</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<% @dashboard.note_activity.each do |activity| %>
<tr>
<td><%= admin_link_to_user(activity.user, :positive) %></td>
<td><%= link_to activity.count, {:controller => "note", :action => "history", :user_id => activity.user.id} %></td>
</tr>
<% end %>
</tbody>
</table>
<table width="100%" class="striped">
<caption>Tag Updates</caption>
<thead>
<tr>
<th>User</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<% @dashboard.tag_activity.each do |activity| %>
<tr>
<td><%= admin_link_to_user(activity.user, :positive) %></td>
<td><%= link_to activity.count, {:controller => "post_tag_history", :action => "index", :user_id => activity.user.id} %></td>
</tr>
<% end %>
</tbody>
</table>
<table width="100%" class="striped">
<caption>Wiki Page Updates</caption>
<thead>
<tr>
<th>User</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<% @dashboard.wiki_page_activity.each do |activity| %>
<tr>
<td><%= admin_link_to_user(activity.user, :positive) %></td>
<td><%= link_to activity.count, {:controller => "wiki", :action => "recent_changes", :user_id => activity.user.id} %></td>
</tr>
<% end %>
</tbody>
</table>
<table width="100%" class="striped">
<caption>Artist Updates</caption>
<thead>
<tr>
<th>User</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<% @dashboard.artist_activity.each do |activity| %>
<tr>
<td><%= admin_link_to_user(activity.user, :positive) %></td>
<td><%= link_to activity.count, {:controller => "artist", :action => "recent_changes", :user_id => activity.user.id} %></td>
</tr>
<% end %>
</tbody>
</table>
<table width="100%" class="striped">
<caption>Comment Activity (Negative)</caption>
<thead>
<tr>
<th>Comment</th>
<th>User</th>
<th>Votes</th>
<th>Score</th>
</tr>
</thead>
<tbody>
<% @dashboard.comment_activity.each do |activity| %>
<tr>
<td><%= link_to activity.comment.body, :controller => "post", :action => "show", :id => activity.comment.post_id %></td>
<td><%= admin_link_to_user(activity.comment.user, :negative) %></td>
<td><%= activity.count %></td>
<td><%= activity.comment.score %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<div id="post-activity">
<table width="100%" class="striped">
<caption>Appealed Posts</caption>
<thead>
<tr>
<th>Post</th>
<th>User</th>
<th>Flags</th>
<th>Appeals</th>
<th>Score</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="5"><%= link_to "View all posts", :controller => "post_appeal", :action => "index" %></td>
</tr>
</tfoot>
<tbody>
<% @dashboard.appealed_posts.each do |appeal| %>
<tr>
<td><%= link_to image_tag(appeal.post.preview_url), :controller => "post", :action => "show", :id => appeal.post.id %></td>
<td><%= admin_link_to_user appeal.post.user, :negative %></td>
<td><%= post_flag_summary(appeal.post) %></td>
<td><%= post_appeal_summary(appeal.post) %></td>
<td><%= appeal.post.score %></td>
</tr>
<% end %>
</tbody>
</table>
<table width="100%" class="striped">
<caption>User Records</caption>
<thead>
<tr>
<th>User</th>
<th>Message</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<% UserRecord.recent(@dashboard.min_date).all(:order => "id desc").each do |record| %>
<tr class="user-record-score-<%= record.score %>">
<td><%= link_to(record.user.name, :controller => "user", :action => "show", :id => record.user_id) %></td>
<td><%= format_text(record.body) %></td>
<td><%= time_ago_in_words(record.created_at) %> ago</td>
</tr>
<% end %>
</tbody>
</table>
<table width="100%" class="striped">
<caption>Mod Actions</caption>
<thead>
<tr>
<th>Moderator</th>
<th>Description</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="2"><%= link_to "View all actions", :controller => "mod_action", :action => "index" %></td>
</tr>
</tfoot>
<tbody>
<% ModAction.all(:order => "id desc", :limit => 10).each do |mod_action| %>
<tr>
<td><%= link_to mod_action.user.name, :controller => "user", :action => "show", :id => mod_action.user_id %></td>
<td><%= format_text(mod_action.description) %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>

View File

@@ -1,6 +1,24 @@
module Danbooru module Danbooru
module Extensions module Extensions
module ActiveRecord module ActiveRecord
extend ActiveSupport::Concern
module ClassMethods
def without_timeout
connection.execute("SET STATEMENT_TIMEOUT = 0")
yield
ensure
connection.execute("SET STATEMENT_TIMEOUT = 10000")
end
def with_timeout(n)
connection.execute("SET STATEMENT_TIMEOUT = #{n}")
yield
ensure
connection.execute("SET STATEMENT_TIMEOUT = 10000")
end
end
%w(execute select_value select_values select_all).each do |method_name| %w(execute select_value select_values select_all).each do |method_name|
define_method("#{method_name}_sql") do |sql, *params| define_method("#{method_name}_sql") do |sql, *params|
connection.__send__(method_name, self.class.sanitize_sql_array([sql, *params])) connection.__send__(method_name, self.class.sanitize_sql_array([sql, *params]))

View File

@@ -1,7 +1,14 @@
Danbooru::Application.routes.draw do Danbooru::Application.routes.draw do
namespace :admin do namespace :admin do
match 'users/edit' => 'users#edit', :via => :get resources :users, :only => [:get, :put, :destroy]
match 'users' => 'users#update', :via => :put end
namespace :moderator do
resource :dashboard, :only => [:show]
resources :ip_addrs, :only => [:index] do
collection do
get :search
end
end
end end
resources :advertisements do resources :advertisements do
resources :hits, :controller => "advertisement_hits", :only => [:create] resources :hits, :controller => "advertisement_hits", :only => [:create]

View File

@@ -3573,6 +3573,7 @@ CREATE TABLE janitor_trials (
id integer NOT NULL, id integer NOT NULL,
creator_id integer NOT NULL, creator_id integer NOT NULL,
user_id integer NOT NULL, user_id integer NOT NULL,
original_level integer NOT NULL,
created_at timestamp without time zone, created_at timestamp without time zone,
updated_at timestamp without time zone updated_at timestamp without time zone
); );
@@ -3604,6 +3605,7 @@ ALTER SEQUENCE janitor_trials_id_seq OWNED BY janitor_trials.id;
CREATE TABLE note_versions ( CREATE TABLE note_versions (
id integer NOT NULL, id integer NOT NULL,
note_id integer NOT NULL, note_id integer NOT NULL,
post_id integer NOT NULL,
updater_id integer NOT NULL, updater_id integer NOT NULL,
updater_ip_addr inet NOT NULL, updater_ip_addr inet NOT NULL,
x integer NOT NULL, x integer NOT NULL,
@@ -3936,9 +3938,9 @@ CREATE TABLE posts (
is_pending boolean DEFAULT false NOT NULL, is_pending boolean DEFAULT false NOT NULL,
is_flagged boolean DEFAULT false NOT NULL, is_flagged boolean DEFAULT false NOT NULL,
is_deleted boolean DEFAULT false NOT NULL, is_deleted boolean DEFAULT false NOT NULL,
uploader_string character varying(255) NOT NULL, uploader_id integer NOT NULL,
uploader_ip_addr inet NOT NULL, uploader_ip_addr inet NOT NULL,
approver_string character varying(255) DEFAULT ''::character varying NOT NULL, approver_id integer,
fav_string text DEFAULT ''::text NOT NULL, fav_string text DEFAULT ''::text NOT NULL,
pool_string text DEFAULT ''::text NOT NULL, pool_string text DEFAULT ''::text NOT NULL,
last_noted_at timestamp without time zone, last_noted_at timestamp without time zone,
@@ -4214,11 +4216,7 @@ CREATE TABLE users (
email_verification_key character varying(255), email_verification_key character varying(255),
inviter_id integer, inviter_id integer,
is_banned boolean DEFAULT false NOT NULL, is_banned boolean DEFAULT false NOT NULL,
is_privileged boolean DEFAULT false NOT NULL, level integer DEFAULT 0 NOT NULL,
is_contributor boolean DEFAULT false NOT NULL,
is_janitor boolean DEFAULT false NOT NULL,
is_moderator boolean DEFAULT false NOT NULL,
is_admin boolean DEFAULT false NOT NULL,
base_upload_limit integer DEFAULT 10 NOT NULL, base_upload_limit integer DEFAULT 10 NOT NULL,
last_logged_in_at timestamp without time zone, last_logged_in_at timestamp without time zone,
last_forum_read_at timestamp without time zone, last_forum_read_at timestamp without time zone,
@@ -7922,6 +7920,13 @@ CREATE INDEX index_janitor_trials_on_user_id ON janitor_trials USING btree (user
CREATE INDEX index_note_versions_on_note_id ON note_versions USING btree (note_id); CREATE INDEX index_note_versions_on_note_id ON note_versions USING btree (note_id);
--
-- Name: index_note_versions_on_post_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
CREATE INDEX index_note_versions_on_post_id ON note_versions USING btree (post_id);
-- --
-- Name: index_note_versions_on_updater_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- Name: index_note_versions_on_updater_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
-- --
@@ -8304,7 +8309,7 @@ CREATE TRIGGER trigger_notes_on_update
CREATE TRIGGER trigger_posts_on_tag_index_update CREATE TRIGGER trigger_posts_on_tag_index_update
BEFORE INSERT OR UPDATE ON posts BEFORE INSERT OR UPDATE ON posts
FOR EACH ROW FOR EACH ROW
EXECUTE PROCEDURE tsvector_update_trigger('tag_index', 'public.danbooru', 'tag_string', 'fav_string', 'pool_string', 'uploader_string', 'approver_string'); EXECUTE PROCEDURE tsvector_update_trigger('tag_index', 'public.danbooru', 'tag_string', 'fav_string', 'pool_string');
-- --

View File

@@ -18,11 +18,11 @@ class CreatePosts < ActiveRecord::Migration
t.column :is_deleted, :boolean, :null => false, :default => false t.column :is_deleted, :boolean, :null => false, :default => false
# Uploader # Uploader
t.column :uploader_string, :string, :null => false t.column :uploader_id, :integer, :null => false
t.column :uploader_ip_addr, "inet", :null => false t.column :uploader_ip_addr, "inet", :null => false
# Approver # Approver
t.column :approver_string, :string, :null => false, :default => "" t.column :approver_id, :integer
# Favorites # Favorites
t.column :fav_string, :text, :null => false, :default => "" t.column :fav_string, :text, :null => false, :default => ""
@@ -101,7 +101,7 @@ class CreatePosts < ActiveRecord::Migration
execute "CREATE TEXT SEARCH CONFIGURATION public.danbooru (PARSER = public.testparser)" execute "CREATE TEXT SEARCH CONFIGURATION public.danbooru (PARSER = public.testparser)"
execute "ALTER TEXT SEARCH CONFIGURATION public.danbooru ADD MAPPING FOR WORD WITH SIMPLE" execute "ALTER TEXT SEARCH CONFIGURATION public.danbooru ADD MAPPING FOR WORD WITH SIMPLE"
execute "SET default_text_search_config = 'public.danbooru'" execute "SET default_text_search_config = 'public.danbooru'"
execute "CREATE TRIGGER trigger_posts_on_tag_index_update BEFORE INSERT OR UPDATE ON posts FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('tag_index', 'public.danbooru', 'tag_string', 'fav_string', 'pool_string', 'uploader_string', 'approver_string')" execute "CREATE TRIGGER trigger_posts_on_tag_index_update BEFORE INSERT OR UPDATE ON posts FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('tag_index', 'public.danbooru', 'tag_string', 'fav_string', 'pool_string')"
end end
def self.down def self.down

View File

@@ -3,6 +3,7 @@ class CreateJanitorTrials < ActiveRecord::Migration
create_table :janitor_trials do |t| create_table :janitor_trials do |t|
t.column :creator_id, :integer, :null => false t.column :creator_id, :integer, :null => false
t.column :user_id, :integer, :null => false t.column :user_id, :integer, :null => false
t.column :original_level, :integer, :null => false
t.timestamps t.timestamps
end end

View File

@@ -52,7 +52,7 @@ module Danbooru
page = [page.to_i, 1].max page = [page.to_i, 1].max
if page > Danbooru.config.max_numbered_pages if page > Danbooru.config.max_numbered_pages
raise "You cannot go beyond page #{Danbooru.config.max_numbered_pages}. Please narrow your search terms." raise PaginationError.new("You cannot go beyond page #{Danbooru.config.max_numbered_pages}. Please narrow your search terms.")
end end
limit(records_per_page).offset((page - 1) * records_per_page).tap do |obj| limit(records_per_page).offset((page - 1) * records_per_page).tap do |obj|

View File

@@ -0,0 +1,6 @@
module Danbooru
module Paginator
class PaginationError < Exception
end
end
end

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
psql -c "UPDATE posts SET is_flagged = false, is_pending = true, approver_string = '' WHERE id = 1" danbooru2 psql -c "UPDATE posts SET is_flagged = false, is_pending = true, approver_id = null WHERE id = 1" danbooru2
psql -c "DELETE FROM unapprovals" danbooru2 psql -c "DELETE FROM unapprovals" danbooru2

View File

@@ -2,7 +2,7 @@ require 'fileutils'
Factory.define(:upload) do |f| Factory.define(:upload) do |f|
f.rating "s" f.rating "s"
f.uploader {|x| x.association(:user, :is_contributor => true)} f.uploader {|x| x.association(:user, :level => 200)}
f.uploader_ip_addr "127.0.0.1" f.uploader_ip_addr "127.0.0.1"
f.tag_string "special" f.tag_string "special"
f.status "pending" f.status "pending"

View File

@@ -13,21 +13,21 @@ Factory.define(:banned_user, :parent => :user) do |f|
end end
Factory.define(:privileged_user, :parent => :user) do |f| Factory.define(:privileged_user, :parent => :user) do |f|
f.is_privileged true f.level 100
end end
Factory.define(:contributor_user, :parent => :user) do |f| Factory.define(:contributor_user, :parent => :user) do |f|
f.is_contributor true f.level 200
end end
Factory.define(:janitor_user, :parent => :user) do |f| Factory.define(:janitor_user, :parent => :user) do |f|
f.is_janitor true f.level 300
end end
Factory.define(:moderator_user, :parent => :user) do |f| Factory.define(:moderator_user, :parent => :user) do |f|
f.is_moderator true f.level 400
end end
Factory.define(:admin_user, :parent => :user) do |f| Factory.define(:admin_user, :parent => :user) do |f|
f.is_admin true f.level 500
end end

View File

@@ -25,16 +25,11 @@ module PostSets
context "a favorite set for before the most recent post" do context "a favorite set for before the most recent post" do
setup do setup do
id = ::Favorite.model_for(@user.id).where(:user_id => @user.id, :post_id => @post_3.id).first.id id = ::Favorite.model_for(@user.id).where(:user_id => @user.id, :post_id => @post_3.id).first.id
@set = PostSets::Base.new(:id => @user.id, :before_id => id) ::Favorite.model_for(@user.id).stubs(:records_per_page).returns(1)
@set.stubs(:limit).returns(1) @set = PostSets::Favorite.new(@user.id, "b#{id}")
@set.extend(PostSets::Favorite)
end end
context "a sequential paginator" do context "a sequential paginator" do
setup do
@set.extend(PostSets::Sequential)
end
should "return the second most recent element" do should "return the second most recent element" do
assert_equal(1, @set.posts.size) assert_equal(1, @set.posts.size)
assert_equal(@post_1.id, @set.posts.first.id) assert_equal(@post_1.id, @set.posts.first.id)
@@ -45,35 +40,25 @@ module PostSets
context "a favorite set for after the second most recent post" do context "a favorite set for after the second most recent post" do
setup do setup do
id = ::Favorite.model_for(@user.id).where(:user_id => @user.id, :post_id => @post_2.id).first.id id = ::Favorite.model_for(@user.id).where(:user_id => @user.id, :post_id => @post_2.id).first.id
@set = PostSets::Base.new(:id => @user.id, :after_id => id) ::Favorite.model_for(@user.id).stubs(:records_per_page).returns(1)
@set.stubs(:limit).returns(1) @set = PostSets::Favorite.new(@user.id, "a#{id}")
@set.extend(PostSets::Favorite)
end end
context "a sequential paginator" do context "a sequential paginator" do
setup do
@set.extend(PostSets::Sequential)
end
should "return the most recent element" do should "return the most recent element" do
assert_equal(1, @set.posts.size) assert_equal(1, @set.posts.size)
assert_equal(@post_3.id, @set.posts.first.id) assert_equal(@post_1.id, @set.posts.first.id)
end end
end end
end end
context "a favorite set for page 2" do context "a favorite set for page 2" do
setup do setup do
@set = PostSets::Base.new(:id => @user.id, :page => 2) ::Favorite.model_for(@user.id).stubs(:records_per_page).returns(1)
@set.stubs(:limit).returns(1) @set = PostSets::Favorite.new(@user.id, 2)
@set.extend(PostSets::Favorite)
end end
context "a numbered paginator" do context "a numbered paginator" do
setup do
@set.extend(PostSets::Numbered)
end
should "return the second most recent element" do should "return the second most recent element" do
assert_equal(1, @set.posts.size) assert_equal(1, @set.posts.size)
assert_equal(@post_1.id, @set.posts.first.id) assert_equal(@post_1.id, @set.posts.first.id)
@@ -83,32 +68,13 @@ module PostSets
context "a favorite set with no page specified" do context "a favorite set with no page specified" do
setup do setup do
@set = PostSets::Base.new(:id => @user.id) ::Favorite.model_for(@user.id).stubs(:records_per_page).returns(1)
@set.stubs(:limit).returns(1) @set = PostSets::Favorite.new(@user.id)
@set.extend(PostSets::Favorite)
end end
context "a numbered paginator" do should "return the most recent element" do
setup do assert_equal(1, @set.posts.size)
@set.extend(PostSets::Numbered) assert_equal(@post_3.id, @set.posts.first.id)
end
should "return the most recent element" do
assert_equal(3, @set.count)
assert_equal(1, @set.posts.size)
assert_equal(@post_3.id, @set.posts.first.id)
end
end
context "a sequential paginator" do
setup do
@set.extend(PostSets::Sequential)
end
should "return the most recent element" do
assert_equal(1, @set.posts.size)
assert_equal(@post_3.id, @set.posts.first.id)
end
end end
end end
end end

View File

@@ -25,40 +25,33 @@ module PostSets
context "a post pool set for page 2" do context "a post pool set for page 2" do
setup do setup do
@set = PostSets::Base.new(:id => @pool.id, :page => 2) @set = PostSets::Pool.new(@pool, 2)
@set.stubs(:limit).returns(1) @set.stubs(:limit).returns(1)
@set.extend(PostSets::Pool)
end end
context "a numbered paginator" do should "return the second element" do
setup do assert_equal(1, @set.posts.size)
@set.extend(PostSets::Numbered) assert_equal(@post_1.id, @set.posts.first.id)
end end
should "return the second element" do should "know the total number of pages" do
assert_equal(1, @set.posts.size) assert_equal(3, @set.total_pages)
assert_equal(@post_1.id, @set.posts.first.id) end
end
should "know the current page" do
assert_equal(2, @set.current_page)
end end
end end
context "a post pool set with no page specified" do context "a post pool set with no page specified" do
setup do setup do
@set = PostSets::Base.new(:id => @pool.id) @set = PostSets::Pool.new(@pool)
@set.stubs(:limit).returns(1) @set.stubs(:limit).returns(1)
@set.extend(PostSets::Pool)
end end
context "a numbered paginator" do should "return the first element" do
setup do assert_equal(1, @set.posts.size)
@set.extend(PostSets::Numbered) assert_equal(@post_2.id, @set.posts.first.id)
end
should "return the first element" do
assert_equal(3, @set.count)
assert_equal(1, @set.posts.size)
assert_equal(@post_2.id, @set.posts.first.id)
end
end end
end end
end end

View File

@@ -1,4 +1,5 @@
require_relative '../../test_helper' require_relative '../../test_helper'
require "danbooru/paginator/pagination_error"
module PostSets module PostSets
class PostTest < ActiveSupport::TestCase class PostTest < ActiveSupport::TestCase
@@ -19,12 +20,10 @@ module PostSets
CurrentUser.ip_addr = nil CurrentUser.ip_addr = nil
end end
context "a numbered set for page 2" do context "a set for page 2" do
setup do setup do
@set = PostSets::Base.new(:page => 2) @set = PostSets::Post.new("", 2)
@set.extend(PostSets::Sequential) ::Post.stubs(:records_per_page).returns(1)
@set.extend(PostSets::Post)
@set.stubs(:limit).returns(1)
end end
should "return the second element" do should "return the second element" do
@@ -32,18 +31,16 @@ module PostSets
end end
end end
context "a sequential set for the 'a' tag query" do context "a set for the 'a' tag query" do
setup do setup do
@post_4 = Factory.create(:post, :tag_string => "a") @post_4 = Factory.create(:post, :tag_string => "a")
@post_5 = Factory.create(:post, :tag_string => "a") @post_5 = Factory.create(:post, :tag_string => "a")
end end
context "with no before_id parameter" do context "with no page" do
setup do setup do
@set = PostSets::Base.new(:tags => "a") @set = PostSets::Post.new("a")
@set.extend(PostSets::Sequential) ::Post.stubs(:records_per_page).returns(1)
@set.extend(PostSets::Post)
@set.stubs(:limit).returns(1)
end end
should "return the first element" do should "return the first element" do
@@ -51,12 +48,10 @@ module PostSets
end end
end end
context "with a before_id parameter for the first element" do context "for before the first element" do
setup do setup do
@set = PostSets::Base.new(:tags => "a", :before_id => @post_5.id) @set = PostSets::Post.new("a", "b#{@post_5.id}")
@set.extend(PostSets::Sequential) ::Post.stubs(:records_per_page).returns(1)
@set.extend(PostSets::Post)
@set.stubs(:limit).returns(1)
end end
should "return the second element" do should "return the second element" do
@@ -64,12 +59,10 @@ module PostSets
end end
end end
context "with an after_id parameter for the second element" do context "for after the second element" do
setup do setup do
@set = PostSets::Base.new(:tags => "a", :after_id => @post_4.id) @set = PostSets::Post.new("a", "a#{@post_4.id}")
@set.extend(PostSets::Sequential) @set.stubs(:records_per_page).returns(1)
@set.extend(PostSets::Post)
@set.stubs(:limit).returns(1)
end end
should "return the first element" do should "return the first element" do
@@ -78,11 +71,9 @@ module PostSets
end end
end end
context "a new numbered set for the 'a b' tag query" do context "a set for the 'a b' tag query" do
setup do setup do
@set = PostSets::Base.new(:tags => "a b") @set = PostSets::Post.new("a b")
@set.extend(PostSets::Numbered)
@set.extend(PostSets::Post)
end end
should "know it isn't a single tag" do should "know it isn't a single tag" do
@@ -90,31 +81,27 @@ module PostSets
end end
end end
context "a new numbered set going to the 1,001st page" do context "a set going to the 1,001st page" do
setup do setup do
@set = PostSets::Base.new(:tags => "a", :page => 1_001) @set = PostSets::Post.new("a", 1_001)
@set.extend(PostSets::Numbered)
@set.extend(PostSets::Post)
end end
should "not validate" do should "fail" do
assert_raises(PostSets::Error) do assert_raises(Danbooru::Paginator::PaginationError) do
@set.validate @set.posts
end end
end end
end end
context "a new numbered set for the 'a b c' tag query" do context "a set for the 'a b c' tag query" do
setup do setup do
@set = PostSets::Base.new(:tags => "a b c") @set = PostSets::Post.new("a b c")
@set.extend(PostSets::Numbered)
@set.extend(PostSets::Post)
end end
context "for a non-privileged user" do context "for a non-privileged user" do
should "not validate" do should "fail" do
assert_raises(PostSets::Error) do assert_raises(PostSets::SearchError) do
@set.validate @set.posts
end end
end end
end end
@@ -124,25 +111,17 @@ module PostSets
CurrentUser.user = Factory.create(:privileged_user) CurrentUser.user = Factory.create(:privileged_user)
end end
should "not validate" do should "pass" do
assert_nothing_raised do assert_nothing_raised do
@set.validate @set.posts
end end
end end
end end
end end
context "a new numbered set for the 'a' tag query" do context "a set for the 'a' tag query" do
setup do setup do
@set = PostSets::Base.new(:tags => "A") @set = PostSets::Post.new("a")
@set.extend(PostSets::Numbered)
@set.extend(PostSets::Post)
end
should "validate" do
assert_nothing_raised do
@set.validate
end
end end
should "know it is a single tag" do should "know it is a single tag" do
@@ -153,8 +132,8 @@ module PostSets
assert_equal("a", @set.tag_string) assert_equal("a", @set.tag_string)
end end
should "find the count" do should "know the count" do
assert_equal(1, @set.count) assert_equal(1, @set.posts.total_count)
end end
should "find the posts" do should "find the posts" do

View File

@@ -1,73 +0,0 @@
require 'test_helper'
module PostSets
class WikiPageTest < ActiveSupport::TestCase
context "In all cases" do
setup do
@user = Factory.create(:user)
CurrentUser.user = @user
CurrentUser.ip_addr = "127.0.0.1"
MEMCACHE.flush_all
@wiki_page = Factory.create(:wiki_page, :title => "a")
@post_1 = Factory.create(:post, :tag_string => "a")
@post_2 = Factory.create(:post, :tag_string => "a")
@post_3 = Factory.create(:post, :tag_string => "a")
end
context "a numbered wiki page set" do
setup do
@set = PostSets::Base.new(:page => 2, :id => @wiki_page.id)
@set.extend(PostSets::Numbered)
@set.extend(PostSets::WikiPage)
@set.stubs(:limit).returns(1)
end
should "return the count" do
assert_equal(3, @set.count)
end
end
context "a sequential wiki page set" do
context "with a before_id for the first element" do
setup do
@set = PostSets::Base.new(:id => @wiki_page.id, :before_id => @post_3.id)
@set.extend(PostSets::Sequential)
@set.extend(PostSets::WikiPage)
@set.stubs(:limit).returns(1)
end
should "return the second element" do
assert_equal(@post_2.id, @set.posts.first.id)
end
end
context "with an after_id for the second element" do
setup do
@set = PostSets::Base.new(:after_id => @post_2.id, :id => @wiki_page.id)
@set.extend(PostSets::Sequential)
@set.extend(PostSets::WikiPage)
@set.stubs(:limit).returns(1)
end
should "return the first element" do
assert_equal(@post_3.id, @set.posts.first.id)
end
end
end
context "a numbered wiki page set for page 2" do
setup do
@set = PostSets::Base.new(:page => 2, :id => @wiki_page.id)
@set.extend(PostSets::Numbered)
@set.extend(PostSets::WikiPage)
@set.stubs(:limit).returns(1)
end
should "return the second element" do
assert_equal(@post_2.id, @set.posts.first.id)
end
end
end
end
end

View File

@@ -178,13 +178,13 @@ class PostTest < ActiveSupport::TestCase
should "preserve the approver's identity when approved" do should "preserve the approver's identity when approved" do
post = Factory.create(:post, :is_pending => true) post = Factory.create(:post, :is_pending => true)
post.approve! post.approve!
assert_equal("approver:#{CurrentUser.name}", post.approver_string) assert_equal(post.approver_id, CurrentUser.id)
end end
context "that was previously approved by person X" do context "that was previously approved by person X" do
should "not allow person X to reapprove that post" do should "not allow person X to reapprove that post" do
user = Factory.create(:janitor_user, :name => "xxx") user = Factory.create(:janitor_user, :name => "xxx")
post = Factory.create(:post, :approver_string => "approver:xxx") post = Factory.create(:post, :approver_id => user.id)
post.flag!("bad") post.flag!("bad")
CurrentUser.scoped(user, "127.0.0.1") do CurrentUser.scoped(user, "127.0.0.1") do
assert_raises(Post::ApprovalError) do assert_raises(Post::ApprovalError) do
@@ -396,10 +396,10 @@ class PostTest < ActiveSupport::TestCase
user3 = Factory.create(:user) user3 = Factory.create(:user)
post.uploader = user1 post.uploader = user1
assert_equal("uploader:#{user1.id}", post.uploader_string) assert_equal(user1.id, post.uploader_id)
post.uploader_id = user2.id post.uploader_id = user2.id
assert_equal("uploader:#{user2.id}", post.uploader_string) assert_equal(user2.id, post.uploader_id)
assert_equal(user2.id, post.uploader_id) assert_equal(user2.id, post.uploader_id)
assert_equal(user2.name, post.uploader_name) assert_equal(user2.name, post.uploader_name)
end end
@@ -493,13 +493,15 @@ class PostTest < ActiveSupport::TestCase
should "return posts for the <uploader> metatag" do should "return posts for the <uploader> metatag" do
second_user = Factory.create(:user) second_user = Factory.create(:user)
post1 = Factory.create(:post) post1 = Factory.create(:post, :uploader => CurrentUser.user)
assert_equal(CurrentUser.id, post1.uploader_id)
CurrentUser.scoped(second_user, "127.0.0.2") do CurrentUser.scoped(second_user, "127.0.0.2") do
post2 = Factory.create(:post) post2 = Factory.create(:post)
post3 = Factory.create(:post) post3 = Factory.create(:post)
end end
relation = Post.tag_match("uploader:#{CurrentUser.user.name}") relation = Post.tag_match("uploader:#{CurrentUser.user.name}")
assert_equal(1, relation.count) assert_equal(1, relation.count)
assert_equal(post1.id, relation.first.id) assert_equal(post1.id, relation.first.id)

View File

@@ -67,7 +67,7 @@ class TagAliasTest < ActiveSupport::TestCase
end end
ta1 = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "xxx") ta1 = Factory.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "xxx")
p1.reload p1.reload
assert_not_equal("uploader:#{ta1.creator_id}", p1.uploader_string) assert_not_equal(ta1.creator_id, p1.uploader_id)
assert_equal(ta1.creator_id, p1.versions.last.updater_id) assert_equal(ta1.creator_id, p1.versions.last.updater_id)
end end
end end

View File

@@ -113,7 +113,7 @@ class TagImplicationTest < ActiveSupport::TestCase
end end
ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "xxx") ti1 = Factory.create(:tag_implication, :antecedent_name => "aaa", :consequent_name => "xxx")
p1.reload p1.reload
assert_not_equal("uploader:#{ti1.creator_id}", p1.uploader_string) assert_not_equal(ti1.creator_id, p1.uploader_id)
assert_equal(ti1.creator_id, p1.versions.last.updater_id) assert_equal(ti1.creator_id, p1.versions.last.updater_id)
end end
end end

View File

@@ -1,181 +1,183 @@
require_relative '../test_helper' require_relative '../test_helper'
class UploadTest < ActiveSupport::TestCase class UploadTest < ActiveSupport::TestCase
setup do context "In all cases" do
user = Factory.create(:contributor_user) setup do
CurrentUser.user = user user = Factory.create(:contributor_user)
CurrentUser.ip_addr = "127.0.0.1" CurrentUser.user = user
MEMCACHE.flush_all CurrentUser.ip_addr = "127.0.0.1"
end MEMCACHE.flush_all
end
teardown do
CurrentUser.user = nil
CurrentUser.ip_addr = nil
@upload.delete_temp_file if @upload
end
context "An upload" do
teardown do teardown do
FileUtils.rm_f(Dir.glob("#{Rails.root}/tmp/test.*")) CurrentUser.user = nil
CurrentUser.ip_addr = nil
@upload.delete_temp_file if @upload
end end
context "image size calculator" do context "An upload" do
should "discover the dimensions for a JPG" do
@upload = Factory.create(:jpg_upload)
assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)}
assert_equal(500, @upload.image_width)
assert_equal(335, @upload.image_height)
end
should "discover the dimensions for a PNG" do
@upload = Factory.create(:png_upload)
assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)}
assert_equal(768, @upload.image_width)
assert_equal(1024, @upload.image_height)
end
should "discover the dimensions for a GIF" do
@upload = Factory.create(:gif_upload)
assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)}
assert_equal(400, @upload.image_width)
assert_equal(400, @upload.image_height)
end
end
context "content type calculator" do
should "know how to parse jpeg, png, gif, and swf file extensions" do
@upload = Factory.create(:jpg_upload)
assert_equal("image/jpeg", @upload.file_ext_to_content_type("test.jpeg"))
assert_equal("image/gif", @upload.file_ext_to_content_type("test.gif"))
assert_equal("image/png", @upload.file_ext_to_content_type("test.png"))
assert_equal("application/x-shockwave-flash", @upload.file_ext_to_content_type("test.swf"))
assert_equal("application/octet-stream", @upload.file_ext_to_content_type(""))
end
should "know how to parse jpeg, png, gif, and swf content types" do
@upload = Factory.create(:jpg_upload)
assert_equal("jpg", @upload.content_type_to_file_ext("image/jpeg"))
assert_equal("gif", @upload.content_type_to_file_ext("image/gif"))
assert_equal("png", @upload.content_type_to_file_ext("image/png"))
assert_equal("swf", @upload.content_type_to_file_ext("application/x-shockwave-flash"))
assert_equal("bin", @upload.content_type_to_file_ext(""))
end
end
context "downloader" do
should "initialize the final path and content type after downloading a file" do
@upload = Factory.create(:source_upload)
path = "#{Rails.root}/tmp/test.download.jpg"
assert_nothing_raised {@upload.download_from_source(path)}
assert(File.exists?(path))
assert_equal(8558, File.size(path))
assert_equal("image/gif", @upload.content_type)
assert_equal(path, @upload.file_path)
assert_equal("gif", @upload.file_ext)
end
end
context "file processor" do
should "parse and process a cgi file representation" do
FileUtils.cp("#{Rails.root}/test/files/test.jpg", "#{Rails.root}/tmp")
@upload = Upload.new(:file => upload_jpeg("#{Rails.root}/tmp/test.jpg"))
assert_nothing_raised {@upload.convert_cgi_file}
assert_equal("image/jpeg", @upload.content_type)
assert(File.exists?(@upload.file_path))
assert_equal(28086, File.size(@upload.file_path))
assert_equal("jpg", @upload.file_ext)
end
end
context "hash calculator" do
should "caculate the hash" do
@upload = Factory.create(:jpg_upload)
@upload.calculate_hash(@upload.file_path)
assert_equal("ecef68c44edb8a0d6a3070b5f8e8ee76", @upload.md5)
end
end
context "resizer" do
teardown do teardown do
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/thumb/test.*.jpg")) FileUtils.rm_f(Dir.glob("#{Rails.root}/tmp/test.*"))
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/medium/test.*.jpg"))
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/large/test.*.jpg"))
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/original/test.*.jpg"))
end end
should "generate several resized versions of the image" do context "image size calculator" do
@upload = Factory.create(:large_jpg_upload) should "discover the dimensions for a JPG" do
@upload.calculate_hash(@upload.file_path) @upload = Factory.create(:jpg_upload)
@upload.calculate_dimensions(@upload.file_path) assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)}
assert_nothing_raised {@upload.generate_resizes(@upload.file_path)} assert_equal(500, @upload.image_width)
assert(File.exists?(@upload.resized_file_path_for(Danbooru.config.small_image_width))) assert_equal(335, @upload.image_height)
assert_equal(6556, File.size(@upload.resized_file_path_for(Danbooru.config.small_image_width))) end
assert(File.exists?(@upload.resized_file_path_for(Danbooru.config.medium_image_width)))
assert_equal(39411, File.size(@upload.resized_file_path_for(Danbooru.config.medium_image_width))) should "discover the dimensions for a PNG" do
assert(File.exists?(@upload.resized_file_path_for(Danbooru.config.large_image_width))) @upload = Factory.create(:png_upload)
assert_equal(179324, File.size(@upload.resized_file_path_for(Danbooru.config.large_image_width))) assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)}
assert_equal(768, @upload.image_width)
assert_equal(1024, @upload.image_height)
end
should "discover the dimensions for a GIF" do
@upload = Factory.create(:gif_upload)
assert_nothing_raised {@upload.calculate_dimensions(@upload.file_path)}
assert_equal(400, @upload.image_width)
assert_equal(400, @upload.image_height)
end
end
context "content type calculator" do
should "know how to parse jpeg, png, gif, and swf file extensions" do
@upload = Factory.create(:jpg_upload)
assert_equal("image/jpeg", @upload.file_ext_to_content_type("test.jpeg"))
assert_equal("image/gif", @upload.file_ext_to_content_type("test.gif"))
assert_equal("image/png", @upload.file_ext_to_content_type("test.png"))
assert_equal("application/x-shockwave-flash", @upload.file_ext_to_content_type("test.swf"))
assert_equal("application/octet-stream", @upload.file_ext_to_content_type(""))
end
should "know how to parse jpeg, png, gif, and swf content types" do
@upload = Factory.create(:jpg_upload)
assert_equal("jpg", @upload.content_type_to_file_ext("image/jpeg"))
assert_equal("gif", @upload.content_type_to_file_ext("image/gif"))
assert_equal("png", @upload.content_type_to_file_ext("image/png"))
assert_equal("swf", @upload.content_type_to_file_ext("application/x-shockwave-flash"))
assert_equal("bin", @upload.content_type_to_file_ext(""))
end
end
context "downloader" do
should "initialize the final path and content type after downloading a file" do
@upload = Factory.create(:source_upload)
path = "#{Rails.root}/tmp/test.download.jpg"
assert_nothing_raised {@upload.download_from_source(path)}
assert(File.exists?(path))
assert_equal(8558, File.size(path))
assert_equal("image/gif", @upload.content_type)
assert_equal(path, @upload.file_path)
assert_equal("gif", @upload.file_ext)
end
end
context "file processor" do
should "parse and process a cgi file representation" do
FileUtils.cp("#{Rails.root}/test/files/test.jpg", "#{Rails.root}/tmp")
@upload = Upload.new(:file => upload_jpeg("#{Rails.root}/tmp/test.jpg"))
assert_nothing_raised {@upload.convert_cgi_file}
assert_equal("image/jpeg", @upload.content_type)
assert(File.exists?(@upload.file_path))
assert_equal(28086, File.size(@upload.file_path))
assert_equal("jpg", @upload.file_ext)
end
end
context "hash calculator" do
should "caculate the hash" do
@upload = Factory.create(:jpg_upload)
@upload.calculate_hash(@upload.file_path)
assert_equal("ecef68c44edb8a0d6a3070b5f8e8ee76", @upload.md5)
end
end
context "resizer" do
teardown do
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/thumb/test.*.jpg"))
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/medium/test.*.jpg"))
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/large/test.*.jpg"))
FileUtils.rm_f(Dir.glob("#{Rails.root}/public/data/original/test.*.jpg"))
end
should "generate several resized versions of the image" do
@upload = Factory.create(:large_jpg_upload)
@upload.calculate_hash(@upload.file_path)
@upload.calculate_dimensions(@upload.file_path)
assert_nothing_raised {@upload.generate_resizes(@upload.file_path)}
assert(File.exists?(@upload.resized_file_path_for(Danbooru.config.small_image_width)))
assert_equal(6556, File.size(@upload.resized_file_path_for(Danbooru.config.small_image_width)))
assert(File.exists?(@upload.resized_file_path_for(Danbooru.config.medium_image_width)))
assert_equal(39411, File.size(@upload.resized_file_path_for(Danbooru.config.medium_image_width)))
assert(File.exists?(@upload.resized_file_path_for(Danbooru.config.large_image_width)))
assert_equal(179324, File.size(@upload.resized_file_path_for(Danbooru.config.large_image_width)))
end
end
should "process completely for a downloaded image" do
@upload = Factory.create(:source_upload,
:rating => "s",
:uploader_ip_addr => "127.0.0.1",
:tag_string => "hoge foo"
)
assert_difference("Post.count") do
assert_nothing_raised {@upload.process!}
end
post = Post.last
assert_equal("hoge foo", post.tag_string)
assert_equal("s", post.rating)
assert_equal(@upload.uploader_id, post.uploader_id)
assert_equal("127.0.0.1", post.uploader_ip_addr)
assert_equal(@upload.md5, post.md5)
assert_equal("gif", post.file_ext)
assert_equal(276, post.image_width)
assert_equal(110, post.image_height)
assert_equal(8558, post.file_size)
assert_equal(post.id, @upload.post_id)
assert_equal("completed", @upload.status)
end end
end end
should "process completely for a downloaded image" do should "process completely for an uploaded image" do
@upload = Factory.create(:source_upload, @upload = Factory.create(:jpg_upload,
:rating => "s", :rating => "s",
:uploader_ip_addr => "127.0.0.1", :uploader_ip_addr => "127.0.0.1",
:tag_string => "hoge foo" :tag_string => "hoge foo"
) )
@upload.file = upload_jpeg("#{Rails.root}/test/files/test.jpg")
@upload.convert_cgi_file
assert_difference("Post.count") do assert_difference("Post.count") do
assert_nothing_raised {@upload.process!} assert_nothing_raised {@upload.process!}
end end
post = Post.last post = Post.last
assert_equal("hoge foo", post.tag_string) assert_equal("hoge foo", post.tag_string)
assert_equal("s", post.rating) assert_equal("s", post.rating)
assert_equal(@upload.uploader_id, post.uploader_id) assert_equal(@upload.uploader_id, post.uploader_id)
assert_equal("127.0.0.1", post.uploader_ip_addr) assert_equal("127.0.0.1", post.uploader_ip_addr)
assert_equal(@upload.md5, post.md5) assert_equal(@upload.md5, post.md5)
assert_equal("gif", post.file_ext) assert_equal("jpg", post.file_ext)
assert_equal(276, post.image_width) assert(File.exists?(post.file_path))
assert_equal(110, post.image_height) assert_equal(28086, File.size(post.file_path))
assert_equal(8558, post.file_size)
assert_equal(post.id, @upload.post_id) assert_equal(post.id, @upload.post_id)
assert_equal("completed", @upload.status) assert_equal("completed", @upload.status)
end end
end
should "process completely for an uploaded image" do
@upload = Factory.create(:jpg_upload,
:rating => "s",
:uploader_ip_addr => "127.0.0.1",
:tag_string => "hoge foo"
)
@upload.file = upload_jpeg("#{Rails.root}/test/files/test.jpg")
@upload.convert_cgi_file
assert_difference("Post.count") do should "delete the temporary file upon completion" do
assert_nothing_raised {@upload.process!} @upload = Factory.create(:source_upload,
:rating => "s",
:uploader_ip_addr => "127.0.0.1",
:tag_string => "hoge foo"
)
@upload.process!
assert(!File.exists?(@upload.temp_file_path))
end end
post = Post.last
assert_equal("hoge foo", post.tag_string)
assert_equal("s", post.rating)
assert_equal(@upload.uploader_id, post.uploader_id)
assert_equal("127.0.0.1", post.uploader_ip_addr)
assert_equal(@upload.md5, post.md5)
assert_equal("jpg", post.file_ext)
assert(File.exists?(post.file_path))
assert_equal(28086, File.size(post.file_path))
assert_equal(post.id, @upload.post_id)
assert_equal("completed", @upload.status)
end
should "delete the temporary file upon completion" do
@upload = Factory.create(:source_upload,
:rating => "s",
:uploader_ip_addr => "127.0.0.1",
:tag_string => "hoge foo"
)
@upload.process!
assert(!File.exists?(@upload.temp_file_path))
end end
end end

View File

@@ -24,9 +24,9 @@ class UserTest < ActiveSupport::TestCase
should "limit post uploads" do should "limit post uploads" do
assert(!@user.can_upload?) assert(!@user.can_upload?)
@user.update_attribute(:is_contributor, true) @user.update_column(:level, User::Levels::CONTRIBUTOR)
assert(@user.can_upload?) assert(@user.can_upload?)
@user.update_attribute(:is_contributor, false) @user.update_column(:level, User::Levels::MEMBER)
40.times do 40.times do
Factory.create(:post, :uploader => @user, :is_deleted => true) Factory.create(:post, :uploader => @user, :is_deleted => true)
@@ -49,10 +49,10 @@ class UserTest < ActiveSupport::TestCase
should "limit comments" do should "limit comments" do
assert(!@user.can_comment?) assert(!@user.can_comment?)
@user.update_attribute(:is_privileged, true) @user.update_column(:level, User::Levels::PRIVILEGED)
assert(@user.can_comment?) assert(@user.can_comment?)
@user.update_attribute(:is_privileged, false) @user.update_column(:level, User::Levels::MEMBER)
@user.update_attribute(:created_at, 1.year.ago) @user.update_column(:created_at, 1.year.ago)
assert(@user.can_comment?) assert(@user.can_comment?)
(Danbooru.config.member_comment_limit).times do (Danbooru.config.member_comment_limit).times do
Factory.create(:comment) Factory.create(:comment)
@@ -79,34 +79,34 @@ class UserTest < ActiveSupport::TestCase
end end
should "normalize its level" do should "normalize its level" do
user = Factory.create(:user, :is_admin => true) user = Factory.create(:user, :level => User::Levels::ADMIN)
assert(user.is_moderator?) assert(user.is_moderator?)
assert(user.is_janitor?) assert(user.is_janitor?)
assert(user.is_contributor?) assert(user.is_contributor?)
assert(user.is_privileged?) assert(user.is_privileged?)
user = Factory.create(:user, :is_moderator => true) user = Factory.create(:user, :level => User::Levels::MODERATOR)
assert(!user.is_admin?) assert(!user.is_admin?)
assert(user.is_moderator?) assert(user.is_moderator?)
assert(user.is_janitor?) assert(user.is_janitor?)
assert(!user.is_contributor?) assert(user.is_contributor?)
assert(user.is_privileged?) assert(user.is_privileged?)
user = Factory.create(:user, :is_janitor => true) user = Factory.create(:user, :level => User::Levels::JANITOR)
assert(!user.is_admin?) assert(!user.is_admin?)
assert(!user.is_moderator?) assert(!user.is_moderator?)
assert(user.is_janitor?) assert(user.is_janitor?)
assert(!user.is_contributor?) assert(!user.is_contributor?)
assert(user.is_privileged?) assert(user.is_privileged?)
user = Factory.create(:user, :is_contributor => true) user = Factory.create(:user, :level => User::Levels::CONTRIBUTOR)
assert(!user.is_admin?) assert(!user.is_admin?)
assert(!user.is_moderator?) assert(!user.is_moderator?)
assert(!user.is_janitor?) assert(!user.is_janitor?)
assert(user.is_contributor?) assert(user.is_contributor?)
assert(user.is_privileged?) assert(user.is_privileged?)
user = Factory.create(:user, :is_privileged => true) user = Factory.create(:user, :level => User::LEvels::PRIVILEGED)
assert(!user.is_admin?) assert(!user.is_admin?)
assert(!user.is_moderator?) assert(!user.is_moderator?)
assert(!user.is_janitor?) assert(!user.is_janitor?)
@@ -133,8 +133,8 @@ class UserTest < ActiveSupport::TestCase
should "be updated" do should "be updated" do
@user = Factory.create(:user) @user = Factory.create(:user)
@user.update_attribute(:name, "danzig") @user.update_column(:name, "danzig")
assert_equal("danzig", User.id_to_name(@user.id)) assert_equal(@user.name, User.id_to_name(@user.id))
end end
end end