From 0c84ae38b3018012d586dbd2c90abfe37d837980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joanna=20W=C3=B3jtowicz?= Date: Tue, 14 Dec 2021 01:08:35 +0100 Subject: [PATCH 1/5] Add SubscriptionLists class --- lib/urbanairship.rb | 1 + .../devices/subscription_lists.rb | 46 +++++++++++++++++ .../devices/subscription_lists_spec.rb | 51 +++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 lib/urbanairship/devices/subscription_lists.rb create mode 100644 spec/lib/urbanairship/devices/subscription_lists_spec.rb diff --git a/lib/urbanairship.rb b/lib/urbanairship.rb index 38af28a..9f2fe4c 100644 --- a/lib/urbanairship.rb +++ b/lib/urbanairship.rb @@ -26,6 +26,7 @@ require 'urbanairship/devices/open_channel' require 'urbanairship/reports/response_statistics' require 'urbanairship/devices/static_lists' +require 'urbanairship/devices/subscription_lists' require 'urbanairship/push/location' require 'urbanairship/automations/pipeline' require 'urbanairship/automations/automation' diff --git a/lib/urbanairship/devices/subscription_lists.rb b/lib/urbanairship/devices/subscription_lists.rb new file mode 100644 index 0000000..d4612fb --- /dev/null +++ b/lib/urbanairship/devices/subscription_lists.rb @@ -0,0 +1,46 @@ +require 'urbanairship' + + +module Urbanairship + module Devices + class SubscriptionLists + include Urbanairship::Common + include Urbanairship::Loggable + SUBSCRIBE = "subscribe" + + def initialize(client: required('client')) + @client = client + end + + def subscribe(list_id, email_addresses) + subscribe_payload = payload(SUBSCRIBE, list_id, email_addresses) + + response = @client.send_request( + method: 'POST', + body: JSON.dump(subscribe_payload), + path: channel_path('subscription_lists'), + content_type: 'application/json' + ) + logger.info("Subscribed #{email_addresses.count} users to #{list_id}") + + response + end + + private + + def payload(action, list_id, email_addresses) + { + subscription_lists: [ + { + action: action, + list_id: list_id + } + ], + audience: { + email_address: email_addresses + } + } + end + end + end +end diff --git a/spec/lib/urbanairship/devices/subscription_lists_spec.rb b/spec/lib/urbanairship/devices/subscription_lists_spec.rb new file mode 100644 index 0000000..d4f59ed --- /dev/null +++ b/spec/lib/urbanairship/devices/subscription_lists_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' +require 'urbanairship' + +describe Urbanairship::Devices do + UA = Urbanairship + airship = UA::Client.new(key: '123', secret: 'abc') + + describe Urbanairship::Devices::SubscriptionLists do + let(:expected_response) do + { + body: { + ok: true + }, + code: 202, + } + end + let(:list_id) { "some-list" } + let(:email_addresses) { ["email@example.com"] } + + describe '#update_attributes' do + let(:payload) do + { + subscription_lists: [ + { + action: "subscribe", + list_id: list_id + } + ], + audience: { + email_address: email_addresses + } + } + end + + describe 'Request' do + it 'makes the expected request' do + allow(airship).to receive(:send_request) do |arguments| + expect(arguments).to eq( + method: 'POST', + body: payload.to_json, + path: '/channels/subscription_lists', + content_type: 'application/json', + ) + expected_response + end + expect(described_class.new(client: airship).subscribe(list_id, email_addresses)).to eq(expected_response) + end + end + end + end +end From 426b35f31c09b80874e1a0481a041747b6b09a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joanna=20W=C3=B3jtowicz?= Date: Tue, 14 Dec 2021 14:26:03 +0100 Subject: [PATCH 2/5] Fail with TypeError in case incorrect type of argument provided --- .../devices/subscription_lists.rb | 4 ++++ .../devices/subscription_lists_spec.rb | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/lib/urbanairship/devices/subscription_lists.rb b/lib/urbanairship/devices/subscription_lists.rb index d4612fb..89e63ad 100644 --- a/lib/urbanairship/devices/subscription_lists.rb +++ b/lib/urbanairship/devices/subscription_lists.rb @@ -13,6 +13,10 @@ def initialize(client: required('client')) end def subscribe(list_id, email_addresses) + fail TypeError, 'list_id string must be privided' unless list_id.is_a? String + fail TypeError, 'email_addresses array must be privided' unless email_addresses.is_a? Array + fail TypeError, 'each email address must be a string' unless email_addresses&.all? { |email| email.is_a? String } + subscribe_payload = payload(SUBSCRIBE, list_id, email_addresses) response = @client.send_request( diff --git a/spec/lib/urbanairship/devices/subscription_lists_spec.rb b/spec/lib/urbanairship/devices/subscription_lists_spec.rb index d4f59ed..be23770 100644 --- a/spec/lib/urbanairship/devices/subscription_lists_spec.rb +++ b/spec/lib/urbanairship/devices/subscription_lists_spec.rb @@ -45,6 +45,30 @@ end expect(described_class.new(client: airship).subscribe(list_id, email_addresses)).to eq(expected_response) end + + it 'fails and raises TypeError list_id is not a String' do + list_id = nil + + expect{ + described_class.new(client: airship).subscribe(list_id, email_addresses) + }.to raise_error(TypeError) + end + + it 'fails and raises TypeError email_addresses is not an Array' do + email_addresses = nil + + expect{ + described_class.new(client: airship).subscribe(list_id, email_addresses) + }.to raise_error(TypeError) + end + + it 'fails and raises TypeError an email address is not a String' do + email_addresses.push(123) + + expect{ + described_class.new(client: airship).subscribe(list_id, email_addresses) + }.to raise_error(TypeError) + end end end end From a024f6058b6eb49104852102e5fba727cf942b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joanna=20W=C3=B3jtowicz?= Date: Tue, 14 Dec 2021 14:47:49 +0100 Subject: [PATCH 3/5] Update documentation --- docs/devices.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/devices.rst b/docs/devices.rst index 204f47e..1a6ac4e 100644 --- a/docs/devices.rst +++ b/docs/devices.rst @@ -103,3 +103,19 @@ that have been iterated over by using the ``count`` method. puts(apid) end puts(apid_list.count) + + +Subscription Lists +--------- + +Subscribe or Unsubscribe Channels to/from Subscription Lists. + +.. code-block:: ruby + + require 'urbanairship' + + UA = Urbanairship + airship = UA::Client.new(key:'application_key', secret:'master_secret') + subscription_lists = UA::SubscriptionLists.new(client: airship) + response = subscription_lists.subscribe(list_id: "some-list", email_addresses: ["test1@example.com", "test2@example.com"]) + puts(response) From aadca44ab832b633b4e949eccd346f9deb45b75d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joanna=20W=C3=B3jtowicz?= Date: Wed, 22 Jun 2022 15:25:28 +0200 Subject: [PATCH 4/5] Add associate_by_email_address method Co-authored-by: name Co-authored-by: name --- lib/urbanairship/devices/named_user.rb | 18 ++++++++ .../urbanairship/devices/named_user_spec.rb | 43 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/lib/urbanairship/devices/named_user.rb b/lib/urbanairship/devices/named_user.rb index c086d72..7d47696 100644 --- a/lib/urbanairship/devices/named_user.rb +++ b/lib/urbanairship/devices/named_user.rb @@ -42,6 +42,24 @@ def associate(channel_id: required('channel_id'), device_type: nil) response end + def associate_by_email_address(email_address: required('email_address')) + fail ArgumentError, + 'named_user_id is required for association' if @named_user_id.nil? + + payload = {} + payload['email_address'] = email_address + payload['named_user_id'] = @named_user_id.to_s + + response = @client.send_request( + method: 'POST', + body: JSON.dump(payload), + path: named_users_path('associate'), + content_type: CONTENT_TYPE + ) + logger.info { "Associated email_address #{email_address} with named_user #{@named_user_id}" } + response + end + def disassociate(channel_id: required('channel_id'), device_type: nil) payload = {} payload['channel_id'] = channel_id diff --git a/spec/lib/urbanairship/devices/named_user_spec.rb b/spec/lib/urbanairship/devices/named_user_spec.rb index a0e267d..fca8282 100644 --- a/spec/lib/urbanairship/devices/named_user_spec.rb +++ b/spec/lib/urbanairship/devices/named_user_spec.rb @@ -7,6 +7,7 @@ let(:channel_id) { '123' } let(:device_type) { 'android' } let(:named_user_id) { 'user' } + let(:email_address) { 'whales@example.com' } named_user = nil @@ -112,6 +113,48 @@ end end + describe '#associate_by_email_address' do + describe 'Request' do + after(:each) { named_user.associate_by_email_address(email_address: email_address) } + + it 'makes the expected request' do + allow(airship).to receive(:send_request) do |arguments| + expect(arguments).to eq( + method: 'POST', + body: { email_address: email_address, named_user_id: named_user_id }.to_json, + path: "/named_users/associate", + content_type: described_class::CONTENT_TYPE, + ) + expected_response + end + end + + context 'Named user ID is an integer' do + let(:named_user_id) { 1985 } + + it 'converts named user ID to a string' do + allow(airship).to receive(:send_request) do |arguments| + expect(JSON.parse(arguments[:body], symbolize_names: true)[:named_user_id]).to eq named_user_id.to_s + expected_response + end + end + end + end + + it 'associates a email_address with a named_user' do + allow(airship).to receive(:send_request).and_return(expected_response) + actual_resp = named_user.associate_by_email_address(email_address: email_address) + expect(actual_resp).to eq(expected_response) + end + + it 'fails when the user_id is not set' do + named_user_without_id = UA::NamedUser.new(client: airship) + expect { + named_user_without_id.associate_by_email_address(email_address: email_address) + }.to raise_error(ArgumentError) + end + end + describe '#disassociate' do it 'disassociates a channel from a named_user' do allow(airship).to receive(:send_request).and_return(expected_response) From be1b421bd391891d390c6a48a4f903c8469cad55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joanna=20W=C3=B3jtowicz?= Date: Tue, 28 Jun 2022 14:30:29 +0200 Subject: [PATCH 5/5] Update docs --- docs/named_user.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/named_user.rst b/docs/named_user.rst index 24fdf69..8167057 100644 --- a/docs/named_user.rst +++ b/docs/named_user.rst @@ -40,6 +40,23 @@ Associate a channel with a named user ID. For more information, see Do not include a ``device_type`` for Web and Open platform associations. +Association by email +----------- + +Associate an email with a named user ID. For more information, see +`the API documentation +`__ + +.. code-block:: ruby + + require 'urbanairship' + UA = Urbanairship + airship = UA::Client.new(key:'application_key', secret:'app_or_master_secret') + named_user = UA::NamedUser.new(client: airship) + named_user.named_user_id = 'named_user' + named_user.associate_by_email_address(email_address: 'email_address') + + Disassociation --------------