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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/README.md +90 -0
- data/Rakefile +114 -0
- data/lib/user_management_api.rb +38 -0
- data/lib/user_management_api/answerbase_session_token.rb +6 -0
- data/lib/user_management_api/client.rb +108 -0
- data/lib/user_management_api/client_methods/answerbase_session_tokens.rb +15 -0
- data/lib/user_management_api/client_methods/registration_groups.rb +38 -0
- data/lib/user_management_api/client_methods/registrations.rb +54 -0
- data/lib/user_management_api/client_methods/urls.rb +65 -0
- data/lib/user_management_api/client_methods/users.rb +24 -0
- data/lib/user_management_api/config.rb +13 -0
- data/lib/user_management_api/connection_manager.rb +17 -0
- data/lib/user_management_api/entity.rb +132 -0
- data/lib/user_management_api/errors.rb +49 -0
- data/lib/user_management_api/lookup.rb +6 -0
- data/lib/user_management_api/paged_collection.rb +16 -0
- data/lib/user_management_api/railtie.rb +8 -0
- data/lib/user_management_api/registration.rb +20 -0
- data/lib/user_management_api/registration_group.rb +8 -0
- data/lib/user_management_api/user.rb +6 -0
- data/lib/user_management_api/version.rb +3 -0
- data/spec/integration/registration_groups_spec.rb +30 -0
- data/spec/integration/registrations_spec.rb +44 -0
- data/spec/integration/users_spec.rb +63 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/client_context.rb +12 -0
- data/spec/support/integration_context.rb +29 -0
- data/spec/unit/client_methods/answerbase_session_tokens_spec.rb +68 -0
- data/spec/unit/client_methods/registration_groups_spec.rb +157 -0
- data/spec/unit/client_methods/registrations_spec.rb +131 -0
- data/spec/unit/client_methods/users_spec.rb +149 -0
- data/spec/unit/client_spec.rb +121 -0
- data/spec/unit/connection_manager_spec.rb +23 -0
- data/spec/unit/entity_spec.rb +93 -0
- data/spec/unit/registration_spec.rb +25 -0
- data/user_management_api.gemspec +32 -0
- 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
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.1.5
|
data/Gemfile
ADDED
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,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
|