respoke 1.1.3

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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 196657fbadbddac896125b5633e9a41ddc6ba4b5
4
+ data.tar.gz: ee0fd8872889c7868049130640092baa13f34294
5
+ SHA512:
6
+ metadata.gz: 15c8773001b7e574b8841fbb58190067f2d97f46a7b55be273ef008710d8b4210c4c2b4e323b100c4948952ec70d75dfa43cde995026e8fea51ee95cb8432926
7
+ data.tar.gz: 8380b37f0d43ffd581d77389d8f5cbb6fbe8eb89c23283e85810102013ab09197e5eb2fbc41969b2ed77e209c0b292786d0f323a607786b743c4f0feaba0c307
@@ -0,0 +1,17 @@
1
+ # EditorConfig is awesome: http://EditorConfig.org
2
+
3
+ # top-most EditorConfig file
4
+ root = true
5
+
6
+ # Unix-style newlines with a newline ending every file
7
+ [*]
8
+ end_of_line = lf
9
+ insert_final_newline = true
10
+ trim_trailing_whitespace = true
11
+ max_line_length = 80
12
+
13
+ # Set default charset
14
+ [*.{rb,gemspec}, Gemfile]
15
+ charset = utf-8
16
+ indent_style = space
17
+ indent_size = 2
@@ -0,0 +1,7 @@
1
+ Gemfile.lock
2
+ .bundle
3
+ coverage
4
+ doc
5
+ .yardoc
6
+ test/test_config*.yml
7
+ !test/test_config.example.yml
@@ -0,0 +1,6 @@
1
+
2
+ SimpleCov.start do
3
+ add_filter '/test/'
4
+ add_filter '.bundle'
5
+ add_filter 'coverage'
6
+ end
@@ -0,0 +1,17 @@
1
+ script: bundle exec rake test
2
+ rvm:
3
+ - 2.1
4
+ notifications:
5
+ email:
6
+ recipients:
7
+ - monitoring@respoke.io
8
+ email:
9
+ on_success: change
10
+ on_failure: always
11
+ cache: bundler
12
+ os:
13
+ - linux
14
+ - osx
15
+ before_install:
16
+ - openssl aes-256-cbc -K $encrypted_4e4ac21e4bd9_key -iv $encrypted_4e4ac21e4bd9_iv
17
+ -in test/test_config.yml.enc -out test/test_config.yml -d
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in respoke-admin.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Digium, Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,93 @@
1
+ [![Gem Version](https://badge.fury.io/rb/respoke.svg)](http://badge.fury.io/rb/respoke)
2
+ [![Build Status](https://travis-ci.org/pho3nixf1re/ruby-respoke.svg?branch=master)](https://travis-ci.org/pho3nixf1re/ruby-respoke)
3
+ [![Dependency Status](https://gemnasium.com/pho3nixf1re/ruby-respoke.svg)](https://gemnasium.com/pho3nixf1re/ruby-respoke)
4
+
5
+ # Respoke
6
+
7
+ ruby-respoke is a wrapper for the Respoke API. For more information on the
8
+ Respoke service and API see [docs.respoke.io](http://docs.respoke.io).
9
+
10
+ ## Installation
11
+
12
+ Using bundler, add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'respoke'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ For details on the ruby-respoke API please refer to the [full documentation].
23
+
24
+ [full documentation]: http://www.rubydoc.info/github/pho3nixf1re/ruby-respoke/master
25
+
26
+ ## Running the tests
27
+
28
+ The test suite uses VCR to record API requests and responses once. After the
29
+ first run it caches these and works offline. These cached files are checked into
30
+ Git and can be found in the `test/vcr_cassettes` directory. To run the tests
31
+ against the live API just delete the `test/vcr_cassettes` directory. Please note
32
+ that this will change the expected input of the encrypted
33
+ `test/test_config.yml.enc` file used by Travis and that will need to be updated
34
+ if you intend to commit the new VCR cache. Otherwise just omit the new cache
35
+ files when making your tests.
36
+
37
+ ### Units
38
+
39
+ Note that the unit tests do not use the VCR cache in favor of stubbing.
40
+
41
+ ```sh
42
+ rake test:unit
43
+ ```
44
+
45
+ ### Specs
46
+
47
+ Before you can run the specs yourself you will need to remove the VCR cache
48
+ files and provide your Respoke API credentials. Copy the `test/test_config.yml`
49
+ file and replace the example values with the ones in the Respoke
50
+ [developer portal].
51
+
52
+ [developer portal]: https://portal.respoke.io
53
+
54
+ ```
55
+ cp test/test_config.example.yml test/test_config.yml
56
+ ```
57
+
58
+ Fill in the test_config.yml values then run the spec rake task.
59
+
60
+ ```sh
61
+ rake test:spec
62
+ ```
63
+
64
+ ## Building the documentation
65
+
66
+ The documentation is marked up using Yard + Markdown. The easiest way to build
67
+ the included docs is to use the rake task.
68
+
69
+ ```sh
70
+ rake yard
71
+ ```
72
+
73
+ ## Contributing
74
+
75
+ If you wish to submit an issue use the [issue tracker].
76
+
77
+ [issue tracker]: https://github.com/pho3nixf1re/ruby-respoke/issues
78
+
79
+ 1. Fork it ( https://github.com/[my-github-username]/ruby-respoke/fork )
80
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
81
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
82
+ 4. Push to the branch (`git push origin my-new-feature`)
83
+ 5. Create a new Pull Request
84
+
85
+ ## License
86
+
87
+ Copyright 2014, Digium, Inc.
88
+ All rights reserved.
89
+
90
+ This source code is licensed under The MIT License found in the
91
+ [LICENSE](LICENSE) file in the root directory of this source tree.
92
+
93
+ For all details and documentation: https://www.respoke.io
@@ -0,0 +1,32 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ require 'yard'
4
+ require 'bundler/version'
5
+
6
+ namespace :test do
7
+ Rake::TestTask.new(:spec) do |t|
8
+ t.libs << "test"
9
+ t.test_files = FileList['test/spec/*_spec.rb']
10
+ end
11
+
12
+ Rake::TestTask.new(:unit) do |t|
13
+ t.libs << "test"
14
+ t.test_files = FileList['test/unit/**/*_test.rb']
15
+ end
16
+ end
17
+
18
+ task :test => ['test:spec', 'test:unit']
19
+
20
+ task :default => :test
21
+
22
+ YARD::Rake::YardocTask.new do |t|
23
+ t.options = ['-m', 'markdown']
24
+ end
25
+
26
+ task :build do
27
+ system "gem build respoke.gemspec"
28
+ end
29
+
30
+ task :release => :build do
31
+ system "gem push respoke-#{Respoke::VERSION}.gem"
32
+ end
@@ -0,0 +1,7 @@
1
+ require "respoke/version"
2
+ require "respoke/client"
3
+ require "respoke/role"
4
+
5
+ # The respoke gem top level namespace.
6
+ module Respoke
7
+ end
@@ -0,0 +1,265 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+
4
+ require 'respoke/errors'
5
+ require 'respoke/response'
6
+
7
+ # Contains methods to make API calls.
8
+ #
9
+ # @example One-step endpoint authentication
10
+ #
11
+ # require 'respoke'
12
+ #
13
+ # client = Respoke::Client.new(app_secret: '77269d84-d7f3-49da-8eab-bd6686160035')
14
+ # client.app_token(
15
+ # appId: '0cdf7bc1-45d1-420a-963e-c797a6f7ba61',
16
+ # roleId: '47ea573f-5a78-42f4-927c-fe658bc00f91',
17
+ # endpointId: 'foo-bar-user'
18
+ # )
19
+ # #=> '3c022dbd-0a82-4382-bd0d-5af6e11b8d67'
20
+ #
21
+ # @example Manual endpoint authentication
22
+ #
23
+ # require 'respoke'
24
+ #
25
+ # client = Respoke::Client.new(app_secret: '77269d84-d7f3-49da-8eab-bd6686160035')
26
+ #
27
+ # session_id_response = client.request_session_token_id(
28
+ # appId: '0cdf7bc1-45d1-420a-963e-c797a6f7ba61',
29
+ # roleId: '47ea573f-5a78-42f4-927c-fe658bc00f91',
30
+ # endpointId: 'foo-bar-user'
31
+ # )
32
+ # session = client.request_session_token(
33
+ # appId: session_id_response.appId,
34
+ # tokenId: session_id_response.tokenId
35
+ # )
36
+ #
37
+ # session.token #=> '3c022dbd-0a82-4382-bd0d-5af6e11b8d67'
38
+ #
39
+ # # OR you can just use Client#app_token since Client#request_session_token
40
+ # # sets `@app_token`.
41
+ # client.app_token #=> '3c022dbd-0a82-4382-bd0d-5af6e11b8d67'
42
+ #
43
+ # @attr_reader app_token
44
+ #
45
+ class Respoke::Client
46
+
47
+ # Default base_url
48
+ DEFAULT_BASE_URL = 'https://api.respoke.io/v1'
49
+
50
+ # Base URL used for API requests
51
+ attr_reader :base_url
52
+
53
+ # Sets the App-Secret token
54
+ attr_reader :app_secret
55
+
56
+ # Creates a new Client instance.
57
+ #
58
+ # @param app_secret [String] The application App-Secret token.
59
+ # (Defaults to nil)
60
+ # @param base_url [String] Overrides the {DEFAULT_BASE_URL} constant.
61
+ # (Defaults to {DEFAULT_BASE_URL})
62
+ #
63
+ # @return [Respoke::Client]
64
+ def initialize(app_secret: nil, base_url: DEFAULT_BASE_URL)
65
+ @base_url = base_url
66
+ @app_secret = app_secret
67
+ end
68
+
69
+ # Either returns the current `@app_token` or sets it based on the parameter
70
+ # Hash `token_request_params`.
71
+ #
72
+ # @param token_request_params [Hash] parameters for
73
+ # {#request_session_token_id}.
74
+ # @option token_request_params [String] appId The application ID.
75
+ # @option token_request_params [String] roleId Role ID to use for permissions
76
+ # on given endpoint ID.
77
+ # @option token_request_params [String] endpointId The endpoint ID to
78
+ # authenticate.
79
+ # @option token_request_params [Number] ttl (86400) Length of time token is
80
+ # valid.
81
+ #
82
+ # @return [String] App-Token value.
83
+ def app_token(token_request_params={})
84
+ @app_token ||= (
85
+ if token_request_params
86
+ response = request_session_token_id(token_request_params)
87
+ request_session_token(
88
+ appId: response.appId,
89
+ tokenId: response.tokenId
90
+ ).token
91
+ end
92
+ )
93
+ end
94
+
95
+ # Request a token ID for use in requesting the App-Token value.
96
+ #
97
+ # @todo test return value
98
+ #
99
+ # @param appId [String] The application ID that matches the App-Secret.
100
+ # @param roleId [String] The role ID to use for the given endpoint.
101
+ # @param endpointId [String] The endpoint ID that is being authenticated.
102
+ # @param ttl [Number] The amount of time in seconds the App-Token is
103
+ # valid. (Defaults to 86400)
104
+ #
105
+ # @return [Respoke::Response::SessionTokenId] The API response object.
106
+ def request_session_token_id(appId:, roleId:, endpointId:, ttl: 86400)
107
+ response = connection.post 'tokens' do |request|
108
+ request.body = {
109
+ appId: appId,
110
+ endpointId: endpointId,
111
+ roleId: roleId,
112
+ ttl: 86400
113
+ }
114
+ end
115
+
116
+ if response.status != 200
117
+ raise Respoke::Errors::UnexpectedServerError, <<-ERR
118
+ request failed with status #{response.status}:
119
+ #{response.body}
120
+ ERR
121
+ else
122
+ Respoke::Response::SessionTokenId.new(response.body)
123
+ end
124
+ end
125
+
126
+ # Request the session token using the tokenId retrived with
127
+ # {#request_session_token_id}. This method sets the `app_token` attribute.
128
+ #
129
+ # @todo test setting of `@app_token`.
130
+ #
131
+ # @param appId [String] The application ID used in the token request.
132
+ # @param tokenId [String] The token ID requested from
133
+ # {#request_session_token_id}.
134
+ #
135
+ # @return [Respoke::Response::SessionToken] The API response object.
136
+ def request_session_token(appId:, tokenId:)
137
+ response = connection.post 'session-tokens' do |request|
138
+ request.body = {
139
+ appId: appId,
140
+ tokenId: tokenId
141
+ }
142
+ end
143
+ @app_token = response.body.fetch('token', nil)
144
+
145
+ if response.status != 200
146
+ raise Respoke::Errors::UnexpectedServerError, <<-ERR
147
+ request failed with status #{response.status}:
148
+ #{response.body}
149
+ ERR
150
+ else
151
+ Respoke::Response::SessionToken.new(response.body)
152
+ end
153
+ end
154
+
155
+ # Get the roles
156
+ #
157
+ # @return [Array<Respoke::Role>] An array of role objects
158
+ # @raise [Respoke::Errors::UnexpectedServerError] if errors occur
159
+ def roles()
160
+ response = connection.get 'roles'
161
+
162
+ if response.status != 200
163
+ raise Respoke::Errors::UnexpectedServerError, <<-ERR
164
+ request failed with status #{response.status}:
165
+ #{response.body}
166
+ ERR
167
+ else
168
+ response.body.map { |r| Respoke::Role.new(connection, r.each_with_object({}) { |(k,v), h| h[k.to_sym] = v} ) }
169
+ end
170
+ end
171
+
172
+ # Create a role
173
+ #
174
+ # @param name [String] The name of the role
175
+ # @param rules [Hash] The permissions for the role
176
+ #
177
+ # @return [Respoke::Role] The role that was created
178
+ # @raise [Respoke::Errors::UnexpectedServerError] if errors occur
179
+ def create_role(name:, rules: {})
180
+ response = connection.post 'roles' do |request|
181
+ request.body = rules.merge( name: name )
182
+ end
183
+
184
+ if response.status != 200
185
+ raise Respoke::Errors::UnexpectedServerError, <<-ERR
186
+ request failed with status #{response.status}:
187
+ #{response.body}
188
+ ERR
189
+ else
190
+ Respoke::Role.new(self, response.body.each_with_object({}) { |(k,v), h| h[k.to_sym] = v} )
191
+ end
192
+ end
193
+
194
+
195
+ # Find a role
196
+ #
197
+ # @param id [String] The id of the role to retrieve
198
+ #
199
+ # @return [Respoke::Role] The role that was retrieved, nil if none found
200
+ # @raise [Respoke::Errors::UnexpectedServerError] if errors occur
201
+ def find_role(id:)
202
+ response = connection.get "roles/#{id}"
203
+
204
+ if response.status == 404
205
+ nil
206
+ elsif !response.success?
207
+ raise Respoke::Errors::UnexpectedServerError, <<-ERR
208
+ request failed with status #{response.status}:
209
+ #{response.body}
210
+ ERR
211
+ else
212
+ Respoke::Role.new(self, response.body.each_with_object({}) { |(k,v), h| h[k.to_sym] = v} )
213
+ end
214
+ end
215
+
216
+ # Update a role
217
+ #
218
+ # @param id [String] The id of the role to update
219
+ # @param rules [Hash] The new permissions for the role
220
+ #
221
+ # @return [Boolean] true if successfully updated
222
+ # @raise [Respoke::Errors::UnexpectedServerError] if errors occur
223
+ def update_role(id:, rules:)
224
+ response = connection.put "roles/#{id}" do |request|
225
+ request.body = rules
226
+ end
227
+
228
+ if !response.success?
229
+ raise Respoke::Errors::UnexpectedServerError, <<-ERR
230
+ request failed with status #{response.status}:
231
+ #{response.body}
232
+ ERR
233
+ else
234
+ true
235
+ end
236
+ end
237
+
238
+ # Delete a role
239
+ #
240
+ # @param id [String] The id of the role to retrieve
241
+ #
242
+ # @return [Boolean] true if the role was deleted, false otherwise
243
+ def delete_role(id:)
244
+ response = connection.delete "roles/#{id}"
245
+ response.success?
246
+ end
247
+
248
+ private
249
+
250
+ # Creates a Faraday connection object to make requests with.
251
+ #
252
+ # @return [Faraday::Connection] The connection object for making API requests.
253
+ def connection
254
+ @connection ||= Faraday.new(
255
+ url: @base_url,
256
+ headers: { :'App-Secret' => @app_secret }
257
+ ) do |faraday|
258
+ faraday.request :json
259
+
260
+ faraday.response :json, :content_type => 'application/json'
261
+
262
+ faraday.adapter Faraday.default_adapter
263
+ end
264
+ end
265
+ end