mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 17:46:05 -05:00
more group progress, UI getting there, controller mostly done
changed it so notify moderators goes to the moderators group allow admins to grant self moderation and revoke self moderation
This commit is contained in:
parent
4f328e3e45
commit
5280b3a01b
27 changed files with 224 additions and 61 deletions
|
@ -1,9 +1,9 @@
|
||||||
Discourse.AdminGroupsController = Ember.ArrayController.extend({
|
Discourse.AdminGroupsController = Ember.Controller.extend({
|
||||||
itemController: 'adminGroup',
|
itemController: 'adminGroup',
|
||||||
|
|
||||||
edit: function(group){
|
edit: function(group){
|
||||||
this.get('model').select(group);
|
this.get('model').select(group);
|
||||||
group.loadUsers();
|
group.load();
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshAutoGroups: function(){
|
refreshAutoGroups: function(){
|
||||||
|
@ -14,9 +14,31 @@ Discourse.AdminGroupsController = Ember.ArrayController.extend({
|
||||||
controller.set('model', Discourse.Group.findAll());
|
controller.set('model', Discourse.Group.findAll());
|
||||||
controller.set('refreshingAutoGroups',false);
|
controller.set('refreshingAutoGroups',false);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
newGroup: function(){
|
||||||
|
var group = Discourse.Group.create();
|
||||||
|
group.set("loaded", true);
|
||||||
|
var model = this.get("model");
|
||||||
|
model.addObject(group);
|
||||||
|
model.select(group);
|
||||||
|
},
|
||||||
|
|
||||||
|
save: function(group){
|
||||||
|
if(!group.get("id")){
|
||||||
|
group.create();
|
||||||
|
} else {
|
||||||
|
group.save();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function(group){
|
||||||
|
var list = this.get("model");
|
||||||
|
if(group.get("id")){
|
||||||
|
group.destroy().then(function(){
|
||||||
|
list.removeObject(group);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Discourse.AdminGroupController = Ember.Controller.extend({
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
|
@ -26,7 +26,8 @@ Discourse.FlaggedPost = Discourse.Post.extend({
|
||||||
if (a.message) {
|
if (a.message) {
|
||||||
return r.push({
|
return r.push({
|
||||||
user: _this.userLookup[a.user_id],
|
user: _this.userLookup[a.user_id],
|
||||||
message: a.message
|
message: a.message,
|
||||||
|
permalink: a.permalink
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
Discourse.Group = Discourse.Model.extend({
|
Discourse.Group = Discourse.Model.extend({
|
||||||
|
loaded: false,
|
||||||
|
|
||||||
userCountDisplay: function(){
|
userCountDisplay: function(){
|
||||||
var c = this.get('user_count');
|
var c = this.get('user_count');
|
||||||
// don't display zero its ugly
|
// don't display zero its ugly
|
||||||
|
@ -7,16 +9,19 @@ Discourse.Group = Discourse.Model.extend({
|
||||||
}
|
}
|
||||||
}.property('user_count'),
|
}.property('user_count'),
|
||||||
|
|
||||||
loadUsers: function() {
|
load: function() {
|
||||||
var group = this;
|
var id = this.get('id');
|
||||||
|
if(id && !this.get('loaded')) {
|
||||||
Discourse.ajax('/admin/groups/' + this.get('id') + '/users').then(function(payload){
|
var group = this;
|
||||||
var users = Em.A()
|
Discourse.ajax('/admin/groups/' + this.get('id') + '/users').then(function(payload){
|
||||||
payload.each(function(user){
|
var users = Em.A()
|
||||||
users.addObject(Discourse.User.create(user));
|
payload.each(function(user){
|
||||||
|
users.addObject(Discourse.User.create(user));
|
||||||
|
});
|
||||||
|
group.set('users', users)
|
||||||
|
group.set('loaded', true)
|
||||||
});
|
});
|
||||||
group.set('users', users)
|
}
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
usernames: function() {
|
usernames: function() {
|
||||||
|
@ -28,7 +33,32 @@ Discourse.Group = Discourse.Model.extend({
|
||||||
}).join(',')
|
}).join(',')
|
||||||
}
|
}
|
||||||
return usernames;
|
return usernames;
|
||||||
}.property('users')
|
}.property('users'),
|
||||||
|
|
||||||
|
destroy: function(){
|
||||||
|
var group = this;
|
||||||
|
group.set('disableSave', true);
|
||||||
|
|
||||||
|
return Discourse.ajax("/admin/groups/" + this.get("id"), {type: "DELETE"})
|
||||||
|
.then(function(){
|
||||||
|
group.set('disableSave', false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
create: function(){
|
||||||
|
var group = this;
|
||||||
|
group.set('disableSave', true);
|
||||||
|
|
||||||
|
return Discourse.ajax("/admin/groups", {type: "POST", data: {
|
||||||
|
group: {
|
||||||
|
name: this.get('name'),
|
||||||
|
usernames: this.get('usernames')
|
||||||
|
}
|
||||||
|
}}).then(function(r){
|
||||||
|
group.set('disableSave', false);
|
||||||
|
group.set('id', r.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td class='message'>
|
<td class='message'>
|
||||||
<div>{{#linkTo 'adminUser' user}}{{avatar user imageSize="small"}}{{/linkTo}} {{message}}</div>
|
<div>{{#linkTo 'adminUser' user}}{{avatar user imageSize="small"}}{{/linkTo}} {{message}} <a href="{{unbound permalink}}">{{i18n admin.flags.view_message}}</a></div>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!-- work in progress, please ignore -->
|
<!-- work in progress, please ignore -->
|
||||||
<div class='row'>
|
<div class='row groups'>
|
||||||
<div class='content-list span6'>
|
<div class='content-list span6'>
|
||||||
<h3>{{i18n admin.groups.edit}}</h3>
|
<h3>{{i18n admin.groups.edit}}</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -9,19 +9,35 @@
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
<div>
|
<div class='controls'>
|
||||||
<button {{bindAttr disabled="refreshingAutoGroups"}} {{action "refreshAutoGroups"}}>Refresh Automatic Groups</button>
|
<button class='btn' {{bindAttr disabled="refreshingAutoGroups"}} {{action "refreshAutoGroups"}}>Refresh</button>
|
||||||
|
<button class='btn' {{action newGroup}}>New</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='content-editor'>
|
<div class='content-editor'>
|
||||||
{{#if model.active}}
|
{{#if model.active}}
|
||||||
{{#with model.active}}
|
{{#if model.active.loaded}}
|
||||||
<h3>{{name}}</h3>
|
{{#with model.active}}
|
||||||
{{view Discourse.UserSelector id="private-message-users" class="span8" placeholderKey="admin.groups.selector_placeholder" tabindex="1" usernamesBinding="usernames"}}
|
{{#if automatic}}
|
||||||
<button {{bindAttr disabled="allowSave"}}>Save</button>
|
<h3>{{name}}</h3>
|
||||||
|
{{else}}
|
||||||
|
{{view Discourse.TextField valueBinding="name" placeholderKey="admin.groups.name_placeholder"}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{/with}}
|
{{view Discourse.UserSelector id="group-users" placeholderKey="admin.groups.selector_placeholder" tabindex="1" usernamesBinding="usernames"}}
|
||||||
|
<div class='controls'>
|
||||||
|
<button {{action save this}} {{bindAttr disabled="disableSave"}} class='btn'>{{i18n admin.customize.save}}</button>
|
||||||
|
{{#unless automatic}}
|
||||||
|
{{#if id}}
|
||||||
|
<a {{action destroy this}} class='delete-link'>{{i18n admin.customize.delete}}</a>
|
||||||
|
{{/if}}
|
||||||
|
{{/unless}}
|
||||||
|
</div>
|
||||||
|
{{/with}}
|
||||||
|
{{else}}
|
||||||
|
<div class='spinner'>{{i18n loading}}</div>
|
||||||
|
{{/if}}
|
||||||
{{else}}
|
{{else}}
|
||||||
nothing here yet
|
nothing here yet
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -18,5 +18,13 @@ Discourse.SelectableArray = Em.ArrayProxy.extend({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.set("active", selected);
|
this.set("active", selected);
|
||||||
|
},
|
||||||
|
removeObject: function(object) {
|
||||||
|
if(object === this.get("active")){
|
||||||
|
this.set("active", null);
|
||||||
|
Em.set(object, "active", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._super(object);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
<h3><i class='icon icon-envelope-alt'></i> {{i18n private_message_info.title}}</h3>
|
<h3><i class='icon icon-envelope-alt'></i> {{i18n private_message_info.title}}</h3>
|
||||||
<div class='participants clearfix'>
|
<div class='participants clearfix'>
|
||||||
|
{{#each content.allowed_groups}}
|
||||||
|
<div class='user group'>
|
||||||
|
#{{unbound name}}
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
{{#each content.allowed_users}}
|
{{#each content.allowed_users}}
|
||||||
<div class='user'>
|
<div class='user'>
|
||||||
<a href='/users/{{lower username}}'>
|
<a href='/users/{{lower username}}'>
|
||||||
|
|
|
@ -654,3 +654,12 @@ table {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.row.groups {
|
||||||
|
input[type='text'] {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
input#group-users {
|
||||||
|
width: 600px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -451,7 +451,12 @@ kbd {
|
||||||
.private_message .participants .user {
|
.private_message .participants .user {
|
||||||
float: left;
|
float: left;
|
||||||
display: block;
|
display: block;
|
||||||
|
line-height: 35px;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
|
margin-top: 8px;
|
||||||
|
&.group {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.posts-wrapper .spinner {
|
.posts-wrapper .spinner {
|
||||||
|
|
|
@ -56,20 +56,23 @@ limit 100
|
||||||
map[p["id"]] = p
|
map[p["id"]] = p
|
||||||
}
|
}
|
||||||
|
|
||||||
sql = SqlBuilder.new "select a.id, a.user_id, post_action_type_id, a.created_at, post_id, a.message
|
sql = SqlBuilder.new "select a.id, a.user_id, post_action_type_id, a.created_at, post_id, a.message, p.topic_id, t.slug
|
||||||
from post_actions a
|
from post_actions a
|
||||||
|
left join posts p on p.id = related_post_id
|
||||||
|
left join topics t on t.id = p.topic_id
|
||||||
/*where*/
|
/*where*/
|
||||||
"
|
"
|
||||||
sql.where("post_action_type_id in (:flag_types)", flag_types: PostActionType.notify_flag_types.values)
|
sql.where("post_action_type_id in (:flag_types)", flag_types: PostActionType.notify_flag_types.values)
|
||||||
sql.where("post_id in (:posts)", posts: posts.map{|p| p["id"].to_i})
|
sql.where("post_id in (:posts)", posts: posts.map{|p| p["id"].to_i})
|
||||||
|
|
||||||
if params[:filter] == 'old'
|
if params[:filter] == 'old'
|
||||||
sql.where('deleted_at is not null')
|
sql.where('a.deleted_at is not null')
|
||||||
else
|
else
|
||||||
sql.where('deleted_at is null')
|
sql.where('a.deleted_at is null')
|
||||||
end
|
end
|
||||||
|
|
||||||
sql.exec.each do |action|
|
sql.exec.each do |action|
|
||||||
|
action["permalink"] = Topic.url(action["topic_id"],action["slug"]) if action["slug"].present?
|
||||||
p = map[action["post_id"]]
|
p = map[action["post_id"]]
|
||||||
p[:post_actions] ||= []
|
p[:post_actions] ||= []
|
||||||
p[:post_actions] << action
|
p[:post_actions] << action
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class Admin::GroupsController < Admin::AdminController
|
class Admin::GroupsController < Admin::AdminController
|
||||||
def index
|
def index
|
||||||
groups = Group.order(:name).all
|
groups = Group.order(:name).all
|
||||||
render_serialized(groups, AdminGroupSerializer)
|
render_serialized(groups, BasicGroupSerializer)
|
||||||
end
|
end
|
||||||
|
|
||||||
def refresh_automatic_groups
|
def refresh_automatic_groups
|
||||||
|
@ -11,7 +11,7 @@ class Admin::GroupsController < Admin::AdminController
|
||||||
|
|
||||||
def users
|
def users
|
||||||
group = Group.find(params[:group_id].to_i)
|
group = Group.find(params[:group_id].to_i)
|
||||||
render_serialized(group.users, BasicUserSerializer)
|
render_serialized(group.users.limit(100).to_a, BasicUserSerializer)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
@ -28,7 +28,7 @@ class Admin::GroupsController < Admin::AdminController
|
||||||
group.name = params[:group][:name]
|
group.name = params[:group][:name]
|
||||||
group.usernames = params[:group][:usernames] if params[:group][:usernames]
|
group.usernames = params[:group][:usernames] if params[:group][:usernames]
|
||||||
group.save!
|
group.save!
|
||||||
render_serialized(group, AdminGroupSerializer)
|
render_serialized(group, BasicGroupSerializer)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
|
@ -7,6 +7,8 @@ class Group < ActiveRecord::Base
|
||||||
|
|
||||||
after_save :destroy_deletions
|
after_save :destroy_deletions
|
||||||
|
|
||||||
|
validate :name_format_validator
|
||||||
|
|
||||||
AUTO_GROUPS = {
|
AUTO_GROUPS = {
|
||||||
:admins => 1,
|
:admins => 1,
|
||||||
:moderators => 2,
|
:moderators => 2,
|
||||||
|
@ -26,8 +28,8 @@ class Group < ActiveRecord::Base
|
||||||
|
|
||||||
id = AUTO_GROUPS[name]
|
id = AUTO_GROUPS[name]
|
||||||
|
|
||||||
unless group = self[name]
|
unless group = self.lookup_group(name)
|
||||||
group = Group.new(name: "", automatic: true)
|
group = Group.new(name: name.to_s, automatic: true)
|
||||||
group.id = id
|
group.id = id
|
||||||
group.save!
|
group.save!
|
||||||
end
|
end
|
||||||
|
@ -61,6 +63,8 @@ class Group < ActiveRecord::Base
|
||||||
|
|
||||||
# we want to ensure consistency
|
# we want to ensure consistency
|
||||||
Group.reset_counters(group.id, :group_users)
|
Group.reset_counters(group.id, :group_users)
|
||||||
|
|
||||||
|
group
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.refresh_automatic_groups!(*args)
|
def self.refresh_automatic_groups!(*args)
|
||||||
|
@ -73,9 +77,15 @@ class Group < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.[](name)
|
def self.[](name)
|
||||||
raise ArgumentError, "unknown group" unless id = AUTO_GROUPS[name]
|
unless g = lookup_group(name)
|
||||||
|
g = refresh_automatic_group!(name)
|
||||||
|
end
|
||||||
|
g
|
||||||
|
end
|
||||||
|
|
||||||
Group.where(id: id).first
|
def self.lookup_group(name)
|
||||||
|
raise ArgumentError, "unknown group" unless id = AUTO_GROUPS[name]
|
||||||
|
g = Group.where(id: id).first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,7 +94,7 @@ class Group < ActiveRecord::Base
|
||||||
|
|
||||||
GroupUser.where(group_id: trust_group_ids, user_id: user_id).delete_all
|
GroupUser.where(group_id: trust_group_ids, user_id: user_id).delete_all
|
||||||
|
|
||||||
if group = Group[name]
|
if group = lookup_group(name)
|
||||||
group.group_users.build(user_id: user_id)
|
group.group_users.build(user_id: user_id)
|
||||||
group.save!
|
group.save!
|
||||||
else
|
else
|
||||||
|
@ -92,6 +102,7 @@ class Group < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def self.builtin
|
def self.builtin
|
||||||
Enum.new(:moderators, :admins, :trust_level_1, :trust_level_2)
|
Enum.new(:moderators, :admins, :trust_level_1, :trust_level_2)
|
||||||
end
|
end
|
||||||
|
@ -131,9 +142,15 @@ class Group < ActiveRecord::Base
|
||||||
def add(user)
|
def add(user)
|
||||||
self.users.push(user)
|
self.users.push(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
def name_format_validator
|
||||||
|
validator = UsernameValidator.new(name)
|
||||||
|
unless validator.valid_format?
|
||||||
|
validator.errors.each { |e| errors.add(:name, e) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# hack around AR
|
# hack around AR
|
||||||
def destroy_deletions
|
def destroy_deletions
|
||||||
if @deletions
|
if @deletions
|
||||||
|
|
|
@ -74,12 +74,16 @@ class PostAction < ActiveRecord::Base
|
||||||
|
|
||||||
def self.act(user, post, post_action_type_id, message = nil)
|
def self.act(user, post, post_action_type_id, message = nil)
|
||||||
begin
|
begin
|
||||||
title, target_usernames, subtype, body = nil
|
title, target_usernames, target_group_names, subtype, body = nil
|
||||||
|
|
||||||
if message
|
if message
|
||||||
[:notify_moderators, :notify_user].each do |k|
|
[:notify_moderators, :notify_user].each do |k|
|
||||||
if post_action_type_id == PostActionType.types[k]
|
if post_action_type_id == PostActionType.types[k]
|
||||||
target_usernames = k == :notify_moderators ? target_moderators(user) : post.user.username
|
if k == :notify_moderators
|
||||||
|
target_group_names = target_moderators
|
||||||
|
else
|
||||||
|
target_usernames = post.user.username
|
||||||
|
end
|
||||||
title = I18n.t("post_action_types.#{k}.email_title",
|
title = I18n.t("post_action_types.#{k}.email_title",
|
||||||
title: post.topic.title)
|
title: post.topic.title)
|
||||||
body = I18n.t("post_action_types.#{k}.email_body",
|
body = I18n.t("post_action_types.#{k}.email_body",
|
||||||
|
@ -91,9 +95,10 @@ class PostAction < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
related_post_id = nil
|
related_post_id = nil
|
||||||
if target_usernames.present?
|
if target_usernames.present? || target_group_names.present?
|
||||||
related_post_id = PostCreator.new(user,
|
related_post_id = PostCreator.new(user,
|
||||||
target_usernames: target_usernames,
|
target_usernames: target_usernames,
|
||||||
|
target_group_names: target_group_names,
|
||||||
archetype: Archetype.private_message,
|
archetype: Archetype.private_message,
|
||||||
subtype: subtype,
|
subtype: subtype,
|
||||||
title: title,
|
title: title,
|
||||||
|
@ -209,13 +214,8 @@ class PostAction < ActiveRecord::Base
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def self.target_moderators(me)
|
def self.target_moderators
|
||||||
User
|
Group[:moderators].name
|
||||||
.where("moderator = 't' or admin = 't'")
|
|
||||||
.where('id <> ?', [me.id])
|
|
||||||
.select('username')
|
|
||||||
.map{|u| u.username}
|
|
||||||
.join(',')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -641,9 +641,16 @@ class Topic < ActiveRecord::Base
|
||||||
"/t/#{slug}/#{id}/#{posts_count}"
|
"/t/#{slug}/#{id}/#{posts_count}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def self.url(id, slug, post_number=nil)
|
||||||
|
url = "#{Discourse.base_url}/t/#{slug}/#{id}"
|
||||||
|
url << "/#{post_number}" if post_number.to_i > 1
|
||||||
|
url
|
||||||
|
end
|
||||||
|
|
||||||
def relative_url(post_number=nil)
|
def relative_url(post_number=nil)
|
||||||
url = "/t/#{slug}/#{id}"
|
url = "/t/#{slug}/#{id}"
|
||||||
url << "/#{post_number}" if post_number.present? && post_number.to_i > 1
|
url << "/#{post_number}" if post_number.to_i > 1
|
||||||
url
|
url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
class AdminGroupSerializer < ApplicationSerializer
|
class BasicGroupSerializer < ApplicationSerializer
|
||||||
attributes :id, :automatic, :name, :user_count
|
attributes :id, :automatic, :name, :user_count
|
||||||
end
|
end
|
|
@ -50,6 +50,7 @@ class TopicViewSerializer < ApplicationSerializer
|
||||||
has_one :created_by, serializer: BasicUserSerializer, embed: :objects
|
has_one :created_by, serializer: BasicUserSerializer, embed: :objects
|
||||||
has_one :last_poster, serializer: BasicUserSerializer, embed: :objects
|
has_one :last_poster, serializer: BasicUserSerializer, embed: :objects
|
||||||
has_many :allowed_users, serializer: BasicUserSerializer, embed: :objects
|
has_many :allowed_users, serializer: BasicUserSerializer, embed: :objects
|
||||||
|
has_many :allowed_groups, serializer: BasicGroupSerializer, embed: :objects
|
||||||
|
|
||||||
has_many :links, serializer: TopicLinkSerializer, embed: :objects
|
has_many :links, serializer: TopicLinkSerializer, embed: :objects
|
||||||
has_many :participants, serializer: TopicPostCountSerializer, embed: :objects
|
has_many :participants, serializer: TopicPostCountSerializer, embed: :objects
|
||||||
|
@ -172,6 +173,10 @@ class TopicViewSerializer < ApplicationSerializer
|
||||||
object.topic.allowed_users
|
object.topic.allowed_users
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def allowed_groups
|
||||||
|
object.topic.allowed_groups
|
||||||
|
end
|
||||||
|
|
||||||
def include_links?
|
def include_links?
|
||||||
object.links.present?
|
object.links.present?
|
||||||
end
|
end
|
||||||
|
|
|
@ -895,11 +895,13 @@ en:
|
||||||
delete_title: "delete post (if its the first post delete topic)"
|
delete_title: "delete post (if its the first post delete topic)"
|
||||||
flagged_by: "Flagged by"
|
flagged_by: "Flagged by"
|
||||||
error: "Something went wrong"
|
error: "Something went wrong"
|
||||||
|
view_message: "view message"
|
||||||
|
|
||||||
groups:
|
groups:
|
||||||
title: "Groups"
|
title: "Groups"
|
||||||
edit: "Edit Groups"
|
edit: "Edit Groups"
|
||||||
selector_placeholder: "add users"
|
selector_placeholder: "add users"
|
||||||
|
name_placeholder: "Group name, no spaces, same as username rule"
|
||||||
|
|
||||||
api:
|
api:
|
||||||
title: "API"
|
title: "API"
|
||||||
|
|
0
config/locales/server.es.yml
Executable file → Normal file
0
config/locales/server.es.yml
Executable file → Normal file
11
db/migrate/20130509040248_update_sequence_for_groups.rb
Normal file
11
db/migrate/20130509040248_update_sequence_for_groups.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
class UpdateSequenceForGroups < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
# even if you alter a sequence you still need to set the seq
|
||||||
|
execute <<SQL
|
||||||
|
SELECT setval('groups_id_seq', 40)
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
end
|
||||||
|
end
|
5
db/migrate/20130509041351_add_unique_name_to_groups.rb
Normal file
5
db/migrate/20130509041351_add_unique_name_to_groups.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddUniqueNameToGroups < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_index :groups, [:name], unique: true
|
||||||
|
end
|
||||||
|
end
|
|
@ -141,15 +141,16 @@ class Guardian
|
||||||
def can_revoke_moderation?(moderator)
|
def can_revoke_moderation?(moderator)
|
||||||
return false unless is_admin?
|
return false unless is_admin?
|
||||||
return false if moderator.blank?
|
return false if moderator.blank?
|
||||||
return false if @user.id == moderator.id
|
return false if @user.id == moderator.id && !is_admin?
|
||||||
|
return false unless moderator.moderator?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_grant_moderation?(user)
|
def can_grant_moderation?(user)
|
||||||
return false unless is_admin?
|
return false unless is_admin?
|
||||||
return false if user.blank?
|
return false unless user
|
||||||
return false if @user.id == user.id
|
return false if @user.id == user.id && !is_admin?
|
||||||
return false if user.staff?
|
return false if user.moderator?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ class PostCreator
|
||||||
# archetype - Topic archetype
|
# archetype - Topic archetype
|
||||||
# category - Category to assign to topic
|
# category - Category to assign to topic
|
||||||
# target_usernames - comma delimited list of usernames for membership (private message)
|
# target_usernames - comma delimited list of usernames for membership (private message)
|
||||||
|
# target_group_names - comma delimited list of groups for membership (private message)
|
||||||
# meta_data - Topic meta data hash
|
# meta_data - Topic meta data hash
|
||||||
def initialize(user, opts)
|
def initialize(user, opts)
|
||||||
# TODO: we should reload user in case it is tainted, should take in a user_id as opposed to user
|
# TODO: we should reload user in case it is tainted, should take in a user_id as opposed to user
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Fabricator(:group) do
|
Fabricator(:group) do
|
||||||
name 'my group'
|
name 'my_group'
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,22 @@ require 'spec_helper'
|
||||||
|
|
||||||
describe Group do
|
describe Group do
|
||||||
|
|
||||||
|
describe "validation" do
|
||||||
|
let(:group) { build(:group) }
|
||||||
|
|
||||||
|
it "is invalid for blank" do
|
||||||
|
group.name = ""
|
||||||
|
group.valid?.should be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is valid for a longer name" do
|
||||||
|
group.name = "this_is_a_name"
|
||||||
|
group.valid?.should be_true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "Can update moderator/staff/admin groups correctly" do
|
it "Can update moderator/staff/admin groups correctly" do
|
||||||
|
|
||||||
admin = Fabricate(:admin)
|
admin = Fabricate(:admin)
|
||||||
moderator = Fabricate(:moderator)
|
moderator = Fabricate(:moderator)
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ describe PostAction do
|
||||||
describe 'notify_moderators' do
|
describe 'notify_moderators' do
|
||||||
before do
|
before do
|
||||||
PostAction.stubs(:create)
|
PostAction.stubs(:create)
|
||||||
PostAction.expects(:target_moderators).returns("bob")
|
PostAction.expects(:target_moderators).returns("moderators")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "sends an email to all moderators if selected" do
|
it "sends an email to all moderators if selected" do
|
||||||
|
|
Loading…
Reference in a new issue