added limit methods to user, more work on post views

This commit is contained in:
albert
2010-03-12 15:18:30 -05:00
parent 9f29ffc8c3
commit 9eb578927c
18 changed files with 282 additions and 108 deletions

View File

@@ -1,10 +1,54 @@
class UploadsController < ApplicationController class UploadsController < ApplicationController
def new def new
@upload = Upload.new
if params[:url]
@post = Post.find_by_source(params[:url])
end
end end
def show def show
end end
def create def create
unless @current_user.can_upload?
respond_to_error("Daily limit exceeded", {:controller => "user", :action => "upload_limit"}, :status => 421)
return
end
if @current_user.is_contributor_or_higher?
status = "active"
else
status = "pending"
end
begin
@post = Post.new(params[:post].merge(:updater_user_id => @current_user.id, :updater_ip_addr => request.remote_ip))
@post.user_id = @current_user.id
@post.status = status
@post.ip_addr = request.remote_ip
@post.save
rescue Errno::ENOENT
respond_to_error("Internal error. Try uploading again.", {:controller => "post", :action => "error"})
return
end
if @post.errors.empty?
if params[:md5] && @post.md5 != params[:md5].downcase
@post.destroy
respond_to_error("MD5 mismatch", {:action => "error"}, :status => 420)
else
respond_to_success("Post uploaded", {:controller => "post", :action => "show", :id => @post.id, :tag_title => @post.tag_title}, :api => {:post_id => @post.id, :location => url_for(:controller => "post", :action => "show", :id => @post.id)})
end
elsif @post.errors.invalid?(:md5)
p = Post.find_by_md5(@post.md5)
update = { :tags => p.cached_tags + " " + params[:post][:tags], :updater_user_id => session[:user_id], :updater_ip_addr => request.remote_ip }
update[:source] = @post.source if p.source.blank? && !@post.source.blank?
p.update_attributes(update)
respond_to_error("Post already exists", {:controller => "post", :action => "show", :id => p.id, :tag_title => @post.tag_title}, :api => {:location => url_for(:controller => "post", :action => "show", :id => p.id)}, :status => 423)
else
respond_to_error(@post, :action => "error")
end
end end
end end

View File

@@ -1,62 +1,28 @@
module ApplicationHelper module ApplicationHelper
def nav_link_to(text, url, html_options = nil) def nav_link_to(text, url, options = nil)
if url.include?(params[:controller]) || (%w(tag_alias tag_implication).include?(params[:controller]) && url =~ /\/tag/) if nav_link_match(params[:controller], url)
klass = "current-page" klass = "current"
else else
klass = nil klass = nil
end end
(%{<li class="#{klass}">} + link_to(text, url, html_options) + "</li>").html_safe content_tag("li", link_to(text, url, options), :class => klass)
end end
def format_text(text, options = {}) protected
DText.parse(text) def nav_link_match(controller, url)
end url =~ case controller
when "tag_aliases", "tag_implications"
/^\/tags/
def id_to_color(id) when "sessions", "user_maintenance"
r = id % 255 /^\/users/
g = (id >> 8) % 255
b = (id >> 16) % 255
"rgb(#{r}, #{g}, #{b})"
end
def tag_header(tags) when "forum_posts"
unless tags.blank? /^\/forum_topics/
'/' + Tag.scan_query(tags).map {|t| link_to(h(t.tr("_", " ")), posts_path(:tags => t))}.join("+")
end
end
def compact_time(time)
if time > Time.now.beginning_of_day
time.strftime("%H:%M")
elsif time > Time.now.beginning_of_year
time.strftime("%b %e")
else else
time.strftime("%b %e, %Y") /^\/#{controller}/
end end
end end
def print_preview(post, options = {})
unless Danbooru.config.can_see_post?(post, @current_user)
return ""
end
options = {:blacklist => true}.merge(options)
blacklist = options[:blacklist] ? "blacklisted" : ""
width, height = post.preview_dimensions
image_id = options[:image_id]
image_id = %{id="#{h(image_id)}"} if image_id
title = "#{h(post.cached_tags)} rating:#{post.rating} score:#{post.score} uploader:#{h(post.uploader_name)}"
content_for(:blacklist) {"Post.register(#{post.to_json});\n"} if options[:blacklist]
%{
<span class="thumb #{blacklist}" id="p#{post.id}">
<a href="/posts/#{post.id}">
<img #{image_id} class="preview #{'flagged' if post.is_flagged?} #{'pending' if post.is_pending?}" src="#{post.preview_url}" title="#{title}" alt="#{title}" width="#{width}" height="#{height}">
</a>
</span>
}
end
end end

View File

@@ -109,6 +109,8 @@ class User < ActiveRecord::Base
module LevelMethods module LevelMethods
def promote_to_admin_if_first_user def promote_to_admin_if_first_user
return if Rails.env.test?
if User.count == 0 if User.count == 0
self.is_admin = true self.is_admin = true
end end
@@ -168,6 +170,54 @@ class User < ActiveRecord::Base
end end
end end
module LimitMethods
def can_upload?
if is_contributor?
true
elsif created_at > 1.week.ago
false
else
upload_limit > 0
end
end
def can_comment?
if is_privileged?
true
elsif created_at > 1.week.ago
false
else
Comment.where("creator_id = ? and created_at > ?", id, 1.hour.ago).count <= Danbooru.config.member_comment_limit
end
end
def can_comment_vote?
CommentVote.where("user_id = ? and created_at > ?", id, 1.hour.ago).count < 10
end
def can_remove_from_pools?
created_at <= 1.week.ago
end
def upload_limit
deleted_count = Post.where("is_deleted = true and user_id = ?", id).count
unapproved_count = Post.where("is_pending = true and user_id = ?", id).count
approved_count = Post.where("is_flagged = false and is_deleted = false and is_pending = false and user_id = ?", id).count
limit = base_upload_limit + (approved_count / 10) - (deleted_count / 4) - unapproved_count
if limit > 20
limit = 20
end
if limit < 0
limit = 0
end
limit
end
end
include NameMethods include NameMethods
include PasswordMethods include PasswordMethods
extend AuthenticationMethods extend AuthenticationMethods
@@ -176,6 +226,7 @@ class User < ActiveRecord::Base
include EmailVerificationMethods include EmailVerificationMethods
include BlacklistMethods include BlacklistMethods
include ForumMethods include ForumMethods
include LimitMethods
def initialize_default_image_size def initialize_default_image_size
self.default_image_size = "Medium" self.default_image_size = "Medium"

View File

@@ -1,7 +1,7 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<title><%= yield(:page_title) || Danbooru.config.app_name %></title> <title><%= yield(:page_title) %></title>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="top" title="<%= Danbooru.config.app_name %>" href="/"> <link rel="top" title="<%= Danbooru.config.app_name %>" href="/">
<%= csrf_meta_tag %> <%= csrf_meta_tag %>
@@ -17,7 +17,7 @@
</head> </head>
<body> <body>
<nav> <nav>
<h1><%= link_to(Danbooru.config.app_name, "/") %><%= yield :page_header %></h1> <h1><%= link_to(Danbooru.config.app_name, "/") %><%= yield :page_title %></h1>
<menu> <menu>
<% if @current_user.is_anonymous? %> <% if @current_user.is_anonymous? %>
<%= nav_link_to("Login", new_session_path) %> <%= nav_link_to("Login", new_session_path) %>

View File

@@ -0,0 +1,13 @@
<% content_for(:secondary_nav_links) do %>
<menu>
<li>Listing</li>
<li><%= link_to "Upload", new_upload_path %></li>
<li>Popular</li>
<li>Favorites</li>
<li>Subscriptions</li>
<li>Changes</li>
<li>Approvals</li>
<li>Moderate</li>
<li>Help</li>
</menu>
<% end %>

View File

@@ -18,10 +18,10 @@
<h1>Mode</h1> <h1>Mode</h1>
<form action="/"> <form action="/">
<select name="mode"> <select name="mode">
<option value="view">View posts</option> <option value="view">View</option>
<option value="edit">Edit posts</option> <option value="edit">Edit</option>
<option value="add-fav">Add to favorites</option> <option value="add-fav">Favorite</option>
<option value="remove-fav">Remove from favorites</option> <option value="remove-fav">Unfavorite</option>
<option value="rating-s">Rate safe</option> <option value="rating-s">Rate safe</option>
<option value="rating-q">Rate questionable</option> <option value="rating-q">Rate questionable</option>
<option value="rating-e">Rate explicit</option> <option value="rating-e">Rate explicit</option>
@@ -32,9 +32,9 @@
<option value="edit-tag-script">Edit tag script</option> <option value="edit-tag-script">Edit tag script</option>
<option value="apply-tag-script">Apply tag script</option> <option value="apply-tag-script">Apply tag script</option>
<% if @current_user.is_janitor? %> <% if @current_user.is_janitor? %>
<option value="approve">Approve post</option> <option value="approve">Approve</option>
<% end %> <% end %>
<option value="flag">Flag post</option> <option value="unapprove">Unapprove</option>
</select> </select>
</form> </form>
</section> </section>
@@ -82,16 +82,4 @@
/ <%= @post_set.tags %> / <%= @post_set.tags %>
<% end %> <% end %>
<% content_for(:secondary_nav_links) do %> <%= render :partial => "posts/common_secondary_nav_links" %>
<menu>
<li>Listing</li>
<li>Upload</li>
<li>Popular</li>
<li>Favorites</li>
<li>Subscriptions</li>
<li>Changes</li>
<li>Approvals</li>
<li>Moderate</li>
<li>Help</li>
</menu>
<% end %>

View File

@@ -0,0 +1,54 @@
<div id="upload-guide-notice">
<p>Before uploading, please read the <%= link_to "how to upload guide", wiki_page_path("howto:upload") %>. It explains how to tag and what ratings are.</p>
</div>
<% form_for @upload do |f| %>
<% if params[:url] %>
<div id="image-preview">
<%= image_tag(params[:url], :title => "Preview") %>
<p id="scale"></p>
</div>
<% if @post %>
<p>This post was probably already uploaded (<%= link_to "post ##{@post.id}", posts_path(@post), :target => "_blank" %>).</p>
<% end %>
<% end %>
<fieldset>
<legend>Upload</legend>
<p>
<%= f.label :file %>
<%= f.file_field :file, :size => 50 %>
</p>
<p>
<%= f.label :source, nil, :title => "You can enter a URL to have #{Danbooru.config.app_name} automatically download and process it" %>
<%= f.text_field :source, :size => 50, :value => params[:url] %>
</p>
<p>
<%= f.label :tag_string, "Tags" %>
<%= f.text_area :tag_string, :size => "60x4" %>
</p>
<p>
<%= f.label :rating_e, "Explicit", :title => "Hardcore porn, visible genitals, gore" %>
<%= f.radio_button :rating, :e %>
<%= f.label :rating_q, "Questionable", :title => "Nudity, anything erotic" %>
<%= f.radio_button :rating, :q %>
<%= f.label :rating_s, "Safe", :title => "Everything else" %>
<%= f.radio_button :rating, :s %>
</p>
<p>
<%= submit_tag "Submit" %>
</p>
</fieldset>
<% end %>
<% content_for(:page_title) do %>
/ Upload
<% end %>

View File

@@ -1,39 +1,45 @@
<% form_for @user do |f| %> <% form_for @user do |f| %>
<p>Hover over the labels to see a brief explanation of the setting. Required fields are marked in red.</p>
<fieldset> <fieldset>
<legend>Basic</legend> <legend>Basic</legend>
<p> <p>
<%= f.label :email %> <%= f.label :email %>
<%= f.text_field :email %> <% if Danbooru.config.enable_email_verification? %>
<%= f.text_field :email %>
<% else %>
<%= f.text_field :email, :class => "required" %>
<% end %>
</p> </p>
<p> <p>
<%= f.label :receive_email_notifications, "Email notifications" %> <%= f.label :receive_email_notifications, "Email notifications", :title => "Enable to receive email notification when you receive a DMail" %>
<%= f.check_box :receive_email_notifications %> <%= f.check_box :receive_email_notifications %>
</p> </p>
<p> <p>
<%= f.label :comment_threshold %> <%= f.label :comment_threshold, nil, :title => "Comments below this score will be hidden by default" %>
<%= f.text_field :comment_threshold, :size => 2 %> <%= f.text_field :comment_threshold, :size => 2 %>
</p> </p>
<p> <p>
<%= f.label :always_resize_images %> <%= f.label :always_resize_images, nil, :title => "Enable to automatically resize images to fit your browser window" %>
<%= f.check_box :always_resize_images %> <%= f.check_box :always_resize_images %>
</p> </p>
<p> <p>
<%= f.label :default_image_size %> <%= f.label :default_image_size, nil, :title => "Medium shows images resized to #{Danbooru.config.medium_image_width} pixels wide, large is #{Danbooru.config.large_image_width} pixels wide, and original is whatever the original image is" %>
<%= f.select :default_image_size, %w(Medium Large Original) %> <%= f.select :default_image_size, %w(Medium Large Original) %>
</p> </p>
<p> <p>
<%= f.label :favorite_tags %> <%= f.label :favorite_tags, nil, :title => "A list of whitespace delimited tags that show up in your profile" %>
<%= f.text_area :favorite_tags, :rows => 5 %> <%= f.text_area :favorite_tags, :rows => 5 %>
</p> </p>
<p> <p>
<%= f.label :blacklisted_tags %> <%= f.label :blacklisted_tags, nil, :title => "A list of newline delimited tags that you never want to see" %>
<%= f.text_area :blacklisted_tags, :rows => 5 %> <%= f.text_area :blacklisted_tags, :rows => 5 %>
</p> </p>
</fieldset> </fieldset>
@@ -43,17 +49,17 @@
<p>For security purposes, changing the following settings requires you to re-enter your password. You can leave the new password field blank to keep your current one.</p> <p>For security purposes, changing the following settings requires you to re-enter your password. You can leave the new password field blank to keep your current one.</p>
<p> <p>
<%= f.label :name %> <%= f.label :name, nil, :title => "Your login name" %>
<%= f.text_field :name %> <%= f.text_field :name %>
</p> </p>
<p> <p>
<%= f.label :password, "New password" %> <%= f.label :password, "New password", :title => "What you want your new password to be (leave blank if you don't want to change your password)" %>
<%= f.text_field :password %> <%= f.text_field :password %>
</p> </p>
<p> <p>
<%= f.label :old_password %> <%= f.label :old_password, nil, :title => "Your old password (you must enter your password if updating your name or password)" %>
<%= f.text_field :old_password %> <%= f.text_field :old_password %>
</p> </p>
</fieldset> </fieldset>
@@ -62,9 +68,5 @@
<% end %> <% end %>
<% content_for(:page_title) do %> <% content_for(:page_title) do %>
/<%= @user.name %>/Settings / Users / <%= @user.name %> / Settings
<% end %>
<% content_for(:page_header) do %>
/ <%= @user.name %> / Settings
<% end %> <% end %>

View File

@@ -6,9 +6,5 @@
</nav> </nav>
<% content_for(:page_title) do %> <% content_for(:page_title) do %>
users/<%= @user.name %> / Users / <%= @user.name %>
<% end %>
<% content_for(:page_header) do %>
/ <%= @user.name %>
<% end %> <% end %>

View File

@@ -41,6 +41,7 @@ Danbooru::Application.routes.draw do |map|
resources :tag_implications resources :tag_implications
resources :tag_subscriptions resources :tag_subscriptions
resources :unapprovals resources :unapprovals
resources :uploads
resources :users resources :users
resources :user_feedback resources :user_feedback
resources :wiki_pages do resources :wiki_pages do

View File

@@ -770,7 +770,6 @@ CREATE TABLE janitor_trials (
id integer NOT NULL, id integer NOT NULL,
user_id integer NOT NULL, user_id integer NOT NULL,
promoted_at timestamp without time zone, promoted_at timestamp without time zone,
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
); );
@@ -1411,6 +1410,7 @@ CREATE TABLE users (
is_janitor boolean DEFAULT false NOT NULL, is_janitor boolean DEFAULT false NOT NULL,
is_moderator boolean DEFAULT false NOT NULL, is_moderator boolean DEFAULT false NOT NULL,
is_admin boolean DEFAULT false NOT NULL, is_admin boolean DEFAULT false 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,
has_mail boolean DEFAULT false NOT NULL, has_mail boolean DEFAULT false NOT NULL,

View File

@@ -14,6 +14,7 @@ class CreateUsers < ActiveRecord::Migration
t.column :is_janitor, :boolean, :null => false, :default => false t.column :is_janitor, :boolean, :null => false, :default => false
t.column :is_moderator, :boolean, :null => false, :default => false t.column :is_moderator, :boolean, :null => false, :default => false
t.column :is_admin, :boolean, :null => false, :default => false t.column :is_admin, :boolean, :null => false, :default => false
t.column :base_upload_limit, :integer, :null => false, :default => 10
# Cached data # Cached data
t.column :last_logged_in_at, :datetime t.column :last_logged_in_at, :datetime

View File

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

View File

@@ -0,0 +1,13 @@
$(document).ready(function() {
var img = $("#image-preview img");
if (img) {
var height = img.attr("height");
var width = img.attr("width");
if (height > 400) {
var ratio = 400.0 / height;
img.attr("height", height * ratio);
img.attr("width", width * ratio);
$("#scale").val("Scaled " + parseInt(100 * ratio) + "%");
}
}
});

View File

@@ -0,0 +1,4 @@
Factory.define(:comment_vote) do |f|
f.comment {|x| x.association(:comment)}
f.user {|x| x.association(:user)}
end

View File

@@ -1,8 +1,10 @@
Factory.define(:user) do |f| Factory.define(:user) do |f|
f.name {Faker::Name.first_name} f.name {Faker::Name.first_name}
f.password "password"
f.password_hash {User.sha1("password")} f.password_hash {User.sha1("password")}
f.email {Faker::Internet.email} f.email {Faker::Internet.email}
f.default_image_size "medium" f.default_image_size "medium"
f.base_upload_limit 10
end end
Factory.define(:banned_user, :parent => :user) do |f| Factory.define(:banned_user, :parent => :user) do |f|

View File

@@ -1,4 +1,5 @@
require File.expand_path(File.dirname(__FILE__) + "/../config/environment") require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'shoulda' require 'shoulda'
require 'factory_girl' require 'factory_girl'
require 'mocha' require 'mocha'

View File

@@ -6,6 +6,45 @@ class UserTest < ActiveSupport::TestCase
MEMCACHE.flush_all MEMCACHE.flush_all
end end
should "limit post uploads" do
user = Factory.create(:user)
assert(!user.can_upload?)
user.update_attribute(:is_contributor, true)
assert(user.can_upload?)
user.update_attribute(:is_contributor, false)
40.times do
Factory.create(:post, :uploader => user, :is_deleted => true)
end
assert(!user.can_upload?)
end
should "limit comment votes" do
user = Factory.create(:user)
assert(user.can_comment_vote?)
12.times do
Factory.create(:comment_vote, :user => user)
end
assert(!user.can_comment_vote?)
CommentVote.update_all("created_at = '1990-01-01'")
assert(user.can_comment_vote?)
end
should "limit comments" do
user = Factory.create(:user)
assert(!user.can_comment?)
user.update_attribute(:is_privileged, true)
assert(user.can_comment?)
user.update_attribute(:is_privileged, false)
user.update_attribute(:created_at, 1.year.ago)
assert(user.can_comment?)
(Danbooru.config.member_comment_limit + 1).times do
Factory.create(:comment, :creator => user)
end
assert(!user.can_comment?)
end
should "verify" do should "verify" do
user = Factory.create(:user) user = Factory.create(:user)
assert(user.is_verified?) assert(user.is_verified?)