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
@@ -0,0 +1,54 @@
|
|
1
|
+
module UserManagementApi
|
2
|
+
module ClientMethods
|
3
|
+
module Registrations
|
4
|
+
|
5
|
+
# Returns all registrations owned by the given user
|
6
|
+
def user_registrations(unique_id)
|
7
|
+
res = conn.get("registrations/#{unique_id}")
|
8
|
+
build_collection(Registration, res)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns the registration given by the user and project
|
12
|
+
def user_registration(project, unique_id)
|
13
|
+
res = conn.get("registrations/#{project}/#{unique_id}")
|
14
|
+
build_entity(Registration, res)
|
15
|
+
end
|
16
|
+
|
17
|
+
# returns a list of registrations for the given project
|
18
|
+
# registrations may be filtered by setting criteria keys as follows:
|
19
|
+
# any of the following keys will filter data:
|
20
|
+
# valid
|
21
|
+
# first_name
|
22
|
+
# last_name
|
23
|
+
# unique_id
|
24
|
+
# email
|
25
|
+
#
|
26
|
+
# The following keys will reflect the order and paging of the returned data:
|
27
|
+
# sort_column: name of the column to sort by. May be one of last_name, first_name, or email
|
28
|
+
# sort_direction: asc or desc
|
29
|
+
# page: page number to return
|
30
|
+
# per: number of users per page (defaults to 25)
|
31
|
+
#
|
32
|
+
# The returned object will be a PagedCollection instance
|
33
|
+
def search_registrations(project, criteria = {})
|
34
|
+
query = {}
|
35
|
+
criteria = criteria.stringify_keys
|
36
|
+
|
37
|
+
%w(first_name last_name unique_id email sort_column sort_direction page per valid).each do |prop|
|
38
|
+
query[prop] = criteria[prop] if criteria[prop]
|
39
|
+
end
|
40
|
+
|
41
|
+
res = conn.get("registrations/#{project}", query)
|
42
|
+
|
43
|
+
build_paged_collection(Registration, 'registrations', res)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Sets the given attributes as custom attributes on the given registration.
|
47
|
+
# Performs a merge on any existing attributes. Any keys with nil or empty values will be deleted.
|
48
|
+
def set_registration_custom_attributes(project, unique_id, attributes)
|
49
|
+
res = conn.patch("registrations/#{project}/#{unique_id}/custom_attributes", MultiJson.dump(custom_attributes: attributes))
|
50
|
+
build_entity(Registration, res)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module UserManagementApi
|
2
|
+
module ClientMethods
|
3
|
+
module URLs
|
4
|
+
|
5
|
+
def create_account_url(project, return_url = nil, parameters = {})
|
6
|
+
build_url("/#{project}/user/new", {return_url: return_url}.merge(parameters))
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_registration_url(project, return_url = nil, parameters = {})
|
10
|
+
build_url("/#{project}/registration/new", {return_url: return_url}.merge(parameters))
|
11
|
+
end
|
12
|
+
|
13
|
+
def edit_registration_url(project, return_url = nil)
|
14
|
+
build_url("/#{project}/registration/edit", return_url: return_url)
|
15
|
+
end
|
16
|
+
|
17
|
+
def renew_registration_url(project = nil, return_url = nil)
|
18
|
+
project_path = project ? "/#{project}" : ''
|
19
|
+
build_url("#{project_path}/registration/renew", return_url: return_url)
|
20
|
+
end
|
21
|
+
|
22
|
+
def forgot_password_url
|
23
|
+
build_url("/user/forgot_password/")
|
24
|
+
end
|
25
|
+
|
26
|
+
def change_password_url(return_url = nil)
|
27
|
+
build_url("/user/change_password/", return_url: return_url)
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_class_group_url(project, return_url = nil)
|
31
|
+
build_url("/#{project}/registration_groups/new", return_url: return_url)
|
32
|
+
end
|
33
|
+
|
34
|
+
def join_class_group_url(project = nil, return_url = nil)
|
35
|
+
project_path = project ? "/#{project}" : ''
|
36
|
+
build_url("#{project_path}/registration_groups/select", return_url: return_url)
|
37
|
+
end
|
38
|
+
|
39
|
+
def admin_url
|
40
|
+
build_url('/admin')
|
41
|
+
end
|
42
|
+
|
43
|
+
def admin_pending_registration_url(project)
|
44
|
+
build_url("/admin/registrations/pending/#{project}")
|
45
|
+
end
|
46
|
+
|
47
|
+
def admin_pending_registration_groups_url(project)
|
48
|
+
build_url("/admin/registration_groups/pending/#{project}")
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def build_url(path, params = {})
|
54
|
+
uri = URI(base_uri)
|
55
|
+
uri.path = path
|
56
|
+
|
57
|
+
p = params.delete_if {|_, v| v.nil? }
|
58
|
+
uri.query = p.map { |k, v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&') unless p.empty?
|
59
|
+
|
60
|
+
uri.to_s
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module UserManagementApi
|
2
|
+
module ClientMethods
|
3
|
+
module Users
|
4
|
+
|
5
|
+
def users_by_email(emails)
|
6
|
+
build_collection(User, conn.get('users/by_email', email: emails))
|
7
|
+
end
|
8
|
+
|
9
|
+
def user(unique_id)
|
10
|
+
build_entity(User, conn.get("users/#{unique_id}"))
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_user(user)
|
14
|
+
res = conn.post("users", encode_entity(user, :user))
|
15
|
+
build_entity(User, res)
|
16
|
+
end
|
17
|
+
|
18
|
+
def update_user(user)
|
19
|
+
res = conn.put("users/#{user.unique_id}", encode_entity(user, :user))
|
20
|
+
build_entity(User, res)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module UserManagementApi
|
2
|
+
class ConnectionManager
|
3
|
+
class << self
|
4
|
+
|
5
|
+
# Disable creating instances
|
6
|
+
private :new
|
7
|
+
|
8
|
+
def get_connection(uri, access_token)
|
9
|
+
Faraday.new(uri, {ssl: {verify: false}}) do |faraday|
|
10
|
+
faraday.headers = {'Content-Type' => 'application/json'}
|
11
|
+
faraday.token_auth(access_token)
|
12
|
+
faraday.adapter(Faraday.default_adapter)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module UserManagementApi
|
2
|
+
class Entity
|
3
|
+
|
4
|
+
class_attribute :_entity_properties
|
5
|
+
class_attribute :_properties
|
6
|
+
self._entity_properties = {}
|
7
|
+
self._properties = []
|
8
|
+
|
9
|
+
def self.entity_attribute(*args)
|
10
|
+
klass = args.pop
|
11
|
+
raise "Invalid arguments" unless klass && klass.is_a?(Class) && args.length > 0
|
12
|
+
|
13
|
+
args.compact.map { |a| a.to_sym }.each do |a|
|
14
|
+
attr_accessor a
|
15
|
+
self._entity_properties[a.to_sym] = klass
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.attribute(*attrs)
|
20
|
+
attrs.compact.map { |a| a.to_sym }.each do |a|
|
21
|
+
attr_accessor a
|
22
|
+
self._properties << a
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
alias_method :entity_attributes, :entity_attribute
|
28
|
+
alias_method :attributes, :attribute
|
29
|
+
end
|
30
|
+
|
31
|
+
# Copy properties on inheritance.
|
32
|
+
def self.inherited(subclass)
|
33
|
+
entities = _entity_properties.dup
|
34
|
+
attrs = _properties.dup
|
35
|
+
subclass._entity_properties = entities.each { |k, v| entities[k] = v.dup }
|
36
|
+
subclass._properties = attrs
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(attrs = {})
|
41
|
+
populate_from_json(attrs)
|
42
|
+
end
|
43
|
+
|
44
|
+
def as_json(options = nil)
|
45
|
+
serialize_attributes(_properties + _entity_properties.keys)
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_json(options = nil)
|
49
|
+
MultiJson.dump(as_json(options))
|
50
|
+
end
|
51
|
+
|
52
|
+
def populate_from_json(attrs)
|
53
|
+
return unless attrs
|
54
|
+
|
55
|
+
attrs.each do |k, v|
|
56
|
+
meth = "#{k}=".to_sym
|
57
|
+
if self.respond_to? meth
|
58
|
+
if entity_class = _entity_properties[k.to_sym]
|
59
|
+
assign_entity(meth, v, entity_class)
|
60
|
+
else
|
61
|
+
self.send(meth, v)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def serialize_attributes(attrs)
|
68
|
+
json = {}
|
69
|
+
attrs.each do |k|
|
70
|
+
meth = k.to_sym
|
71
|
+
if self.respond_to?(meth)
|
72
|
+
if _entity_properties[k.to_sym]
|
73
|
+
json[k] = serialize_entity(meth)
|
74
|
+
else
|
75
|
+
json[k] = self.send(meth)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
json
|
80
|
+
end
|
81
|
+
|
82
|
+
def ==(other)
|
83
|
+
other.class == self.class && other.__state == __state
|
84
|
+
end
|
85
|
+
|
86
|
+
alias_method :eql?, :==
|
87
|
+
|
88
|
+
def hash
|
89
|
+
state.hash
|
90
|
+
end
|
91
|
+
|
92
|
+
protected
|
93
|
+
|
94
|
+
def __state
|
95
|
+
(_properties + _entity_properties.keys).map do |attr|
|
96
|
+
meth = attr.to_sym
|
97
|
+
if self.respond_to?(meth)
|
98
|
+
self.send(meth)
|
99
|
+
else
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def assign_entity(assignment_method, value, klass)
|
108
|
+
case value
|
109
|
+
when nil
|
110
|
+
data = nil
|
111
|
+
when Array
|
112
|
+
data = value.map { |v| klass.new(v) }
|
113
|
+
else
|
114
|
+
data = klass.new(value)
|
115
|
+
end
|
116
|
+
|
117
|
+
self.send(assignment_method, data)
|
118
|
+
end
|
119
|
+
|
120
|
+
def serialize_entity(method)
|
121
|
+
value = self.send(method)
|
122
|
+
case value
|
123
|
+
when nil
|
124
|
+
nil
|
125
|
+
when Array
|
126
|
+
value.map { |v| v.as_json }
|
127
|
+
else
|
128
|
+
value.as_json
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module UserManagementApi
|
2
|
+
|
3
|
+
class ClientConfigurationError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class TokenError < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
class ServerError < StandardError
|
10
|
+
end
|
11
|
+
|
12
|
+
class UnprocessableEntityError < StandardError
|
13
|
+
|
14
|
+
DEFAULT_MESSAGE = 'Remote Server responded with 422: Unprocessable Entity. No further details available'
|
15
|
+
|
16
|
+
def initialize(faraday_response, parsed_body)
|
17
|
+
@response = faraday_response
|
18
|
+
@body = parsed_body
|
19
|
+
@errors = {}
|
20
|
+
super(build_message)
|
21
|
+
end
|
22
|
+
|
23
|
+
def response
|
24
|
+
@response
|
25
|
+
end
|
26
|
+
|
27
|
+
def errors
|
28
|
+
@errors
|
29
|
+
end
|
30
|
+
|
31
|
+
def formatted_errors
|
32
|
+
@errors.map { |k, v| "#{k}: #{v}"}.join("\n")
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def build_message
|
38
|
+
msg = DEFAULT_MESSAGE
|
39
|
+
|
40
|
+
if @body && @body.is_a?(Hash) && !@body.empty?
|
41
|
+
@errors = @body
|
42
|
+
msg = "Remove Server returned 422: Unprocessable Entity. Errors encountered:\n#{formatted_errors}"
|
43
|
+
end
|
44
|
+
|
45
|
+
msg
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module UserManagementApi
|
2
|
+
class PagedCollection
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
def_delegators :@collection, :[], :each, :map, :size, :length, :first, :last, :empty?, :present?
|
6
|
+
|
7
|
+
attr_reader :total_count, :total_pages, :current_page, :collection
|
8
|
+
|
9
|
+
def initialize(entity_type, collection_name, data)
|
10
|
+
@total_count = data['total_count']
|
11
|
+
@total_pages = data['total_pages']
|
12
|
+
@current_page = data['current_page']
|
13
|
+
@collection = (data[collection_name.to_s] || []).map { |e| entity_type.new(e) }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module UserManagementApi
|
2
|
+
class Registration < Entity
|
3
|
+
attributes :institution, :research_statement, :project, :status, :active, :admin, :group_registration, :microdata_access, :max_extract_size, :custom_attributes, :created_at, :updated_at
|
4
|
+
entity_attributes :user, User
|
5
|
+
entity_attributes :field, :occupation, :how_did_you_hear, :research_areas, Lookup
|
6
|
+
|
7
|
+
STATUS = {
|
8
|
+
pending: 'Pending',
|
9
|
+
approved: 'Approved',
|
10
|
+
denied: 'Denied',
|
11
|
+
expired: 'Expired',
|
12
|
+
email_pending: 'Email Pending'
|
13
|
+
}
|
14
|
+
|
15
|
+
STATUS.each do |k, v|
|
16
|
+
define_method("is_#{k}?") { self.status == v }
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module UserManagementApi
|
2
|
+
class RegistrationGroup < Entity
|
3
|
+
attributes :unique_id, :name, :project, :end_date, :active, :status, :created_at, :updated_at, :code, :description
|
4
|
+
entity_attributes :owner, User
|
5
|
+
entity_attributes :field, :course_level, Lookup
|
6
|
+
|
7
|
+
end
|
8
|
+
end
|