kloudless 0.1.0

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.
@@ -0,0 +1,16 @@
1
+ module Kloudless
2
+ # https://developers.kloudless.com/docs#events
3
+ class Event < Model
4
+ # https://developers.kloudless.com/docs#events-list-file/folder-events
5
+ def self.list(account_id:, **params)
6
+ path = "/accounts/#{account_id}/events"
7
+ Kloudless::Collection.new(self, http.get(path, params: params))
8
+ end
9
+
10
+ # https://developers.kloudless.com/docs#events-retrieve-latest-cursor
11
+ def self.cursor(account_id:)
12
+ path = "/accounts/#{account_id}/events/latest"
13
+ new(http.get(path))
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,50 @@
1
+ module Kloudless
2
+ # https://developers.kloudless.com/docs#files
3
+ class File < Model
4
+ def self.upload(account_id:, **params)
5
+ path = "/accounts/#{account_id}/files"
6
+ new(http.post(path, params: params))
7
+ end
8
+
9
+ def self.metadata(account_id:, file_id:)
10
+ path = "/accounts/#{account_id}/files/#{file_id}"
11
+ new(http.get(path))
12
+ end
13
+
14
+ def self.rename(account_id:, file_id:, **params)
15
+ path = "/accounts/#{account_id}/files/#{file_id}"
16
+ new(http.patch(path, params: params))
17
+ end
18
+
19
+ # TODO: unclear how to post binary data over net-http
20
+ def self.update
21
+ raise NotImplementedError
22
+ end
23
+
24
+ def self.download(account_id:, file_id:)
25
+ path = "/accounts/#{account_id}/files/#{file_id}/contents"
26
+ http.get_raw(path)
27
+ end
28
+
29
+ def self.copy(account_id:, file_id:, parent_id:, **params)
30
+ path = "/accounts/#{account_id}/files/#{file_id}/copy"
31
+ params[:parent_id] = parent_id
32
+ new(http.post(path, params: params))
33
+ end
34
+
35
+ def self.delete(account_id:, file_id:, **params)
36
+ path = "/accounts/#{account_id}/files/#{file_id}"
37
+ new(http.delete(path, params: params))
38
+ end
39
+
40
+ def self.recent(account_ids:, **params)
41
+ path = "/accounts/#{account_ids.join(',')}/recent"
42
+ Kloudless::Collection.new(self, http.get(path, params: params))
43
+ end
44
+
45
+ def self.search(account_ids:, **params)
46
+ path = "/accounts/#{account_ids.join(',')}/search"
47
+ Kloudless::Collection.new(self, http.get(path, params: params))
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,41 @@
1
+ module Kloudless
2
+ # https://developers.kloudless.com/docs#folders
3
+ class Folder < Model
4
+ # https://developers.kloudless.com/docs#folders-create-a-folder
5
+ def self.create(account_id:, **params)
6
+ path = "/accounts/#{account_id}/folders"
7
+ new(http.post(path, params: params))
8
+ end
9
+
10
+ # https://developers.kloudless.com/docs#folders-retrieve-folder-metadata
11
+ def self.metadata(account_id:, folder_id:)
12
+ path = "/accounts/#{account_id}/folders/#{folder_id}"
13
+ new(http.get(path))
14
+ end
15
+
16
+ # https://developers.kloudless.com/docs#folders-retrieve-folder-contents
17
+ def self.retrieve(account_id:, folder_id:, **params)
18
+ path = "/accounts/#{account_id}/folders/#{folder_id}/contents"
19
+ Kloudless::Collection.new(self, http.get(path, params: params))
20
+ end
21
+
22
+ # https://developers.kloudless.com/docs#folders-rename/move-a-folder
23
+ def self.rename(account_id:, folder_id:, **params)
24
+ path = "/accounts/#{account_id}/folders/#{folder_id}"
25
+ new(http.patch(path, params: params))
26
+ end
27
+
28
+ # https://developers.kloudless.com/docs#folders-copy-a-folder
29
+ def self.copy(account_id:, folder_id:, parent_id:, **params)
30
+ params[:parent_id] = parent_id
31
+ path = "/accounts/#{account_id}/folders/#{folder_id}/copy"
32
+ new(http.post(path, params: params))
33
+ end
34
+
35
+ # https://developers.kloudless.com/docs#folders-delete-a-folder
36
+ def self.delete(account_id:, folder_id:, **params)
37
+ path = "/accounts/#{account_id}/folders/#{folder_id}"
38
+ new(http.delete(path, params: params))
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,114 @@
1
+ require "net/http"
2
+
3
+ module Kloudless
4
+ # Net::HTTP wrapper
5
+ class HTTP
6
+ # Public: Headers global to all requests
7
+ def self.headers
8
+ @headers ||= {}
9
+ end
10
+
11
+ def self.get(path, params: {}, headers: {})
12
+ uri = URI.parse(Kloudless::API_URL + path)
13
+ uri.query = URI.encode_www_form(params) if !params.empty?
14
+
15
+ request = Net::HTTP::Get.new(uri)
16
+ request.initialize_http_header(headers)
17
+
18
+ execute(request)
19
+ end
20
+
21
+ # TODO: decouple Kloudless::HTTP methods from #execute. Have methods return
22
+ # request object, defaults to json parsing, but allow the option for raw
23
+ def self.get_raw(path)
24
+ uri = URI.parse(Kloudless::API_URL + path)
25
+ request = Net::HTTP::Get.new(uri)
26
+ request.initialize_http_header(headers)
27
+
28
+ execute(request, parse_json: false)
29
+ end
30
+
31
+
32
+ def self.post(path, params: {}, headers: {})
33
+ uri = URI.parse(Kloudless::API_URL + path)
34
+ headers["Content-Type"] = "application/json"
35
+
36
+ request = Net::HTTP::Post.new(uri)
37
+ request.initialize_http_header(headers)
38
+ request.set_form_data(params) if !params.empty?
39
+
40
+ execute(request)
41
+ end
42
+
43
+ def self.patch(path, params: {}, headers: {})
44
+ uri = URI.parse(Kloudless::API_URL + path)
45
+ headers["Content-Type"] = "application/json"
46
+
47
+ request = Net::HTTP::Post.new(uri)
48
+ request.initialize_http_header(headers)
49
+ request.set_form_data(params) if !params.empty?
50
+
51
+ execute(request)
52
+ end
53
+
54
+ def self.delete(path, params: {}, headers: {})
55
+ uri = URI.parse(Kloudless::API_URL + path)
56
+ uri.query = URI.encode_www_form(params) if !params.empty?
57
+
58
+ request = Net::HTTP::Delete.new(uri)
59
+ request.initialize_http_header(headers)
60
+
61
+ execute(request)
62
+ end
63
+
64
+ def self.execute(request, parse_json: true)
65
+ uri = request.uri
66
+ @last_request = request
67
+ headers.each {|k,v| request[k] = v}
68
+
69
+ response = @mock_response || Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == "https")) {|http|
70
+ http.request(request)
71
+ }
72
+
73
+ if parse_json
74
+ json = JSON.parse(response.body)
75
+ raise Kloudless::Error.from_json(json) if json["error_code"]
76
+ json
77
+ else
78
+ response
79
+ end
80
+ end
81
+
82
+ # Internal: Returns `response` the next time #execute is invoked for the
83
+ # duration of `blk`. Used for testing.
84
+ #
85
+ # mock = Struct.new(:body).new("{}")
86
+ # Kloudless::HTTP.mock_response(mock) do
87
+ # Kloudless::HTTP.get "/foo" # returns {}
88
+ # end
89
+ def self.mock_response(response = nil, &blk)
90
+ @mock_response = response || Struct.new(:body).new("{}")
91
+ blk.call
92
+ ensure
93
+ @mock_response = nil
94
+ end
95
+
96
+ require 'minitest/mock'
97
+ def self.expect(method, returns: nil, args: [], &blk)
98
+ begin
99
+ mock = MiniTest::Mock.new
100
+ Kloudless.http = mock
101
+ mock.expect(method, returns, args)
102
+ blk.call
103
+ mock.verify
104
+ ensure
105
+ Kloudless.http = Kloudless::HTTP
106
+ end
107
+ end
108
+
109
+ # Internal: Returns the last Net::HTTP request sent by #execute.
110
+ def self.last_request
111
+ @last_request
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,34 @@
1
+ module Kloudless
2
+ # https://developers.kloudless.com/docs#links
3
+ class Link < Model
4
+ def self.list(account_ids:, **params)
5
+ path = "/accounts/#{account_ids.join(',')}/links"
6
+ Kloudless::Collection.new(self, http.get(path, params: params))
7
+ end
8
+
9
+ # https://developers.kloudless.com/docs#links-create-a-link
10
+ def self.create(account_id:, file_id:, **params)
11
+ params[:file_id] = file_id
12
+ path = "/accounts/#{account_id}/links"
13
+ new(http.post(path, params: params))
14
+ end
15
+
16
+ # https://developers.kloudless.com/docs#links-retrieve-a-link
17
+ def self.retrieve(account_id:, link_id:, **params)
18
+ path = "/accounts/#{account_id}/links/#{link_id}"
19
+ new(http.get(path, params: params))
20
+ end
21
+
22
+ # https://developers.kloudless.com/docs#links-update-a-link
23
+ def self.update(account_id:, link_id:, **params)
24
+ path = "/accounts/#{account_id}/links/#{link_id}"
25
+ new(http.patch(path, params: params))
26
+ end
27
+
28
+ # https://developers.kloudless.com/docs#links-delete-a-link
29
+ def self.delete(account_id:, link_id:)
30
+ path = "/accounts/#{account_id}/links/#{link_id}"
31
+ new(http.delete(path))
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ module Kloudless
2
+ # Public: Base class for different API resources. e.g. Account, Team, Files.
3
+ class Model
4
+ def self.http
5
+ Kloudless.http
6
+ end
7
+
8
+ def http
9
+ self.class.http
10
+ end
11
+
12
+ def initialize(attributes = {})
13
+ @attributes = attributes
14
+ end
15
+
16
+ def method_missing(name, *args, &blk)
17
+ @attributes[name.to_s] || super
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ module Kloudless
2
+ # https://developers.kloudless.com/docs#multipart-upload
3
+ class MultipartUpload < Model
4
+ def self.init(account_id:, **params)
5
+ path = "/accounts/#{account_id}/multipart"
6
+ new(http.post(path, params: params))
7
+ end
8
+
9
+ def self.retrieve(account_id:, multipart_id:)
10
+ path = "/accounts/#{account_id}/multipart/#{multipart_id}"
11
+ new(http.get(path))
12
+ end
13
+
14
+ # https://developers.kloudless.com/docs#multipart-upload-upload-part
15
+ def self.upload(account_id:, multipart_id:, part_number:, **params)
16
+ path = "/accounts/#{account_id}/multipart/#{multipart_id}"
17
+ params[:part_number] = part_number
18
+ new(http.put(path, params: params))
19
+ end
20
+
21
+ # https://developers.kloudless.com/docs#multipart-upload-finalize-multipart-session
22
+ def self.finalize(account_id:, multipart_id:)
23
+ path = "/accounts/#{account_id}/multipart/#{multipart_id}/complete"
24
+ new(http.post(path))
25
+ end
26
+
27
+ # https://developers.kloudless.com/docs#multipart-upload-abort-multipart-session
28
+ def self.abort(account_id:, multipart_id:)
29
+ path = "/accounts/#{account_id}/multipart/#{multipart_id}"
30
+ new(http.delete(path))
31
+ end
32
+
33
+ class << self
34
+ alias_method :delete, :abort
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ module Kloudless
2
+ # https://developers.kloudless.com/docs#team
3
+ class Team < Model
4
+ def self.list(account_id:, **params)
5
+ path = "/accounts/#{account_id}/team"
6
+ Kloudless::Collection.new(self, http.get(path, params: params))
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Kloudless
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env sh
2
+ # Usage: script/changelog [-r <repo>] [-b <base>] [-h <head>]
3
+ #
4
+ # repo: base string of GitHub repository url. e.g. "user_or_org/repository". Defaults to git remote url.
5
+ # base: git ref to compare from. e.g. "v1.3.1". Defaults to latest git tag.
6
+ # head: git ref to compare to. Defaults to "HEAD".
7
+ #
8
+ # Generate a changelog preview from pull requests merged between `base` and
9
+ # `head`.
10
+ #
11
+ set -e
12
+
13
+ [ $# -eq 0 ] && set -- --help
14
+
15
+ # parse args
16
+ repo=$(git remote -v | grep push | awk '{print $2}' | cut -d'/' -f4- | sed 's/\.git//')
17
+ base=$(git tag -l | sort -n | tail -n 1)
18
+ head="HEAD"
19
+ api_url="https://api.github.com"
20
+
21
+ echo "# $repo $base..$head"
22
+ echo
23
+
24
+ # get merged PR's. Better way is to query the API for these, but this is easier
25
+ for pr in $(git log --oneline $base..$head | grep "Merge pull request" | awk '{gsub("#",""); print $5}')
26
+ do
27
+ # frustrated with trying to pull out the right values, fell back to ruby
28
+ curl -s "$api_url/repos/$repo/pulls/$pr" | ruby -rjson -e 'pr=JSON.parse(STDIN.read); puts "* #{pr[%q(title)]} [##{pr[%q(number)]}](#{pr[%q(html_url)]})"'
29
+ done
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ # Usage: script/package
3
+ # Updates the gemspec and builds a new gem in the pkg directory.
4
+
5
+ mkdir -p pkg
6
+ gem build *.gemspec
7
+ mv *.gem pkg
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env bash
2
+ # Usage: script/release
3
+ # Build the package, tag a commit, push it to origin, and then release the
4
+ # package publicly.
5
+
6
+ set -e
7
+
8
+ version="$(script/package | grep Version: | awk '{print $2}')"
9
+ [ -n "$version" ] || exit 1
10
+
11
+ echo $version
12
+ git commit --allow-empty -a -m "Release $version"
13
+ git tag "v$version"
14
+ git push origin
15
+ git push origin "v$version"
16
+ gem push pkg/*-${version}.gem
@@ -0,0 +1,26 @@
1
+ require_relative "../test_helper"
2
+ require 'minitest'
3
+
4
+ class Kloudless::AccountKeyTest < Minitest::Test
5
+ def test_list_account_keys
6
+ Kloudless.http.expect(:get, returns: {"objects" => [{}]}, args: ["/accounts/1,2/keys", params: {}]) do
7
+ account_keys = Kloudless::AccountKey.list(account_ids: [1,2])
8
+ assert_kind_of Kloudless::Collection, account_keys
9
+ assert_kind_of Kloudless::AccountKey, account_keys.first
10
+ end
11
+ end
12
+
13
+ def test_retrieve_account_key
14
+ Kloudless.http.expect(:get, args: ["/accounts/1/keys/2", params: {}]) do
15
+ account_key = Kloudless::AccountKey.retrieve(account_id: 1, key_id: 2)
16
+ assert_kind_of Kloudless::AccountKey, account_key
17
+ end
18
+ end
19
+
20
+ def test_delete_account_key
21
+ Kloudless.http.expect(:delete, args: ["/accounts/1/keys/2"]) do
22
+ account_key = Kloudless::AccountKey.delete(account_id: 1, key_id: 2)
23
+ assert_kind_of Kloudless::AccountKey, account_key
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,78 @@
1
+ require_relative "../test_helper"
2
+
3
+ class Kloudless::AccountTest < Minitest::Test
4
+ def test_list_accounts
5
+ json = JSON.parse <<-JSON
6
+ {
7
+ "total": 2,
8
+ "count": 2,
9
+ "page": 1,
10
+ "objects": [
11
+ {
12
+ "id": 90817234,
13
+ "account": "someone@gmail.com",
14
+ "service": "box",
15
+ "service_name": "Box",
16
+ "admin": false,
17
+ "active": true,
18
+ "created": "2015-03-17T20:42:17.954885Z",
19
+ "modified": "2015-03-17T20:42:17.954885Z",
20
+ "token_expiry": "2015-04-17T20:42:17.954885Z",
21
+ "refresh_token_expiry": null
22
+ },
23
+ {
24
+ "id": 6535892,
25
+ "account": "someone-else@gmail.com",
26
+ "service": "egnyte",
27
+ "service_name": "Egnyte",
28
+ "admin": false,
29
+ "active": true,
30
+ "created": "2015-03-17T20:42:18.627533Z",
31
+ "modified": "2015-03-17T20:42:18.627533Z",
32
+ "token_expiry": "2015-04-17T20:42:18.627533Z",
33
+ "refresh_token_expiry": null
34
+ }
35
+ ]
36
+ }
37
+ JSON
38
+
39
+ Kloudless.http.expect(:get, returns: json, args: ["/accounts", {params: {}}]) do
40
+ accounts = Kloudless::Account.list
41
+ assert_kind_of Kloudless::Collection, accounts
42
+ assert_kind_of Kloudless::Account, accounts.first
43
+ end
44
+ end
45
+
46
+ def test_import_account
47
+ attributes = {
48
+ account: "someone@gmail.com",
49
+ service: "copy",
50
+ token: "foo",
51
+ token_secret: "bar"
52
+ }
53
+ Kloudless.http.expect(:post, args: ["/accounts", {params: attributes}]) do
54
+ Kloudless::Account.import(attributes)
55
+ end
56
+ end
57
+
58
+ def test_retrieve_account
59
+ Kloudless.http.expect(:get, args: ["/accounts/1", {params: {active: false}}]) do
60
+ account = Kloudless::Account.retrieve(account_id: 1, active: false)
61
+ assert_kind_of Kloudless::Account, account
62
+ end
63
+ end
64
+
65
+ def test_update_account
66
+ Kloudless.http.expect(:patch, args: ["/accounts/1", {params: {active: true}}]) do
67
+ account = Kloudless::Account.update(account_id: 1, active: true)
68
+ assert_kind_of Kloudless::Account, account
69
+ end
70
+ end
71
+
72
+ def test_delete_account
73
+ Kloudless.http.expect(:delete, args: ["/accounts/1"]) do
74
+ account = Kloudless::Account.delete(account_id: 1)
75
+ assert_kind_of Kloudless::Account, account
76
+ end
77
+ end
78
+ end