socialcast 1.3.6 → 1.3.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 059c8d71c405b6bd225ddf6bcadd22c55448c244
4
- data.tar.gz: 73dc16b3f63221865f07dd46c74f992d0f8ae96a
3
+ metadata.gz: 788cbe26a9ad449b6b0a366c6d264069586e4653
4
+ data.tar.gz: 1f21d4c2e36ed4ab2e8809ae8d0aea2d7e38b943
5
5
  SHA512:
6
- metadata.gz: 49c4a5675ab1f9832d56aa7ee23678977424020cd002573c72183f1842f6a72adb23ffb1a18464720abcdaf42da17ea5594545866f59174cf86c4746332c1cff
7
- data.tar.gz: 9ca90bb330803ed0dae3fe8ae78b86fccdb1c86c934ed43bf3497c41e455ba494f740abecba293132496149ad6d4eaf292b9d90586239cb7909d90769919b635
6
+ metadata.gz: 90c71da04a539297455463f1b7f81f9b3737c957dd5882acc9539ed52a19f2f43315fcede8e96e38a6b8ce818c91d655d26134e87995715b1444b647e326c777
7
+ data.tar.gz: 7a254b2b4132c6144a58a2d026e8aede0cae18c7a39c4f63c1f680e324578ddd2789c7f099f5cd5308297a56efa60ddfbe50e526d5189449b71afcc8b25a3f98
data/lib/socialcast.rb CHANGED
@@ -3,6 +3,7 @@ require 'fileutils'
3
3
 
4
4
  require_relative 'socialcast/command_line/ldap_connector'
5
5
  require_relative 'socialcast/command_line/provision'
6
+ require_relative 'socialcast/command_line/authenticate'
6
7
  require_relative 'socialcast/command_line/message'
7
8
  require_relative 'socialcast/command_line/cli'
8
9
  require_relative 'socialcast/command_line/version'
@@ -25,8 +26,10 @@ module Socialcast
25
26
  end
26
27
 
27
28
  def self.credentials=(options)
28
- File.open(credentials_file, "w") do |f|
29
- f.write(options.to_yaml)
29
+ File.open(credentials_file, "a+") do |f|
30
+ existing_content = YAML.load(f.read) || {}
31
+ f.truncate(0)
32
+ f.write(existing_content.merge(options).to_yaml)
30
33
  end
31
34
  File.chmod 0600, credentials_file
32
35
  end
@@ -36,7 +39,15 @@ module Socialcast
36
39
  RestClient.log = Logger.new(STDOUT) if debug
37
40
  RestClient.proxy = credentials[:proxy] if credentials[:proxy]
38
41
  url = ['https://', credentials[:domain], path].join
39
- RestClient::Resource.new url, options.merge({ :user => credentials[:user], :password => credentials[:password] })
42
+ RestClient::Resource.new url, options.merge(authentication(options))
43
+ end
44
+
45
+ def self.authentication(options)
46
+ if options[:external_system]
47
+ { :headers => { :Authorization => "SocialcastApiClient #{credentials[:api_client_identifier]}:#{credentials[:api_client_secret]}" } }
48
+ else
49
+ { :user => credentials[:user], :password => credentials[:password] }
50
+ end
40
51
  end
41
52
 
42
53
  end
@@ -0,0 +1,46 @@
1
+ module Socialcast
2
+ module CommandLine
3
+ class Authenticate
4
+ attr_accessor :authenticate_type, :options, :params, :headers
5
+
6
+ def initialize(authenticate_type, options, params, headers = {})
7
+ self.authenticate_type = authenticate_type
8
+ self.options = options
9
+ self.params = params
10
+ self.headers = headers
11
+ end
12
+
13
+ def request
14
+ @request ||= send_request
15
+ end
16
+
17
+ private
18
+
19
+ def send_request
20
+ puts "Authenticating to #{url}"
21
+ RestClient.log = Logger.new($stdout) if options[:trace]
22
+ RestClient.proxy = options[:proxy] if options[:proxy]
23
+ resource = RestClient::Resource.new url, headers
24
+ response = resource.post params, :accept => :json
25
+ puts "API response: #{response.body.to_s}" if options[:trace]
26
+ set_default_credentials
27
+ response
28
+ end
29
+
30
+ def set_default_credentials
31
+ Socialcast::CommandLine.credentials = {
32
+ :domain => domain,
33
+ :proxy => options[:proxy]
34
+ }
35
+ end
36
+
37
+ def url
38
+ @url ||= File.join("https://", domain, 'api', (authenticate_type == :external_system ? 'external_systems/' : ''), 'authentication')
39
+ end
40
+
41
+ def domain
42
+ options[:domain]
43
+ end
44
+ end
45
+ end
46
+ end
@@ -49,23 +49,43 @@ module Socialcast
49
49
  def authenticate
50
50
  user = options[:user] || ask('Socialcast username: ')
51
51
  password = options[:password] || HighLine.new.ask("Socialcast password: ") { |q| q.echo = false }.to_s
52
- domain = options[:domain]
53
52
 
54
- url = ['https://', domain, '/api/authentication'].join
55
- say "Authenticating #{user} to #{url}"
56
53
  params = { :email => user, :password => password }
57
- RestClient.log = Logger.new(STDOUT) if options[:trace]
58
- RestClient.proxy = options[:proxy] if options[:proxy]
59
- resource = RestClient::Resource.new url
60
- response = resource.post params, :accept => :json
61
- say "API response: #{response.body.to_s}" if options[:trace]
54
+ response = Socialcast::CommandLine::Authenticate.new(:user, options, params).request
62
55
  communities = JSON.parse(response.body.to_s)['communities']
63
56
  domain = communities.detect {|c| c['domain'] == domain} ? domain : communities.first['domain']
64
57
 
65
- Socialcast::CommandLine.credentials = {:user => user, :password => password, :domain => domain, :proxy => options[:proxy]}
58
+ Socialcast::CommandLine.credentials = {
59
+ :user => user,
60
+ :password => password,
61
+ :domain => domain
62
+ }
66
63
  say "Authentication successful for #{domain}"
67
64
  end
68
65
 
66
+ desc "authenticate_external_system", "Authenticate using an external system"
67
+ method_option :api_client_identifier, :type => :string, :aliases => '-i', :desc => 'the identifier of the external system'
68
+ method_option :api_client_secret, :type => :string, :aliases => '-s', :desc => 'the secret key of the external system'
69
+ method_option :proxy, :type => :string, :desc => 'HTTP proxy options for connecting to Socialcast server'
70
+ method_option :domain, :type => :string, :default => 'api.socialcast.com', :desc => 'Socialcast community domain'
71
+ def authenticate_external_system
72
+ api_client_identifier = options[:api_client_identifier] || ask("Socialcast external system identifier: ")
73
+ api_client_secret = options[:api_client_secret] || ask("Socialcast external system API secret: ")
74
+
75
+ headers = {
76
+ :headers => {
77
+ :Authorization => "SocialcastApiClient #{api_client_identifier}:#{api_client_secret}"
78
+ }
79
+ }
80
+
81
+ Socialcast::CommandLine::Authenticate.new(:external_system, options, {}, headers).request
82
+
83
+ Socialcast::CommandLine.credentials = {
84
+ :api_client_identifier => api_client_identifier,
85
+ :api_client_secret => api_client_secret,
86
+ }
87
+ end
88
+
69
89
  desc "share MESSAGE", "Posts a new message into socialcast"
70
90
  method_option :url, :type => :string, :desc => '(optional) url to associate to the message'
71
91
  method_option :message_type, :type => :string, :desc => '(optional) force an alternate message_type'
@@ -105,6 +125,7 @@ module Socialcast
105
125
  method_option :skip_emails, :type => :boolean, :desc => 'Do not send signup emails to users'
106
126
  method_option :force, :type => :boolean, :aliases => '-f', :default => false, :desc => 'Proceed with provisioning even if no users are found, which would deactivate all users in the community'
107
127
  method_option :plugins, :type => :array, :desc => "Pass in an array of plugins. Can be either the gem require or the absolute path to a ruby file"
128
+ method_option :external_system, :type => :boolean, :desc => "Use an external system for authentication purposes"
108
129
  def provision
109
130
  config = ldap_config options
110
131
  load_plugins options
@@ -34,7 +34,7 @@ module Socialcast
34
34
  end
35
35
 
36
36
  def provision
37
- http_config = @ldap_config.fetch 'http', {}
37
+ params = @ldap_config.fetch('http', {}).merge(:external_system => !!@options[:external_system])
38
38
 
39
39
  user_whitelist = Set.new
40
40
  output_file = File.join Dir.pwd, @options[:output]
@@ -56,7 +56,7 @@ module Socialcast
56
56
  raise ProvisionError.new "Skipping upload to Socialcast since no users were found"
57
57
  else
58
58
  puts "Uploading dataset to Socialcast..."
59
- resource = Socialcast::CommandLine.resource_for_path '/api/users/provision', http_config
59
+ resource = Socialcast::CommandLine.resource_for_path '/api/users/provision', params
60
60
  begin
61
61
  File.open(output_file, 'r') do |file|
62
62
  request_params = {:file => file}
@@ -65,7 +65,9 @@ module Socialcast
65
65
  resource.post request_params, :accept => :json
66
66
  end
67
67
  rescue RestClient::Unauthorized => e
68
- raise ProvisionError.new "Authenticated user either does not have administration privileges or the community is not configured to allow provisioning. Please contact Socialcast support to if you need help." if e.http_code == 401
68
+ error_message = @options[:external_system] ? "External Provisioning System was not found." : "Authenticated user either does not have administration privileges or the community is not configured to allow provisioning."
69
+ contact_message = "Please contact Socialcast support to if you need help."
70
+ raise ProvisionError.new "#{error_message} #{contact_message}\nResponse from server: #{e.response.body}" if e.http_code == 401
69
71
  end
70
72
  puts "Finished"
71
73
  end
@@ -1,5 +1,5 @@
1
1
  module Socialcast
2
2
  module CommandLine
3
- VERSION = "1.3.6"
3
+ VERSION = "1.3.7"
4
4
  end
5
5
  end
@@ -1,4 +1,6 @@
1
1
  ---
2
2
  :user: ryan@socialcast.com
3
3
  :password: foo
4
+ :api_client_identifier: my_id
5
+ :api_client_secret: mysecret
4
6
  :domain: test.staging.socialcast.com
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Socialcast::CommandLine::Authenticate do
4
+ let(:options) { { :domain => "test.socialcast.local" } }
5
+ let(:params) { { } }
6
+ subject { Socialcast::CommandLine::Authenticate.new(authenticate_type, options, params) }
7
+
8
+ describe '#request' do
9
+ before do
10
+ RestClient::Resource.should_receive(:new).with(url, {}).and_call_original
11
+ RestClient::Resource.any_instance.should_receive(:post).with(subject.params, :accept => :json)
12
+ subject.request
13
+ end
14
+ context 'for a regular user' do
15
+ let(:authenticate_type) { :user }
16
+ let(:url) { "https://test.socialcast.local/api/authentication" }
17
+ # See expectations
18
+ it 'hits the API to try authentication for a regular user' do end
19
+ end
20
+
21
+ context 'for an external system' do
22
+ let(:url) { "https://test.socialcast.local/api/external_systems/authentication" }
23
+ let(:authenticate_type) { :external_system }
24
+ # See expectations
25
+ it 'hits the API to try authentication for an external system' do end
26
+ end
27
+ end
28
+
29
+ end
@@ -34,6 +34,51 @@ describe Socialcast::CommandLine::CLI do
34
34
  end
35
35
  end
36
36
 
37
+ describe '#authenticate' do
38
+ let(:user) { 'mike@socialcast.com' }
39
+ let(:password) { 'password' }
40
+ let(:domain) { 'api.socialcast.com' }
41
+ before do
42
+ Socialcast::CommandLine.should_receive(:credentials=).with({
43
+ :domain => 'api.socialcast.com',
44
+ :proxy => nil
45
+ })
46
+ Socialcast::CommandLine.should_receive(:credentials=).with({
47
+ :user => user,
48
+ :password => password,
49
+ :domain => domain
50
+ })
51
+ stub_request(:post, "https://api.socialcast.com/api/authentication").
52
+ with(:body => {"email"=>"mike@socialcast.com", "password"=>"password"}).
53
+ to_return(:status => 200, :body => { :communities => [{ :domain => domain }] }.to_json, :headers => {})
54
+ Socialcast::CommandLine::CLI.start ['authenticate', "--user=#{user}", "--password=#{password}"]
55
+ end
56
+ ## See expectations
57
+ it 'authenticates with the API and sets the given credentials' do end
58
+ end
59
+
60
+ describe '#authenticate_external_system' do
61
+ let(:api_client_identifier) { 'my-client-id' }
62
+ let(:api_client_secret) { 'my-client-secret' }
63
+ let(:domain) { 'api.socialcast.com' }
64
+ before do
65
+ Socialcast::CommandLine.should_receive(:credentials=).with({
66
+ :domain => 'api.socialcast.com',
67
+ :proxy => nil
68
+ })
69
+ Socialcast::CommandLine.should_receive(:credentials=).with({
70
+ :api_client_identifier => api_client_identifier,
71
+ :api_client_secret => api_client_secret,
72
+ })
73
+ stub_request(:post, "https://api.socialcast.com/api/external_systems/authentication").
74
+ with(:headers => {'Authorization'=>'SocialcastApiClient my-client-id:my-client-secret'}).
75
+ to_return(:status => 200, :body => "", :headers => {})
76
+ Socialcast::CommandLine::CLI.start ['authenticate_external_system', "--api_client_identifier=#{api_client_identifier}", "--api_client_secret=#{api_client_secret}"]
77
+ end
78
+ ## See expectations
79
+ it 'authenticates with the API and sets the given credentials for an authenticated system' do end
80
+ end
81
+
37
82
  describe '#share' do
38
83
  # Expects -u=emily@socialcast.com -p=demo --domain=demo.socialcast.com
39
84
  context 'with a basic message' do
@@ -252,9 +297,9 @@ describe Socialcast::CommandLine::CLI do
252
297
 
253
298
  File.stub(:open).with(/users.xml.gz/, anything).and_yield(@result)
254
299
  rest_client_resource = double(:rest_client_resource)
255
- rest_client_resource.stub(:post).and_raise(RestClient::Unauthorized.new(mock('Unauthorized HTTP Response', :code => '401')))
300
+ rest_client_resource.stub(:post).and_raise(RestClient::Unauthorized.new(double('Unauthorized HTTP Response', :code => '401', :body => 'Unauthorized HTTP Response')))
256
301
  Socialcast::CommandLine.stub(:resource_for_path).and_return(rest_client_resource)
257
- Kernel.should_receive(:abort).with("Authenticated user either does not have administration privileges or the community is not configured to allow provisioning. Please contact Socialcast support to if you need help.").once
302
+ Kernel.should_receive(:abort).with("Authenticated user either does not have administration privileges or the community is not configured to allow provisioning. Please contact Socialcast support to if you need help.\nResponse from server: Unauthorized HTTP Response").once
258
303
 
259
304
  Socialcast::CommandLine::CLI.start ['provision', '-f']
260
305
  end
@@ -5,8 +5,9 @@ describe Socialcast::CommandLine do
5
5
  let(:custom_file) { File.join(File.dirname(__FILE__), '..', 'fixtures', 'custom_credentials.yml') }
6
6
  let(:stubbed_credentials) { File.join(File.dirname(__FILE__), '..', 'fixtures') }
7
7
  before { Socialcast::CommandLine.stub(:config_dir).and_return(stubbed_credentials) }
8
+ let!(:orig_credentials) { Socialcast::CommandLine.credentials }
8
9
 
9
- describe '#credentials_file' do
10
+ describe '.credentials_file' do
10
11
  subject { Socialcast::CommandLine.credentials_file }
11
12
  context 'with ENV variable' do
12
13
  before { ENV['SC_CREDENTIALS_FILE'] = custom_file }
@@ -18,7 +19,7 @@ describe Socialcast::CommandLine do
18
19
  end
19
20
  end
20
21
 
21
- describe '#credentials' do
22
+ describe '.credentials' do
22
23
  subject { Socialcast::CommandLine.credentials }
23
24
  describe 'with ENV variable' do
24
25
  before { ENV['SC_CREDENTIALS_FILE'] = custom_file }
@@ -30,4 +31,35 @@ describe Socialcast::CommandLine do
30
31
  end
31
32
  end
32
33
 
34
+ describe '.credentials=' do
35
+ let(:options) { { :user => 'mike@socialcast.com', :password => 'mypassword' } }
36
+ before { Socialcast::CommandLine.credentials = options }
37
+ after { Socialcast::CommandLine.credentials = orig_credentials }
38
+ subject { Socialcast::CommandLine.credentials }
39
+ context 'modifies the credentials file with the options content' do
40
+ it { subject[:user].should == 'mike@socialcast.com' }
41
+ end
42
+ context 'only changes the content provided' do
43
+ let(:options) { { :api_client_secret => 'mysecret', :api_client_identifier => 'my_id' } }
44
+ it { subject[:api_client_identifier].should == 'my_id' }
45
+ it { subject[:user].should == 'ryan@socialcast.com' }
46
+ end
47
+ end
48
+
49
+ describe '.resource_for_path' do
50
+ let(:path) { '/mypath' }
51
+ let(:url) { "https://test.staging.socialcast.com#{path}" }
52
+ before do
53
+ RestClient::Resource.should_receive(:new).with(url, options)
54
+ Socialcast::CommandLine.resource_for_path(path, options)
55
+ end
56
+ context 'when using basic auth' do
57
+ let(:options) { { :user => Socialcast::CommandLine.credentials[:user], :password => Socialcast::CommandLine.credentials[:password] } }
58
+ it 'sends user email and password' do end
59
+ end
60
+ context 'when using an external system' do
61
+ let(:options) { { :external_system => true, :headers => { :Authorization=>"SocialcastApiClient my_id:mysecret" } } }
62
+ it 'sends external system credentials' do end
63
+ end
64
+ end
33
65
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: socialcast
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.6
4
+ version: 1.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Sonnek
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-05-28 00:00:00.000000000 Z
13
+ date: 2014-06-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rest-client
@@ -217,6 +217,7 @@ files:
217
217
  - bin/socialcast
218
218
  - config/ldap.yml
219
219
  - lib/socialcast.rb
220
+ - lib/socialcast/command_line/authenticate.rb
220
221
  - lib/socialcast/command_line/cli.rb
221
222
  - lib/socialcast/command_line/ldap_connector.rb
222
223
  - lib/socialcast/command_line/message.rb
@@ -244,6 +245,7 @@ files:
244
245
  - spec/fixtures/ldap_with_unique_identifier.yml
245
246
  - spec/fixtures/ldap_without_account_type_or_roles.yml
246
247
  - spec/fixtures/ldap_without_permission_mappings.yml
248
+ - spec/socialcast/command_line/authenticate_spec.rb
247
249
  - spec/socialcast/command_line/cli_spec.rb
248
250
  - spec/socialcast/command_line/ldap_connector_spec.rb
249
251
  - spec/socialcast/command_line/provision_spec.rb
@@ -295,6 +297,7 @@ test_files:
295
297
  - spec/fixtures/ldap_with_unique_identifier.yml
296
298
  - spec/fixtures/ldap_without_account_type_or_roles.yml
297
299
  - spec/fixtures/ldap_without_permission_mappings.yml
300
+ - spec/socialcast/command_line/authenticate_spec.rb
298
301
  - spec/socialcast/command_line/cli_spec.rb
299
302
  - spec/socialcast/command_line/ldap_connector_spec.rb
300
303
  - spec/socialcast/command_line/provision_spec.rb