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
@@ -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,13 @@
1
+ module UserManagementApi
2
+ class Config
3
+ include Confiture::Configuration
4
+
5
+ confiture_allowed_keys(:base_uri, :access_token)
6
+
7
+ confiture_defaults({
8
+ base_uri: nil,
9
+ access_token: nil
10
+ })
11
+
12
+ end
13
+ 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,6 @@
1
+ module UserManagementApi
2
+ class Lookup < Entity
3
+ attributes :id, :label, :text
4
+
5
+ end
6
+ 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,8 @@
1
+ module UserManagementApi
2
+ class UserManagementApiRailtie < ::Rails::Railtie
3
+
4
+ UserManagementApi::Config.configure
5
+ config.user_management_api = UserManagementApi::Config
6
+
7
+ end
8
+ 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
@@ -0,0 +1,6 @@
1
+ module UserManagementApi
2
+ class User < Entity
3
+ attributes :unique_id, :email, :first_name, :last_name, :username, :password, :last_login, :created_at, :updated_at
4
+
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module UserManagementApi
2
+ VERSION = '0.0.16'
3
+ end