ecoportal-api 0.3.8 → 0.4.1

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