FEATURE: allow admins to choose a group as a primary group

FEATURE: allow admins to set a default title for a group
This commit is contained in:
Sam 2015-04-10 12:17:28 +10:00
parent e143eb595f
commit 75890aed26
11 changed files with 220 additions and 19 deletions

View file

@ -38,6 +38,15 @@
</label> </label>
</div> </div>
{{#unless automatic}}
<div>
<label for="primary_group">
{{input type="checkbox" checked=primary_group}}
{{i18n 'admin.groups.primary_group'}}
</label>
</div>
{{/unless}}
<div> <div>
<label for="alias">{{i18n 'groups.alias_levels.title'}}</label> <label for="alias">{{i18n 'groups.alias_levels.title'}}</label>
{{combo-box name="alias" valueAttribute="value" value=alias_level content=aliasLevelOptions}} {{combo-box name="alias" valueAttribute="value" value=alias_level content=aliasLevelOptions}}
@ -52,6 +61,13 @@
{{i18n 'admin.groups.automatic_membership_retroactive'}} {{i18n 'admin.groups.automatic_membership_retroactive'}}
</label> </label>
</div> </div>
<div>
<label for="title">
{{i18n 'admin.groups.default_title'}}
</label>
{{input value=title}}
</div>
{{/unless}} {{/unless}}
<div class='buttons'> <div class='buttons'>

View file

@ -61,7 +61,9 @@ const Group = Discourse.Model.extend({
alias_level: this.get('alias_level'), alias_level: this.get('alias_level'),
visible: !!this.get('visible'), visible: !!this.get('visible'),
automatic_membership_email_domains: this.get('emailDomains'), automatic_membership_email_domains: this.get('emailDomains'),
automatic_membership_retroactive: !!this.get('automatic_membership_retroactive') automatic_membership_retroactive: !!this.get('automatic_membership_retroactive'),
title: this.get('title'),
primary_group: !!this.get('primary_group')
}; };
}, },

View file

@ -23,16 +23,7 @@ class Admin::GroupsController < Admin::AdminController
group = Group.new group = Group.new
group.name = (params[:name] || '').strip group.name = (params[:name] || '').strip
group.alias_level = params[:alias_level].to_i if params[:alias_level].present? save_group(group)
group.visible = params[:visible] == "true"
group.automatic_membership_email_domains = params[:automatic_membership_email_domains]
group.automatic_membership_retroactive = params[:automatic_membership_retroactive] == "true"
if group.save
render_serialized(group, BasicGroupSerializer)
else
render_json_error group
end
end end
def update def update
@ -40,10 +31,20 @@ class Admin::GroupsController < Admin::AdminController
# group rename is ignored for automatic groups # group rename is ignored for automatic groups
group.name = params[:name] if params[:name] && !group.automatic group.name = params[:name] if params[:name] && !group.automatic
save_group(group)
end
def save_group(group)
group.alias_level = params[:alias_level].to_i if params[:alias_level].present? group.alias_level = params[:alias_level].to_i if params[:alias_level].present?
group.visible = params[:visible] == "true" group.visible = params[:visible] == "true"
group.automatic_membership_email_domains = params[:automatic_membership_email_domains]
group.automatic_membership_retroactive = params[:automatic_membership_retroactive] == "true" group.automatic_membership_email_domains = params[:automatic_membership_email_domains] unless group.automatic
group.automatic_membership_retroactive = params[:automatic_membership_retroactive] == "true" unless group.automatic
group.primary_group = group.automatic ? false : params["primary_group"] == "true"
title = params[:title] if params[:title].present?
group.title = group.automatic ? nil : title
if group.save if group.save
render_serialized(group, BasicGroupSerializer) render_serialized(group, BasicGroupSerializer)

View file

@ -12,6 +12,8 @@ class Group < ActiveRecord::Base
after_save :destroy_deletions after_save :destroy_deletions
after_save :automatic_group_membership after_save :automatic_group_membership
after_save :update_primary_group
after_save :update_title
validate :name_format_validator validate :name_format_validator
validates_uniqueness_of :name, case_sensitive: false validates_uniqueness_of :name, case_sensitive: false
@ -301,6 +303,59 @@ class Group < ActiveRecord::Base
end end
end end
def update_title
return if new_record? && !self.title.present?
if self.title_changed?
sql = <<SQL
UPDATE users SET title = :title
WHERE (title = :title_was OR
title = '' OR
title IS NULL) AND
COALESCE(title,'') <> COALESCE(:title,'') AND
id IN (
SELECT user_id
FROM group_users
WHERE group_id = :id
)
SQL
self.class.exec_sql(sql,
title: title,
title_was: title_was,
id: id
)
end
end
def update_primary_group
return if new_record? && !self.primary_group?
if self.primary_group_changed?
sql = <<SQL
UPDATE users
/*set*/
/*where*/
SQL
builder = SqlBuilder.new(sql)
builder.where("
id IN (
SELECT user_id
FROM group_users
WHERE group_id = :id
)", id: id)
if primary_group
builder.set("primary_group_id = :id")
else
builder.set("primary_group_id = NULL")
builder.where("primary_group_id = :id")
end
builder.exec
end
end
end end
# == Schema Information # == Schema Information

View file

@ -1,6 +1,49 @@
class GroupUser < ActiveRecord::Base class GroupUser < ActiveRecord::Base
belongs_to :group, counter_cache: "user_count" belongs_to :group, counter_cache: "user_count"
belongs_to :user belongs_to :user
after_save :update_title
after_destroy :remove_title
after_save :set_primary_group
after_destroy :remove_primary_group
protected
def set_primary_group
if group.primary_group
self.class.exec_sql("UPDATE users
SET primary_group_id = :id
WHERE id = :user_id",
id: group.id, user_id: user_id)
end
end
def remove_primary_group
self.class.exec_sql("UPDATE users
SET primary_group_id = NULL
WHERE id = :user_id AND primary_group_id = :id",
id: group.id, user_id: user_id)
end
def remove_title
if group.title.present?
self.class.exec_sql("UPDATE users SET title = NULL
WHERE title = :title AND id = :id",
id: user_id,
title: group.title)
end
end
def update_title
if group.title.present?
self.class.exec_sql("UPDATE users SET title = :title
WHERE (title IS NULL OR title = '') AND id = :id",
id: user_id,
title: group.title)
end
end
end end
# == Schema Information # == Schema Information

View file

@ -6,5 +6,7 @@ class BasicGroupSerializer < ApplicationSerializer
:alias_level, :alias_level,
:visible, :visible,
:automatic_membership_email_domains, :automatic_membership_email_domains,
:automatic_membership_retroactive :automatic_membership_retroactive,
:primary_group,
:title
end end

View file

@ -1728,6 +1728,8 @@ en:
automatic: "Automatic" automatic: "Automatic"
automatic_membership_email_domains: "Users who register with an email domain that exactly matches one in this list will be automatically added to this group:" automatic_membership_email_domains: "Users who register with an email domain that exactly matches one in this list will be automatically added to this group:"
automatic_membership_retroactive: "Apply the same email domain rule to add existing registered users" automatic_membership_retroactive: "Apply the same email domain rule to add existing registered users"
default_title: "Default title for all users in this group"
primary_group: "Automatically set as primary group"
api: api:
generate_master: "Generate Master API Key" generate_master: "Generate Master API Key"

View file

@ -0,0 +1,5 @@
class AddPrimaryGroupToGroups < ActiveRecord::Migration
def change
add_column :groups, :primary_group, :boolean, default: false, null: false
end
end

View file

@ -0,0 +1,5 @@
class AddTitleToGroups < ActiveRecord::Migration
def change
add_column :groups, :title, :string
end
end

View file

@ -27,7 +27,9 @@ describe Admin::GroupsController do
"alias_level"=>0, "alias_level"=>0,
"visible"=>true, "visible"=>true,
"automatic_membership_email_domains"=>nil, "automatic_membership_email_domains"=>nil,
"automatic_membership_retroactive"=>false "automatic_membership_retroactive"=>false,
"title"=>nil,
"primary_group"=>false
}]) }])
end end
@ -61,13 +63,15 @@ describe Admin::GroupsController do
it "doesn't launch the 'automatic group membership' job when it's not retroactive" do it "doesn't launch the 'automatic group membership' job when it's not retroactive" do
Jobs.expects(:enqueue).never Jobs.expects(:enqueue).never
xhr :put, :update, id: 1, automatic_membership_retroactive: "false" group = Fabricate(:group)
xhr :put, :update, id: group.id, automatic_membership_retroactive: "false"
expect(response).to be_success expect(response).to be_success
end end
it "launches the 'automatic group membership' job when it's retroactive" do it "launches the 'automatic group membership' job when it's retroactive" do
Jobs.expects(:enqueue).with(:automatic_group_membership, group_id: 1) group = Fabricate(:group)
xhr :put, :update, id: 1, automatic_membership_retroactive: "true" Jobs.expects(:enqueue).with(:automatic_group_membership, group_id: group.id)
xhr :put, :update, id: group.id, automatic_membership_retroactive: "true"
expect(response).to be_success expect(response).to be_success
end end

View file

@ -47,7 +47,73 @@ describe Group do
Group[:staff].user_ids - [-1] Group[:staff].user_ids - [-1]
end end
it "Correctly handles primary group" do it "Correctly handles primary groups" do
group = Fabricate(:group, primary_group: true)
user = Fabricate(:user)
group.add(user)
user.reload
expect(user.primary_group_id).to eq group.id
group.remove(user)
user.reload
expect(user.primary_group_id).to eq nil
group.add(user)
group.primary_group = false
group.save
user.reload
expect(user.primary_group_id).to eq nil
end
it "Correctly handles title" do
group = Fabricate(:group, title: 'Super Awesome')
user = Fabricate(:user)
expect(user.title).to eq nil
group.add(user)
user.reload
expect(user.title).to eq 'Super Awesome'
group.title = 'BOOM'
group.save
user.reload
expect(user.title).to eq 'BOOM'
group.title = nil
group.save
user.reload
expect(user.title).to eq nil
group.title = "BOB"
group.save
user.reload
expect(user.title).to eq "BOB"
group.remove(user)
user.reload
expect(user.title).to eq nil
group.add(user)
group.destroy
user.reload
expect(user.title).to eq nil
end
it "Correctly handles removal of primary group" do
group = Fabricate(:group) group = Fabricate(:group)
user = Fabricate(:user) user = Fabricate(:user)
group.add(user) group.add(user)