pebblebed 0.0.22 → 0.0.23
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.
- data/README.md +7 -0
- data/lib/pebblebed/security/access_data.rb +85 -0
- data/lib/pebblebed/security/client.rb +33 -0
- data/lib/pebblebed/security/listener.rb +94 -0
- data/lib/pebblebed/uid.rb +6 -4
- data/lib/pebblebed/version.rb +1 -1
- data/lib/pebblebed.rb +3 -0
- data/spec/security/access_data_spec.rb +40 -0
- data/spec/security/client_spec.rb +29 -0
- data/spec/security/listener_spec.rb +26 -0
- metadata +109 -29
data/README.md
CHANGED
@@ -152,3 +152,10 @@ For some pebbles Pebblebed may furnish a richer client with helper methods. This
|
|
152
152
|
augmented client in the `/lib/pebblebed/clients` folder and naming the class `Pebblebed::<YourPebbleName>Client`. For
|
153
153
|
an example of this see `CheckpointClient` which in addition to the common http-methods provides the method `me` which
|
154
154
|
returns the logged in user and `god?` which checks whether she's a god(dess).
|
155
|
+
|
156
|
+
Troubleshooting
|
157
|
+
===============
|
158
|
+
|
159
|
+
When something fails, say you're trying to post to grove using a pebblebed connector, it might be a good idea to try the same thing from command line first:
|
160
|
+
|
161
|
+
curl -XPOST 'http://example.com/api/grove/v1/posts/post.todo:dna.org.a.b' --data '{"session":"session_name","post":{"document": {"body": "Hello Grove!"},"tags": ["welcome", "tutorial"]}}' -H "Content-Type: application/json"
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Models the checkpoint group access data for one identity
|
2
|
+
module Pebblebed
|
3
|
+
module Security
|
4
|
+
class AccessData
|
5
|
+
attr_reader :group_ids
|
6
|
+
|
7
|
+
def initialize(data)
|
8
|
+
if data[:subtrees] || data[:group_ids]
|
9
|
+
@group_ids = Set.new(data[:group_ids])
|
10
|
+
@subtrees = Set.new
|
11
|
+
data[:subtrees].each do |subtree|
|
12
|
+
@subtrees << subtree.split('.')
|
13
|
+
end
|
14
|
+
else
|
15
|
+
# Assume this is a /identities/:id/memberships result from checkpoint
|
16
|
+
parse_checkpoint_record(data)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Takes a path (possibly with wildcards) and returns
|
21
|
+
# any subtrees that are relevant to determine accessibility
|
22
|
+
# to restricted content in a query of documents in that
|
23
|
+
# wildcard_path. All relevant subtrees are guaranteed to be
|
24
|
+
# returned, but not all returned subtrees are guaranteed to be
|
25
|
+
# relevant. I.e. some irrelevant subtrees may be returned.
|
26
|
+
# (If the path does not use wildcards, relevance is
|
27
|
+
# guaranteed.)
|
28
|
+
def relevant_subtrees(wildcard_path)
|
29
|
+
pristine = self.class.pristine_path(wildcard_path)
|
30
|
+
intersecting_subtrees(pristine)
|
31
|
+
end
|
32
|
+
|
33
|
+
def subtrees
|
34
|
+
@subtrees.map { |subtree| subtree.join('.') }
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# Takes a path possibly containing wildcard characters and returns
|
40
|
+
# a superset path that just contains proper labels. E.g. "a.b.c|d.*" returns
|
41
|
+
# "a.b"
|
42
|
+
def self.pristine_path(wildcard_path)
|
43
|
+
result = []
|
44
|
+
wildcard_path.split('.').each do |label|
|
45
|
+
break unless Pebblebed::Uid.valid_label?(label)
|
46
|
+
result << label
|
47
|
+
end
|
48
|
+
result.join('.')
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns any subtrees that "intersect" the provided location. That is
|
52
|
+
# they are either supersets of the location ("a.b" is a superset of "a.b.c")
|
53
|
+
# or subsets ("a.b.c.d" is a subset of "a.b.c"). Also exact matches are returned
|
54
|
+
# ('a.b.c' matches 'a.b.c', duh!)
|
55
|
+
def intersecting_subtrees(location)
|
56
|
+
location = location.split('.')
|
57
|
+
result = []
|
58
|
+
@subtrees.each do |subtree|
|
59
|
+
if subtree.length >= location.length
|
60
|
+
# is this a subset tree?
|
61
|
+
result << subtree if location == subtree[0...location.length]
|
62
|
+
else
|
63
|
+
# is this a superset tree?
|
64
|
+
result << subtree if subtree == location[0...subtree.length]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
result.map { |subtree| subtree.join('.') }
|
68
|
+
end
|
69
|
+
|
70
|
+
# Initializes the instance with data from a checkpoint GET /identities/:id/memberships request
|
71
|
+
def parse_checkpoint_record(memberships_record)
|
72
|
+
@group_ids = Set.new
|
73
|
+
@subtrees = Set.new
|
74
|
+
memberships_record['memberships'].each do |membership|
|
75
|
+
@group_ids << membership['membership']['group_id']
|
76
|
+
end
|
77
|
+
memberships_record['groups'].each do |group|
|
78
|
+
group['group']['subtrees'].each do |subtree|
|
79
|
+
@subtrees << subtree.split('.')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# A class that helps
|
2
|
+
module Pebblebed
|
3
|
+
module Security
|
4
|
+
class Client
|
5
|
+
IDENTITY_MEMBERSHIPS_TTL = 10*60
|
6
|
+
|
7
|
+
def initialize(connector)
|
8
|
+
@connector = connector
|
9
|
+
@access_data = {} # Memoized identity access data records
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns an object representing the current access data for a given identity
|
13
|
+
def access_data_for(identity)
|
14
|
+
identity = identity.id unless identity.is_a?(Numeric)
|
15
|
+
return @access_data[identity] if @access_data[identity]
|
16
|
+
membership_data = fetch_membership_data_for(identity)
|
17
|
+
result = Pebblebed::Security::AccessData.new(membership_data)
|
18
|
+
@access_data[identity] = result
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def fetch_membership_data_for(identity_id)
|
25
|
+
result = Pebblebed.memcached.fetch("identity_membership_data:#{identity}", IDENTITY_MEMBERSHIPS_TTL) do
|
26
|
+
@connector.checkpoint.get("/identities/#{identity}/memberships").to_json
|
27
|
+
end
|
28
|
+
JSON.parse(result)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# Listens to security configuration updates and lets the client application
|
2
|
+
# register custom handlers for each event.
|
3
|
+
module Pebblebed
|
4
|
+
module Security
|
5
|
+
class Listener
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@app_name = options[:app_name]
|
9
|
+
@handlers = {:group => {}, :group_membership => {}, :group_subtree => {}}
|
10
|
+
end
|
11
|
+
|
12
|
+
def start
|
13
|
+
@thread ||= Thread.new do
|
14
|
+
process
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def stop
|
19
|
+
@thread.kill if @thread
|
20
|
+
@thread = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_group_declared(&block)
|
24
|
+
@handlers[:group][:create] = block
|
25
|
+
@handlers[:group][:update] = block
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_group_removed(&block)
|
29
|
+
@handlers[:group][:delete] = block
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_subtree_declared(&block)
|
33
|
+
@handlers[:group_subtree][:create] = block
|
34
|
+
@handlers[:group_subtree][:update] = block
|
35
|
+
end
|
36
|
+
|
37
|
+
def on_subtree_removed(&block)
|
38
|
+
@handlers[:group_subtree][:delete] = block
|
39
|
+
end
|
40
|
+
|
41
|
+
def on_membership_declared(&block)
|
42
|
+
@handlers[:group_membership][:create] = block
|
43
|
+
@handlers[:group_membership][:update] = block
|
44
|
+
end
|
45
|
+
|
46
|
+
def on_membership_removed(&block)
|
47
|
+
@handlers[:group_membership][:delete] = block
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Subscribe to queue and handle incoming messages
|
53
|
+
def process
|
54
|
+
river = Pebblebed::River.new
|
55
|
+
queue_options = {
|
56
|
+
:name => "#{@app_name}.security_listener",
|
57
|
+
:path => '**',
|
58
|
+
:klass => 'group|group_membership|group_subtree',
|
59
|
+
:event => '**',
|
60
|
+
:interval => 1
|
61
|
+
}
|
62
|
+
queue = river.queue queue_options
|
63
|
+
queue.subscribe(ack: true) do |message|
|
64
|
+
consider message
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Parse an incoming message and pass it on
|
69
|
+
def consider(message)
|
70
|
+
payload = JSON.parse(message[:payload])
|
71
|
+
event = payload['event']
|
72
|
+
attributes = payload['attributes']
|
73
|
+
klass = Pebblebed::Uid.raw_parse(payload['uid']).first
|
74
|
+
handle(event, klass, attributes)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Determines the correct event handler for the message and calls it
|
78
|
+
def handle(event, klass, attributes)
|
79
|
+
event_handler = @handlers[klass.to_sym][event.to_sym]
|
80
|
+
return unless event_handler
|
81
|
+
case klass
|
82
|
+
when 'group'
|
83
|
+
event_handler.call(:id => attributes['id'], :label => attributes['label'])
|
84
|
+
when 'group_membership'
|
85
|
+
event_handler.call(:group_id => attributes['group_id'],
|
86
|
+
:identity_id => attributes['identity_id'])
|
87
|
+
when 'group_subtree'
|
88
|
+
event_handler.call(:group_id => attributes['group_id'],
|
89
|
+
:location => attributes['location'])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/pebblebed/uid.rb
CHANGED
@@ -116,29 +116,31 @@ module Pebblebed
|
|
116
116
|
stars_are_solitary?(path) && pipes_are_interleaved?(path) && carets_are_leading?(path) && stars_are_terminating?(path)
|
117
117
|
end
|
118
118
|
|
119
|
-
# a.*.c is
|
119
|
+
# a.*.c is accepted
|
120
120
|
# a.*b.c is not
|
121
|
+
# A later rule ensures that * always falls at the end of a path
|
121
122
|
def stars_are_solitary?(path)
|
122
123
|
!path.split('.').any? {|s| s.match(/.+\*|\*.+/)}
|
123
124
|
end
|
124
125
|
|
125
|
-
# a.b|c.d is
|
126
|
+
# a.b|c.d is accepted
|
126
127
|
# a.|b.c is not
|
127
128
|
def pipes_are_interleaved?(path)
|
128
129
|
!path.split('.').any? {|s| s.match(/^\||\|$/)}
|
129
130
|
end
|
130
131
|
|
131
|
-
# a.^b.c is
|
132
|
+
# a.^b.c is accepted
|
132
133
|
# a.b^c.d is not
|
133
134
|
def carets_are_leading?(path)
|
134
135
|
!path.split('.').any? {|s| s.match(/.+\^|\^$/) }
|
135
136
|
end
|
136
137
|
|
137
|
-
# a.b.* is
|
138
|
+
# a.b.* is accepted
|
138
139
|
# *.b.c is not
|
139
140
|
def stars_are_terminating?(path)
|
140
141
|
path !~ /.*\*\.\w/
|
141
142
|
end
|
143
|
+
|
142
144
|
end
|
143
145
|
end
|
144
146
|
|
data/lib/pebblebed/version.rb
CHANGED
data/lib/pebblebed.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pebblebed/uid'
|
3
|
+
require 'pebblebed/security/access_data'
|
4
|
+
|
5
|
+
describe Pebblebed::Security::AccessData do
|
6
|
+
let :access_data do
|
7
|
+
Pebblebed::Security::AccessData.new(
|
8
|
+
:groups => [1,2,3],
|
9
|
+
:subtrees => ['a.b', 'a.b.c.d.e', 'a.c.d', 'a.c.e.f']
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can calculate a pristine path" do
|
14
|
+
Pebblebed::Security::AccessData.pristine_path("a.b.c|d").should eq "a.b"
|
15
|
+
Pebblebed::Security::AccessData.pristine_path("a.b").should eq "a.b"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "can calculate relevant paths" do
|
19
|
+
access_data.relevant_subtrees('a.b').sort.should eq ['a.b', 'a.b.c.d.e']
|
20
|
+
access_data.relevant_subtrees('a.b.c').sort.should eq ['a.b', 'a.b.c.d.e']
|
21
|
+
access_data.relevant_subtrees('a.c.e').sort.should eq ['a.c.e.f']
|
22
|
+
access_data.relevant_subtrees('a.*').sort.should eq ['a.b', 'a.b.c.d.e', 'a.c.d', 'a.c.e.f']
|
23
|
+
end
|
24
|
+
|
25
|
+
it "can parse a checkpoint record" do
|
26
|
+
record = {
|
27
|
+
'memberships' => [
|
28
|
+
{'membership' => {'id' => 10, 'group_id' => 1, 'identity_id' => 1}},
|
29
|
+
{'membership' => {'id' => 20, 'group_id' => 2, 'identity_id' => 1}},
|
30
|
+
],
|
31
|
+
'groups' => [
|
32
|
+
{'group' => {'id' => 1, 'label' => "group_1", 'subtrees' => ["a.b.c"]}},
|
33
|
+
{'group' => {'id' => 2, 'label' => "group_2", 'subtrees' => ["a.c.d.c"]}}
|
34
|
+
]
|
35
|
+
}
|
36
|
+
ad = Pebblebed::Security::AccessData.new(record)
|
37
|
+
ad.subtrees.sort.should eq ['a.b.c', 'a.c.d.c']
|
38
|
+
ad.group_ids.sort.should eq [1,2]
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pebblebed/uid'
|
3
|
+
require 'pebblebed/security/access_data'
|
4
|
+
require 'pebblebed/security/client'
|
5
|
+
|
6
|
+
describe Pebblebed::Security::Client do
|
7
|
+
let :client do
|
8
|
+
Pebblebed::Security::Client.new(nil)
|
9
|
+
end
|
10
|
+
|
11
|
+
let :sample_memberships_record do
|
12
|
+
{
|
13
|
+
'memberships' => [
|
14
|
+
{'membership' => {'id' => 10, 'group_id' => 1, 'identity_id' => 1}},
|
15
|
+
{'membership' => {'id' => 20, 'group_id' => 2, 'identity_id' => 1}},
|
16
|
+
],
|
17
|
+
'groups' => [
|
18
|
+
{'group' => {'id' => 1, 'label' => "group_1", 'subtrees' => ["a.b.c"]}},
|
19
|
+
{'group' => {'id' => 2, 'label' => "group_2", 'subtrees' => ["a.c.d.c"]}}
|
20
|
+
]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can fetch access_data" do
|
25
|
+
client.stub(:fetch_membership_data_for).and_return(sample_memberships_record)
|
26
|
+
ad = client.access_data_for(1)
|
27
|
+
ad.subtrees.sort.should eq ['a.b.c', 'a.c.d.c']
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pebblebed/uid'
|
3
|
+
require 'pebblebed/security/listener'
|
4
|
+
|
5
|
+
describe Pebblebed::Security::Listener do
|
6
|
+
let :listener do
|
7
|
+
Pebblebed::Security::Listener.new(:app_name => "test")
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can generate events from incoming messages" do
|
11
|
+
the_attrs = nil
|
12
|
+
listener.on_group_declared do |attrs|
|
13
|
+
the_attrs = attrs
|
14
|
+
end
|
15
|
+
message = {:payload => {
|
16
|
+
'event' => 'create',
|
17
|
+
'uid' => 'group:abc.groups$10',
|
18
|
+
'attributes' => {
|
19
|
+
'id' => 10,
|
20
|
+
'label' => 'the_label'
|
21
|
+
}
|
22
|
+
}.to_json}
|
23
|
+
listener.send(:consider, message)
|
24
|
+
the_attrs[:id].should eq 10
|
25
|
+
end
|
26
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pebblebed
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.23
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-09-
|
13
|
+
date: 2012-09-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
17
|
-
requirement:
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,15 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements:
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
26
31
|
- !ruby/object:Gem::Dependency
|
27
32
|
name: rake
|
28
|
-
requirement:
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
29
34
|
none: false
|
30
35
|
requirements:
|
31
36
|
- - ! '>='
|
@@ -33,10 +38,15 @@ dependencies:
|
|
33
38
|
version: '0'
|
34
39
|
type: :development
|
35
40
|
prerelease: false
|
36
|
-
version_requirements:
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
37
47
|
- !ruby/object:Gem::Dependency
|
38
48
|
name: simplecov
|
39
|
-
requirement:
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
40
50
|
none: false
|
41
51
|
requirements:
|
42
52
|
- - ! '>='
|
@@ -44,10 +54,15 @@ dependencies:
|
|
44
54
|
version: '0'
|
45
55
|
type: :development
|
46
56
|
prerelease: false
|
47
|
-
version_requirements:
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
48
63
|
- !ruby/object:Gem::Dependency
|
49
64
|
name: deepstruct
|
50
|
-
requirement:
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
51
66
|
none: false
|
52
67
|
requirements:
|
53
68
|
- - ! '>='
|
@@ -55,10 +70,15 @@ dependencies:
|
|
55
70
|
version: 0.0.2
|
56
71
|
type: :runtime
|
57
72
|
prerelease: false
|
58
|
-
version_requirements:
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 0.0.2
|
59
79
|
- !ruby/object:Gem::Dependency
|
60
80
|
name: curb
|
61
|
-
requirement:
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
62
82
|
none: false
|
63
83
|
requirements:
|
64
84
|
- - ! '>='
|
@@ -66,10 +86,15 @@ dependencies:
|
|
66
86
|
version: 0.7.14
|
67
87
|
type: :runtime
|
68
88
|
prerelease: false
|
69
|
-
version_requirements:
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 0.7.14
|
70
95
|
- !ruby/object:Gem::Dependency
|
71
96
|
name: yajl-ruby
|
72
|
-
requirement:
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
73
98
|
none: false
|
74
99
|
requirements:
|
75
100
|
- - ! '>='
|
@@ -77,10 +102,15 @@ dependencies:
|
|
77
102
|
version: '0'
|
78
103
|
type: :runtime
|
79
104
|
prerelease: false
|
80
|
-
version_requirements:
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
81
111
|
- !ruby/object:Gem::Dependency
|
82
112
|
name: queryparams
|
83
|
-
requirement:
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
84
114
|
none: false
|
85
115
|
requirements:
|
86
116
|
- - ! '>='
|
@@ -88,10 +118,15 @@ dependencies:
|
|
88
118
|
version: '0'
|
89
119
|
type: :runtime
|
90
120
|
prerelease: false
|
91
|
-
version_requirements:
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
92
127
|
- !ruby/object:Gem::Dependency
|
93
128
|
name: futurevalue
|
94
|
-
requirement:
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
95
130
|
none: false
|
96
131
|
requirements:
|
97
132
|
- - ! '>='
|
@@ -99,10 +134,15 @@ dependencies:
|
|
99
134
|
version: '0'
|
100
135
|
type: :runtime
|
101
136
|
prerelease: false
|
102
|
-
version_requirements:
|
137
|
+
version_requirements: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
103
143
|
- !ruby/object:Gem::Dependency
|
104
144
|
name: pathbuilder
|
105
|
-
requirement:
|
145
|
+
requirement: !ruby/object:Gem::Requirement
|
106
146
|
none: false
|
107
147
|
requirements:
|
108
148
|
- - ! '>='
|
@@ -110,10 +150,15 @@ dependencies:
|
|
110
150
|
version: '0'
|
111
151
|
type: :runtime
|
112
152
|
prerelease: false
|
113
|
-
version_requirements:
|
153
|
+
version_requirements: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
155
|
+
requirements:
|
156
|
+
- - ! '>='
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
114
159
|
- !ruby/object:Gem::Dependency
|
115
160
|
name: nokogiri
|
116
|
-
requirement:
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
117
162
|
none: false
|
118
163
|
requirements:
|
119
164
|
- - ! '>='
|
@@ -121,10 +166,15 @@ dependencies:
|
|
121
166
|
version: '0'
|
122
167
|
type: :runtime
|
123
168
|
prerelease: false
|
124
|
-
version_requirements:
|
169
|
+
version_requirements: !ruby/object:Gem::Requirement
|
170
|
+
none: false
|
171
|
+
requirements:
|
172
|
+
- - ! '>='
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '0'
|
125
175
|
- !ruby/object:Gem::Dependency
|
126
176
|
name: i18n
|
127
|
-
requirement:
|
177
|
+
requirement: !ruby/object:Gem::Requirement
|
128
178
|
none: false
|
129
179
|
requirements:
|
130
180
|
- - ! '>='
|
@@ -132,10 +182,15 @@ dependencies:
|
|
132
182
|
version: '0'
|
133
183
|
type: :runtime
|
134
184
|
prerelease: false
|
135
|
-
version_requirements:
|
185
|
+
version_requirements: !ruby/object:Gem::Requirement
|
186
|
+
none: false
|
187
|
+
requirements:
|
188
|
+
- - ! '>='
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: '0'
|
136
191
|
- !ruby/object:Gem::Dependency
|
137
192
|
name: activesupport
|
138
|
-
requirement:
|
193
|
+
requirement: !ruby/object:Gem::Requirement
|
139
194
|
none: false
|
140
195
|
requirements:
|
141
196
|
- - ! '>='
|
@@ -143,10 +198,15 @@ dependencies:
|
|
143
198
|
version: '0'
|
144
199
|
type: :runtime
|
145
200
|
prerelease: false
|
146
|
-
version_requirements:
|
201
|
+
version_requirements: !ruby/object:Gem::Requirement
|
202
|
+
none: false
|
203
|
+
requirements:
|
204
|
+
- - ! '>='
|
205
|
+
- !ruby/object:Gem::Version
|
206
|
+
version: '0'
|
147
207
|
- !ruby/object:Gem::Dependency
|
148
208
|
name: bunny
|
149
|
-
requirement:
|
209
|
+
requirement: !ruby/object:Gem::Requirement
|
150
210
|
none: false
|
151
211
|
requirements:
|
152
212
|
- - ! '>='
|
@@ -154,7 +214,12 @@ dependencies:
|
|
154
214
|
version: '0'
|
155
215
|
type: :runtime
|
156
216
|
prerelease: false
|
157
|
-
version_requirements:
|
217
|
+
version_requirements: !ruby/object:Gem::Requirement
|
218
|
+
none: false
|
219
|
+
requirements:
|
220
|
+
- - ! '>='
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
158
223
|
description: Development tools for working with Pebblebed
|
159
224
|
email:
|
160
225
|
- katrina@bengler.no
|
@@ -180,6 +245,9 @@ files:
|
|
180
245
|
- lib/pebblebed/parts.rb
|
181
246
|
- lib/pebblebed/river.rb
|
182
247
|
- lib/pebblebed/river/subscription.rb
|
248
|
+
- lib/pebblebed/security/access_data.rb
|
249
|
+
- lib/pebblebed/security/client.rb
|
250
|
+
- lib/pebblebed/security/listener.rb
|
183
251
|
- lib/pebblebed/sinatra.rb
|
184
252
|
- lib/pebblebed/uid.rb
|
185
253
|
- lib/pebblebed/uid_query.rb
|
@@ -194,6 +262,9 @@ files:
|
|
194
262
|
- spec/mockcached.rb
|
195
263
|
- spec/river_spec.rb
|
196
264
|
- spec/river_subscription_spec.rb
|
265
|
+
- spec/security/access_data_spec.rb
|
266
|
+
- spec/security/client_spec.rb
|
267
|
+
- spec/security/listener_spec.rb
|
197
268
|
- spec/spec_helper.rb
|
198
269
|
- spec/uid_query_spec.rb
|
199
270
|
- spec/uid_spec.rb
|
@@ -209,15 +280,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
209
280
|
- - ! '>='
|
210
281
|
- !ruby/object:Gem::Version
|
211
282
|
version: '0'
|
283
|
+
segments:
|
284
|
+
- 0
|
285
|
+
hash: 4364516963973573943
|
212
286
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
213
287
|
none: false
|
214
288
|
requirements:
|
215
289
|
- - ! '>='
|
216
290
|
- !ruby/object:Gem::Version
|
217
291
|
version: '0'
|
292
|
+
segments:
|
293
|
+
- 0
|
294
|
+
hash: 4364516963973573943
|
218
295
|
requirements: []
|
219
296
|
rubyforge_project: pebblebed
|
220
|
-
rubygems_version: 1.8.
|
297
|
+
rubygems_version: 1.8.24
|
221
298
|
signing_key:
|
222
299
|
specification_version: 3
|
223
300
|
summary: Development tools for working with Pebblebed
|
@@ -231,6 +308,9 @@ test_files:
|
|
231
308
|
- spec/mockcached.rb
|
232
309
|
- spec/river_spec.rb
|
233
310
|
- spec/river_subscription_spec.rb
|
311
|
+
- spec/security/access_data_spec.rb
|
312
|
+
- spec/security/client_spec.rb
|
313
|
+
- spec/security/listener_spec.rb
|
234
314
|
- spec/spec_helper.rb
|
235
315
|
- spec/uid_query_spec.rb
|
236
316
|
- spec/uid_spec.rb
|