ecoportal-api 0.3.8 → 0.4.1

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +11 -3
  3. data/.yardopts +10 -0
  4. data/Gemfile.lock +10 -5
  5. data/Rakefile +22 -1
  6. data/ecoportal-api.gemspec +6 -4
  7. data/lib/ecoportal/api/common.rb +7 -4
  8. data/lib/ecoportal/api/common/base_class.rb +29 -0
  9. data/lib/ecoportal/api/common/base_model.rb +89 -20
  10. data/lib/ecoportal/api/common/batch_operation.rb +0 -1
  11. data/lib/ecoportal/api/common/batch_response.rb +5 -0
  12. data/lib/ecoportal/api/common/client.rb +61 -1
  13. data/lib/ecoportal/api/common/doc_helpers.rb +2 -0
  14. data/lib/ecoportal/api/common/hash_diff.rb +25 -23
  15. data/lib/ecoportal/api/common/response.rb +4 -0
  16. data/lib/ecoportal/api/common/wrapped_response.rb +19 -10
  17. data/lib/ecoportal/api/internal.rb +17 -20
  18. data/lib/ecoportal/api/internal/account.rb +23 -16
  19. data/lib/ecoportal/api/internal/login_provider.rb +1 -1
  20. data/lib/ecoportal/api/internal/login_providers.rb +10 -0
  21. data/lib/ecoportal/api/internal/people.rb +3 -8
  22. data/lib/ecoportal/api/internal/permissions.rb +1 -1
  23. data/lib/ecoportal/api/internal/person.rb +18 -16
  24. data/lib/ecoportal/api/internal/person_details.rb +1 -5
  25. data/lib/ecoportal/api/internal/person_schema.rb +1 -5
  26. data/lib/ecoportal/api/internal/person_schemas.rb +2 -6
  27. data/lib/ecoportal/api/internal/policy_group.rb +1 -1
  28. data/lib/ecoportal/api/internal/policy_groups.rb +10 -1
  29. data/lib/ecoportal/api/v1.rb +27 -4
  30. data/lib/ecoportal/api/v1/people.rb +62 -25
  31. data/lib/ecoportal/api/v1/person.rb +47 -28
  32. data/lib/ecoportal/api/v1/person_details.rb +27 -13
  33. data/lib/ecoportal/api/v1/person_schema.rb +3 -6
  34. data/lib/ecoportal/api/v1/person_schemas.rb +26 -9
  35. data/lib/ecoportal/api/v1/schema_field.rb +1 -1
  36. data/lib/ecoportal/api/v1/schema_field_value.rb +2 -1
  37. data/lib/ecoportal/api/version.rb +1 -1
  38. metadata +45 -3
@@ -2,7 +2,7 @@ module Ecoportal
2
2
  module API
3
3
  class Internal
4
4
  class PolicyGroup < Common::BaseModel
5
- passthrough :id, :name, to: :doc
5
+ passthrough :id, :name
6
6
  end
7
7
  end
8
8
  end
@@ -1,16 +1,25 @@
1
1
  module Ecoportal
2
2
  module API
3
3
  class Internal
4
+ # @attr_reader client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
4
5
  class PolicyGroups
5
6
  include Enumerable
7
+
6
8
  attr_reader :client
9
+
10
+ # @param client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
11
+ # @return [PolicyGroups] an instance object ready to make policy groups api requests.
7
12
  def initialize(client)
8
13
  @client = client
9
14
  end
15
+
16
+ # Gets all the policy groups via api request.
17
+ # @return [Enumerable<PolicyGroup>] an `Enumerable` with all the policy groups already wrapped as `PolicyGroup` objects.
10
18
  def get_all
11
- response = @client.get("/policy_groups")
19
+ response = client.get("/policy_groups")
12
20
  Common::WrappedResponse.new(response, Internal::PolicyGroup)
13
21
  end
22
+
14
23
  def each(&block)
15
24
  return to_enum(:each) unless block
16
25
  get_all.each(&block)
@@ -1,26 +1,49 @@
1
1
  module Ecoportal
2
2
  module API
3
+ # @attr_reader client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
4
+ # @attr_reader logger [Logger] the logger.
3
5
  class V1
6
+ extend Common::BaseClass
4
7
  include Common::Logging
8
+
9
+ VERSION = "v1"
10
+ class_resolver :people_class, "Ecoportal::API::V1::People"
11
+ class_resolver :person_schemas_class, "Ecoportal::API::V1::PersonSchemas"
12
+
5
13
  attr_reader :client, :logger
14
+
15
+ # Creates an `V1` object to scope version specific api requests.
16
+ # @note
17
+ # - The const `VERSION` determineds the api version that client will query against.
18
+ # - This means that each sublcass of `V1` should define their own `VERSION` constant.
19
+ # @param api_key [String] the key version to stablish the api connection.
20
+ # @param host [String] api server domain.
21
+ # @param logger [Logger] an object with `Logger` interface to generate logs.
22
+ # @return [V1] an object with the api version suit.
6
23
  def initialize(api_key, host: "live.ecoportal.com", logger: default_logger)
7
24
  @logger = logger
8
25
  @client = Common::Client.new(
9
26
  api_key: api_key,
10
27
  host: host,
11
- version: "v1",
28
+ version: self.class::VERSION,
12
29
  logger: @logger
13
30
  )
14
31
  end
32
+
33
+ # Obtain specific object for people api requests.
34
+ # @return [People] an instance object ready to make people api requests.
15
35
  def people
16
- V1::People.new(client)
36
+ people_class.new(client)
17
37
  end
38
+
39
+ # Obtain specific object for schema api requests.
40
+ # @return [PersonSchemas] an instance object ready to make schema api requests.
18
41
  def person_schemas
19
- V1::PersonSchemas.new(client)
42
+ person_schemas_class.new(client)
20
43
  end
21
44
  end
22
45
  end
23
46
  end
24
47
 
25
- require 'ecoportal/api/v1/people'
26
48
  require 'ecoportal/api/v1/person_schemas'
49
+ require 'ecoportal/api/v1/people'
@@ -1,21 +1,36 @@
1
- require 'ecoportal/api/common/doc_helpers'
2
1
  module Ecoportal
3
2
  module API
4
3
  class V1
4
+ # @attr_reader client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
5
5
  class People
6
+ extend Common::BaseClass
6
7
  include Enumerable
7
8
  include Common::DocHelpers
9
+
10
+ class_resolver :person_class, "Ecoportal::API::V1::Person"
11
+
8
12
  attr_reader :client
9
13
 
14
+ # @param client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
15
+ # @return [People] an instance object ready to make people api requests.
10
16
  def initialize(client)
11
17
  @client = client
12
18
  end
13
19
 
20
+ # Iterates all the people of the organization.
21
+ # @note
22
+ # - it ignores the key `page:` of `params:`.
23
+ # - `each` is called by `to_a`
24
+ # @param params [Hash]
25
+ # @option params [String] :per_page the number of people you get per request.
26
+ # @option params [String] :q some text to search. Omit this parameter to target all the people.
27
+ # @yield [person] does some stuff with the person.
28
+ # @yieldparam person [Person]
14
29
  def each(params: {}, &block)
15
30
  return to_enum(:each) unless block
16
31
  page = 1
17
32
  loop do
18
- response = @client.get("/people", params: params.merge(page: page))
33
+ response = client.get("/people", params: params.merge(page: page))
19
34
  raise "Request failed." unless response.success?
20
35
  response.body["results"].each do |person|
21
36
  yield person_class.new(person)
@@ -26,62 +41,84 @@ module Ecoportal
26
41
  self
27
42
  end
28
43
 
29
- def get(doc)
30
- response = @client.get("/people/"+CGI::escape(get_id(doc)))
31
- Common::WrappedResponse.new(response, person_class)
32
- end
33
-
44
+ # Gets all the people via api requests.
45
+ # @note it ignores the key `:page` in `params:`.
46
+ # @param params [Hash]
47
+ # @option params [Integer] :per_page the number of people you get per request.
48
+ # @option params [String] :q some text to search.
49
+ # @return [Array<Person>] the array of people got via api.
34
50
  def get_all(params: {})
35
51
  each(params: params).to_a
36
52
  end
37
53
 
54
+ # Gets a person via api.
55
+ # @note if the request has `success?` the returned `object.result` gives an object with that `Person`.
56
+ # @param doc [String, Hash, Person] data containing an `id` (internal or external) of the target person.
57
+ # @return [WrappedResponse] an object with the api response.
58
+ def get(doc)
59
+ response = client.get("/people/"+CGI::escape(get_id(doc)))
60
+ Common::WrappedResponse.new(response, person_class)
61
+ end
62
+
63
+ # Requests an update of a person via api.
64
+ # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
65
+ # @return [Response] an object with the api response.
38
66
  def update(doc)
39
67
  body = get_body(doc)
40
68
  id = get_id(doc)
41
- @client.patch("/people/"+CGI::escape(id), data: body)
69
+ client.patch("/people/"+CGI::escape(id), data: body)
42
70
  end
43
71
 
72
+ # Requests to create a person via api.
73
+ # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
74
+ # @return [Response] an object with the api response.
44
75
  def create(doc)
45
76
  body = get_body(doc)
46
- @client.post("/people", data: body)
77
+ client.post("/people", data: body)
47
78
  end
48
79
 
80
+ # Requests to update an existing person or if it does not exist, to create it, via api.
81
+ # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
82
+ # @return [Response] an object with the api response.
49
83
  def upsert(doc)
50
84
  body = get_body(doc)
51
85
  id = get_id(doc)
52
- @client.post("/people/"+CGI::escape(id), data: body)
86
+ client.post("/people/"+CGI::escape(id), data: body)
87
+ end
88
+
89
+ # Requests to completelly remove from an organization an existing person via api.
90
+ # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
91
+ # @return [Response] an object with the api response.
92
+ def delete(doc)
93
+ id = get_id(doc)
94
+ client.delete("/people/"+CGI::escape(id))
53
95
  end
54
96
 
97
+ # Creates a `BatchOperation` and yields it to the given bock.
98
+ # @yield [batch_op] adds multiple api requests for the current batch.
99
+ # @yieldparam batch_op [BatchOperation]
55
100
  def batch
56
- operation = Common::BatchOperation.new("/people", person_class, logger: @client.logger)
101
+ operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
57
102
  yield operation
58
103
  # The batch operation is responsible for logging the output
59
- @client.without_response_logging do
60
- @client.post("/people/batch", data: operation.as_json).tap do |response|
104
+ client.without_response_logging do
105
+ client.post("/people/batch", data: operation.as_json).tap do |response|
61
106
  operation.process_response(response)
62
107
  end
63
108
  end
64
109
  end
65
110
 
66
- def delete(doc)
67
- id = get_id(doc)
68
- @client.delete("/people/"+CGI::escape(id))
69
- end
70
-
111
+ # Creates a new `Person` object.
112
+ # @return [Person] new empty person object of the current version.
71
113
  def new
72
114
  person_class.new
73
115
  end
74
116
 
75
- private
76
-
77
- def person_class
78
- V1::Person
79
- end
80
117
  end
81
118
  end
82
119
  end
83
120
  end
84
121
 
85
- require 'ecoportal/api/v1/person'
86
- require 'ecoportal/api/v1/person_details'
87
122
  require 'ecoportal/api/v1/schema_field_value'
123
+ require 'ecoportal/api/v1/person_details'
124
+ require 'ecoportal/api/v1/person'
@@ -1,29 +1,55 @@
1
1
  module Ecoportal
2
2
  module API
3
3
  class V1
4
+ # @attr id [String] the internal unique id of this person (unique in all the system).
5
+ # @attr external_id [String] the alternative unique id of this person (unique in one organization).
6
+ # @attr name [String] the name of the person.
7
+ # @attr supervisor_id [String] internal or external id of the supervisor of this person.
8
+ # @attr_reader subordinates [Integer] the number of people this person is supervisor of.
9
+ # @attr details [PersonDetails, nil] the details of the person or `nil` if missing.
4
10
  class Person < Common::BaseModel
5
- passthrough :id, :external_id, :name, :email, :supervisor_id, :subordinates, to: :doc
11
+ passthrough :id, :external_id, :name, :email, :supervisor_id, :subordinates
6
12
 
13
+ class_resolver :person_schema_class, "Ecoportal::API::V1::PersonSchema"
14
+ class_resolver :person_details_class, "Ecoportal::API::V1::PersonDetails"
15
+ embeds_one :details, nullable: true, klass: :person_details_class
16
+
17
+ # Gets the supervisor (`Person`) of this person, with given his `supervisor_id`.
18
+ #
19
+ # **Example Usage**:
20
+ # ```ruby
21
+ # API_KEY = 'some-private-api-key-version'
22
+ # HOST = "live.ecoportal.com"
23
+ # api = Ecoportal::API::Internal.new(API_KEY, host: HOST)
24
+ # person = api.people.get({"id": "my-dummy-user"})
25
+ # super = person.supervisor(api.client)
26
+ # pp "#{person.name}'s supervisor is #{super.name}."
27
+ # ```
28
+ #
29
+ # @param client [Common::Client] the api client to make the request.
7
30
  def supervisor(client)
8
31
  return @supervisor if defined?(@supervisor)
9
32
  return @supervisor = nil if supervisor_id.nil?
10
33
  @supervisor = client.people.get(supervisor_id).result
11
34
  end
12
35
 
36
+ # Sets the supervisor of a person.
37
+ # @param person [Person, nil] the supervisor of this person.
13
38
  def supervisor=(person)
14
- self.supervisor_id = person.id
39
+ self.supervisor_id = person&.id || person&.external_id
15
40
  end
16
41
 
17
42
  def as_json
18
43
  super.merge "details" => details&.as_json
19
44
  end
20
45
 
21
- def details
22
- return @details if defined?(@details)
23
- return @details = nil if doc["details"].nil?
24
- @details = person_details_class.new(doc["details"])
25
- end
26
-
46
+ # Sets the PersonDetails to the person, depending on the paramter received:
47
+ # - `nil`: blanks the details.
48
+ # - `PersonDetails`: sets a copy of the object param as details.
49
+ # - `Hash`: sets respectivelly the `schema_id` and the `fields` keys of the Hash to the person details.
50
+ # @note unique point of access to update the PersonDetails.
51
+ # @param value [nil, PersonDetails, Hash] value to be set.
52
+ # @return [nil, PersonDetails] the resulting `PersonDetails` set to the person.
27
53
  def details=(value)
28
54
  case value
29
55
  when NilClass
@@ -33,15 +59,20 @@ module Ecoportal
33
59
  when Hash
34
60
  doc["details"] = value.slice("schema_id", "fields")
35
61
  else
36
- raise "Invalid set on details: Need nil, PersonDetails or Hash; got #{value.class}"
62
+ raise "Invalid type set on details. Required nil, PersonDetails or Hash; got #{value.class}"
37
63
  end
38
64
  remove_instance_variable("@details") if defined?(@details)
39
- details.tap do |details|
40
- # When reassigning details, mark the whole thing as dirty
41
- details&.instance_variable_set("@original_doc", {})
42
- end
43
65
  end
44
66
 
67
+ # Sets the PersonDetails to the person, depending on the parameter received:
68
+ # - `PersonSchema`: initializes the `PersonDetails` as per the schema specified (`schema_id` and `fields`).
69
+ # - `String`: it just sets the `schema_id` on the `PersonDetails` (as `fields` is not include, `details[key]=` will throw error).
70
+ # (see #details=)
71
+ # @note
72
+ # - this method alone only sets the internal structure of the details.
73
+ # - you will not be able to `reset!` after using this method.
74
+ # @param schema_or_id [PersonSchema, String, nil, PersonDetails, Hash] value to be set.
75
+ # @return [nil, PersonDetails] the resulting `PersonDetails` that set to the person.
45
76
  def add_details(schema_or_id)
46
77
  person_details_class.new.tap do |new_details|
47
78
  case schema_or_id
@@ -49,29 +80,17 @@ module Ecoportal
49
80
  schema_or_id.initialize_details(new_details)
50
81
  when String
51
82
  new_details.schema_id = schema_or_id
83
+ else
84
+ raise "Invalid set on details: Requierd PersonSchema or String; got #{schema_or_id.class}"
52
85
  end
53
86
  self.details = new_details
54
87
  # Patch out static data from as_update
55
- @original_doc["details"] = {
88
+ original_doc["details"] = {
56
89
  "fields" => JSON.parse(doc["details"]["fields"].to_json)
57
90
  }
58
91
  end
59
- self.details.tap do |details|
60
- # Patch out static data from as_update
61
- original = details.instance_variable_get("@original_doc")
62
- original["fields"] = JSON.parse(doc["details"]["fields"].to_json)
63
- end
64
92
  end
65
93
 
66
- private
67
-
68
- def person_schema_class
69
- V1::PersonSchema
70
- end
71
-
72
- def person_details_class
73
- V1::PersonDetails
74
- end
75
94
  end
76
95
  end
77
96
  end
@@ -2,17 +2,24 @@ module Ecoportal
2
2
  module API
3
3
  class V1
4
4
  class PersonDetails < Common::BaseModel
5
- passthrough :schema_id, to: :doc
5
+ passthrough :schema_id
6
+
7
+ class_resolver :schema_field_value_class, "Ecoportal::API::V1::SchemaFieldValue"
6
8
 
7
9
  def as_json
8
10
  super.merge "fields" => fields.map(&:as_json)
9
11
  end
10
12
 
13
+ # Sets the `id` of the PersonDetails.
14
+ # @note unless the new `id` is `nil`, this does not reset the `fields`.
15
+ # @param value [nil, String] the id of the schema.
11
16
  def schema_id=(value)
12
17
  @fields = [] if value.nil?
13
18
  doc["schema_id"] = value
14
19
  end
15
20
 
21
+ # Gets all the fields of the PersonDetails.
22
+ # @return [Array<SchemaFieldValue>] the array of fields of the schema.
16
23
  def fields
17
24
  return @fields if defined?(@fields)
18
25
  @fields = (doc["fields"] || []).map do |field|
@@ -20,24 +27,24 @@ module Ecoportal
20
27
  end
21
28
  end
22
29
 
23
- def index_fields
24
- @fields_by_id = {}
25
- @fields_by_alt_id = {}
26
- fields.each do |wrapped|
27
- @fields_by_id[wrapped.id] = wrapped
28
- @fields_by_alt_id[wrapped.alt_id] = wrapped
29
- end
30
- end
31
-
30
+ # Gets one specific field of the PersonDetails.
31
+ # @param id [String] the `id` or the `alt_id` of the target field.
32
+ # @return [nil, SchemaFieldValue] the field or `nil` if missing.
32
33
  def get_field(id)
33
34
  @fields_by_id or index_fields
34
35
  @fields_by_id[id] || @fields_by_alt_id[id]
35
36
  end
36
37
 
38
+ # Gets the value of one specific field of the PersonDetails.
39
+ # @param id [String] the `id` or the `alt_id` of the target field.
40
+ # @return [String, Array<String>, Boolean, Array<Boolean>, Date, Array<Date>, Numberic, Array<Numeric>] the value of field or `nil` if missing.
37
41
  def [](id)
38
42
  get_field(id)&.value
39
43
  end
40
44
 
45
+ # Sets the value to one specific field of the PersonDetails.
46
+ # @param id [String] the `id` or the `alt_id` of the target field.
47
+ # @return [void]
41
48
  def []=(id, value)
42
49
  if field = get_field(id)
43
50
  field.value = value
@@ -46,11 +53,18 @@ module Ecoportal
46
53
  end
47
54
  end
48
55
 
49
- private
56
+ protected
50
57
 
51
- def schema_field_value_class
52
- V1::SchemaFieldValue
58
+ # Rebuilds the internal `id` and `alt_id` references to the fields.
59
+ def index_fields
60
+ @fields_by_id = {}
61
+ @fields_by_alt_id = {}
62
+ fields.each do |wrapped|
63
+ @fields_by_id[wrapped.id] = wrapped
64
+ @fields_by_alt_id[wrapped.alt_id] = wrapped
65
+ end
53
66
  end
67
+
54
68
  end
55
69
  end
56
70
  end
@@ -2,7 +2,9 @@ module Ecoportal
2
2
  module API
3
3
  class V1
4
4
  class PersonSchema < Common::BaseModel
5
- passthrough :id, :name, to: :doc
5
+ passthrough :id, :name
6
+
7
+ class_resolver :schema_field_class, "Ecoportal::API::V1::SchemaField"
6
8
 
7
9
  def fields
8
10
  @fields_by_id or index_fields
@@ -43,11 +45,6 @@ module Ecoportal
43
45
  end
44
46
  end
45
47
 
46
- private
47
-
48
- def schema_field_class
49
- V1::SchemaField
50
- end
51
48
  end
52
49
  end
53
50
  end