socialcast 1.3.7 → 1.3.8
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 +4 -4
- data/lib/socialcast.rb +3 -1
- data/lib/socialcast/command_line/cli.rb +5 -4
- data/lib/socialcast/command_line/provision_photo.rb +79 -0
- data/lib/socialcast/command_line/provision_user.rb +66 -0
- data/lib/socialcast/command_line/provisioner.rb +51 -0
- data/lib/socialcast/command_line/version.rb +1 -1
- data/spec/fixtures/test_images/test-gif-image.gif +0 -0
- data/spec/fixtures/test_images/test-jpg-image.jpg +0 -0
- data/spec/fixtures/test_images/test-png-image.png +0 -0
- data/spec/fixtures/test_images/test-tiff-image.tiff +0 -0
- data/spec/socialcast/command_line/authenticate_spec.rb +3 -2
- data/spec/socialcast/command_line/cli_spec.rb +4 -4
- data/spec/socialcast/command_line/provision_photo_spec.rb +117 -0
- data/spec/socialcast/command_line/{provision_spec.rb → provision_user_spec.rb} +21 -97
- data/spec/spec_helper.rb +13 -0
- metadata +16 -4
- data/lib/socialcast/command_line/provision.rb +0 -166
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 43487693be70d4bd0315db025f57e8a2c492fcc7
|
|
4
|
+
data.tar.gz: a527ada1136ef1d6e3f2fd80ae8fb4e69cd493e7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3f23a5a4c44d39c83c2a8b1b41868ecf7c25938141129b55993cd619e832ae44d835bfa022fb2700a5d68b595108a204c26ae3b4745855fc169453ed73684975
|
|
7
|
+
data.tar.gz: f9703ae386594ee84cac91e11625d2d0589a5697c8ab103b433b3ef1af37826ee7f5b00a915378de274eb77c06afc5b52b8d6bbc6835875cca6d0369f0d470a9
|
data/lib/socialcast.rb
CHANGED
|
@@ -2,8 +2,10 @@ require 'yaml'
|
|
|
2
2
|
require 'fileutils'
|
|
3
3
|
|
|
4
4
|
require_relative 'socialcast/command_line/ldap_connector'
|
|
5
|
-
require_relative 'socialcast/command_line/
|
|
5
|
+
require_relative 'socialcast/command_line/provisioner'
|
|
6
6
|
require_relative 'socialcast/command_line/authenticate'
|
|
7
|
+
require_relative 'socialcast/command_line/provision_user'
|
|
8
|
+
require_relative 'socialcast/command_line/provision_photo'
|
|
7
9
|
require_relative 'socialcast/command_line/message'
|
|
8
10
|
require_relative 'socialcast/command_line/cli'
|
|
9
11
|
require_relative 'socialcast/command_line/version'
|
|
@@ -118,7 +118,7 @@ module Socialcast
|
|
|
118
118
|
|
|
119
119
|
desc 'provision', 'provision users from ldap compatible user repository'
|
|
120
120
|
method_option :config, :default => 'ldap.yml', :aliases => '-c', :desc => 'Path to ldap config file'
|
|
121
|
-
method_option :output, :default => Socialcast::CommandLine::
|
|
121
|
+
method_option :output, :default => Socialcast::CommandLine::ProvisionUser::DEFAULT_OUTPUT_FILE, :aliases => '-o', :desc => 'Name of the output file'
|
|
122
122
|
method_option :setup, :type => :boolean, :desc => 'Create an example ldap config file and exit'
|
|
123
123
|
method_option :delete_users_file, :type => :boolean, :desc => 'Delete the output file'
|
|
124
124
|
method_option :test, :type => :boolean, :desc => 'Do not persist changes'
|
|
@@ -130,18 +130,19 @@ module Socialcast
|
|
|
130
130
|
config = ldap_config options
|
|
131
131
|
load_plugins options
|
|
132
132
|
|
|
133
|
-
Socialcast::CommandLine::
|
|
133
|
+
Socialcast::CommandLine::ProvisionUser.new(config, options).provision
|
|
134
134
|
|
|
135
|
-
rescue Socialcast::CommandLine::
|
|
135
|
+
rescue Socialcast::CommandLine::ProvisionUser::ProvisionError => e
|
|
136
136
|
Kernel.abort e.message
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
desc 'sync_photos', 'Upload default avatar photos from LDAP repository'
|
|
140
140
|
method_option :config, :default => 'ldap.yml', :aliases => '-c'
|
|
141
|
+
method_option :force_sync, :default => false, :aliases => '-f', :desc => 'Pushes all photos from LDAP to socialcast'
|
|
141
142
|
def sync_photos
|
|
142
143
|
config = ldap_config options
|
|
143
144
|
|
|
144
|
-
Socialcast::CommandLine::
|
|
145
|
+
Socialcast::CommandLine::ProvisionPhoto.new(config, options).sync
|
|
145
146
|
end
|
|
146
147
|
|
|
147
148
|
no_tasks do
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'digest/md5'
|
|
2
|
+
|
|
3
|
+
module Socialcast
|
|
4
|
+
module CommandLine
|
|
5
|
+
class ProvisionPhoto
|
|
6
|
+
include Socialcast::CommandLine::Provisioner
|
|
7
|
+
def sync
|
|
8
|
+
each_ldap_connector do |connector|
|
|
9
|
+
|
|
10
|
+
connector.attribute_mappings.fetch('profile_photo')
|
|
11
|
+
|
|
12
|
+
each_ldap_entry do |entry|
|
|
13
|
+
attr_mappings = connector.attribute_mappings
|
|
14
|
+
email = connector.grab(entry, attr_mappings['email'])
|
|
15
|
+
|
|
16
|
+
## GET USER INFO
|
|
17
|
+
search_users_resource = Socialcast::CommandLine.resource_for_path '/api/users/search', http_config
|
|
18
|
+
user_search_response = search_users_resource.get(:params => { :q => email, :per_page => 1 }, :accept => :json)
|
|
19
|
+
user_info = JSON.parse(user_search_response)['users'].first
|
|
20
|
+
|
|
21
|
+
is_community_default = user_info && user_info['avatars'] && user_info['avatars']['is_community_default']
|
|
22
|
+
return unless is_community_default || @options[:force_sync]
|
|
23
|
+
|
|
24
|
+
## PHOTO URL TO BINARY
|
|
25
|
+
if profile_photo_data = connector.grab(entry, attr_mappings['profile_photo'])
|
|
26
|
+
if profile_photo_data.start_with?('http')
|
|
27
|
+
begin
|
|
28
|
+
profile_photo_data = RestClient.get(profile_photo_data)
|
|
29
|
+
rescue => e
|
|
30
|
+
puts "Unable to download photo #{profile_photo_data} for #{email}"
|
|
31
|
+
puts e.response
|
|
32
|
+
next
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
## FORCE ENCODING
|
|
37
|
+
profile_photo_data = profile_photo_data.force_encoding('binary')
|
|
38
|
+
|
|
39
|
+
## CONTENT TYPE
|
|
40
|
+
unless content_type = binary_to_content_type(profile_photo_data)
|
|
41
|
+
puts "Skipping photo for #{email}: unknown image format (supports .gif, .png, .jpg)"
|
|
42
|
+
next
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
## WRITE TEMP FILE
|
|
46
|
+
tempfile = Tempfile.new(["photo_upload", ".#{content_type}"])
|
|
47
|
+
tempfile.write(profile_photo_data)
|
|
48
|
+
tempfile.rewind
|
|
49
|
+
|
|
50
|
+
puts "Uploading photo for #{email}"
|
|
51
|
+
|
|
52
|
+
## SUBMIT PHOTO
|
|
53
|
+
begin
|
|
54
|
+
user_resource = Socialcast::CommandLine.resource_for_path "/api/users/#{user_info['id']}", http_config
|
|
55
|
+
user_resource.put({ :user => { :profile_photo => { :data => tempfile } } })
|
|
56
|
+
ensure
|
|
57
|
+
tempfile.unlink
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def binary_to_content_type(binary_photo_data)
|
|
67
|
+
case binary_photo_data
|
|
68
|
+
when Regexp.new("^GIF8", nil, 'n')
|
|
69
|
+
'gif'
|
|
70
|
+
when Regexp.new('^\x89PNG', nil, 'n')
|
|
71
|
+
'png'
|
|
72
|
+
when Regexp.new("^\xff\xd8\xff\xe0\x00\x10JFIF", nil, 'n'), Regexp.new("^\xff\xd8\xff\xe1(.*){2}Exif", nil, 'n')
|
|
73
|
+
'jpg'
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'zlib'
|
|
2
|
+
require 'builder'
|
|
3
|
+
require 'set'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
|
|
6
|
+
module Socialcast
|
|
7
|
+
module CommandLine
|
|
8
|
+
class ProvisionUser
|
|
9
|
+
include Socialcast::CommandLine::Provisioner
|
|
10
|
+
|
|
11
|
+
def each_user_hash
|
|
12
|
+
each_ldap_connector do |connector|
|
|
13
|
+
connector.each_user_hash do |user_hash|
|
|
14
|
+
yield user_hash
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def fetch_user_hash(identifier, options = {})
|
|
20
|
+
each_ldap_connector do |connector|
|
|
21
|
+
user_hash = connector.fetch_user_hash(identifier, options)
|
|
22
|
+
return user_hash if user_hash
|
|
23
|
+
end
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def provision
|
|
28
|
+
user_whitelist = Set.new
|
|
29
|
+
output_file = File.join Dir.pwd, @options[:output]
|
|
30
|
+
params = http_config.merge(:external_system => !!@options[:external_system])
|
|
31
|
+
|
|
32
|
+
Zlib::GzipWriter.open(output_file) do |gz|
|
|
33
|
+
xml = Builder::XmlMarkup.new(:target => gz, :indent => 1)
|
|
34
|
+
xml.instruct!
|
|
35
|
+
xml.export do |export|
|
|
36
|
+
export.users(:type => "array") do |users|
|
|
37
|
+
each_user_hash do |user_hash|
|
|
38
|
+
users << user_hash.to_xml(:skip_instruct => true, :root => 'user')
|
|
39
|
+
user_whitelist << [user_hash['contact_info']['email'], user_hash['unique_identifier'], user_hash['employee_number']]
|
|
40
|
+
end
|
|
41
|
+
end # users
|
|
42
|
+
end # export
|
|
43
|
+
end # gzip
|
|
44
|
+
|
|
45
|
+
if user_whitelist.empty? && !@options[:force]
|
|
46
|
+
raise ProvisionError.new "Skipping upload to Socialcast since no users were found"
|
|
47
|
+
else
|
|
48
|
+
puts "Uploading dataset to Socialcast..."
|
|
49
|
+
resource = Socialcast::CommandLine.resource_for_path '/api/users/provision', params
|
|
50
|
+
begin
|
|
51
|
+
File.open(output_file, 'r') do |file|
|
|
52
|
+
request_params = {:file => file}
|
|
53
|
+
request_params[:skip_emails] = 'true' if (@ldap_config['options']["skip_emails"] || @options[:skip_emails])
|
|
54
|
+
request_params[:test] = 'true' if (@ldap_config['options']["test"] || @options[:test])
|
|
55
|
+
resource.post request_params, :accept => :json
|
|
56
|
+
end
|
|
57
|
+
rescue RestClient::Unauthorized => e
|
|
58
|
+
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
|
|
59
|
+
end
|
|
60
|
+
puts "Finished"
|
|
61
|
+
end
|
|
62
|
+
File.delete(output_file) if (@ldap_config['options']['delete_users_file'] || @options[:delete_users_file])
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Socialcast
|
|
2
|
+
module CommandLine
|
|
3
|
+
module Provisioner
|
|
4
|
+
class ProvisionError < StandardError; end
|
|
5
|
+
|
|
6
|
+
DEFAULT_OUTPUT_FILE = 'users.xml.gz'
|
|
7
|
+
|
|
8
|
+
def initialize(ldap_config, options = {})
|
|
9
|
+
@ldap_config = ldap_config.dup
|
|
10
|
+
@options = options.dup
|
|
11
|
+
|
|
12
|
+
@options[:output] ||= DEFAULT_OUTPUT_FILE
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def http_config
|
|
18
|
+
@http_config ||= @ldap_config.fetch 'http', {}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def ldap_connector(connection_name)
|
|
22
|
+
@connectors ||= {}
|
|
23
|
+
|
|
24
|
+
unless @connectors[connection_name]
|
|
25
|
+
@connectors[connection_name] = Socialcast::CommandLine::LDAPConnector.new(connection_name, @ldap_config)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
@connectors[connection_name]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def each_ldap_connector
|
|
32
|
+
@ldap_config['connections'].keys.each do |connection_name|
|
|
33
|
+
yield ldap_connector(connection_name)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def each_ldap_entry(&block)
|
|
38
|
+
count = 0
|
|
39
|
+
|
|
40
|
+
each_ldap_connector do |connector|
|
|
41
|
+
connector.each_ldap_entry do |entry|
|
|
42
|
+
yield entry, connector.connection_name
|
|
43
|
+
count += 1
|
|
44
|
+
puts "Scanned #{count} users" if ((count % 100) == 0)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
puts "Finished scanning #{count} users"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -3,13 +3,14 @@ require 'spec_helper'
|
|
|
3
3
|
describe Socialcast::CommandLine::Authenticate do
|
|
4
4
|
let(:options) { { :domain => "test.socialcast.local" } }
|
|
5
5
|
let(:params) { { } }
|
|
6
|
-
subject { Socialcast::CommandLine::Authenticate.new(authenticate_type, options, params) }
|
|
6
|
+
subject(:authenticate) { Socialcast::CommandLine::Authenticate.new(authenticate_type, options, params) }
|
|
7
7
|
|
|
8
8
|
describe '#request' do
|
|
9
9
|
before do
|
|
10
10
|
RestClient::Resource.should_receive(:new).with(url, {}).and_call_original
|
|
11
11
|
RestClient::Resource.any_instance.should_receive(:post).with(subject.params, :accept => :json)
|
|
12
|
-
|
|
12
|
+
authenticate.should_receive(:set_default_credentials).and_return(true)
|
|
13
|
+
authenticate.request
|
|
13
14
|
end
|
|
14
15
|
context 'for a regular user' do
|
|
15
16
|
let(:authenticate_type) { :user }
|
|
@@ -162,7 +162,7 @@ describe Socialcast::CommandLine::CLI do
|
|
|
162
162
|
{
|
|
163
163
|
'id' => 7,
|
|
164
164
|
'avatars' => {
|
|
165
|
-
'
|
|
165
|
+
'is_community_default' => system_default_photo
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
]
|
|
@@ -199,7 +199,7 @@ describe Socialcast::CommandLine::CLI do
|
|
|
199
199
|
{
|
|
200
200
|
'id' => 7,
|
|
201
201
|
'avatars' => {
|
|
202
|
-
'
|
|
202
|
+
'is_community_default' => system_default_photo
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
]
|
|
@@ -232,7 +232,7 @@ describe Socialcast::CommandLine::CLI do
|
|
|
232
232
|
{
|
|
233
233
|
'id' => 7,
|
|
234
234
|
'avatars' => {
|
|
235
|
-
'
|
|
235
|
+
'is_community_default' => system_default_photo
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
]
|
|
@@ -299,7 +299,7 @@ describe Socialcast::CommandLine::CLI do
|
|
|
299
299
|
rest_client_resource = double(:rest_client_resource)
|
|
300
300
|
rest_client_resource.stub(:post).and_raise(RestClient::Unauthorized.new(double('Unauthorized HTTP Response', :code => '401', :body => 'Unauthorized HTTP Response')))
|
|
301
301
|
Socialcast::CommandLine.stub(:resource_for_path).and_return(rest_client_resource)
|
|
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
|
|
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.").once
|
|
303
303
|
|
|
304
304
|
Socialcast::CommandLine::CLI.start ['provision', '-f']
|
|
305
305
|
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Socialcast::CommandLine::ProvisionPhoto do
|
|
4
|
+
let(:ldap_with_profile_photo) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_profile_photo.yml')) }
|
|
5
|
+
|
|
6
|
+
context '#sync' do
|
|
7
|
+
let(:options) { {} }
|
|
8
|
+
subject(:sync_photos) { Socialcast::CommandLine::ProvisionPhoto.new(ldap_with_profile_photo, options).sync }
|
|
9
|
+
let(:user_search_resource) { double(:user_search_resource) }
|
|
10
|
+
let(:user_submit_resource) { double(:user_submit_resource) }
|
|
11
|
+
let(:is_community_default) { true }
|
|
12
|
+
let(:data_fingerprint) { '5d41402abc4b2a76b9719d911017c592' }
|
|
13
|
+
let(:search_api_response) do
|
|
14
|
+
{
|
|
15
|
+
'users' => [
|
|
16
|
+
{
|
|
17
|
+
'id' => 7,
|
|
18
|
+
'avatars' => {
|
|
19
|
+
'is_community_default' => is_community_default,
|
|
20
|
+
'data_fingerprint' => data_fingerprint
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
before do
|
|
27
|
+
entry = create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name', :jpegPhoto => photo_data
|
|
28
|
+
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'jpegPhoto', 'memberof'])).and_yield(entry)
|
|
29
|
+
Socialcast::CommandLine.stub(:resource_for_path).with('/api/users/search', anything).and_return(user_search_resource)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context 'for when it does successfully post the photo' do
|
|
33
|
+
before do
|
|
34
|
+
user_search_resource.should_receive(:get).and_return(search_api_response.to_json)
|
|
35
|
+
user_resource = double(:user_resource)
|
|
36
|
+
user_resource.should_receive(:put) do |data|
|
|
37
|
+
uploaded_data = data[:user][:profile_photo][:data]
|
|
38
|
+
uploaded_data.path.should =~ /\.png\Z/
|
|
39
|
+
end
|
|
40
|
+
Socialcast::CommandLine.stub(:resource_for_path).with('/api/users/7', anything).and_return(user_resource)
|
|
41
|
+
end
|
|
42
|
+
context 'for a binary file' do
|
|
43
|
+
let(:photo_data) { "\x89PNGabc" }
|
|
44
|
+
before do
|
|
45
|
+
RestClient.should_not_receive(:get)
|
|
46
|
+
sync_photos
|
|
47
|
+
end
|
|
48
|
+
it 'uses the original binary to upload the photo' do end
|
|
49
|
+
end
|
|
50
|
+
context 'for an image file' do
|
|
51
|
+
let(:photo_data) { "http://socialcast.com/someimage.png" }
|
|
52
|
+
before do
|
|
53
|
+
RestClient.should_receive(:get).with(photo_data).and_return("\x89PNGabc")
|
|
54
|
+
sync_photos
|
|
55
|
+
end
|
|
56
|
+
it 'downloads the image form the web to upload the photo' do end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'for when it does not successfully post the photo' do
|
|
61
|
+
context 'for an image file' do
|
|
62
|
+
let(:photo_data) { "http://socialcast.com/someimage.png" }
|
|
63
|
+
before do
|
|
64
|
+
user_search_resource.should_receive(:get).and_return(search_api_response.to_json)
|
|
65
|
+
RestClient.should_receive(:get).with(photo_data).and_raise(RestClient::ResourceNotFound)
|
|
66
|
+
sync_photos
|
|
67
|
+
end
|
|
68
|
+
it 'tries to download the image from the web and rescues 404' do end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context 'when their is already a photo set' do
|
|
73
|
+
let(:is_community_default) { false }
|
|
74
|
+
let(:photo_data) { "\x89PNGabc" }
|
|
75
|
+
before { user_search_resource.should_receive(:get).and_return(search_api_response.to_json) }
|
|
76
|
+
context 'for a regular sync' do
|
|
77
|
+
before do
|
|
78
|
+
sync_photos
|
|
79
|
+
Socialcast::CommandLine.should_not_receive(:resource_for_path)
|
|
80
|
+
end
|
|
81
|
+
it 'does not post the new photo' do end
|
|
82
|
+
end
|
|
83
|
+
context 'when they do a force sync' do
|
|
84
|
+
let(:options) { { :force_sync => true } }
|
|
85
|
+
before do
|
|
86
|
+
Socialcast::CommandLine.should_receive(:resource_for_path).with('/api/users/7', {}).and_return(user_submit_resource)
|
|
87
|
+
user_submit_resource.should_receive(:put).and_return(true)
|
|
88
|
+
sync_photos
|
|
89
|
+
end
|
|
90
|
+
it 'submits the photo anyways' do end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
context '.binary_to_content_type' do
|
|
97
|
+
subject { Socialcast::CommandLine::ProvisionPhoto.new(ldap_with_profile_photo, {}).send(:binary_to_content_type, binary_photo_data) }
|
|
98
|
+
let(:file_dir) { File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'test_images') }
|
|
99
|
+
let(:binary_photo_data) { File.open(File.join(file_dir, image_name), 'rb') { |file| file.read } }
|
|
100
|
+
context 'with a jpg' do
|
|
101
|
+
let(:image_name) { 'test-jpg-image.jpg' }
|
|
102
|
+
it { should == 'jpg' }
|
|
103
|
+
end
|
|
104
|
+
context 'with a gif' do
|
|
105
|
+
let(:image_name) { 'test-gif-image.gif' }
|
|
106
|
+
it { should == 'gif' }
|
|
107
|
+
end
|
|
108
|
+
context 'with a png' do
|
|
109
|
+
let(:image_name) { 'test-png-image.png' }
|
|
110
|
+
it { should == 'png' }
|
|
111
|
+
end
|
|
112
|
+
context 'with a tiff' do
|
|
113
|
+
let(:image_name) { 'test-tiff-image.tiff' }
|
|
114
|
+
it { should be_nil }
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
describe Socialcast::CommandLine::
|
|
3
|
+
describe Socialcast::CommandLine::ProvisionUser do
|
|
4
4
|
let!(:credentials) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'credentials.yml')) }
|
|
5
5
|
let!(:ldap_default_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap.yml')) }
|
|
6
6
|
let!(:ldap_blank_basedn_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_blank_basedn.yml')) }
|
|
@@ -13,17 +13,8 @@ describe Socialcast::CommandLine::Provision do
|
|
|
13
13
|
let!(:ldap_with_manager_attribute_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_manager_attribute.yml')) }
|
|
14
14
|
let!(:ldap_with_roles_without_account_type_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_roles_without_account_type.yml')) }
|
|
15
15
|
let!(:ldap_with_unique_identifier_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_unique_identifier.yml')) }
|
|
16
|
-
let!(:ldap_with_profile_photo) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_profile_photo.yml')) }
|
|
17
16
|
let!(:ldap_without_account_type_or_roles_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_without_account_type_or_roles.yml')) }
|
|
18
17
|
|
|
19
|
-
def create_entry(entry_attributes)
|
|
20
|
-
Net::LDAP::Entry.new("dc=example,dc=com").tap do |e|
|
|
21
|
-
entry_attributes.each_pair do |attr, value|
|
|
22
|
-
e[attr] = value
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
18
|
describe "#provision" do
|
|
28
19
|
let(:result) { '' }
|
|
29
20
|
|
|
@@ -39,7 +30,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
39
30
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'isMemberOf'])).and_yield(entry)
|
|
40
31
|
RestClient::Resource.any_instance.should_receive(:post).once.with(hash_including(:file => result), { :accept => :json })
|
|
41
32
|
|
|
42
|
-
Socialcast::CommandLine::
|
|
33
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_default_config, {}).provision
|
|
43
34
|
end
|
|
44
35
|
it "puts the user in the output file" do
|
|
45
36
|
result.should =~ /user@example.com/
|
|
@@ -51,7 +42,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
51
42
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'uid', 'isMemberOf'])).and_yield(entry)
|
|
52
43
|
RestClient::Resource.any_instance.should_receive(:post).once.with(hash_including(:file => result), { :accept => :json })
|
|
53
44
|
|
|
54
|
-
Socialcast::CommandLine::
|
|
45
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_with_unique_identifier_config, {}).provision
|
|
55
46
|
end
|
|
56
47
|
it "puts the user in the output file" do
|
|
57
48
|
result.should =~ /userID/
|
|
@@ -65,8 +56,8 @@ describe Socialcast::CommandLine::Provision do
|
|
|
65
56
|
end
|
|
66
57
|
it "does not put the user in the output file" do
|
|
67
58
|
expect do
|
|
68
|
-
Socialcast::CommandLine::
|
|
69
|
-
end.to raise_error(Socialcast::CommandLine::
|
|
59
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_default_config, {}).provision
|
|
60
|
+
end.to raise_error(Socialcast::CommandLine::ProvisionUser::ProvisionError, "Skipping upload to Socialcast since no users were found")
|
|
70
61
|
end
|
|
71
62
|
end
|
|
72
63
|
context "attribute mappings" do
|
|
@@ -99,7 +90,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
99
90
|
entry = create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name'
|
|
100
91
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'isMemberOf'])).and_yield(entry)
|
|
101
92
|
|
|
102
|
-
Socialcast::CommandLine::
|
|
93
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_default_config, {}).provision
|
|
103
94
|
end
|
|
104
95
|
let(:expected_attribute_xml) do
|
|
105
96
|
%Q[<first-name>first name</first-name>
|
|
@@ -114,7 +105,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
114
105
|
|
|
115
106
|
context "with mappings at the connection level" do
|
|
116
107
|
before do
|
|
117
|
-
provision_instance = Socialcast::CommandLine::
|
|
108
|
+
provision_instance = Socialcast::CommandLine::ProvisionUser.new(ldap_multiple_connection_mapping_config, {})
|
|
118
109
|
|
|
119
110
|
ldap_instance1 = double(Net::LDAP, :encryption => nil, :auth => nil)
|
|
120
111
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance1)
|
|
@@ -148,7 +139,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
148
139
|
entry = create_entry :mail => 'user@example.com', :custom_ldap1 => 'custom value 1', :custom_ldap2 => 'custom value 2'
|
|
149
140
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['custom_ldap1', 'custom_ldap2', 'mail', 'isMemberOf'])).and_yield(entry)
|
|
150
141
|
|
|
151
|
-
Socialcast::CommandLine::
|
|
142
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_with_custom_attributes_config, {}).provision
|
|
152
143
|
end
|
|
153
144
|
let(:expected_attribute_xml) do
|
|
154
145
|
%Q[<contact-info>
|
|
@@ -172,7 +163,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
172
163
|
|
|
173
164
|
context "with manager" do
|
|
174
165
|
before do
|
|
175
|
-
provision_instance = Socialcast::CommandLine::
|
|
166
|
+
provision_instance = Socialcast::CommandLine::ProvisionUser.new(ldap_with_manager_attribute_config, {})
|
|
176
167
|
|
|
177
168
|
ldap_instance = double(Net::LDAP, :encryption => nil, :auth => nil)
|
|
178
169
|
Net::LDAP.should_receive(:new).once.and_return(ldap_instance)
|
|
@@ -205,7 +196,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
205
196
|
entry = create_entry :test_ldap_attribute_mapping => 'user@example.com'
|
|
206
197
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['test_ldap_attribute_mapping', 'isMemberOf'])).and_yield(entry)
|
|
207
198
|
|
|
208
|
-
Socialcast::CommandLine::
|
|
199
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_with_class_ldap_attribute_config, {}).provision
|
|
209
200
|
end
|
|
210
201
|
after do
|
|
211
202
|
Object.send(:remove_const, :TestLdapAttributeMapping)
|
|
@@ -255,7 +246,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
255
246
|
let(:ldap_groups) { ["cn=External,dc=example,dc=com", "cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
|
|
256
247
|
before do
|
|
257
248
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
|
|
258
|
-
Socialcast::CommandLine::
|
|
249
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_default_config, {}).provision
|
|
259
250
|
end
|
|
260
251
|
let(:expected_permission_xml) do
|
|
261
252
|
%Q[<account-type>external</account-type>]
|
|
@@ -267,7 +258,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
267
258
|
let(:ldap_groups) { ["cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
|
|
268
259
|
before do
|
|
269
260
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
|
|
270
|
-
Socialcast::CommandLine::
|
|
261
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_default_config, {}).provision
|
|
271
262
|
end
|
|
272
263
|
let(:expected_permission_xml) do
|
|
273
264
|
%Q[<account-type>member</account-type>
|
|
@@ -283,7 +274,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
283
274
|
let(:ldap_groups) { ["cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
|
|
284
275
|
before do
|
|
285
276
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
|
|
286
|
-
Socialcast::CommandLine::
|
|
277
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_with_account_type_without_roles_config, {}).provision
|
|
287
278
|
end
|
|
288
279
|
let(:expected_permission_xml) do
|
|
289
280
|
%Q[<account-type>member</account-type>]
|
|
@@ -295,7 +286,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
295
286
|
let(:ldap_groups) { ["cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
|
|
296
287
|
before do
|
|
297
288
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
|
|
298
|
-
Socialcast::CommandLine::
|
|
289
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_with_roles_without_account_type_config, {}).provision
|
|
299
290
|
end
|
|
300
291
|
let(:expected_permission_xml) do
|
|
301
292
|
%Q[<account-type>member</account-type>
|
|
@@ -311,7 +302,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
311
302
|
let(:ldap_groups) { ["cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
|
|
312
303
|
before do
|
|
313
304
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
|
|
314
|
-
Socialcast::CommandLine::
|
|
305
|
+
Socialcast::CommandLine::ProvisionUser.new(ldap_without_account_type_or_roles_config, {}).provision
|
|
315
306
|
end
|
|
316
307
|
let(:expected_permission_xml) do
|
|
317
308
|
%Q[<account-type>member</account-type>]
|
|
@@ -323,7 +314,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
323
314
|
let(:ldap_group_attribute) { 'memberOf' }
|
|
324
315
|
let(:ldap_groups) { }
|
|
325
316
|
before do
|
|
326
|
-
provision_instance = Socialcast::CommandLine::
|
|
317
|
+
provision_instance = Socialcast::CommandLine::ProvisionUser.new(ldap_multiple_connection_permission_mapping_config, {})
|
|
327
318
|
|
|
328
319
|
ldap_instance1 = double(Net::LDAP, :encryption => nil, :auth => nil)
|
|
329
320
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance1)
|
|
@@ -355,7 +346,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
355
346
|
before do
|
|
356
347
|
RestClient::Resource.any_instance.should_receive(:post).once.with(hash_including(:file => result), { :accept => :json })
|
|
357
348
|
|
|
358
|
-
provision_instance = Socialcast::CommandLine::
|
|
349
|
+
provision_instance = Socialcast::CommandLine::ProvisionUser.new(ldap_blank_basedn_config, {})
|
|
359
350
|
|
|
360
351
|
root_entry = create_entry(:namingcontexts => ['dc=foo,dc=com', 'dc=bar,dc=com'])
|
|
361
352
|
ldap_instance = double(Net::LDAP, :encryption => nil, :auth => nil)
|
|
@@ -375,7 +366,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
375
366
|
end
|
|
376
367
|
|
|
377
368
|
describe "#each_user_hash" do
|
|
378
|
-
let(:provision_instance) { Socialcast::CommandLine::
|
|
369
|
+
let(:provision_instance) { Socialcast::CommandLine::ProvisionUser.new(ldap_default_config) }
|
|
379
370
|
before do
|
|
380
371
|
entry = create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name'
|
|
381
372
|
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'isMemberOf'])).and_yield(entry)
|
|
@@ -398,7 +389,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
398
389
|
|
|
399
390
|
describe "#fetch_user_hash" do
|
|
400
391
|
context "when the first connector returns the entry" do
|
|
401
|
-
let(:provision_instance) { Socialcast::CommandLine::
|
|
392
|
+
let(:provision_instance) { Socialcast::CommandLine::ProvisionUser.new(ldap_multiple_connection_mapping_config, {}) }
|
|
402
393
|
let(:entry) { create_entry :mailCon => 'user@example.com' }
|
|
403
394
|
before do
|
|
404
395
|
filter = Net::LDAP::Filter.construct('(&(mail=*)(mailCon=user@example.com))')
|
|
@@ -418,7 +409,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
418
409
|
end
|
|
419
410
|
end
|
|
420
411
|
context "when another connector returns the entry" do
|
|
421
|
-
let(:provision_instance) { Socialcast::CommandLine::
|
|
412
|
+
let(:provision_instance) { Socialcast::CommandLine::ProvisionUser.new(ldap_multiple_connection_mapping_config, {}) }
|
|
422
413
|
let(:entry) { create_entry :mailCon2 => 'user@example.com', :firstName => 'first name' }
|
|
423
414
|
before do
|
|
424
415
|
ldap_instance1 = double(Net::LDAP, :auth => nil)
|
|
@@ -448,7 +439,7 @@ describe Socialcast::CommandLine::Provision do
|
|
|
448
439
|
end
|
|
449
440
|
end
|
|
450
441
|
context "when no connectors return the entry" do
|
|
451
|
-
let(:provision_instance) { Socialcast::CommandLine::
|
|
442
|
+
let(:provision_instance) { Socialcast::CommandLine::ProvisionUser.new(ldap_multiple_connection_mapping_config, {}) }
|
|
452
443
|
before do
|
|
453
444
|
ldap_instance1 = double(Net::LDAP, :auth => nil)
|
|
454
445
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance1)
|
|
@@ -467,71 +458,4 @@ describe Socialcast::CommandLine::Provision do
|
|
|
467
458
|
end
|
|
468
459
|
end
|
|
469
460
|
end
|
|
470
|
-
|
|
471
|
-
describe '#sync_photos' do
|
|
472
|
-
let(:user_search_resource) { double(:user_search_resource) }
|
|
473
|
-
let(:search_api_response) do
|
|
474
|
-
{
|
|
475
|
-
'users' => [
|
|
476
|
-
{
|
|
477
|
-
'id' => 7,
|
|
478
|
-
'avatars' => {
|
|
479
|
-
'is_system_default' => true
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
]
|
|
483
|
-
}
|
|
484
|
-
end
|
|
485
|
-
before do
|
|
486
|
-
entry = create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name', :jpegPhoto => photo_data
|
|
487
|
-
Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'jpegPhoto', 'memberof'])).and_yield(entry)
|
|
488
|
-
|
|
489
|
-
Socialcast::CommandLine.stub(:resource_for_path).with('/api/users/search', anything).and_return(user_search_resource)
|
|
490
|
-
end
|
|
491
|
-
let(:sync_photos) { Socialcast::CommandLine::Provision.new(ldap_with_profile_photo, {}).sync_photos }
|
|
492
|
-
|
|
493
|
-
context 'for when it does successfully post the photo' do
|
|
494
|
-
before do
|
|
495
|
-
user_search_resource.should_receive(:get).and_return(search_api_response.to_json)
|
|
496
|
-
user_resource = double(:user_resource)
|
|
497
|
-
user_resource.should_receive(:put) do |data|
|
|
498
|
-
uploaded_data = data[:user][:profile_photo][:data]
|
|
499
|
-
uploaded_data.path.should =~ /\.png\Z/
|
|
500
|
-
end
|
|
501
|
-
Socialcast::CommandLine.stub(:resource_for_path).with('/api/users/7', anything).and_return(user_resource)
|
|
502
|
-
end
|
|
503
|
-
context 'for a binary file' do
|
|
504
|
-
let(:photo_data) { "\x89PNGabc" }
|
|
505
|
-
before do
|
|
506
|
-
RestClient.should_not_receive(:get)
|
|
507
|
-
sync_photos
|
|
508
|
-
end
|
|
509
|
-
it 'uses the original binary to upload the photo' do end
|
|
510
|
-
end
|
|
511
|
-
context 'for an image file' do
|
|
512
|
-
let(:photo_data) { "http://socialcast.com/someimage.png" }
|
|
513
|
-
context 'when it successfully downloads' do
|
|
514
|
-
before do
|
|
515
|
-
RestClient.should_receive(:get).with(photo_data).and_return("\x89PNGabc")
|
|
516
|
-
sync_photos
|
|
517
|
-
end
|
|
518
|
-
it 'downloads the image form the web to upload the photo' do end
|
|
519
|
-
end
|
|
520
|
-
end
|
|
521
|
-
end
|
|
522
|
-
|
|
523
|
-
context 'for when it does not successfully post the photo' do
|
|
524
|
-
context 'for an image file' do
|
|
525
|
-
let(:photo_data) { "http://socialcast.com/someimage.png" }
|
|
526
|
-
before do
|
|
527
|
-
user_search_resource.should_not_receive(:get)
|
|
528
|
-
RestClient.should_receive(:get).with(photo_data).and_raise(RestClient::ResourceNotFound)
|
|
529
|
-
sync_photos
|
|
530
|
-
end
|
|
531
|
-
it 'tries to download the image from the web and rescues 404' do end
|
|
532
|
-
end
|
|
533
|
-
end
|
|
534
|
-
|
|
535
|
-
end
|
|
536
|
-
|
|
537
461
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -10,6 +10,11 @@ require_relative '../lib/socialcast'
|
|
|
10
10
|
RSpec.configure do |config|
|
|
11
11
|
config.mock_with :rspec
|
|
12
12
|
|
|
13
|
+
config.before do
|
|
14
|
+
stubbed_credentials = File.join(File.dirname(__FILE__), '..', 'fixtures')
|
|
15
|
+
Socialcast::CommandLine.stub(:config_dir).and_return(stubbed_credentials)
|
|
16
|
+
end
|
|
17
|
+
|
|
13
18
|
def capture_with_status(stream)
|
|
14
19
|
exit_status = 0
|
|
15
20
|
begin
|
|
@@ -27,6 +32,14 @@ RSpec.configure do |config|
|
|
|
27
32
|
return result, exit_status
|
|
28
33
|
end
|
|
29
34
|
|
|
35
|
+
def create_entry(entry_attributes)
|
|
36
|
+
Net::LDAP::Entry.new("dc=example,dc=com").tap do |e|
|
|
37
|
+
entry_attributes.each_pair do |attr, value|
|
|
38
|
+
e[attr] = value
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
30
43
|
def remove_directories(*names)
|
|
31
44
|
project_dir = Pathname.new(Dir.pwd)
|
|
32
45
|
names.each do |name|
|
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.
|
|
4
|
+
version: 1.3.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Sonnek
|
|
@@ -221,7 +221,9 @@ files:
|
|
|
221
221
|
- lib/socialcast/command_line/cli.rb
|
|
222
222
|
- lib/socialcast/command_line/ldap_connector.rb
|
|
223
223
|
- lib/socialcast/command_line/message.rb
|
|
224
|
-
- lib/socialcast/command_line/
|
|
224
|
+
- lib/socialcast/command_line/provision_photo.rb
|
|
225
|
+
- lib/socialcast/command_line/provision_user.rb
|
|
226
|
+
- lib/socialcast/command_line/provisioner.rb
|
|
225
227
|
- lib/socialcast/command_line/version.rb
|
|
226
228
|
- socialcast.gemspec
|
|
227
229
|
- spec/fixtures/credentials.yml
|
|
@@ -245,10 +247,15 @@ files:
|
|
|
245
247
|
- spec/fixtures/ldap_with_unique_identifier.yml
|
|
246
248
|
- spec/fixtures/ldap_without_account_type_or_roles.yml
|
|
247
249
|
- spec/fixtures/ldap_without_permission_mappings.yml
|
|
250
|
+
- spec/fixtures/test_images/test-gif-image.gif
|
|
251
|
+
- spec/fixtures/test_images/test-jpg-image.jpg
|
|
252
|
+
- spec/fixtures/test_images/test-png-image.png
|
|
253
|
+
- spec/fixtures/test_images/test-tiff-image.tiff
|
|
248
254
|
- spec/socialcast/command_line/authenticate_spec.rb
|
|
249
255
|
- spec/socialcast/command_line/cli_spec.rb
|
|
250
256
|
- spec/socialcast/command_line/ldap_connector_spec.rb
|
|
251
|
-
- spec/socialcast/command_line/
|
|
257
|
+
- spec/socialcast/command_line/provision_photo_spec.rb
|
|
258
|
+
- spec/socialcast/command_line/provision_user_spec.rb
|
|
252
259
|
- spec/socialcast/socialcast_spec.rb
|
|
253
260
|
- spec/spec_helper.rb
|
|
254
261
|
homepage: http://github.com/socialcast/socialcast-command-line
|
|
@@ -297,9 +304,14 @@ test_files:
|
|
|
297
304
|
- spec/fixtures/ldap_with_unique_identifier.yml
|
|
298
305
|
- spec/fixtures/ldap_without_account_type_or_roles.yml
|
|
299
306
|
- spec/fixtures/ldap_without_permission_mappings.yml
|
|
307
|
+
- spec/fixtures/test_images/test-gif-image.gif
|
|
308
|
+
- spec/fixtures/test_images/test-jpg-image.jpg
|
|
309
|
+
- spec/fixtures/test_images/test-png-image.png
|
|
310
|
+
- spec/fixtures/test_images/test-tiff-image.tiff
|
|
300
311
|
- spec/socialcast/command_line/authenticate_spec.rb
|
|
301
312
|
- spec/socialcast/command_line/cli_spec.rb
|
|
302
313
|
- spec/socialcast/command_line/ldap_connector_spec.rb
|
|
303
|
-
- spec/socialcast/command_line/
|
|
314
|
+
- spec/socialcast/command_line/provision_photo_spec.rb
|
|
315
|
+
- spec/socialcast/command_line/provision_user_spec.rb
|
|
304
316
|
- spec/socialcast/socialcast_spec.rb
|
|
305
317
|
- spec/spec_helper.rb
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
require 'zlib'
|
|
2
|
-
require 'builder'
|
|
3
|
-
require 'set'
|
|
4
|
-
require 'fileutils'
|
|
5
|
-
|
|
6
|
-
module Socialcast
|
|
7
|
-
module CommandLine
|
|
8
|
-
class Provision
|
|
9
|
-
DEFAULT_OUTPUT_FILE = 'users.xml.gz'
|
|
10
|
-
|
|
11
|
-
class ProvisionError < StandardError; end
|
|
12
|
-
|
|
13
|
-
def initialize(ldap_config, options = {})
|
|
14
|
-
@ldap_config = ldap_config.dup
|
|
15
|
-
@options = options.dup
|
|
16
|
-
|
|
17
|
-
@options[:output] ||= DEFAULT_OUTPUT_FILE
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def each_user_hash
|
|
21
|
-
each_ldap_connector do |connector|
|
|
22
|
-
connector.each_user_hash do |user_hash|
|
|
23
|
-
yield user_hash
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def fetch_user_hash(identifier, options = {})
|
|
29
|
-
each_ldap_connector do |connector|
|
|
30
|
-
user_hash = connector.fetch_user_hash(identifier, options)
|
|
31
|
-
return user_hash if user_hash
|
|
32
|
-
end
|
|
33
|
-
nil
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def provision
|
|
37
|
-
params = @ldap_config.fetch('http', {}).merge(:external_system => !!@options[:external_system])
|
|
38
|
-
|
|
39
|
-
user_whitelist = Set.new
|
|
40
|
-
output_file = File.join Dir.pwd, @options[:output]
|
|
41
|
-
|
|
42
|
-
Zlib::GzipWriter.open(output_file) do |gz|
|
|
43
|
-
xml = Builder::XmlMarkup.new(:target => gz, :indent => 1)
|
|
44
|
-
xml.instruct!
|
|
45
|
-
xml.export do |export|
|
|
46
|
-
export.users(:type => "array") do |users|
|
|
47
|
-
each_user_hash do |user_hash|
|
|
48
|
-
users << user_hash.to_xml(:skip_instruct => true, :root => 'user')
|
|
49
|
-
user_whitelist << [user_hash['contact_info']['email'], user_hash['unique_identifier'], user_hash['employee_number']]
|
|
50
|
-
end
|
|
51
|
-
end # users
|
|
52
|
-
end # export
|
|
53
|
-
end # gzip
|
|
54
|
-
|
|
55
|
-
if user_whitelist.empty? && !@options[:force]
|
|
56
|
-
raise ProvisionError.new "Skipping upload to Socialcast since no users were found"
|
|
57
|
-
else
|
|
58
|
-
puts "Uploading dataset to Socialcast..."
|
|
59
|
-
resource = Socialcast::CommandLine.resource_for_path '/api/users/provision', params
|
|
60
|
-
begin
|
|
61
|
-
File.open(output_file, 'r') do |file|
|
|
62
|
-
request_params = {:file => file}
|
|
63
|
-
request_params[:skip_emails] = 'true' if (@ldap_config['options']["skip_emails"] || @options[:skip_emails])
|
|
64
|
-
request_params[:test] = 'true' if (@ldap_config['options']["test"] || @options[:test])
|
|
65
|
-
resource.post request_params, :accept => :json
|
|
66
|
-
end
|
|
67
|
-
rescue RestClient::Unauthorized => e
|
|
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
|
|
71
|
-
end
|
|
72
|
-
puts "Finished"
|
|
73
|
-
end
|
|
74
|
-
File.delete(output_file) if (@ldap_config['options']['delete_users_file'] || @options[:delete_users_file])
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def sync_photos
|
|
78
|
-
http_config = @ldap_config.fetch 'http', {}
|
|
79
|
-
|
|
80
|
-
each_ldap_connector do |connector|
|
|
81
|
-
connector.attribute_mappings.fetch('profile_photo')
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
search_users_resource = Socialcast::CommandLine.resource_for_path '/api/users/search', http_config
|
|
85
|
-
|
|
86
|
-
each_ldap_connector do |connector|
|
|
87
|
-
each_ldap_entry do |entry|
|
|
88
|
-
attr_mappings = connector.attribute_mappings
|
|
89
|
-
email = connector.grab(entry, attr_mappings['email'])
|
|
90
|
-
if profile_photo_data = connector.grab(entry, attr_mappings['profile_photo'])
|
|
91
|
-
if profile_photo_data.start_with?('http')
|
|
92
|
-
begin
|
|
93
|
-
profile_photo_data = RestClient.get(profile_photo_data)
|
|
94
|
-
rescue => e
|
|
95
|
-
puts "Unable to download photo #{profile_photo_data} for #{email}"
|
|
96
|
-
puts e.response
|
|
97
|
-
next
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
profile_photo_data = profile_photo_data.force_encoding('binary')
|
|
101
|
-
|
|
102
|
-
user_search_response = search_users_resource.get(:params => { :q => email, :per_page => 1 }, :accept => :json)
|
|
103
|
-
user_info = JSON.parse(user_search_response)['users'].first
|
|
104
|
-
if user_info && user_info['avatars'] && user_info['avatars']['is_system_default']
|
|
105
|
-
puts "Uploading photo for #{email}"
|
|
106
|
-
|
|
107
|
-
user_resource = Socialcast::CommandLine.resource_for_path "/api/users/#{user_info['id']}", http_config
|
|
108
|
-
content_type = case profile_photo_data
|
|
109
|
-
when Regexp.new("\AGIF8", nil, 'n')
|
|
110
|
-
'gif'
|
|
111
|
-
when Regexp.new('\A\x89PNG', nil, 'n')
|
|
112
|
-
'png'
|
|
113
|
-
when Regexp.new("\A\xff\xd8\xff\xe0\x00\x10JFIF", nil, 'n'), Regexp.new("\A\xff\xd8\xff\xe1(.*){2}Exif", nil, 'n')
|
|
114
|
-
'jpg'
|
|
115
|
-
else
|
|
116
|
-
puts "Skipping photo for #{email}: unknown image format (supports .gif, .png, .jpg)"
|
|
117
|
-
next
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
tempfile = Tempfile.new(["photo_upload", ".#{content_type}"])
|
|
121
|
-
tempfile.write(profile_photo_data)
|
|
122
|
-
tempfile.rewind
|
|
123
|
-
begin
|
|
124
|
-
user_resource.put({ :user => { :profile_photo => { :data => tempfile } } })
|
|
125
|
-
ensure
|
|
126
|
-
tempfile.unlink
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
private
|
|
135
|
-
|
|
136
|
-
def ldap_connector(connection_name)
|
|
137
|
-
@connectors ||= {}
|
|
138
|
-
|
|
139
|
-
unless @connectors[connection_name]
|
|
140
|
-
@connectors[connection_name] = Socialcast::CommandLine::LDAPConnector.new(connection_name, @ldap_config)
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
@connectors[connection_name]
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def each_ldap_connector
|
|
147
|
-
@ldap_config['connections'].keys.each do |connection_name|
|
|
148
|
-
yield ldap_connector(connection_name)
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def each_ldap_entry(&block)
|
|
153
|
-
count = 0
|
|
154
|
-
|
|
155
|
-
each_ldap_connector do |connector|
|
|
156
|
-
connector.each_ldap_entry do |entry|
|
|
157
|
-
yield entry, connector.connection_name
|
|
158
|
-
count += 1
|
|
159
|
-
puts "Scanned #{count} users" if ((count % 100) == 0)
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
puts "Finished scanning #{count} users"
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
end
|