philote 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.env.sample +3 -3
- data/.gems +1 -0
- data/.gitignore +1 -2
- data/README.md +73 -0
- data/lib/philote.rb +111 -3
- data/lib/philote/version.rb +1 -1
- data/test/access_key_test.rb +45 -0
- metadata +4 -3
- data/lib/philote/admin.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83d0f685634d24a1933c7b4f1b24f8f2522b75de
|
4
|
+
data.tar.gz: b35d3bbfa5239de1afdf3494ba7568fa8be9fadf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 981e71e46ee073dea63e67f1d5d0dca72ef3afcd8c46a1ca08561ecf426f1ea59be43c12bf9ef193195b282892082b72fba8e88a8b5eb0189b499e90e83d7d47
|
7
|
+
data.tar.gz: 2a0dd3137c8da5ea54e9331350deaa8701bd3ab25ea8f030dff9b9857dd3a19d04c8e6f7af18a29627c83d179dbe7b168366fa3166f0f9bdb918b811c9748b87
|
data/.env.sample
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# vim: ft=sh
|
2
|
-
export GEM_HOME="$PWD/.
|
2
|
+
export GEM_HOME="$PWD/.dependencies"
|
3
3
|
export GEM_BIN="$GEM_HOME/bin"
|
4
|
+
export RUBYLIB="$PWD/lib":"$RUBYLIB"
|
4
5
|
export PATH="$GEM_BIN":"$PATH"
|
5
6
|
|
6
|
-
export
|
7
|
-
export QUEUES="test_medium"
|
7
|
+
export REDIS_TEST_URL="redis://localhost:6379/9"
|
data/.gems
CHANGED
data/.gitignore
CHANGED
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# philote.rb
|
2
|
+
|
3
|
+
This is a helper library for [Philote](https://github.com/13Floor/philote), a [Redis](http://redis.io)-powered websockets server.
|
4
|
+
|
5
|
+
You don't really need this library: philote takes configuration from the Redis database it uses, so you are perfectly capable of create philote access tokens yourself and storing them in redis, however, this library makes it easier for you to do so.
|
6
|
+
|
7
|
+
## Early Stages
|
8
|
+
|
9
|
+
This library is still on very early stages, it does something extremely simple so bugs are generally not expected, but functionality like subscribing to channels and reacting to incoming messages is not yet implemented, if you use Philote for anything and feel like contributing that would be a great way to do it. :)
|
10
|
+
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
### Redis Connection
|
15
|
+
|
16
|
+
By default, Philote connects to Redis using the `REDIS_URL` environment variable, if you want to connect in a different way you can specify the redis client in code when you initialize your application.
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
|
20
|
+
require 'redic'
|
21
|
+
require 'philote'
|
22
|
+
|
23
|
+
Philote.redis = Redic.new('redis://localhost:6379')
|
24
|
+
```
|
25
|
+
|
26
|
+
### Access Keys
|
27
|
+
|
28
|
+
In order to connect to Philote, a websocket client will need an [access key](https://github.com/pote/philote#access-keys), you can create them via `Philote::AccessKey#create`, here's the method signature:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
class AccessKey
|
32
|
+
# read:
|
33
|
+
# an array of channel names the key user will be subscribed to.
|
34
|
+
#
|
35
|
+
# write:
|
36
|
+
# an array of channel names the key user will be able to write to.
|
37
|
+
#
|
38
|
+
# allowed_uses:
|
39
|
+
# the ammount of times a new websocket client will be able to authenticate
|
40
|
+
# using this access key.
|
41
|
+
#
|
42
|
+
# uses:
|
43
|
+
# the ammount of times a new websocket client has authenticated using this
|
44
|
+
# access key.
|
45
|
+
#
|
46
|
+
# token:
|
47
|
+
# the redis identifier.
|
48
|
+
#
|
49
|
+
def initialize(read: [], write: [], allowed_uses: 1, uses: 0, token: nil)
|
50
|
+
# ...
|
51
|
+
end
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
After you create an access key, a client will be able to authenticate in the Philote server running on the same Redis instance, `Philote::AccessKey#token` will contain the identifier, on a regular browser javascript use case you'll render your view with access to this token.
|
56
|
+
|
57
|
+
### Publishing Messages
|
58
|
+
|
59
|
+
As Philote uses Redis PUB/SUB under the hood, as long as your Ruby code has access to the same Redis instance you can publish messages to the websocket channels simply by publishing those messages to Redis, this library provides a helper method to do that.
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
Philote.publish('channel-name', 'data')
|
63
|
+
```
|
64
|
+
|
65
|
+
## Run the test suite
|
66
|
+
|
67
|
+
Here's how to set up the local/test environment:
|
68
|
+
|
69
|
+
```bash
|
70
|
+
$ git clone git@github.com:pote/philote-rb.git && cd philote-rb
|
71
|
+
$ source .env.sample # Make sure to review the settings, as the REDIS_TEST_URL gets flushed when running the test suite.
|
72
|
+
$ make test
|
73
|
+
```
|
data/lib/philote.rb
CHANGED
@@ -7,10 +7,118 @@ module Philote
|
|
7
7
|
@redis ||= Redic.new
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.redis=(
|
11
|
-
@redis =
|
10
|
+
def self.redis=(client)
|
11
|
+
@redis = client
|
12
12
|
end
|
13
|
+
|
14
|
+
def self.prefix
|
15
|
+
@prefix ||= 'philote'
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.prefix=(p)
|
19
|
+
@prefix = p
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.publish(channel, data)
|
23
|
+
redis.call('PUBLISH', channel, data)
|
24
|
+
end
|
25
|
+
|
26
|
+
class AccessKey
|
27
|
+
attr_accessor :read, :write, :allowed_uses, :uses, :token
|
28
|
+
|
29
|
+
|
30
|
+
# read:
|
31
|
+
# an array of channel names the key user will be subscribed to.
|
32
|
+
#
|
33
|
+
# write:
|
34
|
+
# an array of channel names the key user will be able to write to.
|
35
|
+
#
|
36
|
+
# allowed_uses:
|
37
|
+
# the ammount of times a new websocket client will be able to authenticate
|
38
|
+
# using this access key.
|
39
|
+
#
|
40
|
+
# uses:
|
41
|
+
# the ammount of times a new websocket client has authenticated using this
|
42
|
+
# access key.
|
43
|
+
#
|
44
|
+
# token:
|
45
|
+
# the redis identifier.
|
46
|
+
#
|
47
|
+
def initialize(read: [], write: [], allowed_uses: 1, uses: 0, token: nil)
|
48
|
+
@token = token || SecureRandom.urlsafe_base64
|
49
|
+
@read = read
|
50
|
+
@write = write
|
51
|
+
@allowed_uses = allowed_uses
|
52
|
+
@uses = uses
|
53
|
+
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_json
|
58
|
+
self.to_h.to_json
|
59
|
+
end
|
60
|
+
|
61
|
+
def save
|
62
|
+
Philote.redis.call('SET', "#{ Philote.prefix }:access_key:#{ token }", self.to_json)
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_h
|
66
|
+
{
|
67
|
+
read: read,
|
68
|
+
write: write,
|
69
|
+
allowed_uses: allowed_uses,
|
70
|
+
uses: uses
|
71
|
+
}
|
72
|
+
end
|
73
|
+
alias_method :to_hash, :to_h
|
74
|
+
|
75
|
+
|
76
|
+
def self.create(**args)
|
77
|
+
key = self.new(**args)
|
78
|
+
key.save
|
79
|
+
|
80
|
+
return key
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.load!(token)
|
84
|
+
raw_key = Philote.redis.call('GET', "philote:access_key:#{ token }")
|
85
|
+
raise NonExistantAccessKey if raw_key.nil?
|
86
|
+
|
87
|
+
begin
|
88
|
+
parsed_key_attributes = JSON.parse(raw_key)
|
89
|
+
rescue => exception
|
90
|
+
raise UnparsableAccessKeyData.new(exception)
|
91
|
+
end
|
92
|
+
|
93
|
+
begin
|
94
|
+
key_attributes = {
|
95
|
+
read: parsed_key_attributes.fetch('read'),
|
96
|
+
write: parsed_key_attributes.fetch('write'),
|
97
|
+
allowed_uses: parsed_key_attributes.fetch('allowed_uses'),
|
98
|
+
uses: parsed_key_attributes.fetch('uses'),
|
99
|
+
token: token
|
100
|
+
}
|
101
|
+
rescue => exception
|
102
|
+
raise InsufficientAccessKeyData.new(exception)
|
103
|
+
end
|
104
|
+
|
105
|
+
return self.new(key_attributes)
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.load(token)
|
109
|
+
begin
|
110
|
+
key = self.load!(token)
|
111
|
+
return key
|
112
|
+
rescue => exception
|
113
|
+
return nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class Error < StandardError; end
|
119
|
+
class NonExistantAccessKey < Error; end
|
120
|
+
class UnparsableAccessKeyData < Error; end
|
121
|
+
class InsufficientAccessKeyData < Error; end
|
13
122
|
end
|
14
123
|
|
15
124
|
require_relative 'philote/version'
|
16
|
-
require_relative 'philote/admin'
|
data/lib/philote/version.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'cutest'
|
2
|
+
require 'philote'
|
3
|
+
|
4
|
+
|
5
|
+
setup {
|
6
|
+
Philote.redis = Redic.new(ENV.fetch('REDIS_TEST_URL'))
|
7
|
+
}
|
8
|
+
|
9
|
+
at_exit {
|
10
|
+
Redic.new(ENV.fetch('REDIS_TEST_URL')).call('FLUSHDB')
|
11
|
+
}
|
12
|
+
|
13
|
+
test 'client should have a functioning redis connection' do
|
14
|
+
assert_equal 'PONG', Philote.redis.call('PING')
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'creating an access key creates a token with sensible defaults' do
|
18
|
+
access_key = Philote::AccessKey.create
|
19
|
+
|
20
|
+
assert_equal [], access_key.read
|
21
|
+
assert_equal [], access_key.write
|
22
|
+
assert_equal 1, access_key.allowed_uses
|
23
|
+
assert_equal 0, access_key.uses
|
24
|
+
assert !access_key.token.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
test 'loading an access key works' do
|
28
|
+
access_key = Philote::AccessKey.create(
|
29
|
+
read: %w(mychannel), write: %w(mychannel), allowed_uses: 5, uses: 3)
|
30
|
+
|
31
|
+
assert_equal %w(mychannel), access_key.read
|
32
|
+
assert_equal %w(mychannel), access_key.write
|
33
|
+
assert_equal 5, access_key.allowed_uses
|
34
|
+
assert_equal 3, access_key.uses
|
35
|
+
|
36
|
+
access_key = Philote::AccessKey.load(access_key.token)
|
37
|
+
|
38
|
+
assert !access_key.nil?
|
39
|
+
assert access_key.is_a?(Philote::AccessKey)
|
40
|
+
assert_equal %w(mychannel), access_key.read
|
41
|
+
assert_equal %w(mychannel), access_key.write
|
42
|
+
assert_equal 5, access_key.allowed_uses
|
43
|
+
assert_equal 3, access_key.uses
|
44
|
+
assert !access_key.token.nil?
|
45
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: philote
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pote
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-06-
|
11
|
+
date: 2016-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redic
|
@@ -37,10 +37,11 @@ files:
|
|
37
37
|
- CONTRIBUTING.md
|
38
38
|
- LICENSE
|
39
39
|
- Makefile
|
40
|
+
- README.md
|
40
41
|
- lib/philote.rb
|
41
|
-
- lib/philote/admin.rb
|
42
42
|
- lib/philote/version.rb
|
43
43
|
- philote.gemspec
|
44
|
+
- test/access_key_test.rb
|
44
45
|
homepage: https://github.com/pote/philote-rb
|
45
46
|
licenses:
|
46
47
|
- MIT
|
data/lib/philote/admin.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
module Philote::Admin
|
2
|
-
def self.create_token(read: [], write: [], allowed_uses: 1)
|
3
|
-
permissions = {
|
4
|
-
read: read,
|
5
|
-
write: write,
|
6
|
-
allowed_uses: allowed_uses,
|
7
|
-
uses: 0
|
8
|
-
}
|
9
|
-
|
10
|
-
token = SecureRandom.urlsafe_base64
|
11
|
-
|
12
|
-
Philote.redis.call('SET', "philote:access_key:#{token}", permissions.to_json )
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.publish(channel, message)
|
16
|
-
Philote.redis.call('PUBLISH', channel, message )
|
17
|
-
end
|
18
|
-
end
|