Create LDAP users asynchronously
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		
							parent
							
								
									35e2c8cd30
								
							
						
					
					
						commit
						8ad85636d9
					
				
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -39,3 +39,6 @@ yarn-debug.log* | ||||
| 
 | ||||
| # Ignore local dotenv config file | ||||
| .env | ||||
| 
 | ||||
| # Ignore redis dumps from sidekiq | ||||
| dump.rdb | ||||
|  | ||||
| @ -38,6 +38,10 @@ Running the dev server: | ||||
| 
 | ||||
|     bundle exec rails server | ||||
| 
 | ||||
| Running the background workers (requires Redis): | ||||
| 
 | ||||
|     bundle exec sidekiq -C config/sidekiq.yml | ||||
| 
 | ||||
| Running all specs: | ||||
| 
 | ||||
|     bundle exec rspec | ||||
| @ -62,6 +66,11 @@ manual LDIF imports etc. (or provide a staging instance) | ||||
| * [devise_ldap_authenticatable](https://github.com/cschiewek/devise_ldap_authenticatable) | ||||
| * [net/ldap](https://www.rubydoc.info/gems/net-ldap/Net/LDAP) | ||||
| 
 | ||||
| ### Asynchronous jobs/workers | ||||
| 
 | ||||
| * [Sidekiq](https://github.com/mperham/sidekiq/wiki/) | ||||
| * [ActiveJob](https://github.com/mperham/sidekiq/wiki/Active-Job) | ||||
| 
 | ||||
| ## License | ||||
| 
 | ||||
| [GNU Affero General Public License v3.0](https://choosealicense.com/licenses/agpl-3.0/) | ||||
|  | ||||
							
								
								
									
										32
									
								
								app/jobs/create_ldap_user_job.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/jobs/create_ldap_user_job.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| class CreateLdapUserJob < ApplicationJob | ||||
|   queue_as :default | ||||
| 
 | ||||
|   def perform(username, domain, email, hashed_pw) | ||||
|     dn = "cn=#{username},ou=#{domain},cn=users,dc=kosmos,dc=org" | ||||
|     attr = { | ||||
|       objectclass: ["top", "account", "person", "extensibleObject"], | ||||
|       cn: username, | ||||
|       sn: username, | ||||
|       uid: username, | ||||
|       mail: email, | ||||
|       userPassword: hashed_pw | ||||
|     } | ||||
| 
 | ||||
|     ldap_client.add(dn: dn, attributes: attr) | ||||
|   end | ||||
| 
 | ||||
|   def ldap_client | ||||
|     ldap_client ||= Net::LDAP.new host: ldap_config['host'], | ||||
|       port: ldap_config['port'], | ||||
|       encryption: ldap_config['ssl'], | ||||
|       auth: { | ||||
|         method: :simple, | ||||
|         username: ldap_config['admin_user'], | ||||
|         password: ldap_config['admin_password'] | ||||
|       } | ||||
|   end | ||||
| 
 | ||||
|   def ldap_config | ||||
|     ldap_config ||= YAML.load(ERB.new(File.read("#{Rails.root}/config/ldap.yml")).result)[Rails.env] | ||||
|   end | ||||
| end | ||||
| @ -33,33 +33,10 @@ class CreateAccount < ApplicationService | ||||
|     @invitation.update! invited_user_id: user_id, used_at: DateTime.now | ||||
|   end | ||||
| 
 | ||||
|   # TODO move to confirmation | ||||
|   def add_ldap_document | ||||
|     dn = "cn=#{@username},ou=kosmos.org,cn=users,dc=kosmos,dc=org" | ||||
|     attr = { | ||||
|       objectclass: ["top", "account", "person", "extensibleObject"], | ||||
|       cn: @username, | ||||
|       sn: @username, | ||||
|       uid: @username, | ||||
|       mail: @email, | ||||
|       userPassword: Devise.ldap_auth_password_builder.call(@password) | ||||
|     } | ||||
| 
 | ||||
|     ldap_client.add(dn: dn, attributes: attr) | ||||
|   end | ||||
| 
 | ||||
|   def ldap_client | ||||
|     ldap_client ||= Net::LDAP.new host: ldap_config['host'], | ||||
|       port: ldap_config['port'], | ||||
|       encryption: ldap_config['ssl'], | ||||
|       auth: { | ||||
|         method: :simple, | ||||
|         username: ldap_config['admin_user'], | ||||
|         password: ldap_config['admin_password'] | ||||
|       } | ||||
|   end | ||||
| 
 | ||||
|   def ldap_config | ||||
|     ldap_config ||= YAML.load(ERB.new(File.read("#{Rails.root}/config/ldap.yml")).result)[Rails.env] | ||||
|     hashed_pw = Devise.ldap_auth_password_builder.call(@password) | ||||
|     CreateLdapUserJob.perform_later(@username, "kosmos.org", @email, hashed_pw) | ||||
|   end | ||||
| 
 | ||||
|   def exchange_xmpp_contacts | ||||
|  | ||||
| @ -41,5 +41,6 @@ module Akkounts | ||||
|     end | ||||
| 
 | ||||
|     config.active_job.queue_adapter = :sidekiq | ||||
|     config.action_mailer.deliver_later_queue_name = nil # use "default" queue | ||||
|   end | ||||
| end | ||||
|  | ||||
| @ -49,4 +49,6 @@ Rails.application.configure do | ||||
|     protocol: "https", | ||||
|     from: "accounts@kosmos.org" | ||||
|   } | ||||
| 
 | ||||
|   config.active_job.queue_adapter = :test | ||||
| end | ||||
|  | ||||
							
								
								
									
										34
									
								
								spec/jobs/create_ldap_user_job_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								spec/jobs/create_ldap_user_job_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| require 'rails_helper' | ||||
| 
 | ||||
| RSpec.describe CreateLdapUserJob, type: :job do | ||||
|   let(:ldap_client_mock) { instance_double(Net::LDAP) } | ||||
| 
 | ||||
|   subject(:job) { | ||||
|     described_class.any_instance.stub(:ldap_client).and_return(ldap_client_mock) | ||||
|     described_class.perform_later( | ||||
|       'halfinney', 'kosmos.org', 'halfinney@example.com', | ||||
|       'remember-remember-the-5th-of-november' | ||||
|     ) | ||||
|   } | ||||
| 
 | ||||
|   it "creates a new document with the correct attributes" do | ||||
|     ldap_client_mock.should_receive(:add).with( | ||||
|       dn: "cn=halfinney,ou=kosmos.org,cn=users,dc=kosmos,dc=org", | ||||
|       attributes: { | ||||
|         objectclass: ["top", "account", "person", "extensibleObject"], | ||||
|         cn: "halfinney", | ||||
|         sn: "halfinney", | ||||
|         uid: "halfinney", | ||||
|         mail: "halfinney@example.com", | ||||
|         userPassword: "remember-remember-the-5th-of-november" | ||||
|       } | ||||
|     ) | ||||
| 
 | ||||
|     perform_enqueued_jobs { job } | ||||
|   end | ||||
| 
 | ||||
|   after do | ||||
|     clear_enqueued_jobs | ||||
|     clear_performed_jobs | ||||
|   end | ||||
| end | ||||
| @ -69,5 +69,6 @@ RSpec.configure do |config| | ||||
|   config.include Devise::Test::ControllerHelpers, :type => :controller | ||||
|   config.include Warden::Test::Helpers | ||||
|   config.include FactoryBot::Syntax::Methods | ||||
|   config.include ActiveJob::TestHelper, type: :job | ||||
|   config.extend ControllerMacros, :type => :controller | ||||
| end | ||||
|  | ||||
| @ -3,12 +3,6 @@ require 'webmock/rspec' | ||||
| require 'json' | ||||
| 
 | ||||
| RSpec.describe CreateAccount, type: :model do | ||||
|   let(:ldap_client_mock) { instance_double(Net::LDAP) } | ||||
| 
 | ||||
|   before do | ||||
|     allow(service).to receive(:ldap_client).and_return(ldap_client_mock) | ||||
|   end | ||||
| 
 | ||||
|   describe "#create_user_in_database" do | ||||
|     let(:service) { CreateAccount.new( | ||||
|       username: 'isaacnewton', | ||||
| @ -48,26 +42,28 @@ RSpec.describe CreateAccount, type: :model do | ||||
|   end | ||||
| 
 | ||||
|   describe "#add_ldap_document" do | ||||
|     include ActiveJob::TestHelper | ||||
| 
 | ||||
|     let(:service) { CreateAccount.new( | ||||
|       username: 'halfinney', | ||||
|       email: 'halfinney@example.com', | ||||
|       password: 'remember-remember-the-5th-of-november' | ||||
|     )} | ||||
| 
 | ||||
|     it "creates a new document with the correct attributes" do | ||||
|       expect(ldap_client_mock).to receive(:add).with( | ||||
|         dn: "cn=halfinney,ou=kosmos.org,cn=users,dc=kosmos,dc=org", | ||||
|         attributes: { | ||||
|           objectclass: ["top", "account", "person", "extensibleObject"], | ||||
|           cn: "halfinney", | ||||
|           sn: "halfinney", | ||||
|           uid: "halfinney", | ||||
|           mail: "halfinney@example.com", | ||||
|           userPassword: /^{SSHA512}.{171}=/ | ||||
|         } | ||||
|       ) | ||||
| 
 | ||||
|     it "enqueues a job to create the LDAP user document" do | ||||
|       service.send(:add_ldap_document) | ||||
| 
 | ||||
|       expect(enqueued_jobs.size).to eq(1) | ||||
| 
 | ||||
|       args = enqueued_jobs.first['arguments'] | ||||
|       expect(args[0]).to eq('halfinney') | ||||
|       expect(args[1]).to eq('kosmos.org') | ||||
|       expect(args[2]).to eq('halfinney@example.com') | ||||
|       expect(args[3]).to match(/^{SSHA512}.{171}=/) | ||||
|     end | ||||
| 
 | ||||
|     after do | ||||
|       clear_enqueued_jobs | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user