kloudless 0.1.0

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