postini 0.0.3 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ == 0.0.4 2008-10-02
2
+
3
+ * Minor internal reworkings
4
+
1
5
  == 0.0.3 2008-08-21
2
6
 
3
7
  * Added options to allow for the capturing of soap4r wiredumps
@@ -4,10 +4,10 @@ Manifest.txt
4
4
  PostInstall.txt
5
5
  README.txt
6
6
  Rakefile
7
+ TODO
7
8
  config/hoe.rb
8
9
  config/requirements.rb
9
10
  lib/postini.rb
10
- lib/postini/version.rb
11
11
  lib/postini/api.rb
12
12
  lib/postini/api/automatedbatch/AutomatedBatch.rb
13
13
  lib/postini/api/automatedbatch/AutomatedBatchDriver.rb
@@ -18,25 +18,31 @@ lib/postini/api/endpointresolver/EndpointResolverDriver.rb
18
18
  lib/postini/api/endpointresolver/EndpointResolverMappingRegistry.rb
19
19
  lib/postini/api/endpointresolver/EndpointResolverServiceClient.rb
20
20
  lib/postini/domain.rb
21
+ lib/postini/helpers.rb
22
+ lib/postini/helpers/attributes.rb
21
23
  lib/postini/user.rb
24
+ lib/postini/users/aliases.rb
25
+ lib/postini/version.rb
22
26
  script/console
23
27
  script/destroy
24
28
  script/generate
25
29
  script/txt2html
26
30
  setup.rb
31
+ spec/attribute_helper_spec.rb
32
+ spec/domain_spec.rb
27
33
  spec/postini_spec.rb
28
34
  spec/spec.opts
29
35
  spec/spec_helper.rb
30
- spec/domain_spec.rb
31
36
  spec/user_spec.rb
32
37
  tasks/deployment.rake
33
38
  tasks/environment.rake
34
39
  tasks/rspec.rake
35
40
  tasks/website.rake
41
+ vendor/automatedbatch.wsdl
42
+ vendor/endpointresolver.wsdl
36
43
  website/index.html
37
44
  website/index.txt
38
45
  website/javascripts/rounded_corners_lite.inc.js
46
+ website/spam_box.png
39
47
  website/stylesheets/screen.css
40
48
  website/template.html.erb
41
- vendor/automatedbatch.wsdl
42
- vendor/endpointresolver.wsdl
data/Rakefile CHANGED
@@ -1,4 +1,6 @@
1
- require 'config/requirements'
2
- require 'config/hoe' # setup Hoe + all gem configuration
3
-
4
- Dir['tasks/**/*.rake'].each { |rake| load rake }
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
5
+
6
+ task :default => :spec
data/TODO ADDED
@@ -0,0 +1,37 @@
1
+ TODO LIST
2
+ =========
3
+
4
+ Handle exceptions properly, make our own exception classes
5
+ Duplicate domain exception looks like this:
6
+ SOAP::FaultError: Batch: code:general, message: A domain record already exists for 'inx.co.za'. () (Request ID 5328153A-6BBD-11DD-A41F-AE53A6E672CE)
7
+ from #<SOAP::Mapping::Object:0xb7614344>
8
+ Unknown user exception:
9
+ SOAP::FaultError: Batch: code:general, message: No user 'sarie@inx.co.za'. () (Request ID F81C4176-6C88-11DD-8917-A059A6E672CE)
10
+ from #<SOAP::Mapping::Object:0xb75e736c>
11
+
12
+ Prevent unneeded operations:
13
+ * Don't disable an already disabled user
14
+
15
+ Add support for org management
16
+
17
+ Support for lazy-loading:
18
+ * Orgs users => user details
19
+ * Convert search results into fully useable objects
20
+
21
+ Work out a nice set of class+instance method combinations. The API's aren't
22
+ really geared for instance-level stuff. So User.destroy( address ) and
23
+ @user.destroy should essentially be the same thing.
24
+
25
+ PROPER ATTRIBUTE HANDLING, NOT INSTANCE VARIABLES:
26
+
27
+ ActiveRecord-like validations (possible external library)
28
+
29
+ Map remote types to native Ruby types:
30
+ * User#created_on from Unix timestamp to Time instance
31
+ * User#approved_senders 'empty' to []
32
+
33
+ Support for changed attribute tracking, so we can implement a #save method and
34
+ call only the needed API calls or only send the changed paramters.
35
+
36
+ Would it not be cleaner to wrap the records from soap4r (eg UserRecord,
37
+ DomainRecord) inside our own classes instead of having duplicates lying around?
@@ -8,7 +8,7 @@ RUBYFORGE_PROJECT = 'postini4r' # The unix name for your project
8
8
  HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
9
  DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
10
  EXTRA_DEPENDENCIES = [
11
- # ['activesupport', '>= 1.3.1']
11
+ ['activesupport', '>=2.0.2'],
12
12
  ['soap4r', '=1.5.8']
13
13
  ] # An array of rubygem dependencies [name, version]
14
14
 
@@ -73,4 +73,4 @@ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
73
73
  PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
74
74
  $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
75
75
  $hoe.rsync_args = '-av --delete --ignore-errors'
76
- $hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
76
+ $hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
@@ -2,7 +2,12 @@ $:.unshift(File.dirname(__FILE__)) unless
2
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
4
  # requirements
5
- gem 'soap4r'
5
+ require 'rubygems'
6
+ gem 'soap4r', '=1.5.8'
7
+ unless defined?( ActiveSupport )
8
+ gem 'activesupport', '>=2.0.2'
9
+ end
10
+ require 'postini/helpers'
6
11
  require 'postini/user'
7
12
  require 'postini/domain'
8
13
 
@@ -65,7 +70,7 @@ module Postini
65
70
  # On the fly class variable, getter and setter generation...
66
71
  %w{
67
72
  api_key system_number username password xauth
68
- logger debug soap4r_debug soap4r_debug_dev soap4r_wiredump soap4r_wiredump_dev
73
+ logger debug soap4r_wiredump soap4r_wiredump_dev
69
74
  }.each do |config|
70
75
  class_eval <<-EOF
71
76
  @@#{config} = nil
@@ -134,9 +139,9 @@ module Postini
134
139
  end
135
140
 
136
141
  def soap4r_wiredump_dev
137
- @@soap4r_wiredump_dev ||= soap4r_debug_dev
142
+ @@soap4r_wiredump_dev ||= logger
138
143
  end
139
144
 
140
145
  end
141
146
 
142
- end
147
+ end
@@ -59,7 +59,7 @@ module Postini
59
59
  # TODO: Add improved validations here
60
60
  return false if @name.nil? || @org.nil?
61
61
 
62
- remote = automated_batch_port
62
+ remote = self.class.automated_batch_port
63
63
  args = Postini::API::AutomatedBatch::Adddomainargs.new( @name )
64
64
  request = Postini::API::AutomatedBatch::Adddomain.new(
65
65
  Postini.auth, @org, args
@@ -0,0 +1,13 @@
1
+ require 'activesupport'
2
+ require 'postini/helpers/attributes'
3
+
4
+ module Postini
5
+
6
+ # A collection of helpers to implement various needed convenience methods
7
+ # to our other classes and to keep things DRY. The behaviour is very much
8
+ # based on, and inspired by, ActiveRecord and makes excessive use of
9
+ # ActiveSupport to reach its goals.
10
+ module Helpers
11
+
12
+ end
13
+ end
@@ -0,0 +1,94 @@
1
+ module Postini
2
+ module Helpers
3
+ # Provide our classes with ActiveRecord like attribute handling, mapping
4
+ # plain text to native Ruby objects (and vice versa).
5
+ module Attributes
6
+
7
+ def self.included( base ) #:nodoc:
8
+ base.extend( ClassMethods )
9
+ base.send( :include, InstanceMethods )
10
+ end
11
+
12
+ module ClassMethods
13
+
14
+ def self.extended( base )
15
+ base.send( :class_inheritable_hash, :attributes )
16
+ base.attributes = {}
17
+ end
18
+
19
+ # Specifies the list of attributes for the class, together with an
20
+ # optional type to map them to.
21
+ #
22
+ # has_attributes :address
23
+ # has_attributes :active, :welcome, :type => :boolean
24
+ #
25
+ def has_attributes( *args )
26
+ opts = args.extract_options!
27
+ opts[:type] ||= :string
28
+
29
+ args.each do |attr|
30
+ register_attribute( attr => opts[:type] )
31
+ end
32
+ end
33
+
34
+ # Specify a single attribute together with its type
35
+ def has_attribute( attr )
36
+ raise "Invalid parameter, hash expected" unless attr.is_a?( Hash ) &&
37
+ attr.keys.size == 1
38
+
39
+ register_attribute( attr )
40
+ end
41
+
42
+ private
43
+
44
+ # Register an attribute in our internal list
45
+ def register_attribute( attr )
46
+ self.attributes.merge!( attr.stringify_keys! )
47
+
48
+ # :id needs to be handled specialy
49
+ if attr.keys.first == "id"
50
+ class_eval <<-EOF
51
+ def id
52
+ @attributes[ "id" ]
53
+ end
54
+ def id=( value )
55
+ @attributes[ "id" ] = value
56
+ end
57
+ EOF
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ module InstanceMethods
64
+
65
+ # Setup a new instance with all the attributes configured
66
+ def initialize( attributes = {} )
67
+ validate_attributes!( attributes )
68
+
69
+ @attributes = attributes.stringify_keys
70
+ end
71
+
72
+ def method_missing( method_name, *args )
73
+ method_name.to_s =~ /^([^=]+)(\=)?$/
74
+ key = $1.to_s
75
+ if self.class.attributes.has_key?( key )
76
+ if $2
77
+ @attributes[ key ] = *args
78
+ else
79
+ @attributes[ key ]
80
+ end
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ def validate_attributes!( attrs = {} )
87
+ attrs.assert_valid_keys( self.class.attributes.symbolize_keys.keys )
88
+ end
89
+
90
+ end
91
+
92
+ end
93
+ end
94
+ end
@@ -1,4 +1,5 @@
1
1
  require 'postini/api/automatedbatch/AutomatedBatchDriver'
2
+ require 'postini/users/aliases'
2
3
 
3
4
  module Postini
4
5
 
@@ -7,13 +8,22 @@ module Postini
7
8
  # TODO: Expand documentation
8
9
  class User
9
10
 
10
- attr_accessor :id, :active, :address, :approved_recipients,
11
- :approved_senders, :blocked_senders, :create_method, :created_date,
12
- :filter_adult, :filter_bulk, :filter_getrich, :filter_offers,
13
- :filter_racial, :initial_password, :junkmail_filter, :lang_locale,
14
- :lastmod_date, :message_encryption, :message_limit, :message_limited,
15
- :message_count, :notice_address, :orgid, :password, :timezone,
16
- :virus_notify, :virus_state, :weblocked, :welcome_count, :wireless_state
11
+ include Helpers::Attributes
12
+
13
+ has_attributes :id, :message_count, :message_limit, :orgid, :create_method,
14
+ :virus_notify, :type => :int
15
+ has_attributes :active, :junkmail_filter, :message_encryption,
16
+ :message_limited, :virus_state, :weblocked, :welcome_count,
17
+ :wireless_state, :type => :bool
18
+ has_attributes :address, :notice_address, :initial_password, :password,
19
+ :lang_locale, :timezone, :orgtag, :ext_encrypt
20
+ has_attributes :approved_recipients, :approved_senders, :blocked_senders,
21
+ :type => :array
22
+ has_attributes :created_date, :lastmod_date, :type => :timestamp
23
+ has_attributes :filter_adult, :filter_bulk, :filter_getrich,
24
+ :filter_offers, :filter_racial, :type => :filter
25
+
26
+ include Users::Aliases
17
27
 
18
28
  class << self
19
29
 
@@ -52,15 +62,8 @@ module Postini
52
62
 
53
63
  end
54
64
 
55
- # Setup a new instance with the combination of attributes set
56
- def initialize( attributes = {} )
57
- attributes.each_pair do |k,v|
58
- instance_variable_set "@#{k.to_s}", v
59
- end
60
- end
61
-
62
65
  def new?
63
- @id.nil?
66
+ self.id.nil?
64
67
  end
65
68
 
66
69
  # Create the new user. Pass +welcome+ as '1' to have a welcome mail sent
@@ -69,11 +72,11 @@ module Postini
69
72
  return false unless new?
70
73
 
71
74
  # TODO: Add missing validations here
72
- return false if @address.nil? || @org.nil?
75
+ return false if self.address.nil? || self.orgid.nil?
73
76
 
74
- remote = automated_batch_port
75
- args = Postini::API::AutomatedBatch::Adduserargs.new( @org, welcome )
76
- request = Postini::API::AutomatedBatch::Adduser.new( Postini.auth, @address, args )
77
+ remote = self.class.automated_batch_port
78
+ args = Postini::API::AutomatedBatch::Adduserargs.new( self.orgid, welcome )
79
+ request = Postini::API::AutomatedBatch::Adduser.new( Postini.auth, self.address, args )
77
80
  remote.adduser( request )
78
81
  end
79
82
 
@@ -81,54 +84,8 @@ module Postini
81
84
  def destroy
82
85
  return false if new?
83
86
 
84
- self.class.destroy( @address )
87
+ self.class.destroy( self.address )
85
88
  end
86
89
 
87
- # Return the list of aliases for the mailbox
88
- def aliases
89
- if @aliases.nil?
90
- remote = self.class.automated_batch_port( @address )
91
- query = Postini::API::AutomatedBatch::ListusersqueryParams.new
92
- query.aliases = 1
93
- query.childorgs = 1
94
- query.primaryqs = @address
95
- query.targetOrg = @orgid
96
- request = Postini::API::AutomatedBatch::Listusers.new(
97
- Postini.auth,
98
- "ALL",
99
- query
100
- )
101
-
102
- response = remote.listusers( request )
103
-
104
- @aliases = []
105
- response.each { |user_record| @aliases << user_record.address }
106
- end
107
-
108
- @aliases
109
- end
110
-
111
- # Add an alias to this user
112
- def add_alias( address )
113
- @aliases = nil # clear our cache
114
- remote = self.class.automated_batch_port( @address )
115
- request = Postini::API::AutomatedBatch::Addalias.new( Postini.auth, @address, address )
116
- remote.addalias( request )
117
- end
118
-
119
- # Removes the specified alias
120
- def remove_alias( address )
121
- @aliases = nil # clear our cache
122
- remote = self.class.automated_batch_port( @address )
123
- request = Postini::API::AutomatedBatch::Deletealias.new( Postini.auth, address )
124
- remote.deletealias( request )
125
- end
126
-
127
- # Removes all aliases from the user
128
- def clear_aliases
129
- aliases.each do |address|
130
- remove_alias( address )
131
- end
132
- end
133
90
  end
134
91
  end
@@ -0,0 +1,55 @@
1
+ module Postini
2
+ module Users
3
+
4
+ # Managing aliases of the users
5
+ module Aliases
6
+ # Return the list of aliases for the mailbox
7
+ def aliases
8
+ if @aliases.nil?
9
+ remote = self.class.automated_batch_port( self.address )
10
+ query = Postini::API::AutomatedBatch::ListusersqueryParams.new
11
+ query.aliases = 1
12
+ query.childorgs = 1
13
+ query.primaryqs = self.address
14
+ query.targetOrg = self.orgid
15
+ request = Postini::API::AutomatedBatch::Listusers.new(
16
+ Postini.auth,
17
+ "ALL",
18
+ query
19
+ )
20
+
21
+ response = remote.listusers( request )
22
+
23
+ @aliases = []
24
+ response.each { |user_record| @aliases << user_record.address }
25
+ end
26
+
27
+ @aliases
28
+ end
29
+
30
+ # Add an alias to this user
31
+ def add_alias( address )
32
+ @aliases = nil # clear our cache
33
+ remote = self.class.automated_batch_port( self.address )
34
+ request = Postini::API::AutomatedBatch::Addalias.new( Postini.auth, self.address, address )
35
+ remote.addalias( request )
36
+ end
37
+
38
+ # Removes the specified alias
39
+ def remove_alias( address )
40
+ @aliases = nil # clear our cache
41
+ remote = self.class.automated_batch_port( self.address )
42
+ request = Postini::API::AutomatedBatch::Deletealias.new( Postini.auth, address )
43
+ remote.deletealias( request )
44
+ end
45
+
46
+ # Removes all aliases from the user
47
+ def clear_aliases
48
+ aliases.each do |address|
49
+ remove_alias( address )
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -2,7 +2,7 @@ module Postini
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 3
5
+ TINY = 6
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -0,0 +1,47 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ class AttributeTester
4
+ include Postini::Helpers::Attributes
5
+
6
+ has_attribute :id => :int
7
+ has_attribute :now => :timestamp
8
+ has_attribute :active => :boolean
9
+ has_attributes :address, :name, :type => :string
10
+
11
+ end
12
+
13
+ describe Postini::Helpers::Attributes do
14
+
15
+ describe "and initialization" do
16
+
17
+ it "should handle no attributes" do
18
+ lambda {
19
+ at = AttributeTester.new
20
+ }.should_not raise_error
21
+ end
22
+
23
+ it "should set valid attributes" do
24
+ at = AttributeTester.new( :id => 1, :active => true )
25
+ at.id.should be(1)
26
+ at.active.should be_true
27
+ end
28
+
29
+ it "should raise exceptions on invalid values" do
30
+ lambda {
31
+ AttributeTester.new( :wtf => "is this?" )
32
+ }.should raise_error
33
+ end
34
+ end
35
+
36
+ describe "and getters/setters" do
37
+
38
+ before(:each) do
39
+ @at = AttributeTester.new
40
+ end
41
+
42
+ it "that should act like attr_accessors" do
43
+ @at.active = true
44
+ @at.active.should be_true
45
+ end
46
+ end
47
+ end
@@ -27,4 +27,32 @@ describe "Postini master module" do
27
27
  Postini.xauth.should eql('format_unknown_to_author')
28
28
  end
29
29
 
30
+ it "should return a pre-built URI if no user is provided" do
31
+ Postini.system_number = 0
32
+ Postini.endpoint_uri.should eql('https://api-s0.postini.com/api2/automatedbatch')
33
+ end
34
+
35
+ it "should use the Endpoint Resolver service if a user is provided" do
36
+ mock_remote = Postini::API::EndpointResolver::EndpointResolverPort.new
37
+ mock_remote.expects( :getServiceEndpoint ).with(anything).returns(
38
+ OpenStruct.new( :endpointURI => 'https://api-s0.postini.com/api2/automatedbatch' )
39
+ )
40
+ Postini::API::EndpointResolver::EndpointResolverPort.expects(:new).returns(mock_remote)
41
+
42
+ Postini.endpoint_uri( 'support@jumboinc.com' ).should eql('https://api-s0.postini.com/api2/automatedbatch')
43
+
44
+ pending "IMPROVE"
45
+ end
46
+
47
+ it "should generate auth elements without user details" do
48
+ pending
49
+ end
50
+
51
+ it "should generate auth elements with username and passwords" do
52
+ pending
53
+ end
54
+
55
+ it "should generate auth elements with usernames and xauth strings" do
56
+ pending
57
+ end
30
58
  end
@@ -8,3 +8,8 @@ end
8
8
 
9
9
  $:.unshift(File.dirname(__FILE__) + '/../lib')
10
10
  require 'postini'
11
+ require 'ostruct'
12
+
13
+ Spec::Runner.configure do |config|
14
+ config.mock_with :mocha
15
+ end
@@ -1,12 +1,142 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper.rb'
2
2
 
3
3
  describe Postini::User do
4
+
4
5
  before(:each) do
5
- @user = Postini::User.new
6
+ Postini.stubs(:endpoint_uri).with(anything).returns('http://example.com/api2/automatedbatch')
7
+ Postini.stubs(:auth).with(anything).returns(
8
+ Postini::API::AutomatedBatch::AuthElem.new(
9
+ '0000000000000000', 'postini4r@jumboinc.com', 'secret', nil
10
+ )
11
+ )
6
12
  end
13
+
14
+ describe "provides convenience methods" do
15
+ it "load a user" do
16
+ address = 'support@jumboinc.com'
7
17
 
8
- it "should be tested" do
9
- violated "Test me"
18
+ mock_request = Postini::API::AutomatedBatch::Displayuser.new( Postini.auth, address )
19
+ Postini::API::AutomatedBatch::Displayuser.expects(:new).with( Postini.auth, address ).returns( mock_request )
20
+
21
+ mock_remote = Postini::API::AutomatedBatch::AutomatedBatchPort.new( Postini.endpoint_uri(address) )
22
+ Postini::User.expects(:automated_batch_port).with(address).returns(mock_remote)
23
+
24
+ mock_user = Postini::API::AutomatedBatch::UserRecord.new
25
+ mock_user.address = address
26
+ mock_user.user_id = 0
27
+
28
+ mock_response = Postini::API::AutomatedBatch::DisplayuserResponse.new( mock_user )
29
+
30
+ mock_remote.expects(:displayuser).with(mock_request).returns(mock_response)
31
+
32
+ ####
33
+
34
+ user = Postini::User.find( address )
35
+
36
+ user.address.should eql(address)
37
+ user.id.should be(0)
38
+ end
39
+
40
+ it "destroy a user" do
41
+ address = 'support@jumboinc.com'
42
+
43
+ mock_remote = Postini::API::AutomatedBatch::AutomatedBatchPort.new( Postini.endpoint_uri(address) )
44
+ mock_remote.expects(:deleteuser).with(anything)
45
+ Postini::User.expects(:automated_batch_port).with(address).returns(mock_remote)
46
+
47
+ Postini::User.destroy(address)
48
+
49
+ pending "IMPROVE"
50
+ end
10
51
  end
11
- end
12
52
 
53
+ describe "when new" do
54
+ before(:each) do
55
+ @user = Postini::User.new( :active => "no" )
56
+ end
57
+
58
+ it "should convert the options hash into instance variables" do
59
+ @user.active.should eql("no")
60
+ end
61
+
62
+ it "should indicate so" do
63
+ @user.should be_new
64
+ end
65
+
66
+ it "should only be created if all validations pass" do
67
+ Postini::User.expects(:automated_batch_port).never
68
+
69
+ @user.create.should be_false
70
+ end
71
+
72
+ it "should be created if valid" do
73
+ @user.address = 'support@jumboinc.com'
74
+ @user.orgid = 'support'
75
+
76
+ mock_args = Postini::API::AutomatedBatch::Adduserargs.new( @user.orgid, 0 )
77
+ Postini::API::AutomatedBatch::Adduserargs.expects(:new).with( @user.orgid, 0 ).returns(mock_args)
78
+
79
+ mock_request = Postini::API::AutomatedBatch::Adduser.new( Postini.auth, @user.address, mock_args )
80
+ Postini::API::AutomatedBatch::Adduser.expects(:new).with( Postini.auth, @user.address, mock_args ).returns(mock_request)
81
+
82
+ mock_remote = Postini::API::AutomatedBatch::AutomatedBatchPort.new( Postini.endpoint_uri )
83
+ Postini::User.expects(:automated_batch_port).returns(mock_remote)
84
+ mock_remote.expects(:adduser).with(mock_request)
85
+
86
+ ####
87
+
88
+ @user.create
89
+ end
90
+ end
91
+
92
+ describe "when loaded" do
93
+ before(:each) do
94
+ @user = Postini::User.new(
95
+ :id => 0,
96
+ :address => 'support@jumboinc.com',
97
+ :orgid => 'support'
98
+ )
99
+ end
100
+
101
+ it "cannot be created again" do
102
+ Postini::User.expects(:automated_batch_port).never
103
+
104
+ @user.create.should be_false
105
+ end
106
+
107
+ it "can be deleted" do
108
+ Postini::User.expects(:destroy).with(@user.address)
109
+
110
+ @user.destroy
111
+ end
112
+ end
113
+
114
+ describe "and aliases" do
115
+ before(:each) do
116
+ @user = Postini::User.new( :address => 'support@jumboinc.com' )
117
+
118
+ end
119
+
120
+ it "can be loaded" do
121
+ mock_remote = Postini::API::AutomatedBatch::AutomatedBatchPort.new( Postini.endpoint_uri(@user.address) )
122
+ Postini::User.expects(:automated_batch_port).with(@user.address).returns(mock_remote)
123
+ mock_remote.expects(:listusers).with(anything).returns([])
124
+
125
+ @user.aliases.should be_empty
126
+
127
+ pending "IMPROVE"
128
+ end
129
+
130
+ it "can be added to" do
131
+ pending
132
+ end
133
+
134
+ it "can be removed" do
135
+ pending
136
+ end
137
+
138
+ it "can be cleared" do
139
+ pending
140
+ end
141
+ end
142
+ end
@@ -19,3 +19,21 @@ Spec::Rake::SpecTask.new do |t|
19
19
  t.spec_opts = ['--options', "spec/spec.opts"]
20
20
  t.spec_files = FileList['spec/**/*_spec.rb']
21
21
  end
22
+
23
+ namespace :spec do
24
+ desc "Print Specdoc for all specs (excluding plugin specs)"
25
+ Spec::Rake::SpecTask.new(:doc) do |t|
26
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
27
+ t.spec_files = FileList['spec/**/*_spec.rb']
28
+ end
29
+
30
+ desc "Run all specs in spec directory with RCov (excluding plugin specs)"
31
+ Spec::Rake::SpecTask.new(:rcov) do |t|
32
+ t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/../spec/spec.opts\""]
33
+ t.spec_files = FileList['spec/**/*_spec.rb']
34
+ t.rcov = true
35
+ t.rcov_opts = lambda do
36
+ IO.readlines("#{File.dirname(__FILE__)}/../spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
37
+ end
38
+ end
39
+ end
@@ -33,7 +33,8 @@
33
33
  <h1>postini Gem</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/postini4r"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/postini4r" class="numbers">0.0.3</a>
36
+ <a href="http://rubyforge.org/projects/postini4r" class="numbers">0.0.6</a>
37
+ <a href="http://www.spaminabox.co.za"><img src="spam_box.png" alt="SPAM in a Box" /></a>
37
38
  </div>
38
39
  <h2>Part of the postini4r project</h2>
39
40
  <p>The postini4r project is a collection of sub-projects that aim to implement a broad range of Postini-related tools.</p>
@@ -71,7 +72,7 @@ rake install_gem</pre>
71
72
  <p>postini4r is developed by <a href="http://www.opensourcery.co.za/">Kenneth Kalmer</a> for <a href="http://www.spaminabox.co.za"><span class="caps">SPAM</span> in a Box</a> who has allowed the library to be released under the <span class="caps">MIT</span> License through their sponsorship.</p>
72
73
  <p class="coda">
73
74
  <a href="http://www.opensourcery.co.za">Kenneth Kalmer</a> &amp;
74
- <a href="http://www.spaminabox.co.za">SPAM in a Box</a>, 16th August 2008<br>
75
+ <a href="http://www.spaminabox.co.za">SPAM in a Box</a>, 11th March 2009<br>
75
76
  Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
76
77
  </p>
77
78
  </div>
Binary file
@@ -1,138 +1,143 @@
1
- body {
2
- background-color: #E1D1F1;
3
- font-family: "Georgia", sans-serif;
4
- font-size: 16px;
5
- line-height: 1.6em;
6
- padding: 1.6em 0 0 0;
7
- color: #333;
8
- }
9
- h1, h2, h3, h4, h5, h6 {
10
- color: #444;
11
- }
12
- h1 {
13
- font-family: sans-serif;
14
- font-weight: normal;
15
- font-size: 4em;
16
- line-height: 0.8em;
17
- letter-spacing: -0.1ex;
18
- margin: 5px;
19
- }
20
- li {
21
- padding: 0;
22
- margin: 0;
23
- list-style-type: square;
24
- }
25
- a {
26
- color: #5E5AFF;
27
- background-color: #DAC;
28
- font-weight: normal;
29
- text-decoration: underline;
30
- }
31
- blockquote {
32
- font-size: 90%;
33
- font-style: italic;
34
- border-left: 1px solid #111;
35
- padding-left: 1em;
36
- }
37
- .caps {
38
- font-size: 80%;
39
- }
40
-
41
- #main {
42
- width: 45em;
43
- padding: 0;
44
- margin: 0 auto;
45
- }
46
- .coda {
47
- text-align: right;
48
- color: #77f;
49
- font-size: smaller;
50
- }
51
-
52
- table {
53
- font-size: 90%;
54
- line-height: 1.4em;
55
- color: #ff8;
56
- background-color: #111;
57
- padding: 2px 10px 2px 10px;
58
- border-style: dashed;
59
- }
60
-
61
- th {
62
- color: #fff;
63
- }
64
-
65
- td {
66
- padding: 2px 10px 2px 10px;
67
- }
68
-
69
- .success {
70
- color: #0CC52B;
71
- }
72
-
73
- .failed {
74
- color: #E90A1B;
75
- }
76
-
77
- .unknown {
78
- color: #995000;
79
- }
80
- pre, code {
81
- font-family: monospace;
82
- font-size: 90%;
83
- line-height: 1.4em;
84
- color: #ff8;
85
- background-color: #111;
86
- padding: 2px 10px 2px 10px;
87
- }
88
- .comment { color: #aaa; font-style: italic; }
89
- .keyword { color: #eff; font-weight: bold; }
90
- .punct { color: #eee; font-weight: bold; }
91
- .symbol { color: #0bb; }
92
- .string { color: #6b4; }
93
- .ident { color: #ff8; }
94
- .constant { color: #66f; }
95
- .regex { color: #ec6; }
96
- .number { color: #F99; }
97
- .expr { color: #227; }
98
-
99
- #version {
100
- float: right;
101
- text-align: right;
102
- font-family: sans-serif;
103
- font-weight: normal;
104
- background-color: #B3ABFF;
105
- color: #141331;
106
- padding: 15px 20px 10px 20px;
107
- margin: 0 auto;
108
- margin-top: 15px;
109
- border: 3px solid #141331;
110
- }
111
-
112
- #version .numbers {
113
- display: block;
114
- font-size: 4em;
115
- line-height: 0.8em;
116
- letter-spacing: -0.1ex;
117
- margin-bottom: 15px;
118
- }
119
-
120
- #version p {
121
- text-decoration: none;
122
- color: #141331;
123
- background-color: #B3ABFF;
124
- margin: 0;
125
- padding: 0;
126
- }
127
-
128
- #version a {
129
- text-decoration: none;
130
- color: #141331;
131
- background-color: #B3ABFF;
132
- }
133
-
134
- .clickable {
135
- cursor: pointer;
136
- cursor: hand;
137
- }
138
-
1
+ body {
2
+ background-color: #E1D1F1;
3
+ font-family: "Georgia", sans-serif;
4
+ font-size: 16px;
5
+ line-height: 1.6em;
6
+ padding: 1.6em 0 0 0;
7
+ color: #333;
8
+ }
9
+ h1, h2, h3, h4, h5, h6 {
10
+ color: #444;
11
+ }
12
+ h1 {
13
+ font-family: sans-serif;
14
+ font-weight: normal;
15
+ font-size: 4em;
16
+ line-height: 0.8em;
17
+ letter-spacing: -0.1ex;
18
+ margin: 5px;
19
+ }
20
+ li {
21
+ padding: 0;
22
+ margin: 0;
23
+ list-style-type: square;
24
+ }
25
+ a {
26
+ color: #5E5AFF;
27
+ background-color: #DAC;
28
+ font-weight: normal;
29
+ text-decoration: underline;
30
+ }
31
+ blockquote {
32
+ font-size: 90%;
33
+ font-style: italic;
34
+ border-left: 1px solid #111;
35
+ padding-left: 1em;
36
+ }
37
+ .caps {
38
+ font-size: 80%;
39
+ }
40
+
41
+ #main {
42
+ width: 45em;
43
+ padding: 0;
44
+ margin: 0 auto;
45
+ }
46
+ .coda {
47
+ text-align: right;
48
+ color: #77f;
49
+ font-size: smaller;
50
+ }
51
+
52
+ table {
53
+ font-size: 90%;
54
+ line-height: 1.4em;
55
+ color: #ff8;
56
+ background-color: #111;
57
+ padding: 2px 10px 2px 10px;
58
+ border-style: dashed;
59
+ }
60
+
61
+ th {
62
+ color: #fff;
63
+ }
64
+
65
+ td {
66
+ padding: 2px 10px 2px 10px;
67
+ }
68
+
69
+ .success {
70
+ color: #0CC52B;
71
+ }
72
+
73
+ .failed {
74
+ color: #E90A1B;
75
+ }
76
+
77
+ .unknown {
78
+ color: #995000;
79
+ }
80
+ pre, code {
81
+ font-family: monospace;
82
+ font-size: 90%;
83
+ line-height: 1.4em;
84
+ color: #ff8;
85
+ background-color: #111;
86
+ padding: 2px 10px 2px 10px;
87
+ }
88
+ .comment { color: #aaa; font-style: italic; }
89
+ .keyword { color: #eff; font-weight: bold; }
90
+ .punct { color: #eee; font-weight: bold; }
91
+ .symbol { color: #0bb; }
92
+ .string { color: #6b4; }
93
+ .ident { color: #ff8; }
94
+ .constant { color: #66f; }
95
+ .regex { color: #ec6; }
96
+ .number { color: #F99; }
97
+ .expr { color: #227; }
98
+
99
+ #version {
100
+ float: right;
101
+ text-align: right;
102
+ font-family: sans-serif;
103
+ font-weight: normal;
104
+ background-color: #B3ABFF;
105
+ color: #141331;
106
+ padding: 15px 20px 10px 20px;
107
+ margin: 0 auto;
108
+ margin-top: 15px;
109
+ border: 3px solid #141331;
110
+ }
111
+
112
+ #version .numbers {
113
+ display: block;
114
+ font-size: 4em;
115
+ line-height: 0.8em;
116
+ letter-spacing: -0.1ex;
117
+ margin-bottom: 15px;
118
+ }
119
+
120
+ #version p {
121
+ text-decoration: none;
122
+ color: #141331;
123
+ background-color: #B3ABFF;
124
+ margin: 0;
125
+ padding: 0;
126
+ }
127
+
128
+ #version a {
129
+ text-decoration: none;
130
+ color: #141331;
131
+ background-color: #B3ABFF;
132
+ }
133
+
134
+ #version img {
135
+ margin-right: 15px;
136
+ border: 0;
137
+ }
138
+
139
+ .clickable {
140
+ cursor: pointer;
141
+ cursor: hand;
142
+ }
143
+
@@ -34,6 +34,7 @@
34
34
  <div id="version" class="clickable" onclick='document.location = "<%= download %>"; return false'>
35
35
  <p>Get Version</p>
36
36
  <a href="<%= download %>" class="numbers"><%= version %></a>
37
+ <a href="http://www.spaminabox.co.za"><img src="spam_box.png" alt="SPAM in a Box" /></a>
37
38
  </div>
38
39
  <%= body %>
39
40
  <p class="coda">
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: postini
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenneth Kalmer
@@ -9,9 +9,19 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-08-21 00:00:00 +02:00
12
+ date: 2009-03-24 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.0.2
24
+ version:
15
25
  - !ruby/object:Gem::Dependency
16
26
  name: soap4r
17
27
  type: :runtime
@@ -30,7 +40,7 @@ dependencies:
30
40
  requirements:
31
41
  - - ">="
32
42
  - !ruby/object:Gem::Version
33
- version: 1.7.0
43
+ version: 1.8.0
34
44
  version:
35
45
  description: Ruby wrapper around the Postini SOAP API (Early Access Program)
36
46
  email:
@@ -53,10 +63,10 @@ files:
53
63
  - PostInstall.txt
54
64
  - README.txt
55
65
  - Rakefile
66
+ - TODO
56
67
  - config/hoe.rb
57
68
  - config/requirements.rb
58
69
  - lib/postini.rb
59
- - lib/postini/version.rb
60
70
  - lib/postini/api.rb
61
71
  - lib/postini/api/automatedbatch/AutomatedBatch.rb
62
72
  - lib/postini/api/automatedbatch/AutomatedBatchDriver.rb
@@ -67,28 +77,34 @@ files:
67
77
  - lib/postini/api/endpointresolver/EndpointResolverMappingRegistry.rb
68
78
  - lib/postini/api/endpointresolver/EndpointResolverServiceClient.rb
69
79
  - lib/postini/domain.rb
80
+ - lib/postini/helpers.rb
81
+ - lib/postini/helpers/attributes.rb
70
82
  - lib/postini/user.rb
83
+ - lib/postini/users/aliases.rb
84
+ - lib/postini/version.rb
71
85
  - script/console
72
86
  - script/destroy
73
87
  - script/generate
74
88
  - script/txt2html
75
89
  - setup.rb
90
+ - spec/attribute_helper_spec.rb
91
+ - spec/domain_spec.rb
76
92
  - spec/postini_spec.rb
77
93
  - spec/spec.opts
78
94
  - spec/spec_helper.rb
79
- - spec/domain_spec.rb
80
95
  - spec/user_spec.rb
81
96
  - tasks/deployment.rake
82
97
  - tasks/environment.rake
83
98
  - tasks/rspec.rake
84
99
  - tasks/website.rake
100
+ - vendor/automatedbatch.wsdl
101
+ - vendor/endpointresolver.wsdl
85
102
  - website/index.html
86
103
  - website/index.txt
87
104
  - website/javascripts/rounded_corners_lite.inc.js
105
+ - website/spam_box.png
88
106
  - website/stylesheets/screen.css
89
107
  - website/template.html.erb
90
- - vendor/automatedbatch.wsdl
91
- - vendor/endpointresolver.wsdl
92
108
  has_rdoc: true
93
109
  homepage: http://postini4r.rubyforge.org
94
110
  post_install_message: |+
@@ -120,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
136
  requirements: []
121
137
 
122
138
  rubyforge_project: postini4r
123
- rubygems_version: 1.2.0
139
+ rubygems_version: 1.3.1
124
140
  signing_key:
125
141
  specification_version: 2
126
142
  summary: Ruby wrapper around the Postini SOAP API (Early Access Program)