lockitron 0.0.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +1 -2
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +0 -0
- data/{LICENSE → LICENSE.txt} +2 -2
- data/README.md +42 -61
- data/Rakefile +0 -1
- data/lib/lockitron.rb +7 -5
- data/lib/lockitron/auth.rb +24 -0
- data/lib/lockitron/lock.rb +88 -0
- data/lib/lockitron/user.rb +30 -0
- data/lib/lockitron/version.rb +1 -1
- data/lockitron.gemspec +37 -17
- data/spec/fixtures/vcr_cassettes/invite.yml +101 -0
- data/spec/fixtures/vcr_cassettes/lock.yml +55 -0
- data/spec/fixtures/vcr_cassettes/oauth.yml +54 -0
- data/spec/fixtures/vcr_cassettes/unlock.yml +55 -0
- data/spec/fixtures/vcr_cassettes/user.yml +56 -0
- data/spec/request/auth_spec.rb +16 -0
- data/spec/request/lock_spec.rb +35 -0
- data/spec/request/user_spec.rb +12 -0
- data/spec/spec_helper.rb +38 -0
- metadata +166 -43
- data/bin/lockitron +0 -32
- data/lib/lockitron/authentication.rb +0 -26
- data/lib/lockitron/lockitron.rb +0 -67
- data/lib/lockitron/locks.rb +0 -66
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0246c86899da0c2aef15c8eabd4de799cddcf17a
|
4
|
+
data.tar.gz: eb8954188083b4be0f7f219fc0388f357c4f78c6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 959d22f19aca2ddda63f8e4b1675adf1ea75e8e3041d0bb2c1a28eef1ba39c27d4de32e6de02a505ba6155c8625b3396a123096cb0ec4d20056ab0e14e9bc928
|
7
|
+
data.tar.gz: 7017e0f1361f7431796cc5cc167e441cfae3c8d8c3d6bc8ec9c144fdf2546d3b14c9560af206453bc7878079d26082d0c3bc5f3cf40db42aaf346e16c9a7ada9
|
data/.document
ADDED
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0-p195
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
File without changes
|
data/{LICENSE → LICENSE.txt}
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2013 Kurt Nelson
|
2
2
|
|
3
3
|
MIT License
|
4
4
|
|
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
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.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,79 +1,60 @@
|
|
1
|
-
#
|
2
|
-
[
|
1
|
+
#Lockitron
|
2
|
+
[![Build Status](https://secure.travis-ci.org/kurtisnelson/lockitron.png)](http://travis-ci.org/kurtisnelson/lockitron)
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/lockitron.png)](http://badge.fury.io/rb/lockitron)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/kurtisnelson/lockitron.png)](https://codeclimate.com/github/kurtisnelson/lockitron)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/kurtisnelson/lockitron/badge.png?branch=master)](https://coveralls.io/r/kurtisnelson/lockitron)
|
6
|
+
[![Dependency Status](https://gemnasium.com/kurtisnelson/lockitron.png)](https://gemnasium.com/kurtisnelson/lockitron)
|
7
|
+
[Documentation](http://rubydoc.info/gems/lockitron/)
|
3
8
|
|
4
|
-
|
9
|
+
Communicates with the [Lockitron API](http://api.lockitron.com)
|
5
10
|
|
6
|
-
##
|
11
|
+
##Usage
|
7
12
|
|
8
|
-
|
13
|
+
`gem install lockitron`
|
9
14
|
|
10
|
-
|
11
|
-
To use the Lockitron gem or as a shell script, you'll need to set an access token. You can set it in Ruby or in bash, and it'll work either way. Although, I recommend that you set the access token as an environment variable. I've shown how to do that below
|
15
|
+
If you don't have an OAuth2 token already for the user of your app
|
12
16
|
|
13
|
-
|
17
|
+
``ruby
|
18
|
+
auther = Lockitron::Auth.new(client_id: 'YOUR_OAUTH_CLIENT_ID', client_secret: 'YOUR_OAUTH_CLIENT_SECRET', redirect_uri: 'URI_FOR_CODE')
|
19
|
+
auther.authorization_url #Send your user to this URL to authenticate your app
|
20
|
+
auther.token_from_code 'code parameter on the redirect uri'
|
21
|
+
auther.token # Store this, it is your token
|
22
|
+
``
|
14
23
|
|
15
|
-
|
16
|
-
```bash
|
17
|
-
echo "export LOCKITRON_ACCESS_TOKEN=MY_ACCESS_TOKEN" >> ~/.bashrc && exec $SHELL
|
18
|
-
```
|
24
|
+
To use, you will want a User object
|
19
25
|
|
20
|
-
|
26
|
+
`user = Lockitron::User('user oauth token')`
|
21
27
|
|
22
|
-
|
23
|
-
Lockitron::Locks.access_token = MY_ACCESS_TOKEN
|
24
|
-
```
|
28
|
+
Get all the user's locks
|
25
29
|
|
26
|
-
|
27
|
-
You can lock or unlock your Lockitron-powered locks, and list the available locks.
|
30
|
+
`locks = user.locks`
|
28
31
|
|
29
|
-
|
32
|
+
This returns an array of Lock objects, which have a name and uuid method to find the one you want.
|
30
33
|
|
31
|
-
|
34
|
+
Then to actually do something
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
``ruby
|
37
|
+
lock.as user do |l|
|
38
|
+
l.unlock
|
39
|
+
end
|
40
|
+
``
|
36
41
|
|
37
|
-
|
42
|
+
For more examples, check the request tests in spec/request or the documentation.
|
38
43
|
|
39
|
-
|
40
|
-
|
41
|
-
|
44
|
+
##Contributing to lockitron
|
45
|
+
|
46
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
47
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
48
|
+
* Fork the project.
|
49
|
+
* Start a feature/bugfix branch.
|
50
|
+
* Commit and push until you are happy with your contribution.
|
51
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
52
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
42
53
|
|
43
|
-
|
54
|
+
If you want messages from Faraday, set DEBUG in your environment to true.
|
44
55
|
|
45
|
-
|
46
|
-
|
47
|
-
```bash
|
48
|
-
lockitron list
|
49
|
-
```
|
50
|
-
|
51
|
-
###
|
52
|
-
|
53
|
-
## Usage (Ruby)
|
54
|
-
|
55
|
-
You can lock or unlock your locks by their name.
|
56
|
-
|
57
|
-
### Locking & Unlocking
|
58
|
-
|
59
|
-
To unlock by name, run:
|
60
|
-
|
61
|
-
```ruby
|
62
|
-
Lockitron::Locks.unlock("Lock Name")
|
63
|
-
```
|
64
|
-
|
65
|
-
To lock by name, run:
|
66
|
-
|
67
|
-
```ruby
|
68
|
-
Lockitron::Locks.lock("Lock Name")
|
69
|
-
```
|
70
|
-
|
71
|
-
### Listing Locks
|
72
|
-
|
73
|
-
To list all available locks, run:
|
74
|
-
|
75
|
-
```ruby
|
76
|
-
Lockitron::Locks.list
|
77
|
-
```
|
56
|
+
##Copyright
|
78
57
|
|
58
|
+
Copyright (c) 2012 Kurt Nelson. See LICENSE.txt for
|
59
|
+
further details.
|
79
60
|
|
data/Rakefile
CHANGED
data/lib/lockitron.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
module Lockitron
|
3
|
+
class Auth
|
4
|
+
def initialize(params = {})
|
5
|
+
@client_id = params[:client_id]
|
6
|
+
@client_secret = params[:client_secret]
|
7
|
+
@redirect_uri = params[:redirect_uri]
|
8
|
+
@oauth_client = OAuth2::Client.new(@client_id, @client_secret, site: API_ENDPOINT)
|
9
|
+
@oauth_client.options[:token_url] = "/v1/oauth/token"
|
10
|
+
end
|
11
|
+
|
12
|
+
def token_from_code auth_code
|
13
|
+
@token = @oauth_client.auth_code.get_token(auth_code, redirect_uri: @redirect_uri)
|
14
|
+
end
|
15
|
+
|
16
|
+
def token
|
17
|
+
@token.token
|
18
|
+
end
|
19
|
+
|
20
|
+
def authorization_url
|
21
|
+
"#{Lockitron::API_ENDPOINT}/oauth/authorize?client_id=#{@client_id}&response_type=code&redirect_uri=#{@redirect_uri}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Lockitron
|
2
|
+
class Lock
|
3
|
+
attr_reader :name
|
4
|
+
attr_reader :uuid
|
5
|
+
|
6
|
+
# Initializes a lock from a Lockitron JSON representation
|
7
|
+
# @param [Hash] JSON
|
8
|
+
# @return [Lockitron::Lock]
|
9
|
+
def self.from_json blob
|
10
|
+
id = blob['id']
|
11
|
+
name = blob['name']
|
12
|
+
self.new(name: name, uuid: id)
|
13
|
+
end
|
14
|
+
|
15
|
+
# A lock
|
16
|
+
# @param [Hash] options
|
17
|
+
# @options params [String] UUID (Required)
|
18
|
+
# @options params [String] Name
|
19
|
+
def initialize(params={})
|
20
|
+
@uuid = params[:uuid]
|
21
|
+
@name = params[:name]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Takes a block of actions to perform as user
|
25
|
+
# @param user [Lockitron::User]
|
26
|
+
def as user
|
27
|
+
@user = user
|
28
|
+
yield self
|
29
|
+
@user = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Sets up the user context
|
33
|
+
# @param user [Lockitron::User]
|
34
|
+
def insert_key user
|
35
|
+
@user = user
|
36
|
+
end
|
37
|
+
|
38
|
+
# Tears down the user context
|
39
|
+
def remove_key
|
40
|
+
@user = nil
|
41
|
+
end
|
42
|
+
|
43
|
+
# Locks this lock
|
44
|
+
# @note Must be performed in user context
|
45
|
+
# @return [Hash] API response
|
46
|
+
def lock
|
47
|
+
require_user
|
48
|
+
@user.post "locks/#{@uuid}/lock"
|
49
|
+
end
|
50
|
+
|
51
|
+
# Unlocks this lock
|
52
|
+
# @note Must be performed in user context
|
53
|
+
# @return [Hash] API response
|
54
|
+
def unlock
|
55
|
+
require_user
|
56
|
+
@user.post "locks/#{@uuid}/unlock"
|
57
|
+
end
|
58
|
+
|
59
|
+
# Invites a user to this lock.
|
60
|
+
# @note Must be performed in user context
|
61
|
+
#
|
62
|
+
# @param [Hash] Options
|
63
|
+
# @options params [String] :phone
|
64
|
+
# @options params [String] :email
|
65
|
+
# @options params [String] :role Defaults to guest
|
66
|
+
# @options params [String] :fullname
|
67
|
+
# @options params [Time] :start Optional key start time
|
68
|
+
# @options params [Time] :expiration Optional key stop time
|
69
|
+
# @return [Hash] API response
|
70
|
+
def invite(params={})
|
71
|
+
require_user
|
72
|
+
params[:role] ||= 'guest'
|
73
|
+
raise InvalidArgument, "Phone or email required" unless params[:email] or params[:phone]
|
74
|
+
if params[:start]
|
75
|
+
params[:start] = params[:start].to_i
|
76
|
+
else
|
77
|
+
params[:start] = Time.now.to_i
|
78
|
+
end
|
79
|
+
params[:expiration] = params[:expiration].to_i if params[:expiration]
|
80
|
+
@user.post "locks/#{@uuid}/add", params
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
def require_user
|
85
|
+
raise InvalidArgument, "Not in user context" unless @user
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'json'
|
2
|
+
require_relative 'lock'
|
3
|
+
module Lockitron
|
4
|
+
class User
|
5
|
+
def initialize token
|
6
|
+
@token = token
|
7
|
+
end
|
8
|
+
|
9
|
+
def locks
|
10
|
+
get('locks').map {|lock| Lockitron::Lock.from_json lock['lock']}
|
11
|
+
end
|
12
|
+
|
13
|
+
def get action
|
14
|
+
resp = Faraday.get "#{API_ENDPOINT}/#{action}", {access_token: @token}
|
15
|
+
process resp
|
16
|
+
end
|
17
|
+
def post action, params = {}
|
18
|
+
params.merge!({access_token: @token})
|
19
|
+
resp = Faraday.post "#{API_ENDPOINT}/#{action}", params
|
20
|
+
process resp
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def process resp
|
25
|
+
raise "Not authorized" if resp.status == 403
|
26
|
+
raise "Bad API Request: #{resp.status}" unless resp.status == 200
|
27
|
+
data = JSON.parse resp.body
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/lockitron/version.rb
CHANGED
data/lockitron.gemspec
CHANGED
@@ -1,20 +1,40 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'lockitron/version'
|
3
5
|
|
4
|
-
Gem::Specification.new do |
|
5
|
-
|
6
|
-
|
7
|
-
gem.license = "MIT"
|
8
|
-
gem.summary = %Q{Lock and unlock your lock your Lockitron-powered locks from bash and Ruby}
|
9
|
-
gem.description = %Q{Lockitron lets you unlock your front door from anywhere in the world, including your smartphone. We have an iPhone app, an Android app, a webapp, a mobile web app, a REST API, and now, a RubyGem.}
|
10
|
-
gem.email = "jarred@lockitron.com"
|
11
|
-
gem.authors = ["Jarred Sumner"]
|
12
|
-
gem.add_dependency 'rest-client'
|
13
|
-
gem.add_dependency 'thor'
|
14
|
-
gem.add_dependency 'json'
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "lockitron"
|
8
|
+
s.version = Lockitron::VERSION
|
15
9
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
s.authors = ["Kurt Nelson"]
|
11
|
+
s.date = "2013-06-22"
|
12
|
+
s.description = "Communicate with a Lockitron"
|
13
|
+
s.email = "kurtisnelson@gmail.com"
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"LICENSE.txt",
|
16
|
+
"README.md"
|
17
|
+
]
|
18
|
+
s.homepage = "http://github.com/kurtisnelson/lockitron"
|
19
|
+
s.licenses = ["MIT"]
|
20
|
+
s.rubygems_version = "1.8.24"
|
21
|
+
s.summary = "Access the Lockitron API"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split($/)
|
24
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
25
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
|
28
|
+
s.add_dependency 'faraday', ">= 0.8.4"
|
29
|
+
s.add_dependency 'hashie'
|
30
|
+
s.add_dependency 'oauth2'
|
31
|
+
s.add_development_dependency 'rspec', ">= 2.8.0"
|
32
|
+
s.add_development_dependency 'rdoc', ">= 3.12"
|
33
|
+
s.add_development_dependency 'bundler', ">= 1.0.0"
|
34
|
+
s.add_development_dependency 'dotenv'
|
35
|
+
s.add_development_dependency 'coveralls'
|
36
|
+
s.add_development_dependency 'pry'
|
37
|
+
s.add_development_dependency 'vcr'
|
38
|
+
s.add_development_dependency 'webmock'
|
20
39
|
end
|
40
|
+
|
@@ -0,0 +1,101 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://api.lockitron.com/v1/locks/a397ef51-7b33-46dd-9a96-53eb1a7ea07f/add
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: email=someone%40example.com&role=guest&start=1372028005&access_token=<OAUTH_TOKEN>
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.8.7
|
12
|
+
Content-Type:
|
13
|
+
- application/x-www-form-urlencoded
|
14
|
+
Accept-Encoding:
|
15
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
16
|
+
Accept:
|
17
|
+
- '*/*'
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Date:
|
24
|
+
- Sun, 23 Jun 2013 22:52:18 GMT
|
25
|
+
Server:
|
26
|
+
- Apache
|
27
|
+
X-Ua-Compatible:
|
28
|
+
- IE=Edge,chrome=1
|
29
|
+
Etag:
|
30
|
+
- '"1b8915afe54cbed95ed2e53529d49aee"'
|
31
|
+
Cache-Control:
|
32
|
+
- max-age=0, private, must-revalidate
|
33
|
+
X-Request-Id:
|
34
|
+
- 18e6903a65af48755c9e3711e1ee0e26
|
35
|
+
X-Runtime:
|
36
|
+
- '1.318250'
|
37
|
+
X-Rack-Cache:
|
38
|
+
- invalidate, pass
|
39
|
+
Status:
|
40
|
+
- '200'
|
41
|
+
Strict-Transport-Security:
|
42
|
+
- max-age=15768000
|
43
|
+
Content-Length:
|
44
|
+
- '383'
|
45
|
+
Content-Type:
|
46
|
+
- application/json; charset=utf-8
|
47
|
+
body:
|
48
|
+
encoding: UTF-8
|
49
|
+
string: '{"id":"7f02c05a-b94d-4c5a-814e-3bb5a07603b9","start":null,"expire":null,"lock_id":"a397ef51-7b33-46dd-9a96-53eb1a7ea07f","role":"guest","valid":true,"visible":true,"user":{"id":"41d0322d-b03d-4eef-935b-904e05831496","email":"someone@example.com","phone":null,"human_phone":null,"first_name":null,"last_name":null,"full_name":null,"best_name":"someone@example.com","activated":false}}'
|
50
|
+
http_version:
|
51
|
+
recorded_at: Sun, 23 Jun 2013 22:53:27 GMT
|
52
|
+
- request:
|
53
|
+
method: post
|
54
|
+
uri: https://api.lockitron.com/v1/locks/a397ef51-7b33-46dd-9a96-53eb1a7ea07f/add
|
55
|
+
body:
|
56
|
+
encoding: US-ASCII
|
57
|
+
string: email=someone2%40example.com&start=1372031207&role=guest&access_token=<OAUTH_TOKEN>
|
58
|
+
headers:
|
59
|
+
User-Agent:
|
60
|
+
- Faraday v0.8.7
|
61
|
+
Content-Type:
|
62
|
+
- application/x-www-form-urlencoded
|
63
|
+
Accept-Encoding:
|
64
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
65
|
+
Accept:
|
66
|
+
- '*/*'
|
67
|
+
response:
|
68
|
+
status:
|
69
|
+
code: 200
|
70
|
+
message: OK
|
71
|
+
headers:
|
72
|
+
Date:
|
73
|
+
- Sun, 23 Jun 2013 22:52:19 GMT
|
74
|
+
Server:
|
75
|
+
- Apache
|
76
|
+
X-Ua-Compatible:
|
77
|
+
- IE=Edge,chrome=1
|
78
|
+
Etag:
|
79
|
+
- '"95b36bd88e1fb7dcb089e1535bee7815"'
|
80
|
+
Cache-Control:
|
81
|
+
- max-age=0, private, must-revalidate
|
82
|
+
X-Request-Id:
|
83
|
+
- 4f18fb69a1be7b921bc49b97e5756bfb
|
84
|
+
X-Runtime:
|
85
|
+
- '1.410540'
|
86
|
+
X-Rack-Cache:
|
87
|
+
- invalidate, pass
|
88
|
+
Status:
|
89
|
+
- '200'
|
90
|
+
Strict-Transport-Security:
|
91
|
+
- max-age=15768000
|
92
|
+
Content-Length:
|
93
|
+
- '395'
|
94
|
+
Content-Type:
|
95
|
+
- application/json; charset=utf-8
|
96
|
+
body:
|
97
|
+
encoding: UTF-8
|
98
|
+
string: '{"id":"402d031d-21be-4442-9bbb-2ce07ccf84b0","start":-18864896400.0,"expire":null,"lock_id":"a397ef51-7b33-46dd-9a96-53eb1a7ea07f","role":"guest","valid":true,"visible":true,"user":{"id":"40d877eb-03f4-4d66-b631-80f3d54fd832","email":"someone2@example.com","phone":null,"human_phone":null,"first_name":null,"last_name":null,"full_name":null,"best_name":"someone2@example.com","activated":false}}'
|
99
|
+
http_version:
|
100
|
+
recorded_at: Sun, 23 Jun 2013 22:53:29 GMT
|
101
|
+
recorded_with: VCR 2.5.0
|