From bf3411daca315031c69c6c1bce1b8e51e3d3ee80 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 13 Nov 2016 23:59:39 +0100 Subject: [PATCH] Implemented issue#356 - Automatically join users to organizations based on the email address. --- app/models/organization.rb | 12 +++ app/models/user.rb | 16 +++- db/migrate/20120101000001_create_base.rb | 3 + ...01_organization_domain_based_assignment.rb | 85 +++++++++++++++++++ db/seeds.rb | 69 +++++++++++++++ ...ganization_domain_based_assignment_test.rb | 78 +++++++++++++++++ 6 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20161112000001_organization_domain_based_assignment.rb create mode 100644 test/unit/organization_domain_based_assignment_test.rb diff --git a/app/models/organization.rb b/app/models/organization.rb index fcebf68c6..ad984b287 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -13,6 +13,9 @@ class Organization < ApplicationModel has_many :members, class_name: 'User' validates :name, presence: true + before_create :domain_cleanup + before_update :domain_cleanup + activity_stream_support permission: 'admin.role' history_support search_index_support @@ -21,6 +24,15 @@ class Organization < ApplicationModel private + def domain_cleanup + return if !domain + return if domain.empty? + domain.gsub!(/@/, '') + domain.gsub!(/\s*/, '') + domain.strip! + domain.downcase! + end + def cache_delete super diff --git a/app/models/user.rb b/app/models/user.rb index a4652568f..6d3714fc2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -33,7 +33,7 @@ class User < ApplicationModel include User::SearchIndex before_validation :check_name, :check_email, :check_login, :check_password - before_create :check_preferences_default, :validate_roles + before_create :check_preferences_default, :validate_roles, :domain_based_assignment before_update :check_preferences_default, :validate_roles after_create :avatar_for_email_check after_update :avatar_for_email_check @@ -856,6 +856,20 @@ returns } end + def domain_based_assignment + return if !email + return if organization_id + begin + domain = Mail::Address.new(email).domain + return if !domain + organization = Organization.find_by(domain: domain.downcase, domain_assignment: true) + return if !organization + self.organization_id = organization.id + rescue + return + end + end + def avatar_for_email_check return if !email return if email.empty? diff --git a/db/migrate/20120101000001_create_base.rb b/db/migrate/20120101000001_create_base.rb index ecbe5c8d4..9acd58459 100644 --- a/db/migrate/20120101000001_create_base.rb +++ b/db/migrate/20120101000001_create_base.rb @@ -125,6 +125,8 @@ class CreateBase < ActiveRecord::Migration create_table :organizations do |t| t.string :name, limit: 100, null: false t.boolean :shared, null: false, default: true + t.string :domain, limit: 250, null: true, default: '' + t.boolean :domain_assignment, null: false, default: false t.boolean :active, null: false, default: true t.string :note, limit: 250, null: true, default: '' t.integer :updated_by_id, null: false @@ -132,6 +134,7 @@ class CreateBase < ActiveRecord::Migration t.timestamps limit: 3, null: false end add_index :organizations, [:name], unique: true + add_index :organizations, [:domain] create_table :roles_users, id: false do |t| t.integer :user_id diff --git a/db/migrate/20161112000001_organization_domain_based_assignment.rb b/db/migrate/20161112000001_organization_domain_based_assignment.rb new file mode 100644 index 000000000..9d1763379 --- /dev/null +++ b/db/migrate/20161112000001_organization_domain_based_assignment.rb @@ -0,0 +1,85 @@ +class OrganizationDomainBasedAssignment < ActiveRecord::Migration + def up + # return if it's a new setup + return if !Setting.find_by(name: 'system_init_done') + + add_column :organizations, :domain, :string, limit: 250, null: true, default: '' + add_column :organizations, :domain_assignment, :boolean, null: false, default: false + add_index :organizations, [:domain] + + ObjectManager::Attribute.add( + force: true, + object: 'Organization', + name: 'domain_assignment', + display: 'Domain based assignment', + data_type: 'boolean', + data_option: { + null: true, + default: false, + note: 'Assign Users based on users domain.', + item_class: 'formGroup--halfSize', + options: { + true: 'yes', + false: 'no', + }, + translate: true, + }, + editable: false, + active: true, + screens: { + edit: { + Admin: { + null: false, + }, + }, + view: { + '-all-' => { + shown: true, + }, + }, + }, + to_create: false, + to_migrate: false, + to_delete: false, + position: 1410, + updated_by_id: 1, + created_by_id: 1, + ) + + ObjectManager::Attribute.add( + force: true, + object: 'Organization', + name: 'domain', + display: 'Domain', + data_type: 'input', + data_option: { + type: 'text', + maxlength: 150, + null: true, + item_class: 'formGroup--halfSize', + }, + editable: false, + active: true, + screens: { + edit: { + '-all-' => { + null: true, + }, + }, + view: { + '-all-' => { + shown: true, + }, + }, + }, + to_create: false, + to_migrate: false, + to_delete: false, + position: 1420, + updated_by_id: 1, + created_by_id: 1, + ) + + Cache.clear + end +end diff --git a/db/seeds.rb b/db/seeds.rb index 2ca89c295..52b61445c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -4660,6 +4660,75 @@ ObjectManager::Attribute.add( position: 1400, ) +ObjectManager::Attribute.add( + force: true, + object: 'Organization', + name: 'domain_assignment', + display: 'Domain based assignment', + data_type: 'boolean', + data_option: { + null: true, + default: false, + note: 'Assign Users based on users domain.', + item_class: 'formGroup--halfSize', + options: { + true: 'yes', + false: 'no', + }, + translate: true, + }, + editable: false, + active: true, + screens: { + edit: { + Admin: { + null: false, + }, + }, + view: { + '-all-' => { + shown: true, + }, + }, + }, + to_create: false, + to_migrate: false, + to_delete: false, + position: 1410, +) + +ObjectManager::Attribute.add( + force: true, + object: 'Organization', + name: 'domain', + display: 'Domain', + data_type: 'input', + data_option: { + type: 'text', + maxlength: 150, + null: true, + item_class: 'formGroup--halfSize', + }, + editable: false, + active: true, + screens: { + edit: { + '-all-' => { + null: true, + }, + }, + view: { + '-all-' => { + shown: true, + }, + }, + }, + to_create: false, + to_migrate: false, + to_delete: false, + position: 1420, +) + ObjectManager::Attribute.add( force: true, object: 'Organization', diff --git a/test/unit/organization_domain_based_assignment_test.rb b/test/unit/organization_domain_based_assignment_test.rb new file mode 100644 index 000000000..df730b706 --- /dev/null +++ b/test/unit/organization_domain_based_assignment_test.rb @@ -0,0 +1,78 @@ +# encoding: utf-8 +require 'test_helper' + +class OrganizationDomainBasedAssignmentTest < ActiveSupport::TestCase + test 'organization based assignment' do + + organization1 = Organization.create_if_not_exists( + name: 'organization based assignment 1', + domain: '@examPle1.com ', + domain_assignment: true, + updated_by_id: 1, + created_by_id: 1, + ) + organization2 = Organization.create_if_not_exists( + name: 'organization based assignment 2', + domain: 'example2.com', + domain_assignment: false, + updated_by_id: 1, + created_by_id: 1, + ) + + roles = Role.where(name: 'Customer') + customer1 = User.create_or_update( + login: 'organization-based_assignment-customer1@example1.com', + firstname: 'Domain', + lastname: 'Agent1', + email: 'organization-based_assignment-customer1@example1.com', + password: 'customerpw', + active: true, + roles: roles, + updated_by_id: 1, + created_by_id: 1, + ) + assert_equal(organization1.id, customer1.organization_id) + + customer2 = User.create_or_update( + login: 'organization-based_assignment-customer2@example1.com', + firstname: 'Domain', + lastname: 'Agent2', + email: 'organization-based_assignment-customer2@example1.com', + password: 'customerpw', + active: true, + organization_id: organization2.id, + roles: roles, + updated_by_id: 1, + created_by_id: 1, + ) + assert_equal(organization2.id, customer2.organization_id) + + customer3 = User.create_or_update( + login: 'organization-based_assignment-customer3@example2.com', + firstname: 'Domain', + lastname: 'Agent2', + email: 'organization-based_assignment-customer3@example2.com', + password: 'customerpw', + active: true, + roles: roles, + updated_by_id: 1, + created_by_id: 1, + ) + assert_equal(nil, customer3.organization_id) + + customer4 = User.create_or_update( + login: 'organization-based_assignment-customer4', + firstname: 'Domain', + lastname: 'Agent2', + email: '@', + password: 'customerpw', + active: true, + roles: roles, + updated_by_id: 1, + created_by_id: 1, + ) + assert_equal(nil, customer4.organization_id) + + end + +end