add moderation logging
- add users.is_moderator and look at that for most things, not is_admin - make default user in readme be a moderator - log moderator actions in story edits, comment deletions/undeletions (and later, user disabling). - remove ability for moderators to edit comments, there's really no reason to.
This commit is contained in:
parent
4692cf63ea
commit
e6c74e8251
|
@ -51,6 +51,7 @@ This is the source code to the site operating at [https://lobste.rs](https://lob
|
||||||
Loading development environment (Rails 3.2.6)
|
Loading development environment (Rails 3.2.6)
|
||||||
irb(main):001:0> u = User.new(:username => "test", :email => "test@example.com", :password => "test")
|
irb(main):001:0> u = User.new(:username => "test", :email => "test@example.com", :password => "test")
|
||||||
irb(main):002:0> u.is_admin = true
|
irb(main):002:0> u.is_admin = true
|
||||||
|
irb(main):002:0> u.is_moderator = true
|
||||||
irb(main):003:0> u.save
|
irb(main):003:0> u.save
|
||||||
|
|
||||||
irb(main):004:0> t = Tag.new
|
irb(main):004:0> t = Tag.new
|
||||||
|
|
|
@ -626,7 +626,8 @@ div#story_preview {
|
||||||
div#story_box input#story_url {
|
div#story_box input#story_url {
|
||||||
width: 508px;
|
width: 508px;
|
||||||
}
|
}
|
||||||
div#story_box input#story_title {
|
div#story_box input#story_title,
|
||||||
|
div#story_box input#story_moderation_reason {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
}
|
}
|
||||||
div#story_box #story_tags_a {
|
div#story_box #story_tags_a {
|
||||||
|
|
|
@ -70,7 +70,7 @@ class CommentsController < ApplicationController
|
||||||
|
|
||||||
def delete
|
def delete
|
||||||
if !((comment = Comment.find_by_short_id(params[:comment_id])) &&
|
if !((comment = Comment.find_by_short_id(params[:comment_id])) &&
|
||||||
comment.is_editable_by_user?(@user))
|
comment.is_deletable_by_user?(@user))
|
||||||
return render :text => "can't find comment", :status => 400
|
return render :text => "can't find comment", :status => 400
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -175,9 +175,8 @@ class CommentsController < ApplicationController
|
||||||
@title = "Newest Comments"
|
@title = "Newest Comments"
|
||||||
@cur_url = "/comments"
|
@cur_url = "/comments"
|
||||||
|
|
||||||
@comments = Comment.find(:all, :conditions => "is_deleted = 0 AND " +
|
@comments = Comment.find(:all, :conditions => "is_deleted = 0",
|
||||||
"is_moderated = 0", :order => "created_at DESC", :limit => 20,
|
:order => "created_at DESC", :limit => 20, :include => [ :user, :story ])
|
||||||
:include => [ :user, :story ])
|
|
||||||
|
|
||||||
if @user
|
if @user
|
||||||
@votes = Vote.comment_votes_by_user_for_comment_ids_hash(@user.id,
|
@votes = Vote.comment_votes_by_user_for_comment_ids_hash(@user.id,
|
||||||
|
|
|
@ -74,7 +74,7 @@ private
|
||||||
end
|
end
|
||||||
|
|
||||||
def _find_stories_for_user_and_tag_and_newest(user, tag = nil, newest = false)
|
def _find_stories_for_user_and_tag_and_newest(user, tag = nil, newest = false)
|
||||||
conds = [ "is_expired = 0 AND is_moderated = 0 " ]
|
conds = [ "is_expired = 0 " ]
|
||||||
|
|
||||||
if user && !newest
|
if user && !newest
|
||||||
# exclude downvoted items
|
# exclude downvoted items
|
||||||
|
|
13
app/controllers/moderations_controller.rb
Normal file
13
app/controllers/moderations_controller.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
class ModerationsController < ApplicationController
|
||||||
|
def index
|
||||||
|
@pages = Moderation.count
|
||||||
|
@page = params[:page] ? params[:page].to_i : 0
|
||||||
|
|
||||||
|
if @page < 1
|
||||||
|
@page = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
@moderations = Moderation.order("id desc").limit(50).offset((@page - 1) *
|
||||||
|
50).all
|
||||||
|
end
|
||||||
|
end
|
|
@ -45,10 +45,10 @@ class StoriesController < ApplicationController
|
||||||
return redirect_to "/"
|
return redirect_to "/"
|
||||||
end
|
end
|
||||||
|
|
||||||
if @user.is_admin? && @user.id != @story.user_id
|
|
||||||
@story.is_moderated = true
|
|
||||||
else
|
|
||||||
@story.is_expired = true
|
@story.is_expired = true
|
||||||
|
|
||||||
|
if @user.is_moderator? && @user.id != @story.user_id
|
||||||
|
@story.editor_user_id = @user.id
|
||||||
end
|
end
|
||||||
|
|
||||||
@story.save(:validate => false)
|
@story.save(:validate => false)
|
||||||
|
@ -184,7 +184,7 @@ class StoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
@story.is_expired = false
|
@story.is_expired = false
|
||||||
@story.is_moderated = false
|
@story.editor_user_id = @user.id
|
||||||
@story.save(:validate => false)
|
@story.save(:validate => false)
|
||||||
|
|
||||||
redirect_to @story.comments_url
|
redirect_to @story.comments_url
|
||||||
|
@ -197,6 +197,7 @@ class StoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
@story.is_expired = false
|
@story.is_expired = false
|
||||||
|
@story.editor_user_id = @user.id
|
||||||
|
|
||||||
if @story.update_attributes(params[:story].except(:url))
|
if @story.update_attributes(params[:story].except(:url))
|
||||||
return redirect_to @story.comments_url
|
return redirect_to @story.comments_url
|
||||||
|
@ -244,7 +245,7 @@ class StoriesController < ApplicationController
|
||||||
|
|
||||||
private
|
private
|
||||||
def find_story
|
def find_story
|
||||||
if @user.is_admin?
|
if @user.is_moderator?
|
||||||
@story = Story.find_by_short_id(params[:story_id] || params[:id])
|
@story = Story.find_by_short_id(params[:story_id] || params[:id])
|
||||||
else
|
else
|
||||||
@story = Story.find_by_user_id_and_short_id(@user.id,
|
@story = Story.find_by_user_id_and_short_id(@user.id,
|
||||||
|
|
|
@ -6,7 +6,7 @@ class Comment < ActiveRecord::Base
|
||||||
belongs_to :parent_comment,
|
belongs_to :parent_comment,
|
||||||
:class_name => "Comment"
|
:class_name => "Comment"
|
||||||
|
|
||||||
attr_accessible :comment
|
attr_accessible :comment, :moderation_reason
|
||||||
|
|
||||||
attr_accessor :parent_comment_short_id, :current_vote, :previewing,
|
attr_accessor :parent_comment_short_id, :current_vote, :previewing,
|
||||||
:indent_level, :highlighted
|
:indent_level, :highlighted
|
||||||
|
@ -24,10 +24,10 @@ class Comment < ActiveRecord::Base
|
||||||
has "(upvotes - downvotes)", :as => :score, :type => :integer,
|
has "(upvotes - downvotes)", :as => :score, :type => :integer,
|
||||||
:sortable => true
|
:sortable => true
|
||||||
|
|
||||||
has is_moderated, is_deleted
|
has is_deleted
|
||||||
has created_at
|
has created_at
|
||||||
|
|
||||||
where "is_moderated = 0 AND is_deleted = 0"
|
where "is_deleted = 0"
|
||||||
end
|
end
|
||||||
|
|
||||||
validate do
|
validate do
|
||||||
|
@ -81,7 +81,7 @@ class Comment < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_gone?
|
def is_gone?
|
||||||
is_deleted? || is_moderated?
|
is_deleted?
|
||||||
end
|
end
|
||||||
|
|
||||||
def mark_submitter
|
def mark_submitter
|
||||||
|
@ -112,10 +112,16 @@ class Comment < ActiveRecord::Base
|
||||||
def delete_for_user(user)
|
def delete_for_user(user)
|
||||||
Comment.record_timestamps = false
|
Comment.record_timestamps = false
|
||||||
|
|
||||||
if user.is_admin? && user.id != self.user_id
|
|
||||||
self.is_moderated = true
|
|
||||||
else
|
|
||||||
self.is_deleted = true
|
self.is_deleted = true
|
||||||
|
|
||||||
|
if user.is_moderator? && user.id != self.user_id
|
||||||
|
self.is_moderated = true
|
||||||
|
|
||||||
|
m = Moderation.new
|
||||||
|
m.comment_id = self.id
|
||||||
|
m.moderator_user_id = user.id
|
||||||
|
m.action = "deleted comment"
|
||||||
|
m.save
|
||||||
end
|
end
|
||||||
|
|
||||||
self.save(:validate => false)
|
self.save(:validate => false)
|
||||||
|
@ -127,9 +133,18 @@ class Comment < ActiveRecord::Base
|
||||||
def undelete_for_user(user)
|
def undelete_for_user(user)
|
||||||
Comment.record_timestamps = false
|
Comment.record_timestamps = false
|
||||||
|
|
||||||
self.is_moderated = false
|
|
||||||
self.is_deleted = false
|
self.is_deleted = false
|
||||||
|
|
||||||
|
if user.is_moderator? && user.id != self.user_id
|
||||||
|
self.is_moderated = true
|
||||||
|
|
||||||
|
m = Moderation.new
|
||||||
|
m.comment_id = self.id
|
||||||
|
m.moderator_user_id = user.id
|
||||||
|
m.action = "undeleted comment"
|
||||||
|
m.save
|
||||||
|
end
|
||||||
|
|
||||||
self.save(:validate => false)
|
self.save(:validate => false)
|
||||||
Comment.record_timestamps = true
|
Comment.record_timestamps = true
|
||||||
|
|
||||||
|
@ -233,7 +248,7 @@ class Comment < ActiveRecord::Base
|
||||||
if c.is_gone?
|
if c.is_gone?
|
||||||
if ordered[x + 1] && (ordered[x + 1].indent_level > c.indent_level)
|
if ordered[x + 1] && (ordered[x + 1].indent_level > c.indent_level)
|
||||||
# we have child comments, so we must stay
|
# we have child comments, so we must stay
|
||||||
elsif user && (user.is_admin? || c.user_id == user.id)
|
elsif user && (user.is_moderator? || c.user_id == user.id)
|
||||||
# admins and authors should be able to see their deleted comments
|
# admins and authors should be able to see their deleted comments
|
||||||
else
|
else
|
||||||
# drop this one
|
# drop this one
|
||||||
|
@ -248,9 +263,7 @@ class Comment < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_editable_by_user?(user)
|
def is_editable_by_user?(user)
|
||||||
if user && user.is_admin?
|
if user && user.id == self.user_id
|
||||||
return true
|
|
||||||
elsif user && user.id == self.user_id
|
|
||||||
if self.is_moderated?
|
if self.is_moderated?
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
|
@ -262,8 +275,18 @@ class Comment < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def is_deletable_by_user?(user)
|
||||||
|
if user && user.is_moderator?
|
||||||
|
return true
|
||||||
|
elsif user && user.id == self.user_id
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def is_undeletable_by_user?(user)
|
def is_undeletable_by_user?(user)
|
||||||
if user && user.is_admin?
|
if user && user.is_moderator?
|
||||||
return true
|
return true
|
||||||
elsif user && user.id == self.user_id && !self.is_moderated?
|
elsif user && user.id == self.user_id && !self.is_moderated?
|
||||||
return true
|
return true
|
||||||
|
|
10
app/models/moderation.rb
Normal file
10
app/models/moderation.rb
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
class Moderation < ActiveRecord::Base
|
||||||
|
belongs_to :moderator,
|
||||||
|
:class_name => "User",
|
||||||
|
:foreign_key => "moderator_user_id"
|
||||||
|
belongs_to :story
|
||||||
|
belongs_to :comment
|
||||||
|
belongs_to :user
|
||||||
|
|
||||||
|
attr_accessible nil
|
||||||
|
end
|
|
@ -16,10 +16,12 @@ class Story < ActiveRecord::Base
|
||||||
attr_accessor :_comment_count
|
attr_accessor :_comment_count
|
||||||
attr_accessor :vote, :already_posted_story, :fetched_content, :previewing
|
attr_accessor :vote, :already_posted_story, :fetched_content, :previewing
|
||||||
attr_accessor :new_tags, :tags_to_add, :tags_to_delete
|
attr_accessor :new_tags, :tags_to_add, :tags_to_delete
|
||||||
|
attr_accessor :editor_user_id, :moderation_reason
|
||||||
|
|
||||||
attr_accessible :title, :description, :tags_a
|
attr_accessible :title, :description, :tags_a, :moderation_reason
|
||||||
|
|
||||||
before_create :assign_short_id
|
before_create :assign_short_id
|
||||||
|
before_save :log_moderation
|
||||||
after_create :mark_submitter
|
after_create :mark_submitter
|
||||||
after_save :deal_with_tags
|
after_save :deal_with_tags
|
||||||
|
|
||||||
|
@ -31,7 +33,7 @@ class Story < ActiveRecord::Base
|
||||||
indexes tags(:tag), :as => :tags
|
indexes tags(:tag), :as => :tags
|
||||||
|
|
||||||
has created_at, :sortable => true
|
has created_at, :sortable => true
|
||||||
has hotness, is_moderated, is_expired
|
has hotness, is_expired
|
||||||
has "(upvotes - downvotes)", :as => :score, :type => :integer,
|
has "(upvotes - downvotes)", :as => :score, :type => :integer,
|
||||||
:sortable => true
|
:sortable => true
|
||||||
|
|
||||||
|
@ -40,7 +42,7 @@ class Story < ActiveRecord::Base
|
||||||
:tags => 5,
|
:tags => 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
where "is_moderated = 0 AND is_expired = 0"
|
where "is_expired = 0"
|
||||||
end
|
end
|
||||||
|
|
||||||
validate do
|
validate do
|
||||||
|
@ -118,6 +120,37 @@ class Story < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def log_moderation
|
||||||
|
if self.new_record? || self.editor_user_id == self.user_id
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
m = Moderation.new
|
||||||
|
m.moderator_user_id = self.editor_user_id
|
||||||
|
m.story_id = self.id
|
||||||
|
|
||||||
|
if self.changes["is_expired"] && self.is_expired?
|
||||||
|
m.action = "deleted story"
|
||||||
|
elsif self.changes["is_expired"] && !self.is_expired?
|
||||||
|
m.action = "undeleted story"
|
||||||
|
else
|
||||||
|
actions = self.changes.map{|k,v| "changed #{k} from #{v[0].inspect} " <<
|
||||||
|
"to #{v[1].inspect}" }
|
||||||
|
|
||||||
|
if (old_tags = self.tags.map{|t| t.tag }) != self.tags_a
|
||||||
|
actions.push "changed tags from \"#{old_tags.join(", ")}\" to " <<
|
||||||
|
"\"#{self.tags_a.join(", ")}\""
|
||||||
|
end
|
||||||
|
|
||||||
|
m.action = actions.join(", ")
|
||||||
|
end
|
||||||
|
|
||||||
|
m.reason = self.moderation_reason
|
||||||
|
m.save
|
||||||
|
|
||||||
|
self.is_moderated = true
|
||||||
|
end
|
||||||
|
|
||||||
def give_upvote_or_downvote_and_recalculate_hotness!(upvote, downvote)
|
def give_upvote_or_downvote_and_recalculate_hotness!(upvote, downvote)
|
||||||
self.upvotes += upvote.to_i
|
self.upvotes += upvote.to_i
|
||||||
self.downvotes += downvote.to_i
|
self.downvotes += downvote.to_i
|
||||||
|
@ -236,7 +269,7 @@ class Story < ActiveRecord::Base
|
||||||
def tags_a=(new_tags)
|
def tags_a=(new_tags)
|
||||||
self.tags_to_delete = []
|
self.tags_to_delete = []
|
||||||
self.tags_to_add = []
|
self.tags_to_add = []
|
||||||
self.new_tags = new_tags
|
self.new_tags = new_tags.reject{|t| t.blank? }
|
||||||
|
|
||||||
self.tags.each do |tag|
|
self.tags.each do |tag|
|
||||||
if !new_tags.include?(tag.tag)
|
if !new_tags.include?(tag.tag)
|
||||||
|
@ -252,7 +285,7 @@ class Story < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@_tags_a = new_tags
|
@_tags_a = self.new_tags
|
||||||
end
|
end
|
||||||
|
|
||||||
def url=(u)
|
def url=(u)
|
||||||
|
@ -286,7 +319,7 @@ class Story < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_editable_by_user?(user)
|
def is_editable_by_user?(user)
|
||||||
if user && user.is_admin?
|
if user && user.is_moderator?
|
||||||
return true
|
return true
|
||||||
elsif user && user.id == self.user_id
|
elsif user && user.id == self.user_id
|
||||||
if self.is_moderated?
|
if self.is_moderated?
|
||||||
|
@ -300,7 +333,7 @@ class Story < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_undeletable_by_user?(user)
|
def is_undeletable_by_user?(user)
|
||||||
if user && user.is_admin?
|
if user && user.is_moderator?
|
||||||
return true
|
return true
|
||||||
elsif user && user.id == self.user_id && !self.is_moderated?
|
elsif user && user.id == self.user_id && !self.is_moderated?
|
||||||
return true
|
return true
|
||||||
|
@ -310,7 +343,7 @@ class Story < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_be_seen_by_user?(user)
|
def can_be_seen_by_user?(user)
|
||||||
if is_gone? && !(user && (user.is_admin? || user.id == self.user_id))
|
if is_gone? && !(user && (user.is_moderator? || user.id == self.user_id))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -318,12 +351,11 @@ class Story < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_gone?
|
def is_gone?
|
||||||
is_expired? || is_moderated?
|
is_expired?
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_comment_count!
|
def update_comment_count!
|
||||||
Keystore.put("story:#{self.id}:comment_count",
|
Keystore.put("story:#{self.id}:comment_count",
|
||||||
Comment.where(:story_id => self.id, :is_moderated => 0,
|
Comment.where(:story_id => self.id, :is_deleted => 0).count)
|
||||||
:is_deleted => 0).count)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -48,7 +48,7 @@ class="comment <%= comment.current_vote ? (comment.current_vote[:vote] == 1 ?
|
||||||
<% if comment.is_gone? && comment.is_undeletable_by_user?(@user) %>
|
<% if comment.is_gone? && comment.is_undeletable_by_user?(@user) %>
|
||||||
|
|
|
|
||||||
<a class="comment_undeletor">undelete</a>
|
<a class="comment_undeletor">undelete</a>
|
||||||
<% elsif !comment.is_gone? && comment.is_editable_by_user?(@user) %>
|
<% elsif !comment.is_gone? && comment.is_deletable_by_user?(@user) %>
|
||||||
|
|
|
|
||||||
<a class="comment_deletor">delete</a>
|
<a class="comment_deletor">delete</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -73,8 +73,8 @@ class="comment <%= comment.current_vote ? (comment.current_vote[:vote] == 1 ?
|
||||||
<% if comment.is_gone? %>
|
<% if comment.is_gone? %>
|
||||||
<p>
|
<p>
|
||||||
<span class="na">
|
<span class="na">
|
||||||
[Comment removed by <%= comment.is_deleted? ? "author" :
|
[Comment removed by <%= comment.is_moderated? ? "moderator" :
|
||||||
"moderator" %>]
|
"author" %>]
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<% else %>
|
<% else %>
|
||||||
|
|
|
@ -16,5 +16,5 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
<a href="<%= @tag ? "/t/#{@tag.tag}" : (@newest ? "/newest" : "")
|
<a href="<%= @tag ? "/t/#{@tag.tag}" : (@newest ? "/newest" : "")
|
||||||
%>/page/<%= @page + 1 %>">Page <%= @page + 1 %> >></a>
|
%>/page/<%= @page + 1 %>">Page <%= @page + 1 %> >></a>
|
||||||
</div>
|
<% end %>
|
||||||
<% end %>
|
</div>
|
||||||
|
|
54
app/views/moderations/index.html.erb
Normal file
54
app/views/moderations/index.html.erb
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<div class="box wide">
|
||||||
|
<div class="legend">
|
||||||
|
Moderation Log
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="data" width="100%" cellspacing=0>
|
||||||
|
<tr>
|
||||||
|
<th width="20%">Date/Time</th>
|
||||||
|
<th width="15%">Moderator</th>
|
||||||
|
<th width="65%">Story/Comment/User, Changes, Reason</th>
|
||||||
|
</tr>
|
||||||
|
<% bit = 0 %>
|
||||||
|
<% @moderations.each do |mod| %>
|
||||||
|
<tr class="row<%= bit %> nobottom">
|
||||||
|
<td><%= mod.created_at.strftime("%Y-%m-%d %H:%M:%S") %></td>
|
||||||
|
<td><a href="/messages?to=<%= mod.moderator.try(:username) %>"><%=
|
||||||
|
mod.moderator.try(:username) %></a></td>
|
||||||
|
<td><% if mod.story %>
|
||||||
|
<a href="<%= mod.story.comments_url %>">Story: <%= mod.story.title
|
||||||
|
%></a>
|
||||||
|
<% elsif mod.comment %>
|
||||||
|
<a href="<%= mod.comment.url %>">Comment on <%=
|
||||||
|
mod.comment.story.title %></a>
|
||||||
|
<% elsif mod.user %>
|
||||||
|
User <%= mod.user.try(:username) %>
|
||||||
|
<% end %></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="row<%= bit %> <%= mod.reason.present?? "nobottom" : "" %>">
|
||||||
|
<td colspan=2></td>
|
||||||
|
<td>Action: <em><%= mod.action %></em></td>
|
||||||
|
</tr>
|
||||||
|
<% if mod.reason.present? %>
|
||||||
|
<tr class="row<%= bit %>">
|
||||||
|
<td colspan=2></td>
|
||||||
|
<td>Reason: <em><%= mod.reason %></em></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<% bit = (bit == 1 ? 0 : 1) %>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="morelink">
|
||||||
|
<% if @page && @page > 1 %>
|
||||||
|
<a href="/moderations/page/<%= @page - 1 %>"><< Page
|
||||||
|
<%= @page - 1 %></a>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if @page && @page > 1 %>
|
||||||
|
|
|
||||||
|
<a href="/moderations/page/<%= @page + 1 %>">Page <%= @page + 1
|
||||||
|
%> >></a>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -22,8 +22,8 @@ class="story <%= story.vote == 1 ? "upvoted" : (story.vote == -1 ?
|
||||||
<a href="<%= story.url_or_comments_url %>"><%= story.title %></a>
|
<a href="<%= story.url_or_comments_url %>"><%= story.title %></a>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if story.is_gone? %>
|
<% if story.is_gone? %>
|
||||||
[Story removed by <%= story.is_expired? ? "original submitter" :
|
[Story removed by <%= story.is_moderated? ? "moderator" :
|
||||||
"moderator" %>]
|
"original submitter" %>]
|
||||||
<% end %>
|
<% end %>
|
||||||
</span>
|
</span>
|
||||||
<% if story.can_be_seen_by_user?(@user) %>
|
<% if story.can_be_seen_by_user?(@user) %>
|
||||||
|
|
|
@ -8,6 +8,16 @@
|
||||||
<%= render :partial => "stories/form", :locals => { :story => @story,
|
<%= render :partial => "stories/form", :locals => { :story => @story,
|
||||||
:f => f } %>
|
:f => f } %>
|
||||||
|
|
||||||
|
<% if @story.user_id != @user.id %>
|
||||||
|
<div class="box">
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :moderation_reason, "Mod Reason:",
|
||||||
|
:class => "required" %>
|
||||||
|
<%= f.text_field :moderation_reason, :autocomplete => "off" %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<p></p>
|
<p></p>
|
||||||
|
|
||||||
<div class="box">
|
<div class="box">
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
|
|
||||||
<label class="required">Status:</label>
|
<label class="required">Status:</label>
|
||||||
<span class="d">
|
<span class="d">
|
||||||
Active <%= @showing_user.is_admin? ? "administrator" : "user" %>
|
Active <%= @showing_user.is_admin? ? "administrator" :
|
||||||
|
(@showing_user.is_moderator? ? "moderator" : "user") %>
|
||||||
</span>
|
</span>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|
|
@ -71,4 +71,7 @@ Lobsters::Application.routes.draw do
|
||||||
|
|
||||||
post "/invitations" => "invitations#create"
|
post "/invitations" => "invitations#create"
|
||||||
get "/invitations/:invitation_code" => "signup#invited"
|
get "/invitations/:invitation_code" => "signup#invited"
|
||||||
|
|
||||||
|
get "/moderations" => "moderations#index"
|
||||||
|
get "/moderations/page/:page" => "moderations#index"
|
||||||
end
|
end
|
||||||
|
|
18
db/migrate/20120902143549_add_moderation_log.rb
Normal file
18
db/migrate/20120902143549_add_moderation_log.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
class AddModerationLog < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
add_column "users", "is_moderator", :boolean, :default => false
|
||||||
|
|
||||||
|
create_table "moderations" do |t|
|
||||||
|
t.timestamps
|
||||||
|
t.integer "moderator_user_id"
|
||||||
|
t.integer "story_id"
|
||||||
|
t.integer "comment_id"
|
||||||
|
t.integer "user_id"
|
||||||
|
t.text "action"
|
||||||
|
t.text "reason"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
end
|
||||||
|
end
|
14
db/schema.rb
14
db/schema.rb
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended to check this file into your version control system.
|
# It's strongly recommended to check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(:version => 20120816203248) do
|
ActiveRecord::Schema.define(:version => 20120902143549) do
|
||||||
|
|
||||||
create_table "comments", :force => true do |t|
|
create_table "comments", :force => true do |t|
|
||||||
t.datetime "created_at", :null => false
|
t.datetime "created_at", :null => false
|
||||||
|
@ -65,6 +65,17 @@ ActiveRecord::Schema.define(:version => 20120816203248) do
|
||||||
|
|
||||||
add_index "messages", ["short_id"], :name => "random_hash", :unique => true
|
add_index "messages", ["short_id"], :name => "random_hash", :unique => true
|
||||||
|
|
||||||
|
create_table "moderations", :force => true do |t|
|
||||||
|
t.datetime "created_at", :null => false
|
||||||
|
t.datetime "updated_at", :null => false
|
||||||
|
t.integer "moderator_user_id"
|
||||||
|
t.integer "story_id"
|
||||||
|
t.integer "comment_id"
|
||||||
|
t.integer "user_id"
|
||||||
|
t.text "action"
|
||||||
|
t.text "reason"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "stories", :force => true do |t|
|
create_table "stories", :force => true do |t|
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
|
@ -124,6 +135,7 @@ ActiveRecord::Schema.define(:version => 20120816203248) do
|
||||||
t.string "pushover_device"
|
t.string "pushover_device"
|
||||||
t.boolean "email_messages", :default => true
|
t.boolean "email_messages", :default => true
|
||||||
t.boolean "pushover_messages", :default => true
|
t.boolean "pushover_messages", :default => true
|
||||||
|
t.boolean "is_moderator", :default => false
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "users", ["session_token"], :name => "session_hash", :unique => true
|
add_index "users", ["session_token"], :name => "session_hash", :unique => true
|
||||||
|
|
Loading…
Reference in a new issue