cfc 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 40bb48cf72eeb9528ed6c44396499aea91a719845094f1b389a7d891edb64b4c
4
+ data.tar.gz: f2ffa1a259fdb63166799b050f4035a0023ca9424753336cb21ef4b138ddbc76
5
+ SHA512:
6
+ metadata.gz: ae3acc4b662407967520e549a66cd73846ab834a89159d4592a8775af0efccf15ffbdacd09da8464e7f88f3b1a48bf677411614094d5342e95242a795e45b87b
7
+ data.tar.gz: eccf63a35470b2ee94f33324dd733b1393d43c0e36055840855c711c229b11e708bfae42f50c12443b0a6f6dd8f3b81026bf9fd7c5088996c689afa46ad50458
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright 2020– The Codidact Foundation
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ 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, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # cfc
2
+ Simple library for interacting with the Cloudflare API.
3
+
4
+ ## Install
5
+ Clone the repository. That's it!
6
+
7
+ ## Usage
8
+ This library is intended to be very lightweight, to help with usage in quick but effective scripts. Scripts that use
9
+ this library can be added to `scripts/` and run from there—it's *possible* for them to go anywhere, of course,
10
+ but relative `require`s are easier from a proximate directory.
11
+
12
+ You can use the library either by instantiating `CFC::API` and using that class to send API requests directly,
13
+ or, for simpler tasks, you can use pre-provided objects in `lib/objects/`, which represent a data type from the
14
+ Cloudflare API and may provide methods to perform common or simple tasks on those types. See
15
+ `lib/scripts/clear_cache.rb` for an example of how this may be done using `CFC::Zone` objects.
16
+
17
+ ## Contributing
18
+ As with all Codidact projects, contributions are welcome and must adhere to the
19
+ [Codidact Code of Conduct](https://meta.codidact.com/policy/code-of-conduct). Please create an issue to discuss any
20
+ major changes you propose to make, or if you think your changes may not be accepted for any reason—we'd always
21
+ rather discuss something unnecessarily than have to reject someone's hard work.
22
+
23
+ ## License
24
+ This project is licensed under the terms of the MIT license, which may be found in the LICENSE file.
data/lib/cfc/api.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'net/http'
2
+ require 'json'
3
+ require 'digest'
4
+ require 'yaml'
5
+ require_relative 'config'
6
+ require_relative 'cache'
7
+ require_relative 'errors/http_error.rb'
8
+
9
+ module CFC
10
+ class API
11
+ def initialize
12
+ @base = 'https://api.cloudflare.com/client/v4/'
13
+ @cache = CFC::Cache.new
14
+ end
15
+
16
+ def get(path, params: nil, headers: nil, cache: true, expiry: nil)
17
+ request(Net::HTTP::Get, build_uri(path, params), headers: headers, cache: cache, expiry: expiry)
18
+ end
19
+
20
+ def get_json(path, params: nil, headers: nil, cache: true, expiry: nil)
21
+ request_json(Net::HTTP::Get, build_uri(path, params), headers: headers, cache: cache, expiry: expiry)
22
+ end
23
+
24
+ [:post, :put, :patch].each do |method|
25
+ define_method method do |path, data, headers: nil, cache: false, expiry: nil|
26
+ request("Net::HTTP::#{method.capitalize}".constantize, URI("#{@base}#{path}"), data: data, headers: headers, cache: cache, expiry: expiry)
27
+ end
28
+
29
+ define_method "#{method}_to_json" do |path, data, headers: nil, cache: false, expiry: nil|
30
+ request_json(Object.const_get("Net::HTTP::#{method.capitalize}"), URI("#{@base}#{path}"), data: data, headers: headers, cache: cache,
31
+ expiry: expiry)
32
+ end
33
+ end
34
+
35
+ protected
36
+
37
+ def request(cls, uri, data: nil, headers: nil, cache: true, expiry: nil)
38
+ final_headers = (headers || {}).merge({
39
+ 'Authorization' => "Bearer #{CFC::Config.instance.token}",
40
+ 'Content-Type' => 'application/json'
41
+ })
42
+
43
+ rq = cls.new(uri, final_headers)
44
+ unless data.nil? || rq.is_a?(Net::HTTP::Head)
45
+ rq.body = JSON.dump(data)
46
+ end
47
+
48
+ response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
49
+ if cache
50
+ @cache.fetch(Digest::SHA256.hexdigest("#{uri}|#{JSON.dump(final_headers)}"), expiry: expiry) do
51
+ http.request(rq)
52
+ end
53
+ else
54
+ http.request(rq)
55
+ end
56
+ end
57
+
58
+ if response.is_a?(Net::HTTPSuccess)
59
+ response
60
+ else
61
+ raise CFC::Errors::HTTPError.new(rq, response)
62
+ end
63
+ end
64
+
65
+ def request_json(cls, path, data: nil, headers: nil, cache: true, expiry: nil)
66
+ JSON.parse(request(cls, path, data: data, headers: headers, cache: cache, expiry: expiry).body)
67
+ end
68
+
69
+ def build_uri(path, params)
70
+ uri = URI("#{@base}#{path}")
71
+ uri.query = URI.encode_www_form((params || {}).to_a)
72
+ uri
73
+ end
74
+ end
75
+ end
data/lib/cfc/cache.rb ADDED
@@ -0,0 +1,42 @@
1
+ require 'ostruct'
2
+ require 'date'
3
+
4
+ module CFC
5
+ class Cache
6
+ def initialize
7
+ @cache = {}
8
+ end
9
+
10
+ def include?(key)
11
+ @cache.include?(key) && (@cache[key].expiry.nil? || @cache[key].expiry >= DateTime.now.to_time.to_i)
12
+ end
13
+
14
+ def [](key)
15
+ valid?(key) ? @cache[key].data : nil
16
+ end
17
+
18
+ def []=(key, value)
19
+ @cache[key] = OpenStruct.new(data: value, expiry: nil)
20
+ end
21
+
22
+ def write(key, value, expiry: nil)
23
+ @cache[key] = OpenStruct.new(data: value, expiry: expiry)
24
+ end
25
+
26
+ def read(key)
27
+ valid?(key) ? @cache[key].data : nil
28
+ end
29
+
30
+ def fetch(key, expiry: nil)
31
+ if valid?(key)
32
+ @cache[key].data
33
+ else
34
+ data = block_given? ? yield : nil
35
+ write(key, data, expiry: expiry)
36
+ data
37
+ end
38
+ end
39
+
40
+ alias_method :valid?, :include?
41
+ end
42
+ end
data/lib/cfc/config.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'singleton'
2
+
3
+ module CFC
4
+ class Config
5
+ include Singleton
6
+ attr_accessor :token
7
+
8
+ def self.configure
9
+ yield CFC::Config.instance
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ require 'json'
2
+
3
+ module CFC
4
+ module Errors
5
+ class HTTPError < StandardError
6
+ attr_reader :request, :response
7
+
8
+ def initialize(request, response)
9
+ super "Cloudflare API request returned HTTP #{response.code}"
10
+ @request = request
11
+ @response = response
12
+ end
13
+
14
+ def data
15
+ JSON.parse(@response.body)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module CFC
2
+ module Errors
3
+ class MissingProperty < StandardError
4
+ def self.default_message(obj, property)
5
+ "This #{obj.class.name} does not have a `#{property}' property. If you are accessing this object from a relationship on " \
6
+ "another object, the property may not have been fetched."
7
+ end
8
+
9
+ def initialize(message)
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'object'
2
+
3
+ module CFC
4
+ class Account < CFC::APIObject
5
+ def initialize(data)
6
+ super(data)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,55 @@
1
+ require_relative '../errors/missing_property'
2
+ require_relative '../api'
3
+
4
+ module CFC
5
+ class APIObject
6
+ @relationships = []
7
+
8
+ def self.relationships
9
+ @relationships
10
+ end
11
+
12
+ def initialize(data)
13
+ @data = data
14
+ @api = CFC::API.new
15
+ initialize_relationships
16
+ end
17
+
18
+ def method_missing(name)
19
+ if @data.include?(name.to_s)
20
+ @data[name.to_s]
21
+ else
22
+ raise CFC::Errors::MissingProperty,
23
+ CFC::Errors::MissingProperty.default_message(self, name)
24
+ end
25
+ end
26
+
27
+ def respond_to_missing?(name, *_args, **_opts)
28
+ @data.include?(name.to_s)
29
+ end
30
+
31
+ def inspect
32
+ "#<#{self.class.name}:0x#{(object_id << 1).to_s(16)} #{@data.map { |k, v| "#{k}=#{v.inspect}" }.join(', ')}>"
33
+ end
34
+
35
+ alias_method :to_s, :inspect
36
+
37
+ protected
38
+
39
+ def self.relationship(property, cls)
40
+ unless defined?(@relationships)
41
+ @relationships = []
42
+ end
43
+ @relationships << [property, cls]
44
+ end
45
+
46
+ private
47
+
48
+ def initialize_relationships
49
+ (self.class.relationships || []).each do |rel|
50
+ property, cls = rel
51
+ @data[property.to_s] = cls.new(@data[property.to_s])
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,21 @@
1
+ module CFC
2
+ class Record < CFC::APIObject
3
+ def initialize(data)
4
+ super(data)
5
+ end
6
+
7
+ def proxy
8
+ set_proxied(true)
9
+ end
10
+
11
+ def deproxy
12
+ set_proxied(false)
13
+ end
14
+
15
+ private
16
+
17
+ def set_proxied(to)
18
+ @api.patch_to_json("zones/#{zone_id}/dns_records/#{id}", { proxied: to })
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'object'
2
+
3
+ module CFC
4
+ class User < CFC::APIObject
5
+ def initialize(data)
6
+ super(data)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,31 @@
1
+ require_relative 'object'
2
+ require_relative 'user'
3
+ require_relative 'account'
4
+ require_relative 'record'
5
+
6
+ module CFC
7
+ class Zone < CFC::APIObject
8
+ relationship :owner, CFC::User
9
+ relationship :account, CFC::Account
10
+
11
+ @api = CFC::API.new
12
+
13
+ def self.list
14
+ data = @api.get_json('zones')['result']
15
+ data.map { |z| new(z) }
16
+ end
17
+
18
+ def initialize(data)
19
+ super(data)
20
+ end
21
+
22
+ def purge_all_files
23
+ @api.post_to_json("zones/#{id}/purge_cache", { purge_everything: true })
24
+ end
25
+
26
+ def records
27
+ data = @api.get_json("zones/#{id}/dns_records")['result']
28
+ data.map { |r| CFC::Record.new(r) }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module CFC
2
+ VERSION = '0.1.1'
3
+ end
data/lib/cfc.rb ADDED
@@ -0,0 +1,10 @@
1
+ require_relative 'cfc/api'
2
+ require_relative 'cfc/config'
3
+ require_relative 'cfc/version'
4
+
5
+ require_relative 'cfc/objects/account'
6
+ require_relative 'cfc/objects/record'
7
+ require_relative 'cfc/objects/user'
8
+ require_relative 'cfc/objects/zone'
9
+
10
+ module CFC; end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cfc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - The Codidact Foundation
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-31 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: 'See GitHub for usage details: https://github.com/codidact/cfc'
14
+ email: gems@codidact.org
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - LICENSE
20
+ - README.md
21
+ - lib/cfc.rb
22
+ - lib/cfc/api.rb
23
+ - lib/cfc/cache.rb
24
+ - lib/cfc/config.rb
25
+ - lib/cfc/errors/http_error.rb
26
+ - lib/cfc/errors/missing_property.rb
27
+ - lib/cfc/objects/account.rb
28
+ - lib/cfc/objects/object.rb
29
+ - lib/cfc/objects/record.rb
30
+ - lib/cfc/objects/user.rb
31
+ - lib/cfc/objects/zone.rb
32
+ - lib/cfc/version.rb
33
+ homepage: https://github.com/codidact/cfc
34
+ licenses:
35
+ - MIT
36
+ metadata: {}
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 2.1.0
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubygems_version: 3.0.8
53
+ signing_key:
54
+ specification_version: 4
55
+ summary: Simple API library for interacting with the Cloudflare API.
56
+ test_files: []