mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 09:36:19 -05:00
FEATURE: automatic group membership based on email address
This commit is contained in:
parent
a2099110aa
commit
256519dddf
13 changed files with 138 additions and 4 deletions
|
@ -43,6 +43,17 @@
|
|||
{{combo-box name="alias" valueAttribute="value" value=alias_level content=aliasLevelOptions}}
|
||||
</div>
|
||||
|
||||
{{#unless automatic}}
|
||||
<div>
|
||||
<label for="automatic_membership">{{i18n 'admin.groups.automatic_membership_email_domains'}}</label>
|
||||
{{list-setting name="automatic_membership" settingValue=automatic_membership_email_domains}}
|
||||
<label>
|
||||
{{input type="checkbox" checked=automatic_membership_retroactive}}
|
||||
{{i18n 'admin.groups.automatic_membership_retroactive'}}
|
||||
</label>
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
<div class='buttons'>
|
||||
<button {{action "save"}} {{bind-attr disabled="disableSave"}} class='btn btn-primary'>{{i18n 'admin.customize.save'}}</button>
|
||||
{{#unless automatic}}
|
||||
|
|
|
@ -68,7 +68,9 @@ Discourse.Group = Discourse.Model.extend({
|
|||
return {
|
||||
name: this.get('name'),
|
||||
alias_level: this.get('alias_level'),
|
||||
visible: !!this.get('visible')
|
||||
visible: !!this.get('visible'),
|
||||
automatic_membership_email_domains: this.get('automatic_membership_email_domains'),
|
||||
automatic_membership_retroactive: !!this.get('automatic_membership_retroactive')
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
@ -463,6 +463,7 @@ section.details {
|
|||
.groups {
|
||||
.ac-wrap {
|
||||
width: 100% !important;
|
||||
border-color: scale-color($primary, $lightness: 75%);
|
||||
.item {
|
||||
width: 190px;
|
||||
margin-right: 0 !important;
|
||||
|
@ -480,6 +481,13 @@ section.details {
|
|||
.controls {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.select2-container {
|
||||
width: 100%;
|
||||
}
|
||||
.select2-choices {
|
||||
width: 100%;
|
||||
border-color: scale-color($primary, $lightness: 75%);
|
||||
}
|
||||
}
|
||||
|
||||
// Customise area
|
||||
|
|
|
@ -21,8 +21,11 @@ class Admin::GroupsController < Admin::AdminController
|
|||
|
||||
def create
|
||||
group = Group.new
|
||||
|
||||
group.name = (params[:name] || '').strip
|
||||
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)
|
||||
|
@ -36,11 +39,13 @@ class Admin::GroupsController < Admin::AdminController
|
|||
|
||||
group.alias_level = params[:alias_level].to_i if params[:alias_level].present?
|
||||
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 rename is ignored for automatic groups
|
||||
group.name = params[:name] if params[:name] && !group.automatic
|
||||
|
||||
if group.save
|
||||
render json: success_json
|
||||
render_serialized(group, BasicGroupSerializer)
|
||||
else
|
||||
render_json_error group
|
||||
end
|
||||
|
|
23
app/jobs/regular/automatic_group_membership.rb
Normal file
23
app/jobs/regular/automatic_group_membership.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
module Jobs
|
||||
|
||||
class AutomaticGroupMembership < Jobs::Base
|
||||
|
||||
def execute(args)
|
||||
group_id = args[:group_id]
|
||||
|
||||
raise Discourse::InvalidParameters.new(:group_id) if group_id.blank?
|
||||
|
||||
group = Group.find(group_id)
|
||||
|
||||
return unless group.automatic_membership_retroactive
|
||||
|
||||
domains = group.automatic_membership_email_domains.gsub('.', '\.')
|
||||
|
||||
User.where("email ~* '@(#{domains})'").find_each do |user|
|
||||
group.add(user) rescue ActiveRecord::RecordNotUnique
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -11,6 +11,7 @@ class Group < ActiveRecord::Base
|
|||
has_many :managers, through: :group_managers
|
||||
|
||||
after_save :destroy_deletions
|
||||
after_save :automatic_group_membership
|
||||
|
||||
validate :name_format_validator
|
||||
validates_uniqueness_of :name, case_sensitive: false
|
||||
|
@ -301,6 +302,12 @@ class Group < ActiveRecord::Base
|
|||
@deletions = nil
|
||||
end
|
||||
|
||||
def automatic_group_membership
|
||||
if self.automatic_membership_retroactive
|
||||
Jobs.enqueue(:automatic_group_membership, group_id: self.id)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
|
|
@ -79,6 +79,7 @@ class User < ActiveRecord::Base
|
|||
after_create :create_user_stat
|
||||
after_create :create_user_profile
|
||||
after_create :ensure_in_trust_level_group
|
||||
after_create :automatic_group_membership
|
||||
|
||||
before_save :update_username_lower
|
||||
before_save :ensure_password_is_hashed
|
||||
|
@ -715,6 +716,17 @@ class User < ActiveRecord::Base
|
|||
Group.user_trust_level_change!(id, trust_level)
|
||||
end
|
||||
|
||||
def automatic_group_membership
|
||||
Group.where(automatic: false)
|
||||
.where("LENGTH(COALESCE(automatic_membership_email_domains, '')) > 0")
|
||||
.each do |group|
|
||||
domains = group.automatic_membership_email_domains.gsub('.', '\.')
|
||||
if self.email =~ Regexp.new("@(#{domains})", true)
|
||||
group.add(self) rescue ActiveRecord::RecordNotUnique
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_user_stat
|
||||
stat = UserStat.new(new_since: Time.now)
|
||||
stat.user_id = id
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
class BasicGroupSerializer < ApplicationSerializer
|
||||
attributes :id, :automatic, :name, :user_count, :alias_level, :visible
|
||||
attributes :id,
|
||||
:automatic,
|
||||
:name,
|
||||
:user_count,
|
||||
:alias_level,
|
||||
:visible,
|
||||
:automatic_membership_email_domains,
|
||||
:automatic_membership_retroactive
|
||||
|
||||
def automatic_membership_email_domains
|
||||
object.automatic_membership_email_domains.presence || ""
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1633,6 +1633,8 @@ en:
|
|||
add_members: "Add members"
|
||||
custom: "Custom"
|
||||
automatic: "Automatic"
|
||||
automatic_membership_email_domains: "Users registering with an email from that list will automatically be a member of this group"
|
||||
automatic_membership_retroactive: "Registered users matching this list are also member of the group"
|
||||
|
||||
api:
|
||||
generate_master: "Generate Master API Key"
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
class AddAutomaticMembershipToGroup < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :groups, :automatic_membership_email_domains, :text
|
||||
add_column :groups, :automatic_membership_retroactive, :boolean, default: false
|
||||
end
|
||||
end
|
|
@ -25,7 +25,9 @@ describe Admin::GroupsController do
|
|||
"user_count"=>1,
|
||||
"automatic"=>false,
|
||||
"alias_level"=>0,
|
||||
"visible"=>true
|
||||
"visible"=>true,
|
||||
"automatic_membership_email_domains"=>"",
|
||||
"automatic_membership_retroactive"=>false
|
||||
}])
|
||||
end
|
||||
|
||||
|
@ -57,6 +59,18 @@ describe Admin::GroupsController do
|
|||
expect(group.visible).to eq(true)
|
||||
end
|
||||
|
||||
it "doesn't launch the 'automatic group membership' job when it's not retroactive" do
|
||||
Jobs.expects(:enqueue).never
|
||||
xhr :put, :update, id: 1, automatic_membership_retroactive: "false"
|
||||
expect(response).to be_success
|
||||
end
|
||||
|
||||
it "launches the 'automatic group membership' job when it's retroactive" do
|
||||
Jobs.expects(:enqueue).with(:automatic_group_membership, group_id: 1)
|
||||
xhr :put, :update, id: 1, automatic_membership_retroactive: "true"
|
||||
expect(response).to be_success
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context ".destroy" do
|
||||
|
|
22
spec/jobs/automatic_group_membership_spec.rb
Normal file
22
spec/jobs/automatic_group_membership_spec.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
require 'spec_helper'
|
||||
require_dependency 'jobs/regular/automatic_group_membership'
|
||||
|
||||
describe Jobs::AutomaticGroupMembership do
|
||||
|
||||
it "raises an error when the group id is missing" do
|
||||
expect { Jobs::AutomaticGroupMembership.new.execute({}) }.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
|
||||
it "updates the membership" do
|
||||
user1 = Fabricate(:user, email: "foo@wat.com")
|
||||
user2 = Fabricate(:user, email: "foo@bar.com")
|
||||
group = Fabricate(:group, automatic_membership_email_domains: "wat.com", automatic_membership_retroactive: true)
|
||||
|
||||
Jobs::AutomaticGroupMembership.new.execute(group_id: group.id)
|
||||
|
||||
group.reload
|
||||
expect(group.users.include?(user1)).to eq(true)
|
||||
expect(group.users.include?(user2)).to eq(false)
|
||||
end
|
||||
|
||||
end
|
|
@ -1213,4 +1213,15 @@ describe User do
|
|||
|
||||
end
|
||||
|
||||
describe "automatic group membership" do
|
||||
|
||||
it "is automatically added to a group when the email matches" do
|
||||
group = Fabricate(:group, automatic_membership_email_domains: "bar.com|wat.com")
|
||||
user = Fabricate(:user, email: "foo@bar.com")
|
||||
group.reload
|
||||
expect(group.users.include?(user)).to eq(true)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue