user_management_api 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
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