UI still a tad rough, but we have a first pass of secure categories
This commit is contained in:
parent
4030722a8f
commit
942f168ab6
|
@ -9,7 +9,7 @@
|
|||
<li>{{#linkTo 'adminSiteContents'}}{{i18n admin.site_content.title}}{{/linkTo}}</li>
|
||||
{{/if}}
|
||||
<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 'adminFlags.active'}}{{i18n admin.flags.title}}{{/linkTo}}</li>
|
||||
{{#if Discourse.currentUser.admin}}
|
||||
|
|
|
@ -15,6 +15,9 @@ Discourse.Category = Discourse.Model.extend({
|
|||
if (!this.get('color')) this.set('color', Discourse.SiteSettings.uncategorized_color);
|
||||
if (!this.get('text_color')) this.set('text_color', Discourse.SiteSettings.uncategorized_text_color);
|
||||
}
|
||||
|
||||
this.set("availableGroups", Em.A(this.get("available_groups")));
|
||||
this.set("groups", Em.A(this.groups));
|
||||
},
|
||||
|
||||
url: function() {
|
||||
|
@ -40,7 +43,9 @@ Discourse.Category = Discourse.Model.extend({
|
|||
name: this.get('name'),
|
||||
color: this.get('color'),
|
||||
text_color: this.get('text_color'),
|
||||
hotness: this.get('hotness')
|
||||
hotness: this.get('hotness'),
|
||||
secure: this.get('secure'),
|
||||
group_names: this.get('groups').join(",")
|
||||
},
|
||||
type: this.get('id') ? 'PUT' : 'POST'
|
||||
});
|
||||
|
@ -48,6 +53,17 @@ Discourse.Category = Discourse.Model.extend({
|
|||
|
||||
destroy: function(callback) {
|
||||
return Discourse.ajax("/categories/" + (this.get('slug') || this.get('id')), { type: 'DELETE' });
|
||||
},
|
||||
|
||||
addGroup: function(group){
|
||||
this.get("groups").addObject(group);
|
||||
this.get("availableGroups").removeObject(group);
|
||||
},
|
||||
|
||||
|
||||
removeGroup: function(group){
|
||||
this.get("groups").removeObject(group);
|
||||
this.get("availableGroups").addObject(group);
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -23,10 +23,30 @@
|
|||
{{/if}}
|
||||
</section>
|
||||
|
||||
<section class='field'>
|
||||
<label>{{i18n category.security}}</label>
|
||||
<label>
|
||||
{{view Ember.Checkbox checkedBinding="secure"}}
|
||||
{{i18n category.is_secure}}
|
||||
</label>
|
||||
{{#if secure}}
|
||||
<div>
|
||||
{{i18n category.allowed_groups}}
|
||||
{{#each groups}}
|
||||
{{this}} <a {{action removeGroup this target="view"}}>x</a>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{view Ember.Select contentBinding="availableGroups" valueBinding="view.selectedGroup"}}
|
||||
<button {{action addGroup target="view"}}>{{i18n category.add_group}}</button>
|
||||
{{/if}}
|
||||
</section>
|
||||
|
||||
<!-- Sam, disabled for now
|
||||
<section class='field'>
|
||||
<label>{{i18n category.hotness}}</label>
|
||||
{{view Discourse.HotnessView hotnessBinding="hotness"}}
|
||||
</section>
|
||||
-->
|
||||
{{/unless}}
|
||||
|
||||
<section class='field'>
|
||||
|
@ -58,4 +78,4 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{/with}}
|
||||
{{/with}}
|
||||
|
|
|
@ -93,6 +93,16 @@ Discourse.EditCategoryView = Discourse.ModalBodyView.extend({
|
|||
return false;
|
||||
},
|
||||
|
||||
addGroup: function(){
|
||||
this.get("category").addGroup(this.get("selectedGroup"));
|
||||
},
|
||||
|
||||
removeGroup: function(group){
|
||||
// OBVIOUS, Ember treats this as Ember.String, we need a real string here
|
||||
group = group + "";
|
||||
this.get("category").removeGroup(group);
|
||||
},
|
||||
|
||||
saveCategory: function() {
|
||||
var categoryView = this;
|
||||
this.set('saving', true);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
vertical-align: middle;
|
||||
padding-top: 4px;
|
||||
padding-left: 15px;
|
||||
max-width: 320px;
|
||||
max-width: 300px;
|
||||
|
||||
.colorpicker {
|
||||
border: 1px solid $darkish_gray;
|
||||
|
|
|
@ -265,7 +265,6 @@ body {
|
|||
}
|
||||
select, textarea {
|
||||
display: inline-block;
|
||||
height: 18px;
|
||||
padding: 4px;
|
||||
margin-bottom: 9px;
|
||||
font-size: 13px;
|
||||
|
|
|
@ -48,7 +48,7 @@ class CategoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def category_param_keys
|
||||
[required_param_keys, :hotness].flatten!
|
||||
[required_param_keys, :hotness, :secure, :group_names].flatten!
|
||||
end
|
||||
|
||||
def category_params
|
||||
|
|
|
@ -92,7 +92,7 @@ class PostsController < ApplicationController
|
|||
|
||||
result = {post: post_serializer.as_json}
|
||||
if revisor.category_changed.present?
|
||||
result[:category] = CategorySerializer.new(revisor.category_changed, scope: guardian, root: false).as_json
|
||||
result[:category] = BasicCategorySerializer.new(revisor.category_changed, scope: guardian, root: false).as_json
|
||||
end
|
||||
|
||||
render_json_dump(result)
|
||||
|
|
|
@ -99,6 +99,15 @@ class Category < ActiveRecord::Base
|
|||
self.secure
|
||||
end
|
||||
|
||||
def group_names=(names)
|
||||
# this line bothers me, destroying in AR can not seem to be queued, thinking of extending it
|
||||
category_groups.destroy_all unless new_record?
|
||||
ids = Group.where(name: names.split(",")).select(:id).map(&:id)
|
||||
ids.each do |id|
|
||||
category_groups.build(group_id: id)
|
||||
end
|
||||
end
|
||||
|
||||
def deny(group)
|
||||
if group == :all
|
||||
self.secure = true
|
||||
|
@ -108,7 +117,8 @@ class Category < ActiveRecord::Base
|
|||
def allow(group)
|
||||
if group == :all
|
||||
self.secure = false
|
||||
category_groups.clear
|
||||
# this is kind of annoying, there should be a clean way of queuing this stuff
|
||||
category_groups.destroy_all unless new_record?
|
||||
else
|
||||
groups.push(group)
|
||||
end
|
||||
|
|
|
@ -9,7 +9,15 @@ class CategoryList
|
|||
.includes(:featured_users)
|
||||
.where('topics.visible' => true)
|
||||
.order('categories.topics_week desc, categories.topics_month desc, categories.topics_year desc')
|
||||
.to_a
|
||||
|
||||
allowed_ids = current_user ? current_user.secure_category_ids : nil
|
||||
if allowed_ids.present?
|
||||
@categories = @categories.where("categories.secure = 'f' OR categories.id in (?)", allowed_ids)
|
||||
else
|
||||
@categories = @categories.where("categories.secure = 'f'")
|
||||
end
|
||||
|
||||
@categories = @categories.to_a
|
||||
|
||||
# Support for uncategorized topics
|
||||
uncategorized_topics = Topic
|
||||
|
|
|
@ -564,7 +564,7 @@ class User < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def secure_category_ids
|
||||
cats = self.moderator? ? Category.select(:id).where(:secure, true) : secure_categories.select('categories.id')
|
||||
cats = self.staff? ? Category.select(:id).where(secure: true) : secure_categories.select('categories.id')
|
||||
cats.map{|c| c.id}
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
class BasicCategorySerializer < ApplicationSerializer
|
||||
|
||||
attributes :id,
|
||||
:name,
|
||||
:color,
|
||||
:text_color,
|
||||
:slug,
|
||||
:topic_count,
|
||||
:description,
|
||||
:topic_url,
|
||||
:hotness
|
||||
|
||||
end
|
|
@ -1,13 +1,13 @@
|
|||
class CategorySerializer < ApplicationSerializer
|
||||
class CategorySerializer < BasicCategorySerializer
|
||||
|
||||
attributes :id,
|
||||
:name,
|
||||
:color,
|
||||
:text_color,
|
||||
:slug,
|
||||
:topic_count,
|
||||
:description,
|
||||
:topic_url,
|
||||
:hotness
|
||||
attributes :secure, :groups, :available_groups
|
||||
|
||||
def groups
|
||||
@groups ||= object.groups.order("name").all.map(&:name)
|
||||
end
|
||||
|
||||
def available_groups
|
||||
Group.order("name").map(&:name) - groups
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -758,6 +758,11 @@ en:
|
|||
change_in_category_topic: "Edit Description"
|
||||
hotness: "Hotness"
|
||||
already_used: 'This color has been used by another category'
|
||||
is_secure: "Secure category?"
|
||||
add_group: "Add Group"
|
||||
security: "Security"
|
||||
allowed_groups: "Allowed Groups:"
|
||||
|
||||
|
||||
flagging:
|
||||
title: 'Why are you flagging this post?'
|
||||
|
|
|
@ -16,23 +16,11 @@ describe CategoryList do
|
|||
let!(:topic) { Fabricate(:topic)}
|
||||
let(:category) { category_list.categories.first }
|
||||
|
||||
it "has a category" do
|
||||
it "has the right category" do
|
||||
category.should be_present
|
||||
end
|
||||
|
||||
it "has the uncategorized label" do
|
||||
category.name.should == SiteSetting.uncategorized_name
|
||||
end
|
||||
|
||||
it "has the uncategorized slug" do
|
||||
category.slug.should == SiteSetting.uncategorized_name
|
||||
end
|
||||
|
||||
it "has one topic this week" do
|
||||
category.topics_week.should == 1
|
||||
end
|
||||
|
||||
it "contains the topic in featured_topics" do
|
||||
category.featured_topics.should == [topic]
|
||||
end
|
||||
|
||||
|
@ -40,6 +28,23 @@ describe CategoryList do
|
|||
|
||||
end
|
||||
|
||||
context "security" do
|
||||
it "properly hide secure categories" do
|
||||
admin = Fabricate(:admin)
|
||||
user = Fabricate(:user)
|
||||
|
||||
cat = Fabricate(:category)
|
||||
topic = Fabricate(:topic, category: cat)
|
||||
cat.deny(:all)
|
||||
cat.allow(Group[:admins])
|
||||
cat.save
|
||||
|
||||
CategoryList.new(admin).categories.count.should == 1
|
||||
CategoryList.new(user).categories.count.should == 0
|
||||
CategoryList.new(nil).categories.count.should == 0
|
||||
end
|
||||
end
|
||||
|
||||
context "with a category" do
|
||||
|
||||
let!(:topic_category) { Fabricate(:category) }
|
||||
|
|
|
@ -134,22 +134,21 @@ describe CategoriesController do
|
|||
|
||||
describe 'success' do
|
||||
before do
|
||||
xhr :put, :update, id: @category.id, name: 'science', color: '000', text_color: '0ff'
|
||||
# might as well test this as well
|
||||
@category.allow(Group[:admins])
|
||||
@category.save
|
||||
|
||||
xhr :put, :update, id: @category.id, name: 'science', color: '000', text_color: '0ff', group_names: Group[:staff].name, secure: 'true'
|
||||
@category.reload
|
||||
end
|
||||
|
||||
it 'updates the name' do
|
||||
it 'updates the group correctly' do
|
||||
@category.name.should == 'science'
|
||||
end
|
||||
|
||||
it 'updates the color' do
|
||||
@category.color.should == '000'
|
||||
end
|
||||
|
||||
it 'updates the text color' do
|
||||
@category.text_color.should == '0ff'
|
||||
@category.secure?.should be_true
|
||||
@category.groups.count.should == 1
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue