bumbleworks 0.0.69 → 0.0.70
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/bumbleworks.rb +1 -0
- data/lib/bumbleworks/configuration.rb +4 -4
- data/lib/bumbleworks/ruote/exp/broadcast_event_expression.rb +4 -1
- data/lib/bumbleworks/ruote/exp/wait_for_event_expression.rb +4 -1
- data/lib/bumbleworks/support/flow_expression.rb +18 -0
- data/lib/bumbleworks/user.rb +91 -0
- data/lib/bumbleworks/version.rb +1 -1
- data/spec/lib/bumbleworks/ruote/exp/broadcast_event_expression_spec.rb +16 -0
- data/spec/lib/bumbleworks/ruote/exp/wait_for_event_expression_spec.rb +17 -0
- data/spec/lib/bumbleworks/user_spec.rb +152 -0
- metadata +8 -4
data/lib/bumbleworks.rb
CHANGED
@@ -299,10 +299,10 @@ module Bumbleworks
|
|
299
299
|
|
300
300
|
def framework_root
|
301
301
|
case
|
302
|
-
when defined?(Rails) then Rails.root
|
303
|
-
when defined?(Rory) then Rory.root
|
304
|
-
when defined?(Padrino) then Padrino.root
|
305
|
-
when defined?(Sinatra::Application) then Sinatra::Application.root
|
302
|
+
when defined?(::Rails) then ::Rails.root
|
303
|
+
when defined?(::Rory) then ::Rory.root
|
304
|
+
when defined?(::Padrino) then ::Padrino.root
|
305
|
+
when defined?(::Sinatra::Application) then ::Sinatra::Application.root
|
306
306
|
end
|
307
307
|
end
|
308
308
|
|
@@ -1,12 +1,15 @@
|
|
1
1
|
require 'ruote/exp/flow_expression'
|
2
|
+
require 'bumbleworks/support/flow_expression'
|
2
3
|
|
3
4
|
module Ruote::Exp
|
4
5
|
class BroadcastEventExpression < FlowExpression
|
6
|
+
include Bumbleworks::Support::FlowExpression
|
7
|
+
|
5
8
|
names :broadcast_event
|
6
9
|
|
7
10
|
def consider_tag
|
8
11
|
update_tree
|
9
|
-
h.updated_tree[1]['tag'] =
|
12
|
+
h.updated_tree[1]['tag'] = tag_from_attribute
|
10
13
|
super
|
11
14
|
end
|
12
15
|
|
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'ruote/exp/flow_expression'
|
2
2
|
require 'ruote/exp/fe_await'
|
3
|
+
require 'bumbleworks/support/flow_expression'
|
3
4
|
|
4
5
|
module Ruote::Exp
|
5
6
|
class WaitForEventExpression < AwaitExpression
|
7
|
+
include Bumbleworks::Support::FlowExpression
|
8
|
+
|
6
9
|
names :wait_for_event
|
7
10
|
|
8
11
|
# This does the same as the base AwaitExpression#apply, except that this
|
@@ -13,7 +16,7 @@ module Ruote::Exp
|
|
13
16
|
def apply
|
14
17
|
update_tree
|
15
18
|
h.updated_tree[1]['global'] = true
|
16
|
-
h.updated_tree[1]['left_tag'] =
|
19
|
+
h.updated_tree[1]['left_tag'] = tag_from_attribute
|
17
20
|
h.updated_tree[1]['merge'] = 'drop'
|
18
21
|
super
|
19
22
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Bumbleworks
|
2
|
+
module Support
|
3
|
+
module FlowExpression
|
4
|
+
def tag_from_attribute
|
5
|
+
tag = attribute_text.to_s
|
6
|
+
if h.updated_tree[1]['for_entity'].to_s == 'true'
|
7
|
+
workitem_fields = h.applied_workitem['fields']
|
8
|
+
entity_type, entity_id = workitem_fields.values_at('entity_type', 'entity_id')
|
9
|
+
if entity_type && entity_id
|
10
|
+
entity_tag = "#{Bumbleworks::Support.tokenize(entity_type)}_#{entity_id}"
|
11
|
+
tag += "__for_entity__#{entity_tag}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
tag
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Bumbleworks
|
2
|
+
module User
|
3
|
+
class NoRoleIdentifiersMethodDefined < StandardError; end
|
4
|
+
class NoClaimTokenMethodDefined < StandardError; end
|
5
|
+
class MissingRoleQueryMethod < StandardError; end
|
6
|
+
class AmbiguousRoleQueryMethod < StandardError; end
|
7
|
+
class UnauthorizedClaimAttempt < StandardError; end
|
8
|
+
class UnauthorizedReleaseAttempt < StandardError; end
|
9
|
+
|
10
|
+
# The return value from this method is used as the "claimant" token on
|
11
|
+
# tasks, both for claiming a task and for checking if the user is the
|
12
|
+
# current claimant.
|
13
|
+
#
|
14
|
+
# By default, claim_token will first check for `username`, then `email`, and
|
15
|
+
# finally raise an exception if neither method exists. Including classes
|
16
|
+
# should override this method if using something other than username or
|
17
|
+
# email (or if both respond, but email should be preferred).
|
18
|
+
def claim_token
|
19
|
+
[:username, :email].each do |token_method|
|
20
|
+
return send(token_method) if respond_to?(token_method)
|
21
|
+
end
|
22
|
+
raise NoClaimTokenMethodDefined,
|
23
|
+
"If your user class does not respond to :username or :email, define a `claim_token` method"
|
24
|
+
end
|
25
|
+
|
26
|
+
# The return value from this method is used when determining which tasks in
|
27
|
+
# the queue this user should be authorized for. Must return an array of
|
28
|
+
# strings.
|
29
|
+
def role_identifiers
|
30
|
+
raise NoRoleIdentifiersMethodDefined,
|
31
|
+
"Define a `role_identifiers` method that returns an array of role names"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns true if the array returned by #role_identifiers includes the given
|
35
|
+
# name. Can be used to determine authority to perform actions on a task,
|
36
|
+
# for example.
|
37
|
+
def has_role?(role_name)
|
38
|
+
role_identifiers.include? role_name
|
39
|
+
end
|
40
|
+
|
41
|
+
# Attempts to set self as the claimant of the given task. If not authorized
|
42
|
+
# to claim the task, raises exception. Also bubbles exception from Task
|
43
|
+
# when task is already claimed by a different claimant.
|
44
|
+
def claim(task)
|
45
|
+
raise UnauthorizedClaimAttempt unless has_role?(task.role)
|
46
|
+
task.claim(claim_token)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Same as #claim, but first releases (by force) the task, to avoid any
|
50
|
+
# possible UnauthorizedClaimAttempt or AlreadyClaimed exceptions. Should
|
51
|
+
# only be made available to supervisory roles.
|
52
|
+
def claim!(task)
|
53
|
+
release!(task)
|
54
|
+
claim(task)
|
55
|
+
end
|
56
|
+
|
57
|
+
# If we are the current claimant of the given task, release the task. Does
|
58
|
+
# nothing if the task is not claimed, but raises exception if the task is
|
59
|
+
# currently claimed by someone else.
|
60
|
+
def release(task, force = false)
|
61
|
+
return unless task.claimed?
|
62
|
+
raise UnauthorizedReleaseAttempt unless force || task.claimant == claim_token
|
63
|
+
task.release
|
64
|
+
end
|
65
|
+
|
66
|
+
# Same as #release, but releases the task even if we're not the current
|
67
|
+
# claimant. Allows an administrator, for example, to wrench a task away
|
68
|
+
# from an employee who is lagging. Should only be made available to
|
69
|
+
# supervisory roles.
|
70
|
+
def release!(task)
|
71
|
+
release(task, true)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns Task::Finder instance filtered by roles assigned to this user.
|
75
|
+
def authorized_tasks
|
76
|
+
Bumbleworks::Task.for_roles(role_identifiers)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns Task::Finder instance filtered by user roles and availability
|
80
|
+
# (unclaimed and completable).
|
81
|
+
def available_tasks
|
82
|
+
authorized_tasks.available
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns Task::Finder instance filtered by claimant - only tasks this user
|
86
|
+
# has claimed (and not released or completed).
|
87
|
+
def claimed_tasks
|
88
|
+
Bumbleworks::Task.for_claimant(claim_token)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/bumbleworks/version.rb
CHANGED
@@ -21,4 +21,20 @@ describe Ruote::Exp::BroadcastEventExpression do
|
|
21
21
|
Bumbleworks.dashboard.wait_for(waiter.wfid)
|
22
22
|
@tracer.should == ['amazing']
|
23
23
|
end
|
24
|
+
|
25
|
+
it 'appends entity info to tag when :for_entity is true' do
|
26
|
+
Bumbleworks.define_process 'waiter' do
|
27
|
+
await :left_tag => :the_event__for_entity__pig_widget_15, :global => true
|
28
|
+
echo 'amazing'
|
29
|
+
end
|
30
|
+
|
31
|
+
Bumbleworks.define_process 'sender' do
|
32
|
+
broadcast_event :the_event, :for_entity => true
|
33
|
+
end
|
34
|
+
|
35
|
+
waiter = Bumbleworks.launch!('waiter')
|
36
|
+
sender = Bumbleworks.launch!('sender', :entity_type => 'PigWidget', :entity_id => 15)
|
37
|
+
Bumbleworks.dashboard.wait_for(waiter.wfid)
|
38
|
+
@tracer.should == ['amazing']
|
39
|
+
end
|
24
40
|
end
|
@@ -76,4 +76,21 @@ describe Ruote::Exp::WaitForEventExpression do
|
|
76
76
|
Bumbleworks.dashboard.wait_for(waiter3.wfid)
|
77
77
|
@tracer.should == ['entities! Rhubarb,spitpickle-4boof']
|
78
78
|
end
|
79
|
+
|
80
|
+
it 'appends entity info to expected tag when :for_entity is true' do
|
81
|
+
Bumbleworks.define_process 'waiter' do
|
82
|
+
wait_for_event :the_event, :for_entity => true
|
83
|
+
echo 'i found your tag, sucka'
|
84
|
+
end
|
85
|
+
|
86
|
+
Bumbleworks.define_process 'sender' do
|
87
|
+
noop :tag => 'the_event__for_entity__fun_face_yellow5'
|
88
|
+
end
|
89
|
+
|
90
|
+
waiter = Bumbleworks.launch!('waiter', 'entity_type' => 'FunFace', 'entity_id' => 'yellow5')
|
91
|
+
sender = Bumbleworks.launch!('sender')
|
92
|
+
|
93
|
+
Bumbleworks.dashboard.wait_for(waiter.wfid)
|
94
|
+
@tracer.should == ['i found your tag, sucka']
|
95
|
+
end
|
79
96
|
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
describe Bumbleworks::User do
|
2
|
+
let(:user_class) { Class.new { include Bumbleworks::User } }
|
3
|
+
let(:subject) { user_class.new }
|
4
|
+
|
5
|
+
describe '#claim_token' do
|
6
|
+
it 'returns username by default' do
|
7
|
+
subject.stub(:username => 'nerfobot')
|
8
|
+
subject.claim_token.should == 'nerfobot'
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'returns email if no username' do
|
12
|
+
subject.stub(:email => 'fromp@nougatcountry.com')
|
13
|
+
subject.claim_token.should == 'fromp@nougatcountry.com'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'prefers username to email when both respond' do
|
17
|
+
subject.stub(:username => 'dumb', :email => 'moar dumb')
|
18
|
+
subject.claim_token.should == 'dumb'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns nil if method defined' do
|
22
|
+
subject.stub(:username)
|
23
|
+
subject.claim_token.should be_nil
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'raises exception if neither username nor email defined' do
|
27
|
+
expect {
|
28
|
+
subject.claim_token
|
29
|
+
}.to raise_error(Bumbleworks::User::NoClaimTokenMethodDefined)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#claim' do
|
34
|
+
before(:each) do
|
35
|
+
subject.stub(:role_identifiers => ['snoogat'])
|
36
|
+
subject.stub(:claim_token => "the umpire of snorts")
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'claims a task if authorized' do
|
40
|
+
task = double('task', :role => 'snoogat')
|
41
|
+
task.should_receive(:claim).with("the umpire of snorts")
|
42
|
+
subject.claim(task)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'raises exception if unauthorized' do
|
46
|
+
task = double('task', :role => 'fashbone')
|
47
|
+
task.should_receive(:claim).never
|
48
|
+
expect {
|
49
|
+
subject.claim(task)
|
50
|
+
}.to raise_error(Bumbleworks::User::UnauthorizedClaimAttempt)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'raises exception if already claimed by another' do
|
54
|
+
task = double('task', :role => 'snoogat')
|
55
|
+
task.should_receive(:claim).and_raise(Bumbleworks::Task::AlreadyClaimed)
|
56
|
+
expect {
|
57
|
+
subject.claim(task)
|
58
|
+
}.to raise_error(Bumbleworks::Task::AlreadyClaimed)
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '!' do
|
62
|
+
it 'resets even if claimed by another' do
|
63
|
+
task = double('task', :role => 'snoogat', :claimed? => true, :claimant => 'fumbo the monfey')
|
64
|
+
task.should_receive(:release).ordered
|
65
|
+
task.should_receive(:claim).with("the umpire of snorts").ordered
|
66
|
+
subject.claim!(task)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#release' do
|
72
|
+
before(:each) do
|
73
|
+
subject.stub(:claim_token => "the umpire of snorts")
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'releases a claimed task if claimant' do
|
77
|
+
task = double('task', :claimed? => true, :claimant => "the umpire of snorts")
|
78
|
+
task.should_receive(:release)
|
79
|
+
subject.release(task)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'does nothing if task not claimed' do
|
83
|
+
task = double('task', :claimed? => false)
|
84
|
+
task.should_receive(:release).never
|
85
|
+
subject.release(task)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'raises exception if not claimant' do
|
89
|
+
task = double('task', :claimed? => true, :claimant => 'a castanet expert')
|
90
|
+
task.should_receive(:release).never
|
91
|
+
expect {
|
92
|
+
subject.release(task)
|
93
|
+
}.to raise_error(Bumbleworks::User::UnauthorizedReleaseAttempt)
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '!' do
|
97
|
+
it 'releases even if not claimant' do
|
98
|
+
task = double('task', :claimed? => true, :claimant => 'a castanet expert')
|
99
|
+
task.should_receive(:release)
|
100
|
+
subject.release!(task)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#role_identifiers' do
|
106
|
+
it 'raises exception by default' do
|
107
|
+
expect {
|
108
|
+
subject.role_identifiers
|
109
|
+
}.to raise_error(Bumbleworks::User::NoRoleIdentifiersMethodDefined)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#has_role?' do
|
114
|
+
before(:each) do
|
115
|
+
subject.stub(:role_identifiers => ['role1', 'role2'])
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'returns true if role_identifiers includes given role' do
|
119
|
+
subject.has_role?('role1').should be_true
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'returns false if role_identifiers does not include given role' do
|
123
|
+
subject.has_role?('role3').should be_false
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '#authorized_tasks' do
|
128
|
+
it 'returns task query for all tasks for user roles' do
|
129
|
+
subject.stub(:role_identifiers => ['goose', 'midget'])
|
130
|
+
Bumbleworks::Task.stub(:for_roles).with(['goose', 'midget']).and_return(:all_the_tasks)
|
131
|
+
subject.authorized_tasks.should == :all_the_tasks
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#claimed_tasks' do
|
136
|
+
it 'returns task query for all user claimed tasks' do
|
137
|
+
subject.stub(:claim_token => :yay_its_me)
|
138
|
+
Bumbleworks::Task.stub(:for_claimant).with(:yay_its_me).and_return(:my_tasks)
|
139
|
+
subject.claimed_tasks.should == :my_tasks
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#available_tasks' do
|
144
|
+
it 'returns authorized tasks filtered by available' do
|
145
|
+
subject.stub(:role_identifiers => ['goose', 'midget'])
|
146
|
+
task_finder = double('task_finder')
|
147
|
+
task_finder.stub(:available => :only_the_available_tasks)
|
148
|
+
Bumbleworks::Task.stub(:for_roles).with(['goose', 'midget']).and_return(task_finder)
|
149
|
+
subject.available_tasks.should == :only_the_available_tasks
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bumbleworks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.70
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2014-02-
|
15
|
+
date: 2014-02-19 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: ruote
|
@@ -187,11 +187,13 @@ files:
|
|
187
187
|
- lib/bumbleworks/simple_logger.rb
|
188
188
|
- lib/bumbleworks/storage_adapter.rb
|
189
189
|
- lib/bumbleworks/support.rb
|
190
|
+
- lib/bumbleworks/support/flow_expression.rb
|
190
191
|
- lib/bumbleworks/task.rb
|
191
192
|
- lib/bumbleworks/task/base.rb
|
192
193
|
- lib/bumbleworks/task/finder.rb
|
193
194
|
- lib/bumbleworks/tracker.rb
|
194
195
|
- lib/bumbleworks/tree_builder.rb
|
196
|
+
- lib/bumbleworks/user.rb
|
195
197
|
- lib/bumbleworks/version.rb
|
196
198
|
- lib/bumbleworks/workitem.rb
|
197
199
|
- lib/bumbleworks/workitem_entity_storage.rb
|
@@ -240,6 +242,7 @@ files:
|
|
240
242
|
- spec/lib/bumbleworks/task_spec.rb
|
241
243
|
- spec/lib/bumbleworks/tracker_spec.rb
|
242
244
|
- spec/lib/bumbleworks/tree_builder_spec.rb
|
245
|
+
- spec/lib/bumbleworks/user_spec.rb
|
243
246
|
- spec/lib/bumbleworks/workitem_entity_storage_spec.rb
|
244
247
|
- spec/lib/bumbleworks/workitem_spec.rb
|
245
248
|
- spec/lib/bumbleworks_spec.rb
|
@@ -263,7 +266,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
263
266
|
version: '0'
|
264
267
|
segments:
|
265
268
|
- 0
|
266
|
-
hash:
|
269
|
+
hash: -1442108325624690777
|
267
270
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
268
271
|
none: false
|
269
272
|
requirements:
|
@@ -272,7 +275,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
272
275
|
version: '0'
|
273
276
|
segments:
|
274
277
|
- 0
|
275
|
-
hash:
|
278
|
+
hash: -1442108325624690777
|
276
279
|
requirements: []
|
277
280
|
rubyforge_project:
|
278
281
|
rubygems_version: 1.8.23
|
@@ -324,6 +327,7 @@ test_files:
|
|
324
327
|
- spec/lib/bumbleworks/task_spec.rb
|
325
328
|
- spec/lib/bumbleworks/tracker_spec.rb
|
326
329
|
- spec/lib/bumbleworks/tree_builder_spec.rb
|
330
|
+
- spec/lib/bumbleworks/user_spec.rb
|
327
331
|
- spec/lib/bumbleworks/workitem_entity_storage_spec.rb
|
328
332
|
- spec/lib/bumbleworks/workitem_spec.rb
|
329
333
|
- spec/lib/bumbleworks_spec.rb
|