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