cloudflare 3.2.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative 'representation'
24
+ require_relative 'paginate'
25
+
26
+ module Cloudflare
27
+ module Firewall
28
+ class Rule < Representation
29
+ def mode
30
+ value[:mode]
31
+ end
32
+
33
+ def notes
34
+ value[:notes]
35
+ end
36
+
37
+ def configuration
38
+ value[:configuration]
39
+ end
40
+
41
+ def to_s
42
+ "#{configuration[:value]} - #{mode} - #{notes}"
43
+ end
44
+ end
45
+
46
+ class Rules < Representation
47
+ include Paginate
48
+
49
+ def representation
50
+ Rule
51
+ end
52
+
53
+ def set(mode, value, notes: nil, target: 'ip')
54
+ notes ||= "cloudflare gem [#{mode}] #{Time.now.strftime('%m/%d/%y')}"
55
+
56
+ message = self.post({
57
+ mode: mode.to_s,
58
+ notes: notes,
59
+ configuration: {
60
+ target: target,
61
+ value: value.to_s,
62
+ }
63
+ })
64
+
65
+ id = message.result[:id]
66
+ resource = @resource.with(path: id)
67
+
68
+ return representation.new(resource, metadata: message.headers, value: message.result)
69
+ end
70
+
71
+ def find_by_id(id)
72
+ Rule.new(@resource.with(path: id))
73
+ end
74
+
75
+ def each_by_value(value, &block)
76
+ each(configuration_value: value, &block)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'representation'
22
+ require_relative 'paginate'
23
+
24
+ module Cloudflare
25
+ module Logs
26
+ class Entry < Representation
27
+ def to_s
28
+ "#{value[:rayid]}-#{value[:ClientRequestURI]}"
29
+ end
30
+ end
31
+
32
+ class Received < Representation
33
+ include Paginate
34
+
35
+ def representation
36
+ Entry
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,54 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Cloudflare
22
+ module Paginate
23
+ include Enumerable
24
+
25
+ def empty?
26
+ self.value.empty?
27
+ end
28
+
29
+ def representation
30
+ Representation
31
+ end
32
+
33
+ def each(page: 1, per_page: 50, **parameters)
34
+ return to_enum(:each, page: page, per_page: per_page, **parameters) unless block_given?
35
+
36
+ while true
37
+ zones = @resource.get(self.class, page: page, per_page: per_page, **parameters)
38
+
39
+ break if zones.empty?
40
+
41
+ Array(zones.value).each do |attributes|
42
+ resource = @resource.with(path: attributes[:id])
43
+
44
+ yield representation.new(resource, metadata: zones.metadata, value: attributes)
45
+ end
46
+
47
+ page += 1
48
+
49
+ # Was this the last page?
50
+ break if zones.value.count < per_page
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2012, by Marcin Prokop.
4
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+
24
+ require 'json'
25
+
26
+ require 'async/rest/representation'
27
+
28
+ module Cloudflare
29
+ class RequestError < StandardError
30
+ def initialize(resource, errors)
31
+ super("#{resource}: #{errors.map{|attributes| attributes[:message]}.join(', ')}")
32
+
33
+ @representation = representation
34
+ end
35
+
36
+ attr_reader :representation
37
+ end
38
+
39
+ class Message
40
+ def initialize(response)
41
+ @response = response
42
+ @body = response.read
43
+ end
44
+
45
+ attr :response
46
+ attr :body
47
+
48
+ def headers
49
+ @response.headers
50
+ end
51
+
52
+ def result
53
+ @body[:result]
54
+ end
55
+
56
+ def read
57
+ @body[:result]
58
+ end
59
+
60
+ def results
61
+ Array(result)
62
+ end
63
+
64
+ def errors
65
+ @body[:errors]
66
+ end
67
+
68
+ def messages
69
+ @body[:messages]
70
+ end
71
+
72
+ def success?
73
+ @body[:success]
74
+ end
75
+ end
76
+
77
+ class Representation < Async::REST::Representation
78
+ def process_response(*)
79
+ message = Message.new(super)
80
+
81
+ unless message.success?
82
+ raise RequestError.new(@resource, message.errors)
83
+ end
84
+
85
+ return message
86
+ end
87
+
88
+ def to_hash
89
+ if value.is_a?(Hash)
90
+ return value
91
+ end
92
+ end
93
+ end
94
+ end
@@ -20,19 +20,26 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
+ require 'async/rspec'
23
24
  require_relative '../../cloudflare'
24
25
 
25
26
  module Cloudflare
26
- module RSpec
27
- module Connection
28
- end
27
+ module RSpec
28
+ module Connection
29
+ end
29
30
 
30
- RSpec.shared_context Connection do
31
- # You must specify these in order for the tests to run.
32
- let(:email) { 'jake@example.net' }
33
- let(:key) { '5up3rS3cr3tAuthK3y' }
34
-
35
- let(:connection) { Cloudflare.connect(key: key, email: email) }
36
- end
37
- end
31
+ RSpec.shared_context Connection do
32
+ include_context Async::RSpec::Reactor
33
+
34
+ # You must specify these in order for the tests to run.
35
+ let(:email) {ENV['CLOUDFLARE_EMAIL']}
36
+ let(:key) {ENV['CLOUDFLARE_KEY']}
37
+
38
+ let(:connection) {@connection = Cloudflare.connect(key: key, email: email)}
39
+
40
+ after do
41
+ @connection&.close
42
+ end
43
+ end
44
+ end
38
45
  end
@@ -21,15 +21,16 @@
21
21
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
22
  # THE SOFTWARE.
23
23
 
24
- require_relative 'connection'
24
+ require_relative 'representation'
25
25
 
26
26
  module Cloudflare
27
- class Connection < Resource
28
- def user
29
- @user ||= User.new(concat_urls(url, 'user'), options)
30
- end
31
- end
32
-
33
- class User < Resource
34
- end
27
+ class User < Representation
28
+ def id
29
+ value[:id]
30
+ end
31
+
32
+ def email
33
+ value[:email]
34
+ end
35
+ end
35
36
  end
@@ -22,5 +22,5 @@
22
22
  # THE SOFTWARE.
23
23
 
24
24
  module Cloudflare
25
- VERSION = '3.2.1'
25
+ VERSION = '4.0.0'
26
26
  end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2012, by Marcin Prokop.
4
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
5
+ # Copyright, 2017, by David Rosenbloom. <http://artifactory.com>
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ # THE SOFTWARE.
24
+
25
+ require_relative 'representation'
26
+ require_relative 'paginate'
27
+
28
+ require_relative 'firewall'
29
+ require_relative 'dns'
30
+ require_relative 'logs'
31
+
32
+ module Cloudflare
33
+ class Zone < Representation
34
+ def dns_records
35
+ DNS::Records.new(@resource.with(path: 'dns_records'))
36
+ end
37
+
38
+ def firewall_rules
39
+ Firewall::Rules.new(@resource.with(path: 'firewall/access_rules/rules'))
40
+ end
41
+
42
+ def logs
43
+ Logs::Received.new(@resource.with(path: 'logs/received'))
44
+ end
45
+
46
+ DEFAULT_PURGE_CACHE_PARAMS = {
47
+ purge_everything: true
48
+ }.freeze
49
+
50
+ def purge_cache(parameters = DEFAULT_PURGE_CACHE_PARAMS)
51
+ message = self.with(path: 'purge_cache').post(parameters)
52
+
53
+ return message.success?
54
+ end
55
+
56
+ def name
57
+ value[:name]
58
+ end
59
+ end
60
+
61
+ class Zones < Representation
62
+ include Paginate
63
+
64
+ def representation
65
+ Zone
66
+ end
67
+
68
+ def create(name, account, jump_start = false)
69
+ message = self.post(name: name, account: account.to_hash, jump_start: jump_start)
70
+
71
+ id = message.result[:id]
72
+ resource = @resource.with(path: id)
73
+
74
+ return representation.new(resource, metadata: message.headers, value: message.result)
75
+ end
76
+
77
+ def find_by_name(name)
78
+ each(name: name).first
79
+ end
80
+
81
+ def find_by_id(id)
82
+ Zone.new(@resource.with(path: id))
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,32 @@
1
+
2
+ require 'cloudflare/rspec/connection'
3
+
4
+ RSpec.describe Cloudflare::DNS, order: :defined, timeout: 30 do
5
+ include_context Cloudflare::Zone
6
+
7
+ let(:subdomain) {"www#{ENV['TRAVIS_JOB_ID']}"}
8
+
9
+ let(:record) {@record = zone.dns_records.create("A", subdomain, "1.2.3.4")}
10
+
11
+ after do
12
+ if defined? @record
13
+ expect(@record.delete).to be_success
14
+ end
15
+ end
16
+
17
+ it "can create dns record" do
18
+ expect(record.type).to be == "A"
19
+ expect(record.name).to be_start_with subdomain
20
+ expect(record.content).to be == "1.2.3.4"
21
+ end
22
+
23
+ context "with existing record" do
24
+ it "can update dns content" do
25
+ record.update_content("4.3.2.1")
26
+ expect(record.content).to be == "4.3.2.1"
27
+
28
+ fetched_record = zone.dns_records.find_by_name(record.name)
29
+ expect(fetched_record.content).to be == record.content
30
+ end
31
+ end
32
+ end