freckle_io 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +5 -0
- data/.env.sample +3 -0
- data/.env.test.sample +3 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +67 -0
- data/.travis.yml +20 -0
- data/Gemfile +8 -0
- data/README.md +95 -0
- data/Rakefile +5 -0
- data/freckle-io.gemspec +37 -0
- data/icon.svg +192 -0
- data/lib/freckle_io/authentication.rb +26 -0
- data/lib/freckle_io/client/entries.rb +53 -0
- data/lib/freckle_io/client/project_groups.rb +36 -0
- data/lib/freckle_io/client/projects.rb +42 -0
- data/lib/freckle_io/client/tags.rb +33 -0
- data/lib/freckle_io/client/users.rb +35 -0
- data/lib/freckle_io/configuration.rb +48 -0
- data/lib/freckle_io/connection.rb +80 -0
- data/lib/freckle_io/errors/configuration.rb +5 -0
- data/lib/freckle_io/errors/connection.rb +9 -0
- data/lib/freckle_io/errors/params.rb +8 -0
- data/lib/freckle_io/paginator.rb +70 -0
- data/lib/freckle_io/params.rb +46 -0
- data/lib/freckle_io/request/multiple_pages.rb +62 -0
- data/lib/freckle_io/request/single_page.rb +73 -0
- data/lib/freckle_io/validator/entry.rb +57 -0
- data/lib/freckle_io/validator/project.rb +46 -0
- data/lib/freckle_io/validator/project_group.rb +30 -0
- data/lib/freckle_io/validator/restricted_hash.rb +11 -0
- data/lib/freckle_io/validator/tag.rb +30 -0
- data/lib/freckle_io/validator/user.rb +43 -0
- data/lib/freckle_io/validator/validation.yml +14 -0
- data/lib/freckle_io.rb +35 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Entries/with_configuration/_all/result_must_be_a_Request_MultiplePages.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Entries/with_configuration/_all/returns_a_entry_for_each_response.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Entries/with_configuration/with_valid_params/params_should_be_valid.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Entries/with_configuration/with_validator/call_entry_s_validator.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_ProjectGroups/with_configuration/_all/result_must_be_a_Request_MultiplePages.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_ProjectGroups/with_configuration/_all/returns_a_project_group_for_each_response.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_ProjectGroups/with_configuration/with_valid_params/params_should_be_valid.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_ProjectGroups/with_configuration/with_validator/call_project_group_s_validator.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Projects/with_configuration/_all/result_must_be_a_Request_MultiplePages.yml +491 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Projects/with_configuration/_all/returns_a_project_for_each_response.yml +491 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Projects/with_configuration/_show/get_a_spacific_project.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Projects/with_configuration/_show/raw_links_should_be_a_empty_array.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Projects/with_configuration/with_valid_params/params_should_be_valid.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Projects/with_configuration/with_validator/call_project_s_validator.yml +491 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Tags/with_configuration/_all/result_must_be_a_Request_MultiplePages.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Tags/with_configuration/_all/returns_a_tag_for_each_response.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Tags/with_configuration/with_valid_params/params_should_be_valid.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Tags/with_configuration/with_validator/call_tag_s_validator.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Users/with_configuration/_all/result_must_be_a_Request_MultiplePages.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Users/with_configuration/_all/returns_a_user_for_each_response.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Users/with_configuration/_show/get_a_spacific_user.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Users/with_configuration/_show/raw_links_should_be_a_empty_array.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Users/with_configuration/with_valid_params/params_should_be_valid.yml +48 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Client_Users/with_configuration/with_validator/call_user_s_validator.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Connection/with_default_configuration/with_a_valid_response/must_be_a_json_format.yml +51 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Connection/with_default_configuration/with_freckle_token_authentication/set_X-FreckleToken.yml +51 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Connection/with_default_configuration/with_header/set_user_agent.yml +51 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Connection/with_default_configuration/with_invalid_url/raises_a_resource_not_found_error_for_invalid_resource.yml +40 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Connection/with_default_configuration/with_page_param/response_must_be_success.yml +51 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Connection/with_default_configuration/with_per_page_param/response_must_have_per_page_elements.yml +51 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_MultiplePages/with_configuration/_get/returns_an_array_of_faraday_response.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_MultiplePages/with_configuration/_get/returns_freckle_default_per_page_elements.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_MultiplePages/with_per_page/_get/return_per_page_number_elements.yml +148 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_first/next_page_should_be_a_SinglePage.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_first/prev_page_should_be_nil.yml +51 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_first/when_get_last_page_from_the_first_page/next_should_be_nil.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_get/returns_correct_raw_links_for_the_first_page.yml +51 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_last/next_page_should_be_nil.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_last/returns_correct_raw_links_for_the_last_page.yml +99 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_last/when_get_prev_page_from_the_last_page/prev_should_be_nil.yml +147 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_next/previous_page_is_a_SinglePage.yml +147 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_next/previous_page_should_be_not_nil.yml +147 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_prev/next_page_is_a_SinglePage.yml +195 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_prev/when_get_prev_page_from_the_first_page/prev_should_be_nil.yml +147 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_total_page/with_first_page/returns_the_range_of_pages.yml +51 -0
- data/spec/fixtures/vcr_cassettes/FreckleIO_Request_SinglePage/with_configuration/_total_page/with_next_page/returns_an_empty_array.yml +99 -0
- data/spec/freckle_io/client/entries_spec.rb +359 -0
- data/spec/freckle_io/client/project_groups_spec.rb +132 -0
- data/spec/freckle_io/client/projects_spec.rb +183 -0
- data/spec/freckle_io/client/tags_spec.rb +132 -0
- data/spec/freckle_io/client/users_spec.rb +150 -0
- data/spec/freckle_io/configuration_spec.rb +70 -0
- data/spec/freckle_io/connection_spec.rb +116 -0
- data/spec/freckle_io/paginator_spec.rb +105 -0
- data/spec/freckle_io/params_spec.rb +15 -0
- data/spec/freckle_io/request/multiple_pages_spec.rb +39 -0
- data/spec/freckle_io/request/single_page_spec.rb +107 -0
- data/spec/spec_helper.rb +69 -0
- data/spec/support/anonymize/entries.rb +60 -0
- data/spec/support/anonymize/project_groups.rb +55 -0
- data/spec/support/anonymize/projects.rb +60 -0
- data/spec/support/anonymize/tags.rb +47 -0
- data/spec/support/anonymize/users.rb +59 -0
- data/spec/support/anonymize_interaction.rb +60 -0
- data/spec/support/entry_info.rb +19 -0
- data/spec/support/project_group_info.rb +13 -0
- data/spec/support/project_info.rb +26 -0
- data/spec/support/shared/links/raw_links.rb +13 -0
- data/spec/support/tag_info.rb +11 -0
- data/spec/support/user_info.rb +21 -0
- metadata +382 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require "freckle_io/authentication"
|
2
|
+
|
3
|
+
module FreckleIO
|
4
|
+
class Configuration
|
5
|
+
include Authentication
|
6
|
+
|
7
|
+
DEFAULT_URL = "https://api.letsfreckle.com/v2".freeze
|
8
|
+
|
9
|
+
attr_writer :auth_type
|
10
|
+
attr_writer :token
|
11
|
+
attr_writer :url
|
12
|
+
attr_writer :per_page
|
13
|
+
attr_writer :max_concurrency
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@token = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def auth_type
|
20
|
+
unless valid_auth?(@auth_type)
|
21
|
+
raise(
|
22
|
+
Errors::Configuration,
|
23
|
+
"#{@auth_type} isn't valid type authentication"
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
@auth_type || raise(Errors::Configuration, "Authentication type missing!")
|
28
|
+
end
|
29
|
+
|
30
|
+
def token
|
31
|
+
@token || raise(Errors::Configuration, "Token missing!")
|
32
|
+
end
|
33
|
+
|
34
|
+
def url
|
35
|
+
@url || self.class::DEFAULT_URL
|
36
|
+
end
|
37
|
+
|
38
|
+
def per_page
|
39
|
+
@per_page || nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def max_concurrency
|
43
|
+
@max_concurrency || raise(
|
44
|
+
Errors::Configuration, "Max concurrency missing!"
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require "freckle_io/authentication"
|
2
|
+
require "faraday"
|
3
|
+
require "faraday_middleware"
|
4
|
+
|
5
|
+
module FreckleIO
|
6
|
+
class Connection
|
7
|
+
include FreckleIO::Authentication
|
8
|
+
|
9
|
+
# rubocop:disable Metrics/MethodLength
|
10
|
+
def get(path, params: {}, request_options: {})
|
11
|
+
response = connection.get do |request|
|
12
|
+
authorize_request(request)
|
13
|
+
set_request_options(request, request_options)
|
14
|
+
request.url path, params
|
15
|
+
end
|
16
|
+
|
17
|
+
response
|
18
|
+
rescue Faraday::ConnectionFailed => e
|
19
|
+
raise Errors::Connection::Failed.new(e), e.message
|
20
|
+
rescue Faraday::ResourceNotFound => e
|
21
|
+
raise Errors::Connection::ResourceNotFound.new(e), e.message
|
22
|
+
rescue Faraday::ClientError => e
|
23
|
+
raise Errors::Connection::ClientError.new(e), e.message
|
24
|
+
end
|
25
|
+
# rubocop:enable Metrics/MethodLength
|
26
|
+
|
27
|
+
def get_in_parallel(
|
28
|
+
path,
|
29
|
+
from_page_number,
|
30
|
+
to_page_number,
|
31
|
+
params: {},
|
32
|
+
request_options: {}
|
33
|
+
)
|
34
|
+
responses = []
|
35
|
+
|
36
|
+
connection.in_parallel(manager) do
|
37
|
+
(from_page_number..to_page_number).each do |page|
|
38
|
+
merged_params = {page: page}.merge(params)
|
39
|
+
|
40
|
+
responses << get(
|
41
|
+
path, params: merged_params, request_options: request_options
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
responses
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def connection
|
52
|
+
@connection ||= Faraday.new(default_options) do |connection|
|
53
|
+
connection.request :json
|
54
|
+
connection.response :json, content_type: /\bjson$/
|
55
|
+
connection.response :raise_error
|
56
|
+
connection.adapter :typhoeus
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def default_options
|
61
|
+
{
|
62
|
+
url: FreckleIO.configuration.url,
|
63
|
+
headers: {
|
64
|
+
user_agent: "MyFreckleBot/1.0"
|
65
|
+
}
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def set_request_options(request, options)
|
70
|
+
request.options.timeout = options[:timeout]
|
71
|
+
request.options.open_timeout = options[:open_timeout]
|
72
|
+
end
|
73
|
+
|
74
|
+
def manager
|
75
|
+
@manager ||= Typhoeus::Hydra.new(
|
76
|
+
max_concurrency: FreckleIO.configuration.max_concurrency
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "cgi"
|
3
|
+
|
4
|
+
module FreckleIO
|
5
|
+
class Paginator
|
6
|
+
attr_reader :raw_links
|
7
|
+
|
8
|
+
def initialize(raw_links)
|
9
|
+
@raw_links = raw_links
|
10
|
+
end
|
11
|
+
|
12
|
+
def next
|
13
|
+
find("next")&.dig(:url)
|
14
|
+
end
|
15
|
+
|
16
|
+
def prev
|
17
|
+
find("prev")&.dig(:url)
|
18
|
+
end
|
19
|
+
|
20
|
+
def first
|
21
|
+
find("first")&.dig(:url)
|
22
|
+
end
|
23
|
+
|
24
|
+
def last
|
25
|
+
find("last")&.dig(:url)
|
26
|
+
end
|
27
|
+
|
28
|
+
def total_pages
|
29
|
+
find("last")&.dig(:number_page)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def find(rel)
|
35
|
+
pages.find { |page| page[:rel] == rel }
|
36
|
+
end
|
37
|
+
|
38
|
+
def pages
|
39
|
+
return {} if raw_links.empty?
|
40
|
+
|
41
|
+
@pages ||=
|
42
|
+
raw_links.split(",").map do |link|
|
43
|
+
url, rel, number_page = split_and_clean_link(link)
|
44
|
+
|
45
|
+
{
|
46
|
+
url: "#{url.path}?#{url.query}",
|
47
|
+
rel: rel,
|
48
|
+
number_page: number_page
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Example of link response headers:
|
54
|
+
# "<https://api.letsfreckle.com/v2/users?page=2>; rel=\"last\""
|
55
|
+
#
|
56
|
+
# The first element is an URI. "Rel" means the relative position
|
57
|
+
# of the current page, in this case is last page.
|
58
|
+
|
59
|
+
def split_and_clean_link(link)
|
60
|
+
raw_url, rel = link.split(";").map(&:strip)
|
61
|
+
|
62
|
+
raw_url = raw_url.gsub(/<|>/, "")
|
63
|
+
rel = rel.gsub(/(rel=)?"/, "")
|
64
|
+
url = URI.parse(raw_url)
|
65
|
+
page = CGI.parse(url.query)["page"].first
|
66
|
+
|
67
|
+
[url, rel, page]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module FreckleIO
|
2
|
+
class Params
|
3
|
+
attr_reader :params
|
4
|
+
attr_reader :allowed_keys
|
5
|
+
attr_reader :validator_module
|
6
|
+
|
7
|
+
def initialize(
|
8
|
+
params,
|
9
|
+
allowed_keys,
|
10
|
+
validator_module
|
11
|
+
)
|
12
|
+
@params = params
|
13
|
+
@allowed_keys = allowed_keys
|
14
|
+
@validator_module = validator_module
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
return validator.output if valid?
|
19
|
+
|
20
|
+
raise Errors::Params::InvalidParams.new, validator_messages
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def valid?
|
26
|
+
validator.errors.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
def validator
|
30
|
+
@validator ||= which_validator_module.validation(params, allowed_keys)
|
31
|
+
end
|
32
|
+
|
33
|
+
def which_validator_module
|
34
|
+
Kernel.const_get(validator_module)
|
35
|
+
rescue NameError => e
|
36
|
+
raise Errors::Params::InvalidModule.new(e), e.message
|
37
|
+
end
|
38
|
+
|
39
|
+
def validator_messages
|
40
|
+
messages = validator.messages(full: true)
|
41
|
+
return messages.values.join(",") if messages.is_a?(Hash)
|
42
|
+
|
43
|
+
messages.join(",")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "faraday_middleware"
|
2
|
+
|
3
|
+
module FreckleIO
|
4
|
+
module Request
|
5
|
+
class MultiplePages
|
6
|
+
attr_reader :path
|
7
|
+
attr_reader :params
|
8
|
+
attr_reader :last_responses
|
9
|
+
|
10
|
+
def get(path, params: {})
|
11
|
+
@path ||= path
|
12
|
+
@params ||= default_params.merge(params).compact
|
13
|
+
|
14
|
+
retrieve_all_pages
|
15
|
+
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def retrieve_all_pages
|
22
|
+
@last_responses ||= client.get_in_parallel(
|
23
|
+
path,
|
24
|
+
2,
|
25
|
+
total_pages,
|
26
|
+
params: params
|
27
|
+
)
|
28
|
+
|
29
|
+
@last_responses.unshift([@first_response])
|
30
|
+
@last_responses.flatten!
|
31
|
+
end
|
32
|
+
|
33
|
+
def total_pages
|
34
|
+
@total_pages ||= first_page.total_pages
|
35
|
+
end
|
36
|
+
|
37
|
+
def first_page
|
38
|
+
@first_page ||= first_single_page.get(
|
39
|
+
path,
|
40
|
+
params: params
|
41
|
+
)
|
42
|
+
@first_response = @first_page.last_response
|
43
|
+
|
44
|
+
@first_page
|
45
|
+
end
|
46
|
+
|
47
|
+
def first_single_page
|
48
|
+
@first_single_page ||= SinglePage.new
|
49
|
+
end
|
50
|
+
|
51
|
+
def client
|
52
|
+
@client ||= Connection.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_params
|
56
|
+
{
|
57
|
+
per_page: FreckleIO.configuration.per_page
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "freckle_io/paginator"
|
2
|
+
|
3
|
+
module FreckleIO
|
4
|
+
module Request
|
5
|
+
class SinglePage
|
6
|
+
attr_reader :last_response
|
7
|
+
attr_reader :raw_links
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@last_response = nil
|
11
|
+
@raw_links = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(path, params: {}, request_options: {})
|
15
|
+
@last_response = client.get(
|
16
|
+
path,
|
17
|
+
params: params,
|
18
|
+
request_options: request_options
|
19
|
+
)
|
20
|
+
|
21
|
+
@raw_links = @last_response.headers["link"] || []
|
22
|
+
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def next
|
27
|
+
next? ? get(paginator.next) : nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def next?
|
31
|
+
paginator.next
|
32
|
+
end
|
33
|
+
|
34
|
+
def prev
|
35
|
+
prev? ? get(paginator.prev) : nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def prev?
|
39
|
+
paginator.prev
|
40
|
+
end
|
41
|
+
|
42
|
+
def last
|
43
|
+
last? ? get(paginator.last) : nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def last?
|
47
|
+
paginator.last
|
48
|
+
end
|
49
|
+
|
50
|
+
def first
|
51
|
+
first? ? get(paginator.first) : nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def first?
|
55
|
+
paginator.first
|
56
|
+
end
|
57
|
+
|
58
|
+
def total_pages
|
59
|
+
paginator.total_pages.to_i
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def paginator
|
65
|
+
@paginator = Paginator.new(raw_links)
|
66
|
+
end
|
67
|
+
|
68
|
+
def client
|
69
|
+
@client = Connection.new
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module FreckleIO
|
2
|
+
module Validator
|
3
|
+
module Entry
|
4
|
+
# rubocop:disable Metrics/MethodLength,
|
5
|
+
# rubocop:disable Metrics/AbcSize,
|
6
|
+
# rubocop:disable Lint/NestedMethodDefinition
|
7
|
+
# rubocop:disable Metrics/BlockLength,
|
8
|
+
def self.validation(params, valid_keys)
|
9
|
+
Dry::Validation.Schema do
|
10
|
+
configure do
|
11
|
+
config.messages_file = File.join(
|
12
|
+
__dir__, "validation.yml"
|
13
|
+
)
|
14
|
+
config.namespace = :entry
|
15
|
+
|
16
|
+
predicates(RestrictedHash)
|
17
|
+
|
18
|
+
option :allowed_keys
|
19
|
+
|
20
|
+
def valid_tag_filter_type
|
21
|
+
["and", "combination of"]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
restricted_hash?(allowed_keys) do
|
26
|
+
optional(:user_ids).filled :str?
|
27
|
+
optional(:description).filled :str?
|
28
|
+
optional(:project_ids).filled :str?
|
29
|
+
optional(:tag_ids).filled :str?
|
30
|
+
optional(:tag_filter_type).filled :str?
|
31
|
+
optional(
|
32
|
+
:tag_filter_type
|
33
|
+
).value(included_in?: valid_tag_filter_type)
|
34
|
+
optional(:invoice_ids).filled :str?
|
35
|
+
optional(:import_ids).filled :str?
|
36
|
+
optional(:from).filled :str?
|
37
|
+
optional(:to).filled :str?
|
38
|
+
optional(:invoiced).filled :bool?
|
39
|
+
optional(:invoiced_at_from).filled :str?
|
40
|
+
optional(:invoiced_at_to).filled :str?
|
41
|
+
optional(:updated_from).filled :str?
|
42
|
+
optional(:updated_to).filled :str?
|
43
|
+
optional(:billable).filled :bool?
|
44
|
+
optional(:approved_at_from).filled :str?
|
45
|
+
optional(:approved_at_to).filled :str?
|
46
|
+
optional(:approved_by_ids).filled :str?
|
47
|
+
optional(:per_page).filled :int?
|
48
|
+
end
|
49
|
+
end.with(allowed_keys: valid_keys).call(params)
|
50
|
+
end
|
51
|
+
# rubocop:enable Metrics/MethodLength,
|
52
|
+
# rubocop:enable Metrics/AbcSize,
|
53
|
+
# rubocop:enable Lint/NestedMethodDefinition
|
54
|
+
# rubocop:enable Metrics/BlockLength,
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module FreckleIO
|
2
|
+
module Validator
|
3
|
+
module Project
|
4
|
+
# rubocop:disable Metrics/MethodLength,
|
5
|
+
# rubocop:disable Metrics/AbcSize,
|
6
|
+
# rubocop:disable Lint/NestedMethodDefinition
|
7
|
+
def self.validation(params, valid_keys)
|
8
|
+
Dry::Validation.Schema do
|
9
|
+
configure do
|
10
|
+
config.messages_file = File.join(
|
11
|
+
__dir__, "validation.yml"
|
12
|
+
)
|
13
|
+
config.namespace = :project
|
14
|
+
|
15
|
+
predicates(RestrictedHash)
|
16
|
+
|
17
|
+
option :allowed_keys
|
18
|
+
|
19
|
+
def valid_increment
|
20
|
+
%w(1 5 6 10 15)
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_increment?(_options, values)
|
24
|
+
values.split(",").all? do |value|
|
25
|
+
valid_increment.include?(value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
restricted_hash?(allowed_keys) do
|
31
|
+
optional(:name).filled :str?
|
32
|
+
optional(:project_group_ids).filled :str?
|
33
|
+
optional(:billing_increment).filled :str?
|
34
|
+
optional(:billing_increment).filled(valid_increment?: {})
|
35
|
+
optional(:enabled).filled :bool?
|
36
|
+
optional(:billable).filled :bool?
|
37
|
+
optional(:per_page).filled :int?
|
38
|
+
end
|
39
|
+
end.with(allowed_keys: valid_keys).call(params)
|
40
|
+
end
|
41
|
+
# rubocop:enable Metrics/MethodLength,
|
42
|
+
# rubocop:enable Metrics/AbcSize,
|
43
|
+
# rubocop:enable Lint/NestedMethodDefinition
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module FreckleIO
|
2
|
+
module Validator
|
3
|
+
module ProjectGroup
|
4
|
+
# rubocop:disable Metrics/MethodLength,
|
5
|
+
# rubocop:disable Metrics/AbcSize,
|
6
|
+
def self.validation(params, valid_keys)
|
7
|
+
Dry::Validation.Schema do
|
8
|
+
configure do
|
9
|
+
config.messages_file = File.join(
|
10
|
+
__dir__, "validation.yml"
|
11
|
+
)
|
12
|
+
config.namespace = :project_group
|
13
|
+
|
14
|
+
predicates(RestrictedHash)
|
15
|
+
|
16
|
+
option :allowed_keys
|
17
|
+
end
|
18
|
+
|
19
|
+
restricted_hash?(allowed_keys) do
|
20
|
+
optional(:name).filled :str?
|
21
|
+
optional(:project_ids).filled :str?
|
22
|
+
optional(:per_page).filled :int?
|
23
|
+
end
|
24
|
+
end.with(allowed_keys: valid_keys).call(params)
|
25
|
+
end
|
26
|
+
# rubocop:enable Metrics/MethodLength,
|
27
|
+
# rubocop:enable Metrics/AbcSize,
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module FreckleIO
|
2
|
+
module Validator
|
3
|
+
module Tag
|
4
|
+
# rubocop:disable Metrics/MethodLength,
|
5
|
+
# rubocop:disable Metrics/AbcSize,
|
6
|
+
def self.validation(params, valid_keys)
|
7
|
+
Dry::Validation.Schema do
|
8
|
+
configure do
|
9
|
+
config.messages_file = File.join(
|
10
|
+
__dir__, "validation.yml"
|
11
|
+
)
|
12
|
+
config.namespace = :tag
|
13
|
+
|
14
|
+
predicates(RestrictedHash)
|
15
|
+
|
16
|
+
option :allowed_keys
|
17
|
+
end
|
18
|
+
|
19
|
+
restricted_hash?(allowed_keys) do
|
20
|
+
optional(:name).filled :str?
|
21
|
+
optional(:billable).filled :bool?
|
22
|
+
optional(:per_page).filled :int?
|
23
|
+
end
|
24
|
+
end.with(allowed_keys: valid_keys).call(params)
|
25
|
+
end
|
26
|
+
# rubocop:enable Metrics/MethodLength,
|
27
|
+
# rubocop:enable Metrics/AbcSize,
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module FreckleIO
|
2
|
+
module Validator
|
3
|
+
module User
|
4
|
+
# rubocop:disable Metrics/MethodLength,
|
5
|
+
# rubocop:disable Metrics/AbcSize,
|
6
|
+
# rubocop:disable Lint/NestedMethodDefinition
|
7
|
+
def self.validation(params, valid_keys)
|
8
|
+
Dry::Validation.Schema do
|
9
|
+
configure do
|
10
|
+
config.messages_file = File.join(
|
11
|
+
__dir__, "validation.yml"
|
12
|
+
)
|
13
|
+
config.namespace = :user
|
14
|
+
|
15
|
+
predicates(RestrictedHash)
|
16
|
+
|
17
|
+
option :allowed_keys
|
18
|
+
|
19
|
+
def valid_roles
|
20
|
+
%w(supervisor leader coworker contractor)
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_states
|
24
|
+
%w(disabled pending active suspended)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
restricted_hash?(allowed_keys) do
|
29
|
+
optional(:name).filled :str?
|
30
|
+
optional(:email).filled :str?
|
31
|
+
optional(:email).value(format?: /\A[^@\s]+@[^@\s]+\z/)
|
32
|
+
optional(:role).value(included_in?: valid_roles)
|
33
|
+
optional(:state).value(included_in?: valid_states)
|
34
|
+
optional(:per_page).filled :int?
|
35
|
+
end
|
36
|
+
end.with(allowed_keys: valid_keys).call(params)
|
37
|
+
end
|
38
|
+
# rubocop:enable Metrics/MethodLength,
|
39
|
+
# rubocop:enable Metrics/AbcSize,
|
40
|
+
# rubocop:enable Lint/NestedMethodDefinition
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
en:
|
2
|
+
errors:
|
3
|
+
rules:
|
4
|
+
user:
|
5
|
+
restricted_hash?: "has unknown keys. Allowed keys are: name, email, role, state and per_page"
|
6
|
+
project:
|
7
|
+
restricted_hash?: "has unknown keys. Allowed keys are: name, project_group_ids, billing_increment, enabled, billable and per_page"
|
8
|
+
valid_increment?: "has invalid values. Allowed values are: 1, 5, 6, 10, 15"
|
9
|
+
entry:
|
10
|
+
restricted_hash?: "has unknown keys. Allowed keys are: user_ids, description, project_ids, tag_ids, tag_filter_type, invoice_ids, import_ids, from, to, invoiced, invoice_at_from, invoice_at_to, updated_from, updated_to, billable, approved_at_from, approved_at_to, approved_by_ids and per_page"
|
11
|
+
tag:
|
12
|
+
restricted_hash?: "has unknown keys. Allowed keys are: name, billable and per_page"
|
13
|
+
project_group:
|
14
|
+
restricted_hash?: "has unknown keys. Allowed keys are: name, project ids and per_page"
|
data/lib/freckle_io.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require "dry-validation"
|
2
|
+
|
3
|
+
require "freckle_io/configuration"
|
4
|
+
require "freckle_io/connection"
|
5
|
+
require "freckle_io/params"
|
6
|
+
require "freckle_io/errors/configuration"
|
7
|
+
require "freckle_io/errors/connection"
|
8
|
+
require "freckle_io/errors/params"
|
9
|
+
require "freckle_io/request/multiple_pages"
|
10
|
+
require "freckle_io/request/single_page"
|
11
|
+
require "freckle_io/validator/restricted_hash"
|
12
|
+
require "freckle_io/validator/user"
|
13
|
+
require "freckle_io/validator/project"
|
14
|
+
require "freckle_io/validator/entry"
|
15
|
+
require "freckle_io/validator/tag"
|
16
|
+
require "freckle_io/validator/project_group"
|
17
|
+
require "freckle_io/client/users"
|
18
|
+
require "freckle_io/client/projects"
|
19
|
+
require "freckle_io/client/entries"
|
20
|
+
require "freckle_io/client/tags"
|
21
|
+
require "freckle_io/client/project_groups"
|
22
|
+
|
23
|
+
module FreckleIO
|
24
|
+
def self.configuration
|
25
|
+
@configuration ||= Configuration.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.reset
|
29
|
+
@configuration = Configuration.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.configure
|
33
|
+
yield(configuration)
|
34
|
+
end
|
35
|
+
end
|