user_management_api 0.0.16

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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +3 -0
  5. data/README.md +90 -0
  6. data/Rakefile +114 -0
  7. data/lib/user_management_api.rb +38 -0
  8. data/lib/user_management_api/answerbase_session_token.rb +6 -0
  9. data/lib/user_management_api/client.rb +108 -0
  10. data/lib/user_management_api/client_methods/answerbase_session_tokens.rb +15 -0
  11. data/lib/user_management_api/client_methods/registration_groups.rb +38 -0
  12. data/lib/user_management_api/client_methods/registrations.rb +54 -0
  13. data/lib/user_management_api/client_methods/urls.rb +65 -0
  14. data/lib/user_management_api/client_methods/users.rb +24 -0
  15. data/lib/user_management_api/config.rb +13 -0
  16. data/lib/user_management_api/connection_manager.rb +17 -0
  17. data/lib/user_management_api/entity.rb +132 -0
  18. data/lib/user_management_api/errors.rb +49 -0
  19. data/lib/user_management_api/lookup.rb +6 -0
  20. data/lib/user_management_api/paged_collection.rb +16 -0
  21. data/lib/user_management_api/railtie.rb +8 -0
  22. data/lib/user_management_api/registration.rb +20 -0
  23. data/lib/user_management_api/registration_group.rb +8 -0
  24. data/lib/user_management_api/user.rb +6 -0
  25. data/lib/user_management_api/version.rb +3 -0
  26. data/spec/integration/registration_groups_spec.rb +30 -0
  27. data/spec/integration/registrations_spec.rb +44 -0
  28. data/spec/integration/users_spec.rb +63 -0
  29. data/spec/spec_helper.rb +26 -0
  30. data/spec/support/client_context.rb +12 -0
  31. data/spec/support/integration_context.rb +29 -0
  32. data/spec/unit/client_methods/answerbase_session_tokens_spec.rb +68 -0
  33. data/spec/unit/client_methods/registration_groups_spec.rb +157 -0
  34. data/spec/unit/client_methods/registrations_spec.rb +131 -0
  35. data/spec/unit/client_methods/users_spec.rb +149 -0
  36. data/spec/unit/client_spec.rb +121 -0
  37. data/spec/unit/connection_manager_spec.rb +23 -0
  38. data/spec/unit/entity_spec.rb +93 -0
  39. data/spec/unit/registration_spec.rb +25 -0
  40. data/user_management_api.gemspec +32 -0
  41. metadata +264 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8376a6c25481cc0791b5773a8e8f2310bdd0b85e
4
+ data.tar.gz: e830e75632e58cd72d504a239df747861c884009
5
+ SHA512:
6
+ metadata.gz: fb713efaa205d81030337fa7eb30c03b7d6df405ed176ae12d9972f6051bde1d43f1825f0847ad6220c9495e2145bfaaba5909cabcbba4ada4abbe0e2351e63b
7
+ data.tar.gz: 8b5d1ad7823a8d4c4ffabd7b9d160d28338e650a01e3779212c123f39e7ece973f475fe49261a8bead76741fb835d7d33dd14909a2b9c524395d103a65f0c1a1
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ .idea
21
+
22
+ Gemfile.lock
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.1.5
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,90 @@
1
+ User Management API
2
+ ===================
3
+
4
+ Client library for the User Management App API
5
+
6
+ # Installation
7
+
8
+ ### Add the gem to your Gemfile (note the tag)
9
+
10
+ ```ruby
11
+ gem 'user_management_api', git: 'git@github.umn.edu:mpc/user_management_api.git', tag: 'v0.0.15'
12
+ ```
13
+
14
+ # Configuration
15
+
16
+ There are four ways to configure the gem, and they can be used interchangeably.
17
+
18
+ ### 1. Application or environment configuration files.
19
+
20
+ In config/application.rb or config/environments/<ENV>.rb
21
+ ```ruby
22
+ config.user_management_api.KEY = VALUE
23
+ ```
24
+
25
+ ### 2. Initializer
26
+
27
+ In config/initializers/mpc_shib_auth.rb
28
+ ```ruby
29
+ UserManagementApi::Config.configure do |config|
30
+ config.KEY = VALUE
31
+ end
32
+ ```
33
+
34
+ ### 3. Anywhere else
35
+
36
+ From anywhere
37
+ ```ruby
38
+ UserManagementApi::Config.KEY = VALUE
39
+ ```
40
+
41
+ ### 4. Constructor
42
+
43
+ Any configuration can be overridden by passing values into the constructor:
44
+ ```ruby
45
+ UserManagementApi::Client.new('http://someserver.com', '111-TOKEN-0000')
46
+ ```
47
+
48
+ # Configuration Options
49
+
50
+ #### base_uri
51
+
52
+ Base URL of the target User Management App. Should not include any path information. Ex: `http://localhost:3000`
53
+
54
+ #### access_token
55
+
56
+ Access token used in all requests made to the API
57
+
58
+ # Usage
59
+
60
+ Provided the base_uri and token have been configured, a client can be created without any constructor parameters: `UserManagementApi::Client.new`
61
+
62
+ # Client Methods
63
+
64
+ ### Registrations
65
+
66
+ * `user_registrations(unique_id)`
67
+ * `user_registration(project, unique_id)`
68
+ * `search_registrations(project, criteria = {})`
69
+ * `set_registration_custom_attributes(project, unique_id, attributes)`
70
+
71
+ ### URLs
72
+
73
+ * `create_account_url(project, return_url = nil)` - Create new user account with project registration
74
+ * `create_registration_url(project, return_url = nil)` - Create new registration for existing, logged in user
75
+ * `edit_registration_url(project, return_url = nil)` - Edit existing registration for logged in user
76
+ * `renew_registration_url(project = nil, return_url = nil)` - Renew all registrations for given user (with brand of optional project)
77
+ * `forgot_password_url`
78
+ * `change_password_url(return_url = nil)`
79
+
80
+ ### Registration Groups
81
+
82
+ * `owned_registration_groups(project, user_unique_id)`
83
+ * `enrolled_registration_groups(project, user_unique_id)`
84
+
85
+ ### Users
86
+
87
+ * `users_by_email(emails)`
88
+ * `user(unique_id)`
89
+ * `create_user(user)`
90
+ * `update_user(user)`
data/Rakefile ADDED
@@ -0,0 +1,114 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ require 'ci/reporter/rake/rspec'
4
+
5
+ RSpec::Core::RakeTask.new(:spec => 'ci:setup:rspec')
6
+
7
+ task :test => :spec
8
+ task :default => :spec
9
+
10
+ task :disable_rubygems do
11
+ ENV['gem_push'] = 'no'
12
+ end
13
+
14
+ Rake::Task[:release].enhance [:disable_rubygems]
15
+
16
+ namespace :spec do
17
+ # This task reads two env variables: UMA_PORT and UMA_PATH.
18
+ # UMA_PORT is the port the integration_test version of UMA will listen on
19
+ # UMA_PATH is the location of the app checkout
20
+ desc "Starts UMA instance and runs full specs"
21
+ task :start_server_and_run_all do
22
+ uma_path = ENV['UMA_PATH'] || File.expand_path('../../user_management_app/', __FILE__)
23
+ uma_port = ENV['UMA_PORT'] || 3019
24
+ ENV['UMA_PORT'] = uma_port.to_s
25
+ pid = nil
26
+ read_pipe = nil
27
+ write_pipe = nil
28
+
29
+ raise "UMA_PATH [#{uma_path} does not appear to be valid" unless File.exists?("#{uma_path}/bin/rails")
30
+
31
+ begin
32
+ read_pipe, write_pipe = IO.pipe
33
+
34
+ # since bundler sets the BUNDLE_GEMFILE env var, we need to clear it so this invocation picks up the right one
35
+ pid = Process.spawn({"RAILS_ENV" => "integration_test", "BUNDLE_GEMFILE" => nil}, "bundle exec rails server -p #{uma_port}", chdir: uma_path, [:out, :err] => write_pipe)
36
+ puts "Waiting for server to start..."
37
+
38
+ server_output = ''
39
+ wait_start = Time.now
40
+ server_started = false
41
+ server_failed = false
42
+
43
+ while !server_started && !server_failed
44
+ begin
45
+ buffer = read_pipe.read_nonblock(128)
46
+ #STDOUT.write(buffer)
47
+ server_output << buffer
48
+ rescue IO::WaitReadable
49
+ IO.select([read_pipe], nil, nil, 2)
50
+ end
51
+
52
+ if (Time.now - wait_start) >= 15
53
+ server_failed = true
54
+ end
55
+
56
+ begin
57
+ if Process.waitpid(pid, Process::WNOHANG)
58
+ server_failed = true
59
+ end
60
+ rescue
61
+ server_failed = true
62
+ end
63
+
64
+ if server_output =~ /WEBrick::HTTPServer#start: pid=\d+ port=\d+/
65
+ server_started = true
66
+ end
67
+ end
68
+
69
+ if server_started
70
+ puts "Server started"
71
+ else
72
+ STDERR.puts "Unable to start webserver:"
73
+ STDERR.puts server_output
74
+ exit false
75
+ end
76
+
77
+ Rake::Task['spec:all'].invoke
78
+ ensure
79
+ begin
80
+ Process.kill('KILL', pid) if pid
81
+ write_pipe.close if write_pipe
82
+ read_pipe.close if read_pipe
83
+ rescue
84
+ # do nothing
85
+ end
86
+ end
87
+ end
88
+
89
+ desc "integration test the JSON API endpoints"
90
+ RSpec::Core::RakeTask.new(:integration) do |t|
91
+ # set the RAILS_ENV such that :integration tagged
92
+ # specs are run
93
+ ENV['ENABLE_INTEGRATION'] = 'true'
94
+
95
+ # only run those files in the 'integration' directory
96
+ t.pattern = "./spec/integration{,/*/**}/*_spec.rb"
97
+ end
98
+
99
+ desc 'Run unit and integration tests'
100
+ task :all do
101
+ ENV['ENABLE_INTEGRATION'] = 'true'
102
+ Rake::Task[:spec].invoke
103
+ end
104
+ end
105
+
106
+ namespace :test do
107
+ task :integration => 'spec:integration'
108
+ task :all => 'spec:all'
109
+ end
110
+
111
+ desc "Open an irb session preloaded with this library"
112
+ task :console do
113
+ sh "irb -rubygems -I lib -r user_management_api.rb"
114
+ end
@@ -0,0 +1,38 @@
1
+ require 'confiture'
2
+ require 'uri'
3
+ require 'faraday'
4
+ require 'multi_json'
5
+ require 'active_support/core_ext/class/attribute'
6
+ require 'active_support/core_ext/hash/keys'
7
+
8
+ files = [
9
+ 'version',
10
+ 'errors',
11
+ 'connection_manager',
12
+ 'client_methods/answerbase_session_tokens',
13
+ 'client_methods/users',
14
+ 'client_methods/registrations',
15
+ 'client_methods/registration_groups',
16
+ 'client_methods/urls',
17
+ 'client',
18
+ 'entity',
19
+ 'answerbase_session_token',
20
+ 'paged_collection',
21
+ 'lookup',
22
+ 'user',
23
+ 'registration',
24
+ 'registration_group',
25
+ 'config'
26
+ ]
27
+
28
+ if defined?(::Rails::Railtie)
29
+ files << 'railtie'
30
+ end
31
+
32
+ files.each do |f|
33
+ require File.expand_path("../user_management_api/#{f}", __FILE__)
34
+ end
35
+
36
+ module UserManagementApi
37
+
38
+ end
@@ -0,0 +1,6 @@
1
+ module UserManagementApi
2
+ class AnswerbaseSessionToken < Entity
3
+ attributes :user_unique_id, :session_id, :created_at, :updated_at
4
+
5
+ end
6
+ end
@@ -0,0 +1,108 @@
1
+ module UserManagementApi
2
+ class Client
3
+ include ClientMethods::AnswerbaseSessionTokens
4
+ include ClientMethods::Users
5
+ include ClientMethods::Registrations
6
+ include ClientMethods::RegistrationGroups
7
+ include ClientMethods::URLs
8
+
9
+ API_VERSION = 'v1'
10
+
11
+ attr_reader :conn
12
+
13
+ def initialize(uri = nil, token = nil)
14
+ uri = uri || UserManagementApi::Config.base_uri
15
+ token = token || UserManagementApi::Config.access_token
16
+
17
+ if uri.nil? || token.nil?
18
+ raise UserManagementApi::ClientConfigurationError, "You must either pass a URI and token or configure UserManagementApi::Config"
19
+ end
20
+
21
+ base_uri = URI(uri)
22
+
23
+ unless ['', '/', nil].include? base_uri.path
24
+ raise UserManagementApi::ClientConfigurationError, "uri should not contain path information"
25
+ end
26
+
27
+ path_prefix = "/api/#{API_VERSION}"
28
+
29
+ base_uri.path = path_prefix
30
+
31
+ @conn = UserManagementApi::ConnectionManager.get_connection(base_uri.to_s, token)
32
+ @token = token
33
+ end
34
+
35
+ def base_api_uri
36
+ conn.url_prefix.to_s
37
+ end
38
+
39
+ def base_uri
40
+ uri = URI(base_api_uri)
41
+ uri.path = ''
42
+ uri.to_s
43
+ end
44
+
45
+ def token
46
+ @token
47
+ end
48
+
49
+ private
50
+
51
+ def get_parsed_response(response)
52
+ case response.status.to_i
53
+ when 200
54
+ parse_body(response.body)
55
+ when 401
56
+ raise UserManagementApi::TokenError, "Token [#{self.token}] rejected by Remote Server"
57
+ when 404
58
+ nil
59
+ when 422
60
+ raise UserManagementApi::UnprocessableEntityError.new(response, parse_body(response.body))
61
+ when 500...600
62
+ raise UserManagementApi::ServerError, "Remote Server returned error: [#{response.status}]"
63
+ else
64
+ raise UserManagementApi::ServerError, "Remote Server returned unknown HTTP response code: [#{response.status}]"
65
+ end
66
+ end
67
+
68
+ def parse_body(body)
69
+ if body && body != ''
70
+ MultiJson.load(body)
71
+ else
72
+ {}
73
+ end
74
+ end
75
+
76
+ def build_entity(type, response)
77
+ data = get_parsed_response(response)
78
+ if data
79
+ type.new(data)
80
+ else
81
+ nil
82
+ end
83
+ end
84
+
85
+ def build_paged_collection(type, collection_name, response)
86
+ data = get_parsed_response(response)
87
+ if data
88
+ PagedCollection.new(type, collection_name, data)
89
+ else
90
+ nil
91
+ end
92
+ end
93
+
94
+ def build_collection(type, response)
95
+ data = get_parsed_response(response)
96
+ if data
97
+ data.map { |e| type.new(e) }
98
+ else
99
+ nil
100
+ end
101
+ end
102
+
103
+ def encode_entity(entity, entity_name)
104
+ MultiJson.dump({entity_name.to_sym => entity.as_json})
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,15 @@
1
+ module UserManagementApi
2
+ module ClientMethods
3
+ module AnswerbaseSessionTokens
4
+
5
+ def answerbase_session_token(session_id)
6
+ build_entity(AnswerbaseSessionToken, conn.get("answerbase_session_tokens/#{session_id}"))
7
+ end
8
+
9
+ def create_answerbase_session_token(user_unique_id)
10
+ res = conn.post("answerbase_session_tokens/#{user_unique_id}")
11
+ build_entity(AnswerbaseSessionToken, res)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ module UserManagementApi
2
+ module ClientMethods
3
+ module RegistrationGroups
4
+
5
+ def registration_group(unique_id)
6
+ res = conn.get("registration_groups/#{unique_id}")
7
+ build_entity(RegistrationGroup, res)
8
+ end
9
+
10
+ def registration_group_enrollees(unique_id)
11
+ res = conn.get("registration_groups/#{unique_id}/enrollees")
12
+ build_collection(User, res)
13
+ end
14
+
15
+ def registration_group_remove_enrollee(unique_id, user_unique_id)
16
+ res = conn.delete("registration_groups/#{unique_id}/enrollees/#{user_unique_id}")
17
+ data = get_parsed_response(res)
18
+ !data.nil?
19
+ end
20
+
21
+ def owned_registration_groups(project, user_unique_id)
22
+ res = conn.get("registration_groups/#{project}/owned/#{user_unique_id}")
23
+ build_collection(RegistrationGroup, res)
24
+ end
25
+
26
+ def enrolled_registration_groups(project, user_unique_id)
27
+ res = conn.get("registration_groups/#{project}/enrolled/#{user_unique_id}")
28
+ build_collection(RegistrationGroup, res)
29
+ end
30
+
31
+ def pending_registration_groups(project)
32
+ res = conn.get("registration_groups/#{project}/pending")
33
+ build_collection(RegistrationGroup, res)
34
+ end
35
+
36
+ end
37
+ end
38
+ end