mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 17:46:05 -05:00
moderators now have teeth, more at http://meta.discourse.org/t/moderator-permission-set/6307/5
allow pms to be targetted at groups
This commit is contained in:
parent
e59ab32210
commit
65cd00cf25
27 changed files with 176 additions and 61 deletions
|
@ -12,10 +12,11 @@ Discourse.AdminDashboardController = Ember.Controller.extend({
|
||||||
problemsCheckInterval: '1 minute ago',
|
problemsCheckInterval: '1 minute ago',
|
||||||
|
|
||||||
foundProblems: function() {
|
foundProblems: function() {
|
||||||
return(this.get('problems') && this.get('problems').length > 0);
|
return(Discourse.currentUser.admin && this.get('problems') && this.get('problems').length > 0);
|
||||||
}.property('problems'),
|
}.property('problems'),
|
||||||
|
|
||||||
thereWereProblems: function() {
|
thereWereProblems: function() {
|
||||||
|
if(!Discourse.currentUser.admin) { return false }
|
||||||
if( this.get('foundProblems') ) {
|
if( this.get('foundProblems') ) {
|
||||||
this.set('hadProblems', true);
|
this.set('hadProblems', true);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -4,14 +4,18 @@
|
||||||
|
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
<li>{{#linkTo 'admin.dashboard'}}{{i18n admin.dashboard.title}}{{/linkTo}}</li>
|
<li>{{#linkTo 'admin.dashboard'}}{{i18n admin.dashboard.title}}{{/linkTo}}</li>
|
||||||
|
{{#if Discourse.currentUser.admin}}
|
||||||
<li>{{#linkTo 'admin.site_settings'}}{{i18n admin.site_settings.title}}{{/linkTo}}</li>
|
<li>{{#linkTo 'admin.site_settings'}}{{i18n admin.site_settings.title}}{{/linkTo}}</li>
|
||||||
<li>{{#linkTo 'adminSiteContents'}}{{i18n admin.site_content.title}}{{/linkTo}}</li>
|
<li>{{#linkTo 'adminSiteContents'}}{{i18n admin.site_content.title}}{{/linkTo}}</li>
|
||||||
|
{{/if}}
|
||||||
<li>{{#linkTo 'adminUsersList.active'}}{{i18n admin.users.title}}{{/linkTo}}</li>
|
<li>{{#linkTo 'adminUsersList.active'}}{{i18n admin.users.title}}{{/linkTo}}</li>
|
||||||
<!--<li>{{#linkTo 'admin.groups'}}{{i18n admin.groups.title}}{{/linkTo}}</li>-->
|
<!--<li>{{#linkTo 'admin.groups'}}{{i18n admin.groups.title}}{{/linkTo}}</li>-->
|
||||||
<li>{{#linkTo 'admin.email_logs'}}{{i18n admin.email_logs.title}}{{/linkTo}}</li>
|
<li>{{#linkTo 'admin.email_logs'}}{{i18n admin.email_logs.title}}{{/linkTo}}</li>
|
||||||
<li>{{#linkTo 'adminFlags.active'}}{{i18n admin.flags.title}}{{/linkTo}}</li>
|
<li>{{#linkTo 'adminFlags.active'}}{{i18n admin.flags.title}}{{/linkTo}}</li>
|
||||||
|
{{#if Discourse.currentUser.admin}}
|
||||||
<li>{{#linkTo 'admin.customize'}}{{i18n admin.customize.title}}{{/linkTo}}</li>
|
<li>{{#linkTo 'admin.customize'}}{{i18n admin.customize.title}}{{/linkTo}}</li>
|
||||||
<li>{{#linkTo 'admin.api'}}{{i18n admin.api.title}}{{/linkTo}}</li>
|
<li>{{#linkTo 'admin.api'}}{{i18n admin.api.title}}{{/linkTo}}</li>
|
||||||
|
{{/if}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class='boxed white admin-content'>
|
<div class='boxed white admin-content'>
|
||||||
|
|
|
@ -31,9 +31,11 @@
|
||||||
<div class='field'>{{i18n user.ip_address.title}}</div>
|
<div class='field'>{{i18n user.ip_address.title}}</div>
|
||||||
<div class='value'>{{content.ip_address}}</div>
|
<div class='value'>{{content.ip_address}}</div>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
|
{{#if Discourse.currentUser.admin}}
|
||||||
<button class='btn' {{action refreshBrowsers target="content"}}>
|
<button class='btn' {{action refreshBrowsers target="content"}}>
|
||||||
{{i18n admin.user.refresh_browsers}}
|
{{i18n admin.user.refresh_browsers}}
|
||||||
</button>
|
</button>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ Discourse = Ember.Application.createWithMixins({
|
||||||
if (user) {
|
if (user) {
|
||||||
bus.callbackInterval = Discourse.SiteSettings.polling_interval;
|
bus.callbackInterval = Discourse.SiteSettings.polling_interval;
|
||||||
bus.enableLongPolling = true;
|
bus.enableLongPolling = true;
|
||||||
if (user.admin) {
|
if (user.admin || user.moderator) {
|
||||||
bus.subscribe("/flagged_counts", function(data) {
|
bus.subscribe("/flagged_counts", function(data) {
|
||||||
user.set('site_flagged_posts_count', data.total);
|
user.set('site_flagged_posts_count', data.total);
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,7 +13,7 @@ Discourse.UserController = Discourse.ObjectController.extend({
|
||||||
}).property('content.username', 'Discourse.currentUser.username'),
|
}).property('content.username', 'Discourse.currentUser.username'),
|
||||||
|
|
||||||
canSeePrivateMessages: (function() {
|
canSeePrivateMessages: (function() {
|
||||||
return this.get('viewingSelf') || Discourse.get('currentUser.admin');
|
return this.get('viewingSelf') || Discourse.get('currentUser.moderator');
|
||||||
}).property('viewingSelf', 'Discourse.currentUser')
|
}).property('viewingSelf', 'Discourse.currentUser')
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
|
|
||||||
<section class='d-dropdown' id='site-map-dropdown'>
|
<section class='d-dropdown' id='site-map-dropdown'>
|
||||||
<ul>
|
<ul>
|
||||||
{{#if Discourse.currentUser.admin}}
|
{{#if Discourse.currentUser.moderator}}
|
||||||
<li><a href="/admin"><i class='icon-cog'></i>{{i18n admin_title}}</a></li>
|
<li><a href="/admin"><i class='icon-cog'></i>{{i18n admin_title}}</a></li>
|
||||||
<li><a href="/admin/flags/active"><i class='icon-flag'></i>{{i18n flags_title}}</a></li>
|
<li><a href="/admin/flags/active"><i class='icon-flag'></i>{{i18n flags_title}}</a></li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -134,6 +134,6 @@
|
||||||
{{render share}}
|
{{render share}}
|
||||||
{{render quoteButton}}
|
{{render quoteButton}}
|
||||||
|
|
||||||
{{#if Discourse.currentUser.admin}}
|
{{#if Discourse.currentUser.moderator}}
|
||||||
{{render topicAdminMenu content}}
|
{{render topicAdminMenu content}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
{{#if viewingSelf}}
|
{{#if viewingSelf}}
|
||||||
<button {{action "logout" target="Discourse"}} class='btn'>{{i18n user.log_out}}</button>
|
<button {{action "logout" target="Discourse"}} class='btn'>{{i18n user.log_out}}</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if Discourse.currentUser.admin}}
|
{{#if Discourse.currentUser.moderator}}
|
||||||
<a href="{{unbound content.adminPath}}" class='btn'><i class="icon-wrench"></i> {{i18n admin.user.show_admin_profile}}</a>
|
<a href="{{unbound content.adminPath}}" class='btn'><i class="icon-wrench"></i> {{i18n admin.user.show_admin_profile}}</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class Admin::AdminController < ApplicationController
|
class Admin::AdminController < ApplicationController
|
||||||
|
|
||||||
before_filter :ensure_logged_in
|
before_filter :ensure_logged_in
|
||||||
before_filter :ensure_is_admin
|
before_filter :ensure_is_moderator
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render nothing: true
|
render nothing: true
|
||||||
|
@ -9,8 +9,8 @@ class Admin::AdminController < ApplicationController
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def ensure_is_admin
|
def ensure_is_moderator
|
||||||
raise Discourse::InvalidAccess.new unless current_user.admin?
|
raise Discourse::InvalidAccess.new unless current_user.moderator?
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,6 +34,10 @@ module ApplicationHelper
|
||||||
current_user.try(:admin?)
|
current_user.try(:admin?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def moderator?
|
||||||
|
current_user.try(:moderator?)
|
||||||
|
end
|
||||||
|
|
||||||
# Creates open graph and twitter card meta data
|
# Creates open graph and twitter card meta data
|
||||||
def crawlable_meta_data(opts=nil)
|
def crawlable_meta_data(opts=nil)
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ class PostAction < ActiveRecord::Base
|
||||||
'topics.deleted_at' => nil).count('DISTINCT posts.id')
|
'topics.deleted_at' => nil).count('DISTINCT posts.id')
|
||||||
|
|
||||||
$redis.set('posts_flagged_count', posts_flagged_count)
|
$redis.set('posts_flagged_count', posts_flagged_count)
|
||||||
admins = User.admins.select(:id).map {|u| u.id}
|
user_ids = User.where("admin = 't' or moderator = 't'").select(:id).map {|u| u.id}
|
||||||
MessageBus.publish('/flagged_counts', { total: posts_flagged_count }, { user_ids: admins })
|
MessageBus.publish('/flagged_counts', { total: posts_flagged_count }, { user_ids: user_ids })
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.flagged_posts_count
|
def self.flagged_posts_count
|
||||||
|
|
|
@ -60,8 +60,8 @@ class PostAlertObserver < ActiveRecord::Observer
|
||||||
def after_create_post(post)
|
def after_create_post(post)
|
||||||
if post.topic.private_message?
|
if post.topic.private_message?
|
||||||
# If it's a private message, notify the topic_allowed_users
|
# If it's a private message, notify the topic_allowed_users
|
||||||
post.topic.topic_allowed_users.reject{ |a| a.user_id == post.user_id }.each do |a|
|
post.topic.all_allowed_users.reject{ |a| a.id == post.user_id }.each do |a|
|
||||||
create_notification(a.user, Notification.types[:private_message], post)
|
create_notification(a, Notification.types[:private_message], post)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# If it's not a private message, notify the users
|
# If it's not a private message, notify the users
|
||||||
|
|
|
@ -38,6 +38,10 @@ class Topic < ActiveRecord::Base
|
||||||
belongs_to :category
|
belongs_to :category
|
||||||
has_many :posts
|
has_many :posts
|
||||||
has_many :topic_allowed_users
|
has_many :topic_allowed_users
|
||||||
|
has_many :topic_allowed_groups
|
||||||
|
|
||||||
|
has_many :allowed_group_users, through: :allowed_groups, source: :users
|
||||||
|
has_many :allowed_groups, through: :topic_allowed_groups, source: :group
|
||||||
has_many :allowed_users, through: :topic_allowed_users, source: :user
|
has_many :allowed_users, through: :topic_allowed_users, source: :user
|
||||||
|
|
||||||
has_one :hot_topic
|
has_one :hot_topic
|
||||||
|
@ -94,6 +98,12 @@ class Topic < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# all users (in groups or directly targetted) that are going to get the pm
|
||||||
|
def all_allowed_users
|
||||||
|
# TODO we should probably change this from 3 queries to 1
|
||||||
|
User.where('id in (?)', allowed_users.select('users.id').to_a + allowed_group_users.select('users.id').to_a)
|
||||||
|
end
|
||||||
|
|
||||||
# Additional rate limits on topics: per day and private messages per day
|
# Additional rate limits on topics: per day and private messages per day
|
||||||
def limit_topics_per_day
|
def limit_topics_per_day
|
||||||
RateLimiter.new(user, "topics-per-day:#{Date.today.to_s}", SiteSetting.max_topics_per_day, 1.day.to_i)
|
RateLimiter.new(user, "topics-per-day:#{Date.today.to_s}", SiteSetting.max_topics_per_day, 1.day.to_i)
|
||||||
|
|
7
app/models/topic_allowed_group.rb
Normal file
7
app/models/topic_allowed_group.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
class TopicAllowedGroup < ActiveRecord::Base
|
||||||
|
belongs_to :topic
|
||||||
|
belongs_to :group
|
||||||
|
attr_accessible :group_id, :user_id
|
||||||
|
|
||||||
|
validates_uniqueness_of :topic_id, scope: :group_id
|
||||||
|
end
|
|
@ -51,8 +51,8 @@ class TopicList
|
||||||
|
|
||||||
def has_rank_details?
|
def has_rank_details?
|
||||||
|
|
||||||
# Only admins can see rank details
|
# Only moderators can see rank details
|
||||||
return false unless @current_user.try(:admin?)
|
return false unless @current_user.try(:moderator?)
|
||||||
|
|
||||||
# Only show them on 'Hot'
|
# Only show them on 'Hot'
|
||||||
return @filter == :hot
|
return @filter == :hot
|
||||||
|
|
|
@ -15,8 +15,15 @@ class CurrentUserSerializer < BasicUserSerializer
|
||||||
|
|
||||||
# we probably want to move this into site, but that json is cached so hanging it off current user seems okish
|
# we probably want to move this into site, but that json is cached so hanging it off current user seems okish
|
||||||
|
|
||||||
|
def moderator
|
||||||
|
# TODO we probably want better terminology
|
||||||
|
#
|
||||||
|
# we have admins / moderators and users who are either moderators or admins denoted by moderator?
|
||||||
|
object.moderator?
|
||||||
|
end
|
||||||
|
|
||||||
def include_site_flagged_posts_count?
|
def include_site_flagged_posts_count?
|
||||||
object.admin
|
object.moderator?
|
||||||
end
|
end
|
||||||
|
|
||||||
def topic_count
|
def topic_count
|
||||||
|
|
|
@ -88,7 +88,7 @@ class PostSerializer < ApplicationSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def cooked
|
def cooked
|
||||||
if object.hidden && !scope.is_admin?
|
if object.hidden && !scope.is_moderator?
|
||||||
if scope.current_user && object.user_id == scope.current_user.id
|
if scope.current_user && object.user_id == scope.current_user.id
|
||||||
I18n.t('flagging.you_must_edit')
|
I18n.t('flagging.you_must_edit')
|
||||||
else
|
else
|
||||||
|
@ -154,7 +154,7 @@ class PostSerializer < ApplicationSerializer
|
||||||
|
|
||||||
# The following only applies if you're logged in
|
# The following only applies if you're logged in
|
||||||
if action_summary[:can_act] && scope.current_user.present?
|
if action_summary[:can_act] && scope.current_user.present?
|
||||||
action_summary[:can_clear_flags] = scope.is_admin? && PostActionType.flag_types.values.include?(id)
|
action_summary[:can_clear_flags] = scope.is_moderator? && PostActionType.flag_types.values.include?(id)
|
||||||
end
|
end
|
||||||
|
|
||||||
if post_actions.present? && post_actions.has_key?(id)
|
if post_actions.present? && post_actions.has_key?(id)
|
||||||
|
@ -163,7 +163,7 @@ class PostSerializer < ApplicationSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
# anonymize flags
|
# anonymize flags
|
||||||
if !scope.is_admin? && PostActionType.flag_types.values.include?(id)
|
if !scope.is_moderator? && PostActionType.flag_types.values.include?(id)
|
||||||
action_summary[:count] = action_summary[:acted] ? 1 : 0
|
action_summary[:count] = action_summary[:acted] ? 1 : 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<%# load the selected locale before any other scripts %>
|
<%# load the selected locale before any other scripts %>
|
||||||
<%= javascript_include_tag "locales/#{I18n.locale}" %>
|
<%= javascript_include_tag "locales/#{I18n.locale}" %>
|
||||||
<%= javascript_include_tag "application" %>
|
<%= javascript_include_tag "application" %>
|
||||||
<%- if admin? %>
|
<%- if moderator? %>
|
||||||
<%= javascript_include_tag "admin"%>
|
<%= javascript_include_tag "admin"%>
|
||||||
<%- end %>
|
<%- end %>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<%=stylesheet_link_tag "application"%>
|
<%=stylesheet_link_tag "application"%>
|
||||||
<%- end %>
|
<%- end %>
|
||||||
|
|
||||||
<%- if admin? %>
|
<%- if moderator? %>
|
||||||
<%= stylesheet_link_tag "admin"%>
|
<%= stylesheet_link_tag "admin"%>
|
||||||
<%-end%>
|
<%-end%>
|
||||||
<%=SiteCustomization.custom_stylesheet(session[:preview_style])%>
|
<%=SiteCustomization.custom_stylesheet(session[:preview_style])%>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
require 'sidekiq/web'
|
require 'sidekiq/web'
|
||||||
|
|
||||||
require_dependency 'admin_constraint'
|
require_dependency 'admin_constraint'
|
||||||
|
require_dependency 'moderator_constraint'
|
||||||
require_dependency 'homepage_constraint'
|
require_dependency 'homepage_constraint'
|
||||||
|
|
||||||
# This used to be User#username_format, but that causes a preload of the User object
|
# This used to be User#username_format, but that causes a preload of the User object
|
||||||
|
@ -21,13 +22,14 @@ Discourse::Application.routes.draw do
|
||||||
end
|
end
|
||||||
get 'srv/status' => 'forums#status'
|
get 'srv/status' => 'forums#status'
|
||||||
|
|
||||||
namespace :admin, constraints: AdminConstraint.new do
|
namespace :admin, constraints: ModeratorConstraint.new do
|
||||||
get '' => 'admin#index'
|
get '' => 'admin#index'
|
||||||
|
|
||||||
resources :site_settings
|
resources :site_settings, constraints: AdminConstraint.new
|
||||||
|
|
||||||
get 'reports/:type' => 'reports#show'
|
get 'reports/:type' => 'reports#show'
|
||||||
|
|
||||||
resources :groups
|
resources :groups, constraints: AdminConstraint.new
|
||||||
resources :users, id: USERNAME_ROUTE_FORMAT do
|
resources :users, id: USERNAME_ROUTE_FORMAT do
|
||||||
collection do
|
collection do
|
||||||
get 'list/:query' => 'users#index'
|
get 'list/:query' => 'users#index'
|
||||||
|
@ -36,35 +38,35 @@ Discourse::Application.routes.draw do
|
||||||
put 'ban'
|
put 'ban'
|
||||||
put 'delete_all_posts'
|
put 'delete_all_posts'
|
||||||
put 'unban'
|
put 'unban'
|
||||||
put 'revoke_admin'
|
put 'revoke_admin', constraints: AdminConstraint.new
|
||||||
put 'grant_admin'
|
put 'grant_admin', constraints: AdminConstraint.new
|
||||||
put 'revoke_moderation'
|
put 'revoke_moderation', constraints: AdminConstraint.new
|
||||||
put 'grant_moderation'
|
put 'grant_moderation', constraints: AdminConstraint.new
|
||||||
put 'approve'
|
put 'approve'
|
||||||
post 'refresh_browsers'
|
post 'refresh_browsers', constraints: AdminConstraint.new
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :impersonate
|
resources :impersonate, constraints: AdminConstraint.new
|
||||||
resources :email_logs do
|
resources :email_logs do
|
||||||
collection do
|
collection do
|
||||||
post 'test'
|
post 'test'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
get 'customize' => 'site_customizations#index'
|
get 'customize' => 'site_customizations#index', constraints: AdminConstraint.new
|
||||||
get 'flags' => 'flags#index'
|
get 'flags' => 'flags#index'
|
||||||
get 'flags/:filter' => 'flags#index'
|
get 'flags/:filter' => 'flags#index'
|
||||||
post 'flags/clear/:id' => 'flags#clear'
|
post 'flags/clear/:id' => 'flags#clear'
|
||||||
resources :site_customizations
|
resources :site_customizations, constraints: AdminConstraint.new
|
||||||
resources :site_contents
|
resources :site_contents, constraints: AdminConstraint.new
|
||||||
resources :site_content_types
|
resources :site_content_types, constraints: AdminConstraint.new
|
||||||
resources :export
|
resources :export, constraints: AdminConstraint.new
|
||||||
get 'version_check' => 'versions#show'
|
get 'version_check' => 'versions#show'
|
||||||
resources :dashboard, only: [:index] do
|
resources :dashboard, only: [:index] do
|
||||||
collection do
|
collection do
|
||||||
get 'problems'
|
get 'problems'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :api, only: [:index] do
|
resources :api, only: [:index], constraints: AdminConstraint.new do
|
||||||
collection do
|
collection do
|
||||||
post 'generate_key'
|
post 'generate_key'
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
class AddTopicAllowedGroups < ActiveRecord::Migration
|
class AddTopicAllowedGroups < ActiveRecord::Migration
|
||||||
def change
|
def change
|
||||||
create_table :topic_allowed_groups do |t|
|
create_table :topic_allowed_groups do |t|
|
||||||
|
# oops
|
||||||
t.integer :group_id, :integer, null: false
|
t.integer :group_id, :integer, null: false
|
||||||
t.integer :topic_id, :integer, null: false
|
t.integer :topic_id, :integer, null: false
|
||||||
end
|
end
|
||||||
|
|
6
db/migrate/20130501105651_fix_topic_allowed_groups.rb
Normal file
6
db/migrate/20130501105651_fix_topic_allowed_groups.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class FixTopicAllowedGroups < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
# big oops
|
||||||
|
remove_column :topic_allowed_groups, :integer
|
||||||
|
end
|
||||||
|
end
|
|
@ -207,7 +207,7 @@ class Guardian
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_see_private_messages?(user_id)
|
def can_see_private_messages?(user_id)
|
||||||
return true if is_admin?
|
return true if is_moderator?
|
||||||
return false if @user.blank?
|
return false if @user.blank?
|
||||||
@user.id == user_id
|
@user.id == user_id
|
||||||
end
|
end
|
||||||
|
@ -263,7 +263,7 @@ class Guardian
|
||||||
|
|
||||||
def can_edit_user?(user)
|
def can_edit_user?(user)
|
||||||
return true if user == @user
|
return true if user == @user
|
||||||
@user.admin?
|
@user.moderator?
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_edit_topic?(topic)
|
def can_edit_topic?(topic)
|
||||||
|
@ -311,12 +311,12 @@ class Guardian
|
||||||
return post_action.created_at > SiteSetting.post_undo_action_window_mins.minutes.ago
|
return post_action.created_at > SiteSetting.post_undo_action_window_mins.minutes.ago
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_send_private_message?(target_user)
|
def can_send_private_message?(target)
|
||||||
return false unless User === target_user
|
return false unless User === target || Group === target
|
||||||
return false if @user.blank?
|
return false if @user.blank?
|
||||||
|
|
||||||
# Can't send message to yourself
|
# Can't send message to yourself
|
||||||
return false if @user.id == target_user.id
|
return false if User === target && @user.id == target.id
|
||||||
|
|
||||||
# Have to be a basic level at least
|
# Have to be a basic level at least
|
||||||
return false unless @user.has_trust_level?(:basic)
|
return false unless @user.has_trust_level?(:basic)
|
||||||
|
@ -336,15 +336,15 @@ class Guardian
|
||||||
return false unless topic
|
return false unless topic
|
||||||
|
|
||||||
return true if @user && @user.moderator?
|
return true if @user && @user.moderator?
|
||||||
return false if topic.deleted_at.present?
|
return false if topic.deleted_at
|
||||||
|
|
||||||
if topic.category && topic.category.secure
|
if topic.category && topic.category.secure
|
||||||
return false unless @user && can_see_category?(topic.category)
|
return false unless @user && can_see_category?(topic.category)
|
||||||
end
|
end
|
||||||
|
|
||||||
if topic.private_message?
|
if topic.private_message?
|
||||||
return false if @user.blank?
|
return false unless @user
|
||||||
return true if topic.allowed_users.include?(@user)
|
return true if topic.all_allowed_users.where(id: @user.id).exists?
|
||||||
return is_admin?
|
return is_admin?
|
||||||
end
|
end
|
||||||
true
|
true
|
||||||
|
@ -375,11 +375,11 @@ class Guardian
|
||||||
def post_can_act?(post, action_key, opts={})
|
def post_can_act?(post, action_key, opts={})
|
||||||
return false if @user.blank?
|
return false if @user.blank?
|
||||||
return false if post.blank?
|
return false if post.blank?
|
||||||
return false if post.topic.archived?
|
|
||||||
|
|
||||||
taken = opts[:taken_actions]
|
taken = opts[:taken_actions]
|
||||||
taken = taken.keys if taken
|
taken = taken.keys if taken
|
||||||
|
|
||||||
|
# we always allow flagging
|
||||||
if PostActionType.is_flag?(action_key)
|
if PostActionType.is_flag?(action_key)
|
||||||
return false unless @user.has_trust_level?(:basic)
|
return false unless @user.has_trust_level?(:basic)
|
||||||
|
|
||||||
|
@ -390,6 +390,9 @@ class Guardian
|
||||||
return false if taken && taken.include?(PostActionType.types[action_key])
|
return false if taken && taken.include?(PostActionType.types[action_key])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# nothing else on archived posts
|
||||||
|
return false if post.topic.archived?
|
||||||
|
|
||||||
case action_key
|
case action_key
|
||||||
when :like
|
when :like
|
||||||
return false if post.user == @user
|
return false if post.user == @user
|
||||||
|
|
10
lib/moderator_constraint.rb
Normal file
10
lib/moderator_constraint.rb
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
require_dependency 'current_user'
|
||||||
|
|
||||||
|
class ModeratorConstraint
|
||||||
|
|
||||||
|
def matches?(request)
|
||||||
|
return false unless request.session[:current_user_id].present?
|
||||||
|
User.where("admin = 't' or moderator = 't'").where(id: request.session[:current_user_id].to_i).exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -56,17 +56,14 @@ class PostCreator
|
||||||
|
|
||||||
topic.subtype = TopicSubtype.user_to_user unless topic.subtype
|
topic.subtype = TopicSubtype.user_to_user unless topic.subtype
|
||||||
|
|
||||||
usernames = @opts[:target_usernames].split(',')
|
unless @opts[:target_usernames].present? || @opts[:target_group_names].present?
|
||||||
User.where(username: usernames).each do |u|
|
|
||||||
|
|
||||||
unless guardian.can_send_private_message?(u)
|
|
||||||
topic.errors.add(:archetype, :cant_send_pm)
|
topic.errors.add(:archetype, :cant_send_pm)
|
||||||
@errors = topic.errors
|
@errors = topic.errors
|
||||||
raise ActiveRecord::Rollback.new
|
raise ActiveRecord::Rollback.new
|
||||||
end
|
end
|
||||||
|
|
||||||
topic.topic_allowed_users.build(user_id: u.id)
|
add_users(topic,@opts[:target_usernames])
|
||||||
end
|
add_groups(topic,@opts[:target_group_names])
|
||||||
topic.topic_allowed_users.build(user_id: @user.id)
|
topic.topic_allowed_users.build(user_id: @user.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -148,4 +145,35 @@ class PostCreator
|
||||||
PostCreator.new(user, opts).create
|
PostCreator.new(user, opts).create
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def add_users(topic, usernames)
|
||||||
|
return unless usernames
|
||||||
|
usernames = usernames.split(',')
|
||||||
|
User.where(username: usernames).each do |u|
|
||||||
|
|
||||||
|
unless guardian.can_send_private_message?(u)
|
||||||
|
topic.errors.add(:archetype, :cant_send_pm)
|
||||||
|
@errors = topic.errors
|
||||||
|
raise ActiveRecord::Rollback.new
|
||||||
|
end
|
||||||
|
|
||||||
|
topic.topic_allowed_users.build(user_id: u.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_groups(topic, groups)
|
||||||
|
return unless groups
|
||||||
|
groups = groups.split(',')
|
||||||
|
Group.where(name: groups).each do |g|
|
||||||
|
|
||||||
|
unless guardian.can_send_private_message?(g)
|
||||||
|
topic.errors.add(:archetype, :cant_send_pm)
|
||||||
|
@errors = topic.errors
|
||||||
|
raise ActiveRecord::Rollback.new
|
||||||
|
end
|
||||||
|
|
||||||
|
topic.topic_allowed_groups.build(group_id: g.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -485,8 +485,8 @@ describe Guardian do
|
||||||
Guardian.new(user).can_edit?(user).should be_true
|
Guardian.new(user).can_edit?(user).should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns false as a moderator' do
|
it 'returns true as a moderator' do
|
||||||
Guardian.new(moderator).can_edit?(user).should be_false
|
Guardian.new(moderator).can_edit?(user).should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns true as an admin' do
|
it 'returns true as an admin' do
|
||||||
|
|
|
@ -190,5 +190,35 @@ describe PostCreator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'private message to group' do
|
||||||
|
let(:target_user1) { Fabricate(:coding_horror) }
|
||||||
|
let(:target_user2) { Fabricate(:moderator) }
|
||||||
|
let(:group) do
|
||||||
|
g = Fabricate.build(:group)
|
||||||
|
g.add(target_user1)
|
||||||
|
g.add(target_user2)
|
||||||
|
g.save
|
||||||
|
g
|
||||||
|
end
|
||||||
|
let(:unrelated) { Fabricate(:user) }
|
||||||
|
let(:post) do
|
||||||
|
PostCreator.create(user, title: 'hi there welcome to my topic',
|
||||||
|
raw: "this is my awesome message @#{unrelated.username_lower}",
|
||||||
|
archetype: Archetype.private_message,
|
||||||
|
target_group_names: group.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'acts correctly' do
|
||||||
|
post.topic.archetype.should == Archetype.private_message
|
||||||
|
post.topic.topic_allowed_users.count.should == 1
|
||||||
|
post.topic.topic_allowed_groups.count.should == 1
|
||||||
|
|
||||||
|
# does not notify an unrelated user
|
||||||
|
unrelated.notifications.count.should == 0
|
||||||
|
post.topic.subtype.should == TopicSubtype.user_to_user
|
||||||
|
target_user1.notifications.count.should == 1
|
||||||
|
target_user2.notifications.count.should == 1
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue