ecircle_soap_client 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ require 'ostruct'
2
+ module Ecircle
3
+ class Configuration
4
+ attr_accessor :realm, :user, :password, :wsdl
5
+
6
+ def initialize
7
+ @session_token = nil
8
+ @wsdl = OpenStruct.new
9
+ wsdl.document = "http://webservices.ecircle-ag.com/soap/ecm.wsdl"
10
+ wsdl.endpoint = "http://webservices.ecircle-ag.com/rpc"
11
+ wsdl.namespace = "http://webservices.ecircleag.com/rpcns"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,73 @@
1
+ module Ecircle
2
+ class Group < Ecircle::Base
3
+ class << self
4
+ def find_all_by_name(group_name)
5
+ ary = Ecircle.client.lookup_groups :lookupParams => { :groupName => group_name }
6
+ ary.is_a?(Array) ? ary.collect { |a| Ecircle::Group.new(a) } : []
7
+ end
8
+
9
+ def find_by_name(group_name)
10
+ hsh = Ecircle.client.lookup_groups :lookupParams => { :groupName => group_name }
11
+ hsh.is_a?(Hash) ? Group.new(hsh) : raise("Group name #{group_name} not unique")
12
+ end
13
+
14
+ def all
15
+ find_all_by_name("")
16
+ end
17
+
18
+ def find_by_id(idstr)
19
+ ## TODO there must be a better way of doing this?!
20
+ ## TODO but there isn't a lookupGroupById in the wsdl specification.
21
+ all.reject { |a| a.id != idstr }.first
22
+ end
23
+ end
24
+
25
+ def initialize(hsh = nil)
26
+ super()
27
+ @all_fields = hsh || {}
28
+ @id = self[:id]
29
+ end
30
+
31
+ # Make a user a member of a group. Can be called multiple times for the same
32
+ # user, eCircle checks for duplicates based on the email or whatever.
33
+ # Returns a member object.
34
+ def add_member(user, send_invite = false, send_message = false)
35
+ member_id = Ecircle.client.
36
+ create_member(:userId => user.id, :groupId => @id,
37
+ :invite => send_invite, :sendMessage => send_message)
38
+ Ecircle::Member.find_by_id(member_id)
39
+ end
40
+
41
+ def remove_user(user, send_message = false)
42
+ user.leave_group(self, send_message)
43
+ end
44
+
45
+ def remove_member(member, send_message = false)
46
+ member.user.leave_group(self, send_message)
47
+ end
48
+
49
+ # clone this group at eCircle. For example,
50
+ # Ecircle::Group.
51
+ # find_by_name("fubar").
52
+ # clone( "snafu", "snafu@cmXX.ecircle-ag.com", false )
53
+ def clone(with_name, with_email, keep_owner = true)
54
+ Ecircle.client.
55
+ clone_group(:templateGroupId => @id, :newGroupEmail => with_email,
56
+ :newGroupName => with_name, :keepOwner => keep_owner)
57
+ end
58
+
59
+ def delete
60
+ Ecircle.client.delete_group :groupId => @id
61
+ end
62
+
63
+ def to_xml
64
+ # prefer to use u.send(...) but that creates a new xml element called 'send'!
65
+ # hence this is using instance_eval with a string.
66
+ Savon::SOAP::XML.new.xml do |x|
67
+ x.group(:id => @id) do |u|
68
+ u.name(@id)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,31 @@
1
+ module Ecircle
2
+ class Member < Ecircle::Base
3
+ class << self
4
+ def find_by_id(member_id)
5
+ Ecircle.client.lookup_member_by_id :memberid => member_id
6
+ end
7
+ end
8
+
9
+ def initialize(xml_string)
10
+ super()
11
+ init_with_xml("member", xml_string)
12
+ end
13
+
14
+ def delete
15
+ Ecircle.client.delete_member :memberId => @id
16
+ end
17
+
18
+ ## TODO with assume that the member id is the form of "<userid>g<groupid>", hence
19
+ ## TODO split on 'g' should work!
20
+ def user_id ; @id.split(/g/).first ; end
21
+ def group_id ; @id.split(/g/).last ; end
22
+
23
+ def group
24
+ Ecircle::Group.find_by_id(group_id)
25
+ end
26
+ def user
27
+ Ecircle::User.find_by_id(user_id)
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,93 @@
1
+ module Ecircle
2
+ class Message < Ecircle::Base
3
+
4
+ MessageTypeUnknown = Class.new(RuntimeError)
5
+ MessageGroupNotDefined = Class.new(RuntimeError)
6
+
7
+ class << self
8
+ def find_all_by_group_name(group_name)
9
+ ary = Ecircle.client.lookup_messages :lookupParams => { :groupName => group_name }
10
+ ary.is_a?(Array) ? ary.collect { |a| Ecircle::Message.new(a) } : []
11
+ end
12
+
13
+ def find_by_id(idstr)
14
+ ## TODO no lookupMessageById, hence this workaround.
15
+ all.reject { |msg| msg.id != idstr }.first
16
+ end
17
+
18
+ def all
19
+ find_all_by_group_name("")
20
+ end
21
+ end
22
+
23
+ def initialize(hsh)
24
+ super()
25
+ @all_fields = hsh
26
+ @id = self[:id]
27
+ end
28
+
29
+ def subject
30
+ self[:subject]
31
+ end
32
+
33
+ def group
34
+ # a single message could potentially have no group_id? Either case this
35
+ # should just return nil instead of raising an exception.
36
+ Ecircle::Group.find_by_id(self[:group_id]) if self[:group_id]
37
+ end
38
+
39
+ def delete
40
+ Ecircle.client.delete_message :messageId => self.id
41
+ true
42
+ rescue Ecircle::Client::PermissionDenied => e
43
+ false
44
+ end
45
+
46
+ # This does one of two things, if the message is of type 'single', then
47
+ # it uses send_single_message_to_user, else if the type is 'normal' then
48
+ # it uses the send_group_message_to_user.
49
+ #
50
+ # If parameters are given and this is a single message, then a parameterized
51
+ # version of the message is sent.
52
+ #
53
+ # Return value is an array with the first value being boolean to indicate
54
+ # success status. The second value is the original result returned by the
55
+ # ecircle API. The thing is, that ecircle will return nil on success, so
56
+ # in that case, we return [true, nil].
57
+ def send_to_user(user, parameters = nil)
58
+ result = case self[:type]
59
+
60
+ when /single/
61
+ if parameters.nil?
62
+ Ecircle.client.
63
+ send_single_message_to_user(:singleMessageId => @id,
64
+ :userId => user.id)
65
+ else
66
+ paras = { :singleMessageId => @id,
67
+ :userId => user.id,
68
+ :names => parameters.keys,
69
+ :values => parameters.values,
70
+ }
71
+ Ecircle.client.send_parametrized_single_message_to_user(paras)
72
+ end
73
+
74
+ when /normal/
75
+ # raise an exception because this is inconsistent: a group message without
76
+ # group_id is not possible.
77
+ raise MessageGroupNotDefined, "MsgId: #{self.id}" unless self[:group_id]
78
+
79
+ Ecircle.client.
80
+ send_group_message_to_user(:userId => user.id,
81
+ :messageId => @id,
82
+ :groupid => self[:group_id])
83
+ else
84
+ raise(MessageTypeUnknown, "Type: #{self[:type]} unknown for "+
85
+ "MsgId: #{self.id}")
86
+ end
87
+
88
+ # strangely, if the message sending worked out, then ecircle sends nil, i.e.
89
+ # nothing back. Else we get some sort of strange error or exception.
90
+ result.nil? ? [true, nil] : [false, result]
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,120 @@
1
+ module Ecircle
2
+ class User < Ecircle::Base
3
+
4
+ class << self
5
+ def create_by_email(email)
6
+ u = User.new
7
+ u.email = email
8
+ ## TODO why must the title be defined
9
+ u.title = "-1"
10
+ u.id = Ecircle.client.create_user :userXmlSpec => u.to_xml
11
+ u
12
+ end
13
+
14
+ def find_by_email(email)
15
+ Ecircle.client.lookup_user_by_email :email => email
16
+ end
17
+
18
+ def find_by_identifier(idstr)
19
+ Ecircle.client.lookup_user_by_identifier :identifier => idstr
20
+ end
21
+
22
+ def find_by_id(idstr)
23
+ Ecircle.client.lookup_user_by_id :userId => idstr
24
+ end
25
+ end
26
+
27
+ def initialize(xml_string = nil)
28
+ super()
29
+ initialize_with_xml(xml_string) if xml_string
30
+ end
31
+
32
+ def email
33
+ self[:email]
34
+ end
35
+
36
+ def delete
37
+ Ecircle.client.delete_user :user_id => @id
38
+ end
39
+
40
+ def create_or_update(send_message = false)
41
+ Ecircle.client.
42
+ create_or_update_user_by_email :userXml => to_xml, :sendMessage => send_message
43
+ end
44
+
45
+ def save
46
+ Ecircle.client.update_user :userXmlSpec => to_xml
47
+ end
48
+
49
+ # Returns the group ids this user is signed up to as an Array of strings.
50
+ def group_ids
51
+ [Ecircle.client.find_memberships_by_email(:email => email)].flatten.compact
52
+ end
53
+
54
+ def groups
55
+ group_ids.collect { |grpid| Ecircle::Group.find_by_id(grpid) }
56
+ end
57
+ alias_method :memberships, :groups
58
+
59
+ # +group_or_id+ may be a Ecircle::Group
60
+ # object, containing the group's id, or the id directly.
61
+ def in_group?(group_or_id)
62
+ group_ids.include?(Ecircle::User.group_id(group_or_id))
63
+ end
64
+
65
+ def join_group(group, send_invite = false, send_message = false)
66
+ group.add_member self, send_invite, send_message
67
+ end
68
+
69
+ # Unsubscribe this user from the given group. group may be a Ecircle::Group
70
+ # object, containing the group's id, or the id directly.
71
+ # Always returns true.
72
+ def leave_group(group_or_id, send_message = false)
73
+ Ecircle.client.
74
+ unsubscribe_member_by_email(:groupId => Ecircle::User.group_id(group_or_id),
75
+ :email => email,
76
+ :sendMessage => send_message)
77
+ end
78
+
79
+ def to_xml
80
+ obj = self # in instance_eval 'self' will be something else, so create new
81
+ # reference to te self containing all the data.
82
+
83
+ # prefer to use u.send(...) but that creates a new xml element called 'send'!
84
+ # hence this is using instance_eval with a string.
85
+ Savon::SOAP::XML.new.xml do |x|
86
+ x.user(:id => @id) do |u|
87
+ # email is special, so so so special.
88
+ u.email(self.email)
89
+
90
+ # base attributes of a user
91
+ [:title, :firstname, :lastname, :nickname, :dob_dd,
92
+ :dob_mm, :dob_yyyy,:countrycode,:languagecode].each do |field_name|
93
+ u.instance_eval "%s(obj[:%s])" % ([field_name]*2)
94
+ end
95
+
96
+ # cust_attr_X
97
+ 9.times.collect { |idx| "cust_attr_#{idx+1}" }.
98
+ each do |field_name|
99
+ u.instance_eval "%s(obj[:%s])" % ([field_name]*2)
100
+ end
101
+
102
+ # named attributes, these are generic and defined by some guy in a suit.
103
+ named_attrs.each do |key,value|
104
+ u.namedattr({:name => key}, value)
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ private
111
+
112
+ def self.group_id(group_obj_or_id)
113
+ (group_obj_or_id.is_a?(Ecircle::Group) ? group_obj_or_id.id : group_obj_or_id).to_s
114
+ end
115
+
116
+ def initialize_with_xml(xml_string)
117
+ init_with_xml("user", xml_string)
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,48 @@
1
+ require 'savon'
2
+ require 'nokogiri'
3
+ require 'net/http/post/multipart'
4
+ require 'uuidtools'
5
+ require 'base64'
6
+ require 'ostruct'
7
+
8
+ require 'ecircle/configuration'
9
+ require 'ecircle/client'
10
+ require 'ecircle/base'
11
+ require 'ecircle/member'
12
+ require 'ecircle/group'
13
+ require 'ecircle/user'
14
+ require 'ecircle/message'
15
+
16
+ # Helper for converting times to ecircle expected format.
17
+ module EcircleTimeHelper
18
+ def ecircle_format(prefix)
19
+ # ecircle uses JS month indices
20
+ strftime("yyyy:%Y,dd:%d,hh:%H,min:%M,ss:%S,mm:#{'%02d' % (month - 1)}").split(',').
21
+ inject({}) do |hsh, postfix_and_value|
22
+ postfix, value = postfix_and_value.split(':')
23
+ hsh.merge( "#{prefix}_#{postfix}".to_sym => value )
24
+ end
25
+ end
26
+ end
27
+
28
+ [Date, Time].each do |clazz|
29
+ clazz.send(:include, EcircleTimeHelper)
30
+ end
31
+
32
+ module Ecircle
33
+ extend self
34
+
35
+ def configuration
36
+ @configuration ||= Configuration.new
37
+ end
38
+
39
+ def client
40
+ @client ||= Client.new
41
+ end
42
+
43
+ def configure
44
+ config = configuration
45
+ block_given? ? yield(config) : config
46
+ config
47
+ end
48
+ end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- ruby -*-
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+
13
+ original_load_path = $LOAD_PATH
14
+ dirs = ['ext', 'lib'].select { |dir| File.directory?(dir) }
15
+ $LOAD_PATH.unshift(*dirs)
16
+
17
+ require 'pry'
18
+ require 'ecircle_soap_client'
19
+
20
+ settings = YAML::load_file(File.join(File.dirname(__FILE__), 'test', '.login.yml'))
21
+ Ecircle.configure do |config|
22
+ config.user = settings["user"]
23
+ config.realm = settings["realm"]
24
+ config.password = settings["password"]
25
+ end
26
+ puts "*** Setup Ecircle"
27
+
28
+ Pry.editor = "emacs"
29
+ Pry.start
30
+
31
+ $LOAD_PATH.reject! { |path| !(original_load_path.include?(path)) }
@@ -0,0 +1,4 @@
1
+ ---
2
+ user: username
3
+ realm: http://example.com
4
+ password: password
data/test/helper.rb ADDED
@@ -0,0 +1,116 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'test/unit'
13
+ require 'shoulda'
14
+ require 'yaml'
15
+ require 'rr'
16
+
17
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
18
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
19
+
20
+ require 'ecircle_soap_client'
21
+
22
+ class Test::Unit::TestCase
23
+ include RR::Adapters::TestUnit
24
+
25
+ def _soap_fault(msg)
26
+ os = OpenStruct.new
27
+ os.body = Savon::SOAP::XML.new.xml do |x|
28
+ x.envelope do |e|
29
+ e.body do |b|
30
+ b.Fault do |f|
31
+ f.faultcode("client")
32
+ f.faultstring(msg)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ Savon::SOAP::Fault.new(os)
38
+ end
39
+
40
+ def mock_ecircle_client(create_client_object = false)
41
+ if create_client_object
42
+ client, req_obj = Ecircle::Client.new, Object.new
43
+ mock(client).client { req_obj }
44
+ # don't mock client since this will be used directly.
45
+ yield(client, mock(req_obj))
46
+ else
47
+ req_object = Object.new
48
+ mock(Ecircle).client { req_object }
49
+ yield(mock(req_object))
50
+ end
51
+ end
52
+
53
+ def in_soap_body
54
+ <<-SOAP
55
+ <?xml version="1.0" encoding="UTF-8"?>
56
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
57
+ <soapenv:Body>
58
+ #{yield}
59
+ </soapenv:Body>
60
+ </soapenv:Envelope>
61
+ SOAP
62
+ end
63
+
64
+ def mock_response(resp)
65
+ mock_ecircle_client(true) do |client, savon_client|
66
+ mock(Ecircle).client { client }
67
+ mock(client).logon { nil }
68
+ savon_client.request.with_any_args do
69
+ Savon::SOAP::Response.new(HTTPI::Response.new(200, {}, resp))
70
+ end
71
+ end
72
+ end
73
+
74
+ def config_soap_client
75
+ # keep login details separate from gem.
76
+ settings = begin
77
+ YAML::load_file(File.join(File.dirname(__FILE__), '.login.yml'))
78
+ rescue
79
+ puts "NO test/.login.yml --> copy the sample across to test"
80
+ exit 1
81
+ end
82
+
83
+ Ecircle.configure do |config|
84
+ config.user = settings["user"]
85
+ config.realm = settings["realm"]
86
+ config.password = settings["password"]
87
+ end
88
+ end
89
+
90
+ def assert_difference(expression, difference = 1, message = nil, &block)
91
+ b = block.send(:binding)
92
+ exps = Array.wrap(expression)
93
+ before = exps.map { |e| eval(e, b) }
94
+
95
+ yield
96
+
97
+ exps.each_with_index do |e, i|
98
+ error = "#{e.inspect} didn't change by #{difference}"
99
+ error = "#{message}.\n#{error}" if message
100
+ assert_equal(before[i] + difference, eval(e, b), error)
101
+ end
102
+ end
103
+ end
104
+
105
+ # Rails extension required for assert_difference (another rails extension)
106
+ class Array
107
+ def self.wrap(object)
108
+ if object.nil?
109
+ []
110
+ elsif object.respond_to?(:to_ary)
111
+ object.to_ary
112
+ else
113
+ [object]
114
+ end
115
+ end
116
+ end