northpasser 0.1.1
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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +57 -0
- data/LICENSE.txt +21 -0
- data/README.md +209 -0
- data/Rakefile +6 -0
- data/bin/console +9 -0
- data/bin/setup +13 -0
- data/lib/northpasser/constants.rb +52 -0
- data/lib/northpasser/path_builder.rb +90 -0
- data/lib/northpasser/request.rb +78 -0
- data/lib/northpasser/version.rb +3 -0
- data/lib/northpasser.rb +28 -0
- data/northpasser.gemspec +28 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 754649575db1e0559e07c31846aa2ba37c3d344f
|
4
|
+
data.tar.gz: 77891153f6f48d64cc280900702e0053a77ec5f5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 02c6c3c051960bc718e94428fa5c7b04061f4bb9bbebf6b9718bfbaf27b5bbf9af4f981ef44e011cf1ff75d2f56ed80fccb68b11f238ecd37e4c43108a85a3ee
|
7
|
+
data.tar.gz: 023bcb04f722d1eee97e6a1fa7902a61ccf7e2b9b2f6cb55985cc054b5d81ece6735df99cf1f052d505dae9d8b378b43972eabf6b01df593321a61bfe2cdd896
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.env
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
northpass (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
addressable (2.5.2)
|
10
|
+
public_suffix (>= 2.0.2, < 4.0)
|
11
|
+
coderay (1.1.2)
|
12
|
+
crack (0.4.3)
|
13
|
+
safe_yaml (~> 1.0.0)
|
14
|
+
diff-lcs (1.3)
|
15
|
+
dotenv (2.2.1)
|
16
|
+
hashdiff (0.3.7)
|
17
|
+
method_source (0.9.0)
|
18
|
+
pry (0.11.1)
|
19
|
+
coderay (~> 1.1.0)
|
20
|
+
method_source (~> 0.9.0)
|
21
|
+
public_suffix (3.0.2)
|
22
|
+
rake (10.5.0)
|
23
|
+
rspec (3.7.0)
|
24
|
+
rspec-core (~> 3.7.0)
|
25
|
+
rspec-expectations (~> 3.7.0)
|
26
|
+
rspec-mocks (~> 3.7.0)
|
27
|
+
rspec-core (3.7.1)
|
28
|
+
rspec-support (~> 3.7.0)
|
29
|
+
rspec-expectations (3.7.0)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.7.0)
|
32
|
+
rspec-mocks (3.7.0)
|
33
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
+
rspec-support (~> 3.7.0)
|
35
|
+
rspec-support (3.7.1)
|
36
|
+
safe_yaml (1.0.4)
|
37
|
+
vcr (3.0.3)
|
38
|
+
webmock (2.3.2)
|
39
|
+
addressable (>= 2.3.6)
|
40
|
+
crack (>= 0.3.2)
|
41
|
+
hashdiff
|
42
|
+
|
43
|
+
PLATFORMS
|
44
|
+
ruby
|
45
|
+
|
46
|
+
DEPENDENCIES
|
47
|
+
bundler (~> 1.12)
|
48
|
+
dotenv (~> 2.1)
|
49
|
+
northpass!
|
50
|
+
pry
|
51
|
+
rake (~> 10.0)
|
52
|
+
rspec (~> 3.0)
|
53
|
+
vcr (~> 3.0)
|
54
|
+
webmock (~> 2.1)
|
55
|
+
|
56
|
+
BUNDLED WITH
|
57
|
+
1.15.4
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Mark Hutter
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
# Northpasser
|
2
|
+
|
3
|
+
Northpasser is a lightweight Ruby wrapper of the
|
4
|
+
[Northpass API](https://app.northpass.com/api/v1/).
|
5
|
+
|
6
|
+
[Northpass](https://northpass.com) is a radical project management tool
|
7
|
+
particularly well suited to software development. If you're not familiar with
|
8
|
+
them, go check them out! :heart:
|
9
|
+
|
10
|
+
|
11
|
+
## Inspiration
|
12
|
+
This gem is heavily inspired by [Philip Castiglione](https://github.com/PhilipCastiglione)'s
|
13
|
+
Ruby [gem](https://github.com/PhilipCastiglione/clubhouse_ruby) for the Clubhouse API
|
14
|
+
|
15
|
+
Philip's restated philosophy on these techniques:
|
16
|
+
> ...A good API wrapper is a simpler alternative to a comprehensive client
|
17
|
+
> library and can provide a nice interface to the API using dynamic
|
18
|
+
> Ruby metaprogramming techniques rather than mapping functionality from
|
19
|
+
> the API to the library piece by piece.
|
20
|
+
|
21
|
+
> This enables the wrapper to be loosely coupled to the current implementation of
|
22
|
+
> the API, which makes it more resilient to change. Also, this approach takes much
|
23
|
+
> less code and maintenance effort, allowing the developer to be lazy. A
|
24
|
+
> reasonable person might fairly assume this to be the true rationale behind the
|
25
|
+
> philosophy. They'd be right.
|
26
|
+
|
27
|
+
My "strong inspiration" is almost entirely motivated by the latter part
|
28
|
+
of Philip's philosophy :)
|
29
|
+
|
30
|
+
|
31
|
+
## Installation
|
32
|
+
|
33
|
+
Add this line to your application's Gemfile:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
gem 'northpasser'
|
37
|
+
```
|
38
|
+
|
39
|
+
And then execute:
|
40
|
+
|
41
|
+
$ bundle
|
42
|
+
|
43
|
+
Or install it yourself as:
|
44
|
+
|
45
|
+
$ gem install northpasser
|
46
|
+
|
47
|
+
## Usage
|
48
|
+
|
49
|
+
This gem is a lightweight API wrapper. That means you'll need to refer to the
|
50
|
+
[API documentation](https://app.northpass.com/api/v1/) to figure out what resources
|
51
|
+
and actions exist.
|
52
|
+
|
53
|
+
|
54
|
+
Instantiate an object to interface with the API:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
northpass = Northpasser::Northpass.new(<YOUR NORTHPASS API TOKEN>)
|
58
|
+
```
|
59
|
+
|
60
|
+
The API can also provide responses in CSV format instead of the default JSON:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
northpass = Northpasser::Northpass.new(<YOUR NORTHPASS API TOKEN>, response_format: :csv)
|
64
|
+
```
|
65
|
+
|
66
|
+
Then, call methods on the object matching the resource(s) and action you are
|
67
|
+
interested in. For example, if you want to list all available courses, you need to
|
68
|
+
access the endpoint at https://api.northpass.com/v1/courses. The
|
69
|
+
northpasser gem uses an explicit action:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
northpass.courses.list
|
73
|
+
# => {
|
74
|
+
# "links": {
|
75
|
+
# "self": "https://api.northpass.com/v1/courses"
|
76
|
+
# },
|
77
|
+
# "data": [
|
78
|
+
# {
|
79
|
+
# "type": "courses",
|
80
|
+
# "id": "72673479-ad0c-4e81-bb2f-47174ff09396",
|
81
|
+
# "attributes": {
|
82
|
+
# "name": "Getting Started with Pixel (Sample Course)",
|
83
|
+
# "enrollments_count": 0,
|
84
|
+
# "list_image_url": "https://d3p3alwwakpeoy.cloudfront.net/api/file/YKu1Zb0fSqmrpsNL7nbu/convert?cache=true&fit=crop&h=500&w=820",
|
85
|
+
# "course_enrollment_link": "https://shipt.schoolkeep.com/c/071e0fd038cb23f005d5ff3f9519a8266774eafe",
|
86
|
+
# "share_course_link": "https://shipt.schoolkeep.com/outline/j16njpjy/cover",
|
87
|
+
# "permalink": "j16njpjy",
|
88
|
+
# "created_at": "2017-11-10T20:09:53Z",
|
89
|
+
# "updated_at": "2017-11-10T20:09:53Z"
|
90
|
+
# },
|
91
|
+
# "relationships": {
|
92
|
+
# "categories": {
|
93
|
+
# "data": []
|
94
|
+
# },
|
95
|
+
# "instructor_partnerships": {
|
96
|
+
# "data": []
|
97
|
+
# }
|
98
|
+
# },
|
99
|
+
# "links": {
|
100
|
+
# "self": "https://api.northpass.com/v1/courses/j16njpjy",
|
101
|
+
# "teaching": "https://app.northpass.com/courses/j16njpjy",
|
102
|
+
# "build": {
|
103
|
+
# "href": "https://app.northpass.com/courses/j16njpjy/builder",
|
104
|
+
# "methods": [
|
105
|
+
# "get"
|
106
|
+
# ]
|
107
|
+
# }
|
108
|
+
# }
|
109
|
+
# }
|
110
|
+
```
|
111
|
+
|
112
|
+
If the endpoint you want requires parameters, say if you wanted to create a
|
113
|
+
learner, you provide a hash to the action call following the resource:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
northpass.learners.create(data: { type: 'people', attributes: {email: "spiderman@marvel.com"} })
|
117
|
+
# => {
|
118
|
+
# "data": {
|
119
|
+
# "type": "people",
|
120
|
+
# "id": "b813a22e-7442-449b-a150-d3275a2cee29",
|
121
|
+
# "attributes": {
|
122
|
+
# "created_at": "2018-04-06T16:05:17Z",
|
123
|
+
# "email": "spiderman@marvel.com",
|
124
|
+
# "updated_at": "2018-04-06T16:05:17Z",
|
125
|
+
# "unsubscribed": false
|
126
|
+
# },
|
127
|
+
# "links": {
|
128
|
+
# "self": "https://api.northpass.com/v1/people/b813a22e-7442-449b-a150-d3275a2cee29",
|
129
|
+
# "teaching": "https://app.northpass.com/people/b813a22e-7442-449b-a150-d3275a2cee29"
|
130
|
+
# },
|
131
|
+
# "relationships": {
|
132
|
+
# "school": {
|
133
|
+
# "data": {
|
134
|
+
# "type": "schools",
|
135
|
+
# "id": "3825127e-011b-4b71-a6bb-543244406292"
|
136
|
+
# }
|
137
|
+
# }
|
138
|
+
# }
|
139
|
+
# }
|
140
|
+
#}
|
141
|
+
```
|
142
|
+
|
143
|
+
If you are building a path and you make a mistake, you can clear the path:
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
northpass.courses
|
147
|
+
northpass.epics
|
148
|
+
northpass.clear_path
|
149
|
+
# => []
|
150
|
+
```
|
151
|
+
|
152
|
+
You don't need to clear the path after a complete request, as that happens
|
153
|
+
automatically.
|
154
|
+
|
155
|
+
|
156
|
+
The resources and methods are enumerated in the source code
|
157
|
+
[here](https://github.com/mrkhutter/northpasser/blob/master/lib/northpasser/constants.rb)
|
158
|
+
but generally you should find the url you are interested in from the docs.
|
159
|
+
|
160
|
+
## Errors
|
161
|
+
|
162
|
+
Errors are passed through from the API relatively undecorated:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
northpass = Northpasser::Northpass.new("unrecognized token")
|
166
|
+
northpass.courses.list
|
167
|
+
# => {
|
168
|
+
# "errors": [
|
169
|
+
# {
|
170
|
+
# "status": "401",
|
171
|
+
# "title": "Unauthorized",
|
172
|
+
# "detail": "You don't have the necessary credentials",
|
173
|
+
# "source": {}
|
174
|
+
# }
|
175
|
+
# ]
|
176
|
+
#}
|
177
|
+
```
|
178
|
+
|
179
|
+
## Development
|
180
|
+
|
181
|
+
After checking out the repo, run `bin/setup` to install dependencies and
|
182
|
+
following the instructions. Specifically, you can choose to provide a genuine
|
183
|
+
northpass API token in the `.env` file. This will be important if you want to
|
184
|
+
use `bin/console` for an interactive prompt that allows you to experiment with
|
185
|
+
the gem and real API responses.
|
186
|
+
|
187
|
+
Use `rake spec` to run the tests. The tests don't make external requests but
|
188
|
+
rather use VCR for stubbed responses. If you want to play with the tests and
|
189
|
+
get real API responses (perhaps to extend the suite or for a new feature) then
|
190
|
+
you'll need to have an API token in the env as described above.
|
191
|
+
|
192
|
+
The current test suite is far from exhaustive and could do with some
|
193
|
+
love.
|
194
|
+
|
195
|
+
**NB: If you have implemented a feature that requires a new cassette, make sure
|
196
|
+
you change the uri referenced by the cassette you added to remove the API token
|
197
|
+
if you have updated the environment to use your token. Otherwise your API token
|
198
|
+
will be in publically visible from the code in this repo.**
|
199
|
+
|
200
|
+
## Contributing
|
201
|
+
|
202
|
+
Bug reports and pull requests are entirely welcome on GitHub at
|
203
|
+
https://github.com/philipcastiglione/northpasser.
|
204
|
+
|
205
|
+
|
206
|
+
## License
|
207
|
+
|
208
|
+
The gem is available as open source under the terms of the
|
209
|
+
[MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
set -euo pipefail
|
3
|
+
IFS=$'\n\t'
|
4
|
+
|
5
|
+
bundle install
|
6
|
+
|
7
|
+
touch .env
|
8
|
+
if [[ $(grep NORTHPASS_API_TOKEN .env) == "" ]]; then
|
9
|
+
echo "NORTHPASS_API_TOKEN=<YOUR NORTHPASS API TOKEN>" >> .env
|
10
|
+
echo ;
|
11
|
+
echo "DEVELOPER: Please edit .env to contain your northpass api token if you wish to use the console."
|
12
|
+
echo ;
|
13
|
+
fi
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
module Northpasser
|
5
|
+
V1_API_URL = "https://api.northpass.com/v1/".freeze
|
6
|
+
|
7
|
+
# Response formats the northpass api knows about
|
8
|
+
FORMATS = {
|
9
|
+
json: {
|
10
|
+
headers: { header: 'Content-Type', content: 'application/json' },
|
11
|
+
parser: JSON
|
12
|
+
},
|
13
|
+
csv: {
|
14
|
+
headers: { header: 'Accept', content: 'text/csv' },
|
15
|
+
parser: CSV
|
16
|
+
}
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
# Action words are nice for our internal api and match the api path too
|
20
|
+
ACTIONS = {
|
21
|
+
get: :Get,
|
22
|
+
update: :Put,
|
23
|
+
delete: :Delete,
|
24
|
+
list: :Get,
|
25
|
+
create: :Post
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
# These are the resource for the northpass api and can form part of the path
|
29
|
+
RESOURCES = [
|
30
|
+
:assignments,
|
31
|
+
:categories,
|
32
|
+
:coupons,
|
33
|
+
:courses,
|
34
|
+
:groups,
|
35
|
+
:learners,
|
36
|
+
:memberships,
|
37
|
+
:people,
|
38
|
+
:quizzes
|
39
|
+
].freeze
|
40
|
+
|
41
|
+
# These are the annoying edge cases in the northpass api that are don't fit
|
42
|
+
EXCEPTIONS = {
|
43
|
+
bulk_people: {
|
44
|
+
path: "bulk/people",
|
45
|
+
action: :Post
|
46
|
+
},
|
47
|
+
bulk_groups: {
|
48
|
+
path: "bulk/groups",
|
49
|
+
action: :Post
|
50
|
+
}
|
51
|
+
}.freeze
|
52
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Northpasser
|
2
|
+
module PathBuilder
|
3
|
+
def self.included(_)
|
4
|
+
class_exec do
|
5
|
+
attr_accessor :path
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# Uh oh! This will allow the class including this module to "build a path"
|
10
|
+
# by chaining calls to resources, terminated with a method linked to an
|
11
|
+
# action that will execute the api call.
|
12
|
+
#
|
13
|
+
# For example:
|
14
|
+
#
|
15
|
+
# `foo.stories(story_id).comments.update(id: comment_id, text: "comment text")`
|
16
|
+
#
|
17
|
+
# This example will execute a call to:
|
18
|
+
#
|
19
|
+
# `https://api.northpass.com/api/v1/courses/{course-id}/comments/{comment-id}`
|
20
|
+
#
|
21
|
+
# with arguments:
|
22
|
+
#
|
23
|
+
# `{ text: "comment text" }`
|
24
|
+
#
|
25
|
+
def method_missing(name, *args)
|
26
|
+
if known_action?(name)
|
27
|
+
execute_request(ACTIONS[name], args.first)
|
28
|
+
elsif known_resource?(name)
|
29
|
+
build_path(name, args.first)
|
30
|
+
elsif known_exception?(name)
|
31
|
+
build_path(EXCEPTIONS[name][:path], nil)
|
32
|
+
execute_request(EXCEPTIONS[name][:action], args.first)
|
33
|
+
else
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# You can build a path without executing in stages like this:
|
39
|
+
#
|
40
|
+
# `foo.stories(story_id)`
|
41
|
+
#
|
42
|
+
# This will partly populate foo:path, but won't execute the call (which
|
43
|
+
# clears it). In case you made a mistake and want to start again, you can
|
44
|
+
# clear the path using this public method.
|
45
|
+
#
|
46
|
+
def clear_path
|
47
|
+
self.path = []
|
48
|
+
end
|
49
|
+
|
50
|
+
# We'd better not lie when asked.
|
51
|
+
#
|
52
|
+
def respond_to_missing?(name, include_private = false)
|
53
|
+
known_action?(name) ||
|
54
|
+
known_resource?(name) ||
|
55
|
+
known_exception?(name) ||
|
56
|
+
super
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def known_action?(name)
|
62
|
+
ACTIONS.keys.include?(name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def known_resource?(name)
|
66
|
+
RESOURCES.include?(name)
|
67
|
+
end
|
68
|
+
|
69
|
+
def known_exception?(name)
|
70
|
+
EXCEPTIONS.keys.include?(name)
|
71
|
+
end
|
72
|
+
|
73
|
+
def execute_request(action, params)
|
74
|
+
req = Request.new(
|
75
|
+
self,
|
76
|
+
action: action,
|
77
|
+
params: params
|
78
|
+
)
|
79
|
+
clear_path
|
80
|
+
req.fetch
|
81
|
+
end
|
82
|
+
|
83
|
+
def build_path(resource, id)
|
84
|
+
self.path ||= []
|
85
|
+
self.path << resource
|
86
|
+
self.path << id if id
|
87
|
+
self
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
module Northpasser
|
5
|
+
class Request
|
6
|
+
attr_accessor :uri, :action, :response_format, :params
|
7
|
+
|
8
|
+
# Prepares a fancy request object and ensures the inputs make as much sense
|
9
|
+
# as possible. It's still totally possible to just provide a path that
|
10
|
+
# doesn't match a real url though.
|
11
|
+
#
|
12
|
+
def initialize(northpass, action:, params: {})
|
13
|
+
raise ArgumentError unless validate_input(northpass, action, params)
|
14
|
+
|
15
|
+
self.params = params || {}
|
16
|
+
self.uri = construct_uri(northpass)
|
17
|
+
self.action = action
|
18
|
+
self.response_format = northpass.response_format
|
19
|
+
end
|
20
|
+
|
21
|
+
# Executes the http(s) request and provides the response with some
|
22
|
+
# additional decoration in a Hash.
|
23
|
+
#
|
24
|
+
def fetch
|
25
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |https|
|
26
|
+
req = Net::HTTP.const_get(action).new(uri)
|
27
|
+
|
28
|
+
set_body(req)
|
29
|
+
set_format_header(req)
|
30
|
+
|
31
|
+
wrap_response(https.request(req))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def validate_input(northpass, action, params)
|
38
|
+
northpass.is_a?(Northpass) &&
|
39
|
+
!northpass.path.nil? &&
|
40
|
+
!northpass.token.nil? &&
|
41
|
+
!northpass.response_format.nil? &&
|
42
|
+
ACTIONS.values.include?(action) &&
|
43
|
+
(params.is_a?(Hash) || params.nil?)
|
44
|
+
end
|
45
|
+
|
46
|
+
def construct_uri(northpass)
|
47
|
+
base_url = V1_API_URL
|
48
|
+
path = northpass.path.map(&:to_s).map { |p| p.gsub('_', '-') }.join('/')
|
49
|
+
object_id = "/#{self.params.delete(:id)}" if self.params.key?(:id)
|
50
|
+
token = northpass.token
|
51
|
+
URI("#{base_url}#{path}#{object_id}?api_key=#{token}")
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_format_header(req)
|
55
|
+
format_header = FORMATS[response_format][:headers][:header]
|
56
|
+
format_content = FORMATS[response_format][:headers][:content]
|
57
|
+
req[format_header] = format_content
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_body(req)
|
61
|
+
req.body = params.to_json if params
|
62
|
+
end
|
63
|
+
|
64
|
+
def wrap_response(res)
|
65
|
+
begin
|
66
|
+
content = FORMATS[response_format][:parser].parse(res.body) if res.body
|
67
|
+
rescue FORMATS[response_format][:parser]::ParserError
|
68
|
+
content = res.body
|
69
|
+
end
|
70
|
+
|
71
|
+
{
|
72
|
+
code: res.code,
|
73
|
+
status: res.message,
|
74
|
+
content: content
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/northpasser.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "northpasser/version"
|
2
|
+
require "northpasser/constants"
|
3
|
+
require "northpasser/path_builder"
|
4
|
+
require "northpasser/request"
|
5
|
+
|
6
|
+
module Northpasser
|
7
|
+
class Northpass
|
8
|
+
include PathBuilder
|
9
|
+
|
10
|
+
attr_accessor :token, :response_format
|
11
|
+
|
12
|
+
# This is the basic object to interact with the northpass api. An api token
|
13
|
+
# is required, and optionally the response format can be set.
|
14
|
+
#
|
15
|
+
def initialize(token, response_format: :json)
|
16
|
+
raise ArgumentError unless input_valid?(token, response_format)
|
17
|
+
|
18
|
+
self.token = token
|
19
|
+
self.response_format = response_format
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def input_valid?(token, response_format)
|
25
|
+
!token.nil? && FORMATS.keys.include?(response_format)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/northpasser.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'northpasser/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "northpasser"
|
8
|
+
spec.version = Northpasser::VERSION
|
9
|
+
spec.authors = ["Mark Hutter"]
|
10
|
+
spec.email = ["mrkhutter@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A lightweight ruby wrapper for the Northpass API: https://northpass.com/api/v1}
|
13
|
+
spec.homepage = "https://github.com/mrkhutter/northpasser"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
24
|
+
spec.add_development_dependency "dotenv", "~> 2.1"
|
25
|
+
spec.add_development_dependency "webmock", "~> 2.1"
|
26
|
+
spec.add_development_dependency "vcr", "~> 3.0"
|
27
|
+
spec.add_development_dependency "pry"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: northpasser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mark Hutter
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-04-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: dotenv
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: webmock
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.1'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: vcr
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- mrkhutter@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- Gemfile
|
120
|
+
- Gemfile.lock
|
121
|
+
- LICENSE.txt
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- bin/console
|
125
|
+
- bin/setup
|
126
|
+
- lib/northpasser.rb
|
127
|
+
- lib/northpasser/constants.rb
|
128
|
+
- lib/northpasser/path_builder.rb
|
129
|
+
- lib/northpasser/request.rb
|
130
|
+
- lib/northpasser/version.rb
|
131
|
+
- northpasser.gemspec
|
132
|
+
homepage: https://github.com/mrkhutter/northpasser
|
133
|
+
licenses:
|
134
|
+
- MIT
|
135
|
+
metadata: {}
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
require_paths:
|
139
|
+
- lib
|
140
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
requirements: []
|
151
|
+
rubyforge_project:
|
152
|
+
rubygems_version: 2.4.8
|
153
|
+
signing_key:
|
154
|
+
specification_version: 4
|
155
|
+
summary: 'A lightweight ruby wrapper for the Northpass API: https://northpass.com/api/v1'
|
156
|
+
test_files: []
|