socialcast 1.0.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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