Create LDAP users asynchronously
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Basti 2021-02-02 21:15:52 +01:00
parent 35e2c8cd30
commit 8ad85636d9
Signed by untrusted user: basti
GPG Key ID: 9F88009D31D99C72
9 changed files with 100 additions and 45 deletions

3
.gitignore vendored
View File

@ -39,3 +39,6 @@ yarn-debug.log*
# Ignore local dotenv config file
.env
# Ignore redis dumps from sidekiq
dump.rdb

View File

@ -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/)

View 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

View File

@ -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

View File

@ -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

View File

@ -49,4 +49,6 @@ Rails.application.configure do
protocol: "https",
from: "accounts@kosmos.org"
}
config.active_job.queue_adapter = :test
end

View 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

View File

@ -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

View File

@ -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