diff --git a/.env.example b/.env.example index c09dba1..5e587f2 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1 @@ -LDAP_HOST=192.168.33.10 -LDAP_PORT=389 -# -# Production LDAP server: -# -# LDAP_HOST=ldap.kosmos.org -# LDAP_PORT=636 -# LDAP_USE_TLS=true +EJABBERD_API_URL='https://xmpp.kosmos.org/api' diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..932c595 --- /dev/null +++ b/.env.test @@ -0,0 +1 @@ +EJABBERD_API_URL='http://xmpp.example.com/api' diff --git a/Gemfile b/Gemfile index 3895a98..8a5b728 100644 --- a/Gemfile +++ b/Gemfile @@ -21,7 +21,7 @@ gem 'jbuilder', '~> 2.7' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false -gem 'dotenv-rails', groups: [:development, :test] +gem 'dotenv-rails' gem 'warden' gem 'devise' diff --git a/app/services/create_account.rb b/app/services/create_account.rb index e000631..eb60824 100644 --- a/app/services/create_account.rb +++ b/app/services/create_account.rb @@ -10,7 +10,11 @@ class CreateAccount < ApplicationService def call user = create_user_in_database add_ldap_document - update_invitation(user.id) if @invitation.present? + + if @invitation.present? + update_invitation(user.id) + exchange_xmpp_contacts + end end private @@ -57,4 +61,23 @@ class CreateAccount < ApplicationService def ldap_config ldap_config ||= YAML.load(ERB.new(File.read("#{Rails.root}/config/ldap.yml")).result)[Rails.env] end + + def exchange_xmpp_contacts + #TODO enable in development when we have easy setup of ejabberd etc. + return if Rails.env.development? + + ejabberd = EjabberdApiClient.new + inviter = @invitation.user + + ejabberd.add_rosteritem({ + "localuser": @username, "localhost": @domain, + "user": inviter.cn, "host": inviter.ou, + "nick": inviter.cn, "group": "Friends", "subs": "both" + }) + ejabberd.add_rosteritem({ + "localuser": inviter.cn, "localhost": inviter.ou, + "user": @username, "host": @domain, + "nick": @username, "group": "Friends", "subs": "both" + }) + end end diff --git a/app/services/ejabberd_api_client.rb b/app/services/ejabberd_api_client.rb new file mode 100644 index 0000000..ddce590 --- /dev/null +++ b/app/services/ejabberd_api_client.rb @@ -0,0 +1,20 @@ +class EjabberdApiClient + def initialize + @base_url = ENV["EJABBERD_API_URL"] + end + + def post(endpoint, payload) + res = Faraday.post("#{@base_url}/#{endpoint}", payload, + "Content-Type" => "application/json") + + if res.status != 200 + Rails.logger.error "[ejabberd] API request failed:" + Rails.logger.error res.body + #TODO add some kind of exception tracking/notifications + end + end + + def add_rosteritem(payload) + post "add_rosteritem", payload + end +end diff --git a/spec/services/create_account_spec.rb b/spec/services/create_account_spec.rb index 8641beb..2808836 100644 --- a/spec/services/create_account_spec.rb +++ b/spec/services/create_account_spec.rb @@ -1,4 +1,6 @@ require 'rails_helper' +require 'webmock/rspec' +require 'json' RSpec.describe CreateAccount, type: :model do let(:ldap_client_mock) { instance_double(Net::LDAP) } @@ -68,4 +70,37 @@ RSpec.describe CreateAccount, type: :model do service.send(:add_ldap_document) end end + + describe "#exchange_xmpp_contacts" do + let(:inviter) { create :user, cn: "willherschel", ou: "kosmos.org" } + let(:invitation) { create :invitation, user: inviter } + let(:service) { CreateAccount.new( + username: 'isaacnewton', + email: 'isaacnewton@example.com', + password: 'bright-ideas-in-autumn', + invitation: invitation + )} + + before do + stub_request(:post, "http://xmpp.example.com/api/add_rosteritem") + .to_return(status: 200, body: "", headers: {}) + end + + it "posts add_rosteritem commands to the ejabberd API" do + service.send(:exchange_xmpp_contacts) + + expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/add_rosteritem") + .with { |req| req.body == { + localuser: "isaacnewton", localhost: "kosmos.org", + user: "willherschel", host: "kosmos.org", + nick: "willherschel", group: "Friends", subs: "both" + }} + expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/add_rosteritem") + .with { |req| req.body == { + localuser: "willherschel", localhost: "kosmos.org", + user: "isaacnewton", host: "kosmos.org", + nick: "isaacnewton", group: "Friends", subs: "both" + }} + end + end end