socialcast 1.0.8 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm use ree-1.8.7-2011.03@socialcast-command-line --create
1
+ rvm use ree-1.8.7-2011.12@socialcast-command-line --create
data/config/ldap.yml CHANGED
@@ -34,6 +34,15 @@ mappings:
34
34
  # employee_number: emp_id
35
35
  # only use unique_identifier if you do not wish to use email as the main user identification method
36
36
  # unique_identifier: samaccountname
37
+ # To combine multiple ldap attributes into one Socialcast attribute use the following pattern
38
+ # The key is the socialcast attribute and the value is a hash. The hash requires a key of value
39
+ # which will use the other keys to interpolate the values.
40
+ # location:
41
+ # value: "%{city}, %{state} %{zip}"
42
+ # city: city
43
+ # state: state
44
+ # zip: zipcode
45
+
37
46
 
38
47
 
39
48
  # Map LDAP Group Memberships to Socialcast Permissions
@@ -0,0 +1,13 @@
1
+ if RUBY_VERSION < '1.9.2'
2
+ class String
3
+ old_format = instance_method(:%)
4
+
5
+ define_method(:%) do |arg|
6
+ if arg.is_a?(Hash)
7
+ self.gsub(/%\{(.*?)\}/) { arg[$1.to_sym] }
8
+ else
9
+ old_format.bind(self).call(arg)
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/socialcast.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'yaml'
2
2
  require 'fileutils'
3
3
  require File.join(File.dirname(__FILE__), 'ext', 'array_ext') unless Array.respond_to?(:wrap)
4
+ require File.join(File.dirname(__FILE__), 'ext', 'string_ext')
4
5
 
5
6
  module Socialcast
6
7
  class << self
@@ -80,6 +80,7 @@ module Socialcast
80
80
  method_option :delete_users_file, :type => :boolean
81
81
  method_option :test, :type => :boolean
82
82
  method_option :skip_emails, :type => :boolean
83
+ method_option :force, :type => :boolean, :aliases => '-f', :default => false
83
84
  def provision
84
85
  config_file = File.expand_path options[:config]
85
86
 
@@ -136,17 +137,20 @@ module Socialcast
136
137
  end # gzip
137
138
  say "Finished scanning #{count} users"
138
139
 
139
- say "Uploading dataset to Socialcast..."
140
- http_config = config.fetch('http', {})
141
- resource = Socialcast.resource_for_path '/api/users/provision', http_config
142
- File.open(output_file, 'r') do |file|
143
- request_params = {:file => file}
144
- request_params[:skip_emails] = 'true' if (config['options']["skip_emails"] || options[:skip_emails])
145
- request_params[:test] = 'true' if (config['options']["test"] || options[:test])
146
- resource.post request_params
140
+ if count == 0 && !options[:force]
141
+ Kernel.abort("Skipping upload to Socialcast since no users were found")
142
+ else
143
+ say "Uploading dataset to Socialcast..."
144
+ http_config = config.fetch('http', {})
145
+ resource = Socialcast.resource_for_path '/api/users/provision', http_config
146
+ File.open(output_file, 'r') do |file|
147
+ request_params = {:file => file}
148
+ request_params[:skip_emails] = 'true' if (config['options']["skip_emails"] || options[:skip_emails])
149
+ request_params[:test] = 'true' if (config['options']["test"] || options[:test])
150
+ resource.post request_params
151
+ end
152
+ say "Finished"
147
153
  end
148
- say "Finished"
149
-
150
154
  File.delete(output_file) if (config['options']['delete_users_file'] || options[:delete_users_file])
151
155
  end
152
156
  end
@@ -5,7 +5,13 @@ class Net::LDAP::Entry
5
5
  # grab a *single* value of an attribute
6
6
  # abstracts away ldap multivalue attributes
7
7
  def grab(attribute)
8
- Array.wrap(self[attribute]).compact.first
8
+ case attribute
9
+ when Hash
10
+ value = attribute.delete("value")
11
+ value % Hash[attribute.map {|k,v| [k, grab(v)]}].symbolize_keys
12
+ else
13
+ Array.wrap(self[attribute]).compact.first
14
+ end
9
15
  end
10
16
 
11
17
  def build_xml_from_mappings(user, mappings = {}, permission_mappings = {})
@@ -1,3 +1,3 @@
1
1
  module Socialcast
2
- VERSION = "1.0.8"
2
+ VERSION = "1.1.0"
3
3
  end
data/spec/cli_spec.rb CHANGED
@@ -6,8 +6,10 @@ describe Socialcast::CLI do
6
6
  # Expects -u=emily@socialcast.com -p=demo --domain=demo.socialcast.com
7
7
  context 'with a basic message' do
8
8
  before do
9
- stub_request(:post, "https://emily%40socialcast.com:demo@demo.socialcast.com/api/messages.xml").
10
- with(:body => /<message-type.*nil="true">.*testing/m).
9
+ File.stub(:open).with(/credentials.yml/).and_yield(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'credentials.yml')))
10
+ stub_request(:post, "https://ryan%40socialcast.com:foo@test.staging.socialcast.com/api/messages.json").
11
+ with(:body => /message\_type\"\:null/).
12
+ with(:body => /testing/).
11
13
  to_return(:status => 200, :body => "", :headers => {})
12
14
 
13
15
  Socialcast::CLI.start ['share', 'testing']
@@ -19,8 +21,10 @@ describe Socialcast::CLI do
19
21
 
20
22
  context 'with a message_type message' do
21
23
  before do
22
- stub_request(:post, "https://emily%40socialcast.com:demo@demo.socialcast.com/api/messages.xml").
23
- with(:body => /<message-type>review_request<\/message-type>.*please review/m).
24
+ File.stub(:open).with(/credentials.yml/).and_yield(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'credentials.yml')))
25
+ stub_request(:post, "https://ryan%40socialcast.com:foo@test.staging.socialcast.com/api/messages.json").
26
+ with(:body => /message\_type\"\:review\_request/).
27
+ with(:body => /please\sreview/).
24
28
  to_return(:status => 200, :body => "", :headers => {})
25
29
 
26
30
  Socialcast::CLI.start ['share', 'please review', '--message_type=review_request']
@@ -33,6 +37,44 @@ describe Socialcast::CLI do
33
37
  end
34
38
 
35
39
  describe '#provision' do
40
+ context 'with 0 users found in ldap' do
41
+ before do
42
+ Net::LDAP.any_instance.stub(:search).and_return(nil)
43
+
44
+ @result = ''
45
+ Zlib::GzipWriter.stub(:open).and_yield(@result)
46
+
47
+ File.should_receive(:open).with('/my/path/to/ldap.yml').and_yield(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'ldap_without_permission_mappings.yml')))
48
+ File.should_receive(:exists?).with('/my/path/to/ldap.yml').and_return(true)
49
+ File.stub(:open).with(/users.xml.gz/, anything).and_yield(@result)
50
+ File.stub(:open).with(/credentials.yml/).and_yield(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'credentials.yml')))
51
+
52
+ RestClient::Resource.any_instance.should_not_receive(:post)
53
+ Kernel.should_receive(:abort).once
54
+
55
+ Socialcast::CLI.start ['provision', '-c', '/my/path/to/ldap.yml']
56
+ end
57
+ it 'does not post to Socialcast and throws Kernel.abort' do end # see expectations
58
+ end
59
+ context 'with 0 users found in ldap and force option passed' do
60
+ before do
61
+ Net::LDAP.any_instance.stub(:search).and_return(nil)
62
+
63
+ @result = ''
64
+ Zlib::GzipWriter.stub(:open).and_yield(@result)
65
+
66
+ File.should_receive(:open).with('/my/path/to/ldap.yml').and_yield(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'ldap_without_permission_mappings.yml')))
67
+ File.should_receive(:exists?).with('/my/path/to/ldap.yml').and_return(true)
68
+ File.stub(:open).with(/users.xml.gz/, anything).and_yield(@result)
69
+ File.stub(:open).with(/credentials.yml/).and_yield(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'credentials.yml')))
70
+
71
+ RestClient::Resource.any_instance.should_receive(:post).once
72
+ Kernel.should_not_receive(:abort)
73
+
74
+ Socialcast::CLI.start ['provision', '-c', '/my/path/to/ldap.yml', '-f']
75
+ end
76
+ it 'does post to Socialcast and does not call Kernel.abort' do end # see expectations
77
+ end
36
78
  context 'with absolute path to ldap.yml file' do
37
79
  before do
38
80
  @entry = Net::LDAP::Entry.new("dc=example,dc=com")
@@ -194,4 +236,27 @@ describe Socialcast::CLI do
194
236
  end
195
237
  end
196
238
  end
239
+ context 'with ldap.yml configuration including template value' do
240
+ before do
241
+ @entry = Net::LDAP::Entry.new("dc=example,dc=com")
242
+ @entry[:mail] = 'ryan@example.com'
243
+ @entry[:l] = 'San Francisco'
244
+ @entry[:co] = 'USA'
245
+
246
+ Net::LDAP.any_instance.stub(:search).and_yield(@entry)
247
+
248
+ @result = ''
249
+ Zlib::GzipWriter.stub(:open).and_yield(@result)
250
+ File.stub(:open).with(/ldap.yml/).and_yield(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'ldap_with_interpolated_values.yml')))
251
+ File.stub(:open).with(/users.xml.gz/, anything).and_yield(@result)
252
+ File.stub(:open).with(/credentials.yml/).and_yield(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'credentials.yml')))
253
+
254
+ RestClient::Resource.any_instance.stub(:post)
255
+
256
+ Socialcast::CLI.start ['provision', '-c', 'spec/fixtures/ldap.yml']
257
+ end
258
+ it 'formats l and co according to template' do
259
+ @result.should =~ %r{<location>San Francisco, USA</location>}
260
+ end
261
+ end
197
262
  end
@@ -0,0 +1,57 @@
1
+ ---
2
+ # LDAP connections
3
+ connections:
4
+ example_connection_1:
5
+ username: "cn=Directory Manager"
6
+ password: "test"
7
+ host: localhost
8
+ port: 1389
9
+ basedn: "dc=example,dc=com"
10
+ filter: "(mail=*)"
11
+
12
+
13
+ # LDAP attribute mappings
14
+ mappings:
15
+ first_name: givenName
16
+ last_name: sn
17
+ email: mail
18
+ location:
19
+ value: "%{city}, %{country}"
20
+ city: l
21
+ country: co
22
+ # only use employee_number if the email is unknown
23
+ # employee_number: emp_id
24
+ # only use unique_identifier if you do not wish to use email as the main user identification method
25
+ # unique_identifier: samaccountname
26
+
27
+
28
+ # Map LDAP Group Memberships to Socialcast Permissions
29
+ # permission_mappings:
30
+ # # configure LDAP field for group memberships (ex: memberof, isMemberOf, etc)
31
+ # attribute_name: isMemberOf
32
+ # account_types:
33
+ # external: "cn=External,dc=example,dc=com"
34
+ # roles:
35
+ # tenant_admin: "cn=Admins,dc=example,dc=com"
36
+ # sbi_admin: "cn=SbiAdmins,dc=example,dc=com"
37
+ # reach_admin: "cn=ReachAdmins,dc=example,dc=com"
38
+ # town_hall_admin: "cn=TownHallAdmins,dc=example,dc=com"
39
+
40
+
41
+ # general script options
42
+ options:
43
+ # cleanup the extracted ldap data file after run is complete
44
+ delete_users_file: false
45
+ # skip sending emails to newly activated users
46
+ skip_emails: true
47
+ # do not actually provision accounts
48
+ # useful during testing
49
+ test: true
50
+
51
+
52
+ # http options for connecting to Socialcast servers
53
+ http:
54
+ timeout: 660
55
+ # optional setting if script must connect to Socialcast server through a proxy
56
+ # proxy: "http://username:password@proxy.company.com:3128"
57
+
metadata CHANGED
@@ -1,178 +1,124 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: socialcast
3
- version: !ruby/object:Gem::Version
4
- hash: 7
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
5
  prerelease:
6
- segments:
7
- - 1
8
- - 0
9
- - 8
10
- version: 1.0.8
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Ryan Sonnek
14
9
  - Sean Cashin
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2011-11-07 00:00:00 Z
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
13
+ date: 2012-03-06 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
22
16
  name: rest-client
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &2156569520 !ruby/object:Gem::Requirement
25
18
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 7
30
- segments:
31
- - 1
32
- - 4
33
- - 0
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
34
22
  version: 1.4.0
35
- version_requirements: *id001
36
23
  type: :runtime
37
- - !ruby/object:Gem::Dependency
38
- name: json
39
24
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: *2156569520
26
+ - !ruby/object:Gem::Dependency
27
+ name: json
28
+ requirement: &2156568780 !ruby/object:Gem::Requirement
41
29
  none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- hash: 11
46
- segments:
47
- - 1
48
- - 4
49
- - 6
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
50
33
  version: 1.4.6
51
- version_requirements: *id002
52
34
  type: :runtime
53
- - !ruby/object:Gem::Dependency
54
- name: thor
55
35
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
36
+ version_requirements: *2156568780
37
+ - !ruby/object:Gem::Dependency
38
+ name: thor
39
+ requirement: &2156568060 !ruby/object:Gem::Requirement
57
40
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 43
62
- segments:
63
- - 0
64
- - 14
65
- - 6
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
66
44
  version: 0.14.6
67
- version_requirements: *id003
68
45
  type: :runtime
69
- - !ruby/object:Gem::Dependency
70
- name: highline
71
46
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
47
+ version_requirements: *2156568060
48
+ - !ruby/object:Gem::Dependency
49
+ name: highline
50
+ requirement: &2156567200 !ruby/object:Gem::Requirement
73
51
  none: false
74
- requirements:
75
- - - ">="
76
- - !ruby/object:Gem::Version
77
- hash: 11
78
- segments:
79
- - 1
80
- - 6
81
- - 2
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
82
55
  version: 1.6.2
83
- version_requirements: *id004
84
56
  type: :runtime
85
- - !ruby/object:Gem::Dependency
86
- name: scashin133-net-ldap
87
57
  prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
58
+ version_requirements: *2156567200
59
+ - !ruby/object:Gem::Dependency
60
+ name: scashin133-net-ldap
61
+ requirement: &2156566420 !ruby/object:Gem::Requirement
89
62
  none: false
90
- requirements:
91
- - - ">="
92
- - !ruby/object:Gem::Version
93
- hash: 19
94
- segments:
95
- - 0
96
- - 1
97
- - 4
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
98
66
  version: 0.1.4
99
- version_requirements: *id005
100
67
  type: :runtime
101
- - !ruby/object:Gem::Dependency
102
- name: activeresource
103
68
  prerelease: false
104
- requirement: &id006 !ruby/object:Gem::Requirement
69
+ version_requirements: *2156566420
70
+ - !ruby/object:Gem::Dependency
71
+ name: activeresource
72
+ requirement: &2156565780 !ruby/object:Gem::Requirement
105
73
  none: false
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- hash: 21
110
- segments:
111
- - 2
112
- - 3
113
- - 11
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
114
77
  version: 2.3.11
115
- version_requirements: *id006
116
78
  type: :runtime
117
- - !ruby/object:Gem::Dependency
118
- name: rspec
119
79
  prerelease: false
120
- requirement: &id007 !ruby/object:Gem::Requirement
80
+ version_requirements: *2156565780
81
+ - !ruby/object:Gem::Dependency
82
+ name: rspec
83
+ requirement: &2156564700 !ruby/object:Gem::Requirement
121
84
  none: false
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- hash: 23
126
- segments:
127
- - 2
128
- - 6
129
- - 0
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
130
88
  version: 2.6.0
131
- version_requirements: *id007
132
89
  type: :development
133
- - !ruby/object:Gem::Dependency
134
- name: webmock
135
90
  prerelease: false
136
- requirement: &id008 !ruby/object:Gem::Requirement
91
+ version_requirements: *2156564700
92
+ - !ruby/object:Gem::Dependency
93
+ name: webmock
94
+ requirement: &2156564040 !ruby/object:Gem::Requirement
137
95
  none: false
138
- requirements:
139
- - - ">="
140
- - !ruby/object:Gem::Version
141
- hash: 5
142
- segments:
143
- - 1
144
- - 7
145
- - 7
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
146
99
  version: 1.7.7
147
- version_requirements: *id008
148
100
  type: :development
149
- - !ruby/object:Gem::Dependency
150
- name: rake
151
101
  prerelease: false
152
- requirement: &id009 !ruby/object:Gem::Requirement
102
+ version_requirements: *2156564040
103
+ - !ruby/object:Gem::Dependency
104
+ name: rake
105
+ requirement: &2156563440 !ruby/object:Gem::Requirement
153
106
  none: false
154
- requirements:
155
- - - "="
156
- - !ruby/object:Gem::Version
157
- hash: 11
158
- segments:
159
- - 0
160
- - 9
161
- - 2
162
- - 2
107
+ requirements:
108
+ - - =
109
+ - !ruby/object:Gem::Version
163
110
  version: 0.9.2.2
164
- version_requirements: *id009
165
111
  type: :development
112
+ prerelease: false
113
+ version_requirements: *2156563440
166
114
  description: publish messages to your stream from a command line interface
167
- email:
115
+ email:
168
116
  - ryan@socialcast.com
169
- executables:
117
+ executables:
170
118
  - socialcast
171
119
  extensions: []
172
-
173
120
  extra_rdoc_files: []
174
-
175
- files:
121
+ files:
176
122
  - .document
177
123
  - .gitignore
178
124
  - .rspec
@@ -185,6 +131,7 @@ files:
185
131
  - bin/socialcast
186
132
  - config/ldap.yml
187
133
  - lib/ext/array_ext.rb
134
+ - lib/ext/string_ext.rb
188
135
  - lib/socialcast.rb
189
136
  - lib/socialcast/cli.rb
190
137
  - lib/socialcast/message.rb
@@ -195,45 +142,38 @@ files:
195
142
  - spec/fixtures/credentials.yml
196
143
  - spec/fixtures/ldap.yml
197
144
  - spec/fixtures/ldap_with_array_permission_mapping.yml
145
+ - spec/fixtures/ldap_with_interpolated_values.yml
198
146
  - spec/fixtures/ldap_without_permission_mappings.yml
199
147
  - spec/spec_helper.rb
200
148
  homepage: http://github.com/wireframe/socialcast-command-line
201
149
  licenses: []
202
-
203
150
  post_install_message:
204
151
  rdoc_options: []
205
-
206
- require_paths:
152
+ require_paths:
207
153
  - lib
208
- required_ruby_version: !ruby/object:Gem::Requirement
154
+ required_ruby_version: !ruby/object:Gem::Requirement
209
155
  none: false
210
- requirements:
211
- - - ">="
212
- - !ruby/object:Gem::Version
213
- hash: 3
214
- segments:
215
- - 0
216
- version: "0"
217
- required_rubygems_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
218
161
  none: false
219
- requirements:
220
- - - ">="
221
- - !ruby/object:Gem::Version
222
- hash: 3
223
- segments:
224
- - 0
225
- version: "0"
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
226
166
  requirements: []
227
-
228
167
  rubyforge_project: socialcast
229
- rubygems_version: 1.8.5
168
+ rubygems_version: 1.8.10
230
169
  signing_key:
231
170
  specification_version: 3
232
171
  summary: command line interface to socialcast api
233
- test_files:
172
+ test_files:
234
173
  - spec/cli_spec.rb
235
174
  - spec/fixtures/credentials.yml
236
175
  - spec/fixtures/ldap.yml
237
176
  - spec/fixtures/ldap_with_array_permission_mapping.yml
177
+ - spec/fixtures/ldap_with_interpolated_values.yml
238
178
  - spec/fixtures/ldap_without_permission_mappings.yml
239
179
  - spec/spec_helper.rb