lita-locker 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -1
- data/README.md +5 -6
- data/Rakefile +1 -1
- data/TODO.md +5 -0
- data/lib/lita/handlers/locker.rb +91 -136
- data/lita-locker.gemspec +3 -3
- data/locales/en.yml +50 -31
- data/spec/lita/handlers/locker_spec.rb +135 -116
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 228a4b3898980e9de630cee8152cd4ea8104c830
|
4
|
+
data.tar.gz: fd299284bef188f5d7fee52c79c925c91b979187
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 078690a522779d50e1f8f5f83d3635bf401d26027cd68496a29b2f4472af7c444367df91e5c368d1def23b02946ff4f30cef6c67d1743b90f7442ccd13d526bf
|
7
|
+
data.tar.gz: 05fa9b743fa6a22e6c68e44d6f445cf143cb345c91c09fdad7fb959effc79299c36f3e91721e0b8123ab9af969197ee8595f011135bac98a6e0538dd8b9d485f
|
data/.rubocop.yml
CHANGED
@@ -5,7 +5,7 @@ ClassLength:
|
|
5
5
|
Max: 500
|
6
6
|
|
7
7
|
CyclomaticComplexity:
|
8
|
-
Max:
|
8
|
+
Max: 8
|
9
9
|
|
10
10
|
Documentation:
|
11
11
|
Exclude:
|
@@ -17,3 +17,10 @@ FileName:
|
|
17
17
|
|
18
18
|
MethodLength:
|
19
19
|
Max: 200
|
20
|
+
|
21
|
+
LineLength:
|
22
|
+
Max: 85
|
23
|
+
|
24
|
+
GuardClause:
|
25
|
+
Exclude:
|
26
|
+
- lib/lita/handlers/locker.rb
|
data/README.md
CHANGED
@@ -31,17 +31,16 @@ if all of the resources it uses are available.
|
|
31
31
|
### Examples
|
32
32
|
```
|
33
33
|
lock web - Make something unavailable to others
|
34
|
-
lock web 30m - Make something unavailable to others for 30 minutes
|
35
34
|
unlock web - Make something available to others
|
36
|
-
|
37
|
-
locker status
|
35
|
+
steal web - Make yourself the owner of something locked by someone else
|
36
|
+
locker status web - Show the current state of web
|
38
37
|
```
|
39
38
|
|
40
39
|
### Locking, Unlocking, State
|
41
40
|
```
|
42
|
-
lock <
|
43
|
-
unlock <
|
44
|
-
|
41
|
+
lock <label> - A basic reservation, with no time limit. Can have # comments afterwards.
|
42
|
+
unlock <label> - Remove a reservation. This can only be done by whomever made the request. Can have # comments afterwards.
|
43
|
+
steal <label> - Force removal of a reservation. This can be done by anyone. Can have # comments afterwards.
|
45
44
|
```
|
46
45
|
|
47
46
|
### Time-based locking - Not implemented yet!
|
data/Rakefile
CHANGED
data/TODO.md
ADDED
data/lib/lita/handlers/locker.rb
CHANGED
@@ -4,63 +4,53 @@ module Lita
|
|
4
4
|
http.get '/locker/label/:name', :http_label_show
|
5
5
|
http.get '/locker/resource/:name', :http_resource_show
|
6
6
|
|
7
|
-
LABEL_REGEX = /([\
|
8
|
-
RESOURCE_REGEX = /([
|
7
|
+
LABEL_REGEX = /([\.\w\s-]+)/
|
8
|
+
RESOURCE_REGEX = /([\.\w-]+)/
|
9
|
+
COMMENT_REGEX = /(\s\#.+)?/
|
9
10
|
|
10
11
|
route(
|
11
|
-
/^\(lock\)\s#{LABEL_REGEX}$/,
|
12
|
+
/^\(lock\)\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
|
12
13
|
:lock
|
13
14
|
)
|
14
15
|
|
15
16
|
route(
|
16
|
-
|
17
|
+
/^(?:\(unlock\)|\(release\))\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
|
17
18
|
:unlock
|
18
19
|
)
|
19
20
|
|
20
21
|
route(
|
21
|
-
/^lock\s#{LABEL_REGEX}$/,
|
22
|
+
/^lock\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
|
22
23
|
:lock,
|
23
24
|
command: true,
|
24
|
-
help: {
|
25
|
-
t('help.lock_key') => t('help.lock_value')
|
26
|
-
}
|
25
|
+
help: { t('help.lock.syntax') => t('help.lock.desc') }
|
27
26
|
)
|
28
27
|
|
29
|
-
# route(
|
30
|
-
# /^lock\s([a-zA-Z0-9_-]+)\s(\d+)(s|m|h)$/,
|
31
|
-
# :lock,
|
32
|
-
# command: true,
|
33
|
-
# help: {
|
34
|
-
# t('help.lock_time_key') => t('help.lock_time_value')
|
35
|
-
# }
|
36
|
-
# )
|
37
|
-
|
38
28
|
route(
|
39
|
-
/^unlock\s#{LABEL_REGEX}$/,
|
29
|
+
/^unlock\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
|
40
30
|
:unlock,
|
41
31
|
command: true,
|
42
|
-
help: {
|
43
|
-
t('help.unlock_key') => t('help.unlock_value')
|
44
|
-
}
|
32
|
+
help: { t('help.unlock.syntax') => t('help.unlock.desc') }
|
45
33
|
)
|
46
34
|
|
47
35
|
route(
|
48
|
-
/^
|
49
|
-
:
|
36
|
+
/^steal\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
|
37
|
+
:steal,
|
50
38
|
command: true,
|
51
|
-
help: {
|
52
|
-
|
53
|
-
|
39
|
+
help: { t('help.steal.syntax') => t('help.steal.desc') }
|
40
|
+
)
|
41
|
+
|
42
|
+
route(
|
43
|
+
/^locker\sstatus\s#{LABEL_REGEX}$/,
|
44
|
+
:status,
|
45
|
+
command: true,
|
46
|
+
help: { t('help.status.syntax') => t('help.status.desc') }
|
54
47
|
)
|
55
48
|
|
56
49
|
route(
|
57
50
|
/^locker\sresource\slist$/,
|
58
51
|
:resource_list,
|
59
52
|
command: true,
|
60
|
-
help: {
|
61
|
-
t('help.resource_list_key') =>
|
62
|
-
t('help.resource_list_value')
|
63
|
-
}
|
53
|
+
help: { t('help.resource.list.syntax') => t('help.resource.list.desc') }
|
64
54
|
)
|
65
55
|
|
66
56
|
route(
|
@@ -69,8 +59,7 @@ module Lita
|
|
69
59
|
command: true,
|
70
60
|
restrict_to: [:locker_admins],
|
71
61
|
help: {
|
72
|
-
t('help.
|
73
|
-
t('help.resource_create_value')
|
62
|
+
t('help.resource.create.syntax') => t('help.resource.create.desc')
|
74
63
|
}
|
75
64
|
)
|
76
65
|
|
@@ -80,8 +69,7 @@ module Lita
|
|
80
69
|
command: true,
|
81
70
|
restrict_to: [:locker_admins],
|
82
71
|
help: {
|
83
|
-
t('help.
|
84
|
-
t('help.resource_delete_value')
|
72
|
+
t('help.resource.delete.syntax') => t('help.resource.delete.desc')
|
85
73
|
}
|
86
74
|
)
|
87
75
|
|
@@ -89,178 +77,142 @@ module Lita
|
|
89
77
|
/^locker\sresource\sshow\s#{RESOURCE_REGEX}$/,
|
90
78
|
:resource_show,
|
91
79
|
command: true,
|
92
|
-
help: {
|
93
|
-
t('help.resource_show_key') =>
|
94
|
-
t('help.resource_show_value')
|
95
|
-
}
|
80
|
+
help: { t('help.resource.show.syntax') => t('help.resource.show.desc') }
|
96
81
|
)
|
97
82
|
|
98
83
|
route(
|
99
84
|
/^locker\slabel\slist$/,
|
100
85
|
:label_list,
|
101
86
|
command: true,
|
102
|
-
help: {
|
103
|
-
t('help.label_list_key') =>
|
104
|
-
t('help.label_list_value')
|
105
|
-
}
|
87
|
+
help: { t('help.label.list.syntax') => t('help.label.list.desc') }
|
106
88
|
)
|
107
89
|
|
108
90
|
route(
|
109
91
|
/^locker\slabel\screate\s#{LABEL_REGEX}$/,
|
110
92
|
:label_create,
|
111
93
|
command: true,
|
112
|
-
help: {
|
113
|
-
t('help.label_create_key') =>
|
114
|
-
t('help.label_create_value')
|
115
|
-
}
|
94
|
+
help: { t('help.label.create.syntax') => t('help.label.create.desc') }
|
116
95
|
)
|
117
96
|
|
118
97
|
route(
|
119
98
|
/^locker\slabel\sdelete\s#{LABEL_REGEX}$/,
|
120
99
|
:label_delete,
|
121
100
|
command: true,
|
122
|
-
help: {
|
123
|
-
t('help.label_delete_key') =>
|
124
|
-
t('help.label_delete_value')
|
125
|
-
}
|
101
|
+
help: { t('help.label.delete.syntax') => t('help.label.delete.desc') }
|
126
102
|
)
|
127
103
|
|
128
104
|
route(
|
129
105
|
/^locker\slabel\sshow\s#{LABEL_REGEX}$/,
|
130
106
|
:label_show,
|
131
107
|
command: true,
|
132
|
-
help: {
|
133
|
-
t('help.label_show_key') =>
|
134
|
-
t('help.label_show_value')
|
135
|
-
}
|
108
|
+
help: { t('help.label.show.syntax') => t('help.label.show.desc') }
|
136
109
|
)
|
137
110
|
|
138
111
|
route(
|
139
112
|
/^locker\slabel\sadd\s#{RESOURCE_REGEX}\sto\s#{LABEL_REGEX}$/,
|
140
113
|
:label_add,
|
141
114
|
command: true,
|
142
|
-
help: {
|
143
|
-
t('help.label_add_key') =>
|
144
|
-
t('help.label_add_value')
|
145
|
-
}
|
115
|
+
help: { t('help.label.add.syntax') => t('help.label.add.desc') }
|
146
116
|
)
|
147
117
|
|
148
118
|
route(
|
149
119
|
/^locker\slabel\sremove\s#{RESOURCE_REGEX}\sfrom\s#{LABEL_REGEX}$/,
|
150
120
|
:label_remove,
|
151
121
|
command: true,
|
152
|
-
help: {
|
153
|
-
t('help.label_remove_key') =>
|
154
|
-
t('help.label_remove_value')
|
155
|
-
}
|
122
|
+
help: { t('help.label.remove.syntax') => t('help.label.remove.desc') }
|
156
123
|
)
|
157
124
|
|
158
125
|
def http_label_show(request, response)
|
159
126
|
name = request.env['router.params'][:name]
|
160
127
|
response.headers['Content-Type'] = 'application/json'
|
161
|
-
|
162
|
-
response.write(result.to_json)
|
128
|
+
response.write(label(name).to_json)
|
163
129
|
end
|
164
130
|
|
165
131
|
def http_resource_show(request, response)
|
166
132
|
name = request.env['router.params'][:name]
|
167
133
|
response.headers['Content-Type'] = 'application/json'
|
168
|
-
|
169
|
-
response.write(result.to_json)
|
134
|
+
response.write(resource(name).to_json)
|
170
135
|
end
|
171
136
|
|
172
137
|
def lock(response)
|
173
138
|
name = response.matches[0][0]
|
174
|
-
timeamt = response.matches[0][1]
|
175
|
-
timeunit = response.matches[0][2]
|
176
|
-
case timeunit
|
177
|
-
when 's'
|
178
|
-
time_until = Time.now.utc + timeamt.to_i
|
179
|
-
when 'm'
|
180
|
-
time_until = Time.now.utc + (timeamt.to_i * 60)
|
181
|
-
when 'h'
|
182
|
-
time_until = Time.now.utc + (timeamt.to_i * 3600)
|
183
|
-
else
|
184
|
-
time_until = nil
|
185
|
-
end
|
186
139
|
|
187
|
-
if
|
188
|
-
if lock_resource!(name, response.user, time_until)
|
189
|
-
response.reply(t('resource.lock', name: name))
|
190
|
-
else
|
191
|
-
response.reply(t('resource.is_locked', name: name))
|
192
|
-
end
|
193
|
-
elsif label_exists?(name)
|
140
|
+
if label_exists?(name)
|
194
141
|
m = label_membership(name)
|
195
142
|
if m.count > 0
|
196
|
-
if lock_label!(name, response.user,
|
197
|
-
response.reply(t('label.lock', name: name))
|
143
|
+
if lock_label!(name, response.user, nil)
|
144
|
+
response.reply('(successful) ' + t('label.lock', name: name))
|
198
145
|
else
|
199
|
-
|
146
|
+
l = label(name)
|
147
|
+
if l['state'] == 'locked'
|
148
|
+
response.reply('(failed) ' + t('label.owned',
|
149
|
+
name: name,
|
150
|
+
owner_name: l['owner_name'],
|
151
|
+
owner_mention: l['owner_mention']))
|
152
|
+
else
|
153
|
+
response.reply('(failed) ' + t('label.dependency'))
|
154
|
+
end
|
200
155
|
end
|
201
156
|
else
|
202
|
-
response.reply(t('label.no_resources', name: name))
|
157
|
+
response.reply('(failed) ' + t('label.no_resources', name: name))
|
203
158
|
end
|
204
159
|
else
|
205
|
-
response.reply(t('
|
160
|
+
response.reply('(failed) ' + t('label.does_not_exist', name: name))
|
206
161
|
end
|
207
162
|
end
|
208
163
|
|
209
164
|
def unlock(response)
|
210
165
|
name = response.matches[0][0]
|
211
|
-
if
|
212
|
-
res = resource(name)
|
213
|
-
if res['state'] == 'unlocked'
|
214
|
-
response.reply(t('resource.is_unlocked', name: name))
|
215
|
-
else
|
216
|
-
# FIXME: NOT SECURE
|
217
|
-
if response.user.name == res['owner']
|
218
|
-
unlock_resource!(name)
|
219
|
-
response.reply(t('resource.unlock', name: name))
|
220
|
-
# FIXME: Handle the case where things can't be unlocked?
|
221
|
-
else
|
222
|
-
response.reply(t('resource.owned', name: name,
|
223
|
-
owner: res['owner']))
|
224
|
-
end
|
225
|
-
end
|
226
|
-
elsif label_exists?(name)
|
166
|
+
if label_exists?(name)
|
227
167
|
l = label(name)
|
228
168
|
if l['state'] == 'unlocked'
|
229
|
-
response.reply(t('label.is_unlocked',
|
169
|
+
response.reply('(successful) ' + t('label.is_unlocked',
|
170
|
+
name: name))
|
230
171
|
else
|
231
|
-
|
232
|
-
if response.user.name == l['owner']
|
172
|
+
if response.user.id == l['owner_id']
|
233
173
|
unlock_label!(name)
|
234
|
-
response.reply(t('label.unlock', name: name))
|
235
|
-
# FIXME: Handle the case where things can't be unlocked?
|
174
|
+
response.reply('(successful) ' + t('label.unlock', name: name))
|
236
175
|
else
|
237
|
-
response.reply(t('label.owned',
|
238
|
-
|
176
|
+
response.reply('(failed) ' + t('label.owned',
|
177
|
+
name: name,
|
178
|
+
owner_name: l['owner_name'],
|
179
|
+
owner_mention: l['owner_mention']))
|
239
180
|
end
|
240
181
|
end
|
241
182
|
else
|
242
|
-
response.reply(t('subject.does_not_exist', name: name))
|
183
|
+
response.reply('(failed) ' + t('subject.does_not_exist', name: name))
|
243
184
|
end
|
244
185
|
end
|
245
186
|
|
246
|
-
def
|
187
|
+
def steal(response)
|
247
188
|
name = response.matches[0][0]
|
248
|
-
if
|
249
|
-
unlock_resource!(name)
|
250
|
-
response.reply(t('resource.unlock', name: name))
|
251
|
-
# FIXME: Handle the case where things can't be unlocked?
|
252
|
-
elsif label_exists?(name)
|
189
|
+
if label_exists?(name)
|
253
190
|
unlock_label!(name)
|
254
|
-
response.reply(t('label.unlock', name: name))
|
191
|
+
response.reply('(successful) ' + t('label.unlock', name: name))
|
255
192
|
# FIXME: Handle the case where things can't be unlocked?
|
193
|
+
else
|
194
|
+
response.reply('(failed) ' + t('subject.does_not_exist', name: name))
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def status(response)
|
199
|
+
name = response.matches[0][0]
|
200
|
+
if label_exists?(name)
|
201
|
+
l = label(name)
|
202
|
+
response.reply(t('label.desc', name: name, state: l['state']))
|
203
|
+
elsif resource_exists?(name)
|
204
|
+
r = resource(name)
|
205
|
+
response.reply(t('resource.desc', name: name, state: r['state']))
|
256
206
|
else
|
257
207
|
response.reply(t('subject.does_not_exist', name: name))
|
258
208
|
end
|
259
209
|
end
|
260
210
|
|
261
211
|
def label_list(response)
|
262
|
-
labels.each do |
|
263
|
-
|
212
|
+
labels.each do |n|
|
213
|
+
name = n.sub('label_', '')
|
214
|
+
l = label(name)
|
215
|
+
response.reply(t('label.desc', name: name, state: l['state']))
|
264
216
|
end
|
265
217
|
end
|
266
218
|
|
@@ -336,11 +288,13 @@ module Lita
|
|
336
288
|
end
|
337
289
|
|
338
290
|
def resource_list(response)
|
291
|
+
output = ''
|
339
292
|
resources.each do |r|
|
340
293
|
r_name = r.sub('resource_', '')
|
341
294
|
res = resource(r_name)
|
342
|
-
|
295
|
+
output += t('resource.desc', name: r_name, state: res['state'])
|
343
296
|
end
|
297
|
+
response.reply(output)
|
344
298
|
end
|
345
299
|
|
346
300
|
def resource_create(response)
|
@@ -425,9 +379,10 @@ module Lita
|
|
425
379
|
value = redis.hget(resource_key, 'state')
|
426
380
|
if value == 'unlocked'
|
427
381
|
# FIXME: Race condition!
|
428
|
-
# FIXME: Store something better than name
|
429
382
|
redis.hset(resource_key, 'state', 'locked')
|
430
|
-
redis.hset(resource_key, '
|
383
|
+
redis.hset(resource_key, 'owner_id', owner.id)
|
384
|
+
redis.hset(resource_key, 'owner_name', owner.name)
|
385
|
+
redis.hset(resource_key, 'owner_mention', owner.mention_name)
|
431
386
|
redis.hset(resource_key, 'until', time_until)
|
432
387
|
true
|
433
388
|
else
|
@@ -443,15 +398,12 @@ module Lita
|
|
443
398
|
key = "label_#{name}"
|
444
399
|
members = label_membership(name)
|
445
400
|
members.each do |m|
|
446
|
-
|
447
|
-
return false if r['state'] == 'locked'
|
448
|
-
end
|
449
|
-
# FIXME: No, really, race condition.
|
450
|
-
members.each do |m|
|
451
|
-
lock_resource!(m, owner, time_until)
|
401
|
+
return false unless lock_resource!(m, owner, time_until)
|
452
402
|
end
|
453
403
|
redis.hset(key, 'state', 'locked')
|
454
|
-
redis.hset(key, '
|
404
|
+
redis.hset(key, 'owner_id', owner.id)
|
405
|
+
redis.hset(key, 'owner_name', owner.name)
|
406
|
+
redis.hset(key, 'owner_mention', owner.mention_name)
|
455
407
|
redis.hset(key, 'until', time_until)
|
456
408
|
true
|
457
409
|
else
|
@@ -461,10 +413,11 @@ module Lita
|
|
461
413
|
|
462
414
|
def unlock_resource!(name)
|
463
415
|
if resource_exists?(name)
|
464
|
-
# FIXME: Tracking here?
|
465
416
|
key = "resource_#{name}"
|
466
417
|
redis.hset(key, 'state', 'unlocked')
|
467
|
-
redis.hset(key, '
|
418
|
+
redis.hset(key, 'owner_name', '')
|
419
|
+
redis.hset(key, 'owner_mention', '')
|
420
|
+
redis.hset(key, 'owner_id', '')
|
468
421
|
else
|
469
422
|
false
|
470
423
|
end
|
@@ -478,7 +431,9 @@ module Lita
|
|
478
431
|
unlock_resource!(m)
|
479
432
|
end
|
480
433
|
redis.hset(key, 'state', 'unlocked')
|
481
|
-
redis.hset(key, '
|
434
|
+
redis.hset(key, 'owner_name', '')
|
435
|
+
redis.hset(key, 'owner_mention', '')
|
436
|
+
redis.hset(key, 'owner_id', '')
|
482
437
|
true
|
483
438
|
else
|
484
439
|
false
|
data/lita-locker.gemspec
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = 'lita-locker'
|
3
|
-
spec.version = '0.
|
3
|
+
spec.version = '0.5.0'
|
4
4
|
spec.authors = ['Eric Sigler']
|
5
5
|
spec.email = ['me@esigler.com']
|
6
|
-
spec.description =
|
7
|
-
spec.summary =
|
6
|
+
spec.description = '"lock" and "unlock" arbitrary subjects'
|
7
|
+
spec.summary = '"lock" and "unlock" arbitrary subjects'
|
8
8
|
spec.homepage = 'https://github.com/esigler/lita-locker'
|
9
9
|
spec.license = 'MIT'
|
10
10
|
spec.metadata = { 'lita_plugin_type' => 'handler' }
|
data/locales/en.yml
CHANGED
@@ -3,32 +3,50 @@ en:
|
|
3
3
|
handlers:
|
4
4
|
locker:
|
5
5
|
help:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
6
|
+
lock:
|
7
|
+
syntax: lock <subject>
|
8
|
+
desc: Make something unavailable to others. Can have # comments afterwards.
|
9
|
+
unlock:
|
10
|
+
syntax: unlock <subject>
|
11
|
+
desc: Make something available to others. Can have # comments afterwards.
|
12
|
+
steal:
|
13
|
+
syntax: steal <subject>
|
14
|
+
desc: Force removal of a reservation. Can have # comments afterwards.
|
15
|
+
status:
|
16
|
+
syntax: locker status <label or resource>
|
17
|
+
desc: Show the current state of <label or resource>
|
18
|
+
resource:
|
19
|
+
list:
|
20
|
+
syntax: locker resource list
|
21
|
+
desc: List all resources
|
22
|
+
create:
|
23
|
+
syntax: locker resource create <name>
|
24
|
+
desc: Create a resource with <name>
|
25
|
+
delete:
|
26
|
+
syntax: locker resource delete <name>
|
27
|
+
desc: Delete the resource with <name>
|
28
|
+
show:
|
29
|
+
syntax: locker resource show <name>
|
30
|
+
desc: Show the state of <name>
|
31
|
+
label:
|
32
|
+
list:
|
33
|
+
syntax: locker label list
|
34
|
+
desc: List all labels
|
35
|
+
create:
|
36
|
+
syntax: locker label create <name>
|
37
|
+
desc: Create a label with <name>
|
38
|
+
delete:
|
39
|
+
syntax: locker label delete <name>
|
40
|
+
desc: Delete the label with <name>
|
41
|
+
show:
|
42
|
+
syntax: locker label show <name>
|
43
|
+
desc: Show all resources for <name>
|
44
|
+
add:
|
45
|
+
syntax: locker label add <resource> to <name>
|
46
|
+
desc: Adds <resource> to the list of things to lock/unlock for <name>
|
47
|
+
remove:
|
48
|
+
syntax: locker label remove <resource> from <name>
|
49
|
+
desc: Removes <resource> from <name>
|
32
50
|
resource:
|
33
51
|
created: "Resource %{name} created"
|
34
52
|
desc: "Resource: %{name}, state: %{state}"
|
@@ -39,23 +57,24 @@ en:
|
|
39
57
|
is_locked: "%{name} is locked"
|
40
58
|
unlock: "%{name} unlocked"
|
41
59
|
is_unlocked: "%{name} is unlocked"
|
42
|
-
owned: "%{name} is locked by %{
|
60
|
+
owned: "%{name} is locked by %{owner_name} %{owner_mention}"
|
43
61
|
subject:
|
44
|
-
does_not_exist: "
|
62
|
+
does_not_exist: "Sorry, that does not exist"
|
45
63
|
label:
|
46
64
|
unlock: "%{name} unlocked"
|
47
|
-
owned: "%{name} is locked by %{
|
65
|
+
owned: "%{name} is locked by %{owner_name} %{owner_mention}"
|
48
66
|
is_unlocked: "%{name} is unlocked"
|
49
67
|
unable_to_lock: "%{name} unable to be locked"
|
50
68
|
lock: "%{name} locked"
|
51
|
-
desc: "Label: %{name}"
|
69
|
+
desc: "Label: %{name}, state: %{state}"
|
52
70
|
created: "Label %{name} created"
|
53
71
|
exists: "%{name} already exists"
|
54
72
|
deleted: "Label %{name} deleted"
|
55
|
-
does_not_exist: "Label %{name} does not exist"
|
73
|
+
does_not_exist: "Label %{name} does not exist. To create it: \"!locker label create %{name}\""
|
56
74
|
has_no_resources: "Label %{name} has no resources"
|
57
75
|
resource_added: "Resource %{resource} has been added to %{label}"
|
58
76
|
resource_removed: "Resource %{resource} has been removed from %{label}"
|
59
77
|
resources: "Label %{name} has: %{resources}"
|
60
78
|
does_not_have_resource: "Label %{label} does not have Resource %{resource}"
|
61
79
|
no_resources: "%{name} has no resources, so it cannot be locked"
|
80
|
+
dependency: 'Label unable to be locked, blocked on a dependency'
|
@@ -1,35 +1,51 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Lita::Handlers::Locker, lita_handler: true do
|
4
|
-
|
5
|
-
|
4
|
+
label_examples = ['foobar', 'foo bar', 'foo-bar', 'foo_bar']
|
5
|
+
resource_examples = ['foobar', 'foo.bar', 'foo-bar', 'foo_bar']
|
6
|
+
|
7
|
+
label_examples.each do |l|
|
8
|
+
it { routes("(lock) #{l}").to(:lock) }
|
9
|
+
it { routes("(unlock) #{l}").to(:unlock) }
|
10
|
+
it { routes("(release) #{l}").to(:unlock) }
|
11
|
+
|
12
|
+
it { routes("(lock) #{l} #this is a comment").to(:lock) }
|
13
|
+
it { routes("(unlock) #{l} #this is a comment").to(:unlock) }
|
14
|
+
it { routes("(release) #{l} #this is a comment").to(:unlock) }
|
15
|
+
|
16
|
+
it { routes_command("lock #{l}").to(:lock) }
|
17
|
+
it { routes_command("lock #{l} #this is a comment").to(:lock) }
|
18
|
+
it { routes_command("unlock #{l}").to(:unlock) }
|
19
|
+
it { routes_command("unlock #{l} #this is a comment").to(:unlock) }
|
20
|
+
it { routes_command("steal #{l}").to(:steal) }
|
21
|
+
it { routes_command("steal #{l} #this is a comment").to(:steal) }
|
22
|
+
end
|
6
23
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
it { routes_command('lock foo_bar').to(:lock) }
|
11
|
-
# it { routes_command('lock foobar 30m').to(:lock) }
|
24
|
+
label_examples.each do |l|
|
25
|
+
it { routes_command("locker status #{l}").to(:status) }
|
26
|
+
end
|
12
27
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
it { routes_command('unlock foo_bar').to(:unlock) }
|
17
|
-
it { routes_command('unlock foobar force').to(:unlock_force) }
|
28
|
+
resource_examples.each do |r|
|
29
|
+
it { routes_command("locker status #{r}").to(:status) }
|
30
|
+
end
|
18
31
|
|
19
32
|
it { routes_command('locker resource list').to(:resource_list) }
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
33
|
+
|
34
|
+
resource_examples.each do |r|
|
35
|
+
it { routes_command("locker resource create #{r}").to(:resource_create) }
|
36
|
+
it { routes_command("locker resource delete #{r}").to(:resource_delete) }
|
37
|
+
it { routes_command("locker resource show #{r}").to(:resource_show) }
|
38
|
+
end
|
26
39
|
|
27
40
|
it { routes_command('locker label list').to(:label_list) }
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
41
|
+
|
42
|
+
label_examples.each do |l|
|
43
|
+
it { routes_command("locker label create #{l}").to(:label_create) }
|
44
|
+
it { routes_command("locker label delete #{l}").to(:label_delete) }
|
45
|
+
it { routes_command("locker label show #{l}").to(:label_show) }
|
46
|
+
it { routes_command("locker label add resource to #{l}").to(:label_add) }
|
47
|
+
it { routes_command("locker label remove resource from #{l}").to(:label_remove) }
|
48
|
+
end
|
33
49
|
|
34
50
|
it { routes_http(:get, '/locker/label/foobar').to(:http_label_show) }
|
35
51
|
it { routes_http(:get, '/locker/resource/foobar').to(:http_resource_show) }
|
@@ -41,19 +57,21 @@ describe Lita::Handlers::Locker, lita_handler: true do
|
|
41
57
|
).and_return(true)
|
42
58
|
end
|
43
59
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
send_command('lock foobar')
|
48
|
-
expect(replies.last).to eq('foobar locked')
|
49
|
-
end
|
60
|
+
let(:alice) do
|
61
|
+
Lita::User.create('9001@hipchat', name: 'Alice', mention_name: '@alice')
|
62
|
+
end
|
50
63
|
|
64
|
+
let(:bob) do
|
65
|
+
Lita::User.create('9002@hipchat', name: 'Bob', mention_name: '@bob')
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#lock' do
|
51
69
|
it 'locks a label when it is available and has resources' do
|
52
70
|
send_command('locker resource create foobar')
|
53
71
|
send_command('locker label create bazbat')
|
54
72
|
send_command('locker label add foobar to bazbat')
|
55
|
-
send_command('lock bazbat')
|
56
|
-
expect(replies.last).to eq('bazbat locked')
|
73
|
+
send_command('lock bazbat # with a comment')
|
74
|
+
expect(replies.last).to eq('(successful) bazbat locked')
|
57
75
|
send_command('locker resource show foobar')
|
58
76
|
expect(replies.last).to eq('Resource: foobar, state: locked')
|
59
77
|
end
|
@@ -61,87 +79,69 @@ describe Lita::Handlers::Locker, lita_handler: true do
|
|
61
79
|
it 'shows a warning when a label has no resources' do
|
62
80
|
send_command('locker label create foobar')
|
63
81
|
send_command('lock foobar')
|
64
|
-
expect(replies.last).to eq('foobar has no resources, ' \
|
82
|
+
expect(replies.last).to eq('(failed) foobar has no resources, ' \
|
65
83
|
'so it cannot be locked')
|
66
84
|
end
|
67
85
|
|
68
|
-
it 'shows a warning when a resource is unavailable' do
|
69
|
-
send_command('locker resource create foobar')
|
70
|
-
send_command('lock foobar')
|
71
|
-
send_command('lock foobar')
|
72
|
-
expect(replies.last).to eq('foobar is locked')
|
73
|
-
end
|
74
|
-
|
75
86
|
it 'shows a warning when a label is unavailable' do
|
87
|
+
send_command('locker resource create r1')
|
88
|
+
send_command('locker label create l1')
|
89
|
+
send_command('locker label create l2')
|
90
|
+
send_command('locker label add r1 to l1')
|
91
|
+
send_command('locker label add r1 to l2')
|
92
|
+
send_command('lock l1', as: alice)
|
93
|
+
send_command('lock l2', as: alice)
|
94
|
+
expect(replies.last).to eq('(failed) Label unable to be locked, ' \
|
95
|
+
'blocked on a dependency')
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'shows a warning when a label is taken by someone else' do
|
76
99
|
send_command('locker resource create foobar')
|
77
100
|
send_command('locker label create bazbat')
|
78
101
|
send_command('locker label add foobar to bazbat')
|
79
|
-
send_command('lock
|
80
|
-
send_command('lock bazbat')
|
81
|
-
expect(replies.last).to eq('bazbat
|
102
|
+
send_command('lock bazbat', as: alice)
|
103
|
+
send_command('lock bazbat', as: bob)
|
104
|
+
expect(replies.last).to eq('(failed) bazbat is locked by Alice @alice')
|
82
105
|
end
|
83
106
|
|
84
|
-
it 'shows an error when a
|
107
|
+
it 'shows an error when a label does not exist' do
|
85
108
|
send_command('lock foobar')
|
86
|
-
expect(replies.last).to eq('foobar does not exist'
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
109
|
+
expect(replies.last).to eq('(failed) Label foobar does not exist. To ' \
|
110
|
+
'create it: "!locker label create foobar"')
|
111
|
+
end
|
112
|
+
|
113
|
+
# it 'locks a resource when it is available for a period of time' do
|
114
|
+
# send_command('locker resource create foobar')
|
115
|
+
# send_command('lock foobar 17m')
|
116
|
+
# expect(replies.last).to eq('foobar locked for 17 minutes')
|
117
|
+
# send_command('locker resource show foobar')
|
118
|
+
# expect(replies.last).to eq('Resource: foobar, state: locked')
|
119
|
+
# send_command('unlock foobar')
|
120
|
+
# send_command('lock foobar 12s')
|
121
|
+
# expect(replies.last).to eq('foobar locked for 17 seconds')
|
122
|
+
# send_command('unlock foobar')
|
123
|
+
# send_command('lock foobar 14h')
|
124
|
+
# expect(replies.last).to eq('foobar locked for 14 hours')
|
125
|
+
# end
|
102
126
|
end
|
103
127
|
|
104
128
|
describe '#unlock' do
|
105
|
-
it 'unlocks a resource when it is available' do
|
106
|
-
send_command('locker resource create foobar')
|
107
|
-
send_command('lock foobar')
|
108
|
-
send_command('unlock foobar')
|
109
|
-
expect(replies.last).to eq('foobar unlocked')
|
110
|
-
end
|
111
|
-
|
112
|
-
it 'does not unlock a resource when someone else locked it' do
|
113
|
-
alice = Lita::User.create(1, name: 'Alice')
|
114
|
-
bob = Lita::User.create(2, name: 'Bob')
|
115
|
-
send_command('locker resource create foobar')
|
116
|
-
send_command('lock foobar', as: alice)
|
117
|
-
send_command('unlock foobar', as: bob)
|
118
|
-
expect(replies.last).to eq('foobar is locked by Alice')
|
119
|
-
end
|
120
|
-
|
121
129
|
it 'unlocks a label when it is available' do
|
122
130
|
send_command('locker resource create foobar')
|
123
131
|
send_command('locker label create bazbat')
|
124
132
|
send_command('locker label add foobar to bazbat')
|
125
133
|
send_command('lock bazbat')
|
126
|
-
send_command('unlock bazbat')
|
127
|
-
expect(replies.last).to eq('bazbat unlocked')
|
134
|
+
send_command('unlock bazbat # with a comment')
|
135
|
+
expect(replies.last).to eq('(successful) bazbat unlocked')
|
128
136
|
end
|
129
137
|
|
130
138
|
it 'does not unlock a label when someone else locked it' do
|
131
|
-
alice = Lita::User.create(1, name: 'Alice')
|
132
|
-
bob = Lita::User.create(2, name: 'Bob')
|
133
139
|
send_command('locker resource create foobar')
|
134
140
|
send_command('locker label create bazbat')
|
135
141
|
send_command('locker label add foobar to bazbat')
|
136
142
|
send_command('lock bazbat', as: alice)
|
137
143
|
send_command('unlock bazbat', as: bob)
|
138
|
-
expect(replies.last).to eq('bazbat is locked by Alice')
|
139
|
-
end
|
140
|
-
|
141
|
-
it 'shows a warning when a resource is already unlocked' do
|
142
|
-
send_command('locker resource create foobar')
|
143
|
-
send_command('unlock foobar')
|
144
|
-
expect(replies.last).to eq('foobar is unlocked')
|
144
|
+
expect(replies.last).to eq('(failed) bazbat is locked by Alice @alice')
|
145
145
|
end
|
146
146
|
|
147
147
|
it 'shows a warning when a label is already unlocked' do
|
@@ -150,39 +150,57 @@ describe Lita::Handlers::Locker, lita_handler: true do
|
|
150
150
|
send_command('locker label add foobar to bazbat')
|
151
151
|
send_command('unlock bazbat')
|
152
152
|
send_command('unlock bazbat')
|
153
|
-
expect(replies.last).to eq('bazbat is unlocked')
|
153
|
+
expect(replies.last).to eq('(successful) bazbat is unlocked')
|
154
154
|
end
|
155
155
|
|
156
156
|
it 'shows an error when a <subject> does not exist' do
|
157
157
|
send_command('unlock foobar')
|
158
|
-
expect(replies.last).to eq('
|
158
|
+
expect(replies.last).to eq('(failed) Sorry, that does not exist')
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
162
|
-
describe '#
|
163
|
-
it 'unlocks a resource from someone else when it is available' do
|
164
|
-
alice = Lita::User.create(1, name: 'Alice')
|
165
|
-
bob = Lita::User.create(2, name: 'Bob')
|
166
|
-
send_command('locker resource create foobar')
|
167
|
-
send_command('lock foobar', as: alice)
|
168
|
-
send_command('unlock foobar force', as: bob)
|
169
|
-
expect(replies.last).to eq('foobar unlocked')
|
170
|
-
end
|
171
|
-
|
162
|
+
describe '#steal' do
|
172
163
|
it 'unlocks a label from someone else when it is available' do
|
173
|
-
alice = Lita::User.create(1, name: 'Alice')
|
174
|
-
bob = Lita::User.create(2, name: 'Bob')
|
175
164
|
send_command('locker resource create foobar')
|
176
165
|
send_command('locker label create bazbat')
|
177
166
|
send_command('locker label add foobar to bazbat')
|
178
167
|
send_command('lock bazbat', as: alice)
|
179
|
-
send_command('
|
180
|
-
expect(replies.last).to eq('bazbat unlocked')
|
168
|
+
send_command('steal bazbat # with a comment', as: bob)
|
169
|
+
expect(replies.last).to eq('(successful) bazbat unlocked')
|
181
170
|
end
|
182
171
|
|
183
172
|
it 'shows an error when a <subject> does not exist' do
|
184
|
-
send_command('
|
185
|
-
expect(replies.last).to eq('
|
173
|
+
send_command('steal foobar')
|
174
|
+
expect(replies.last).to eq('(failed) Sorry, that does not exist')
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe '#status' do
|
179
|
+
it 'shows the status of a label' do
|
180
|
+
send_command('locker resource create bar')
|
181
|
+
send_command('locker label create foo')
|
182
|
+
send_command('locker label add bar to foo')
|
183
|
+
send_command('locker status foo')
|
184
|
+
expect(replies.last).to eq('Label: foo, state: unlocked')
|
185
|
+
send_command('lock foo')
|
186
|
+
send_command('locker status foo')
|
187
|
+
expect(replies.last).to eq('Label: foo, state: locked')
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'shows the status of a resource' do
|
191
|
+
send_command('locker resource create bar')
|
192
|
+
send_command('locker label create foo')
|
193
|
+
send_command('locker label add bar to foo')
|
194
|
+
send_command('locker status bar')
|
195
|
+
expect(replies.last).to eq('Resource: bar, state: unlocked')
|
196
|
+
send_command('lock foo')
|
197
|
+
send_command('locker status bar')
|
198
|
+
expect(replies.last).to eq('Resource: bar, state: locked')
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'shows an error if nothing exists with that name' do
|
202
|
+
send_command('locker status foo')
|
203
|
+
expect(replies.last).to eq('Sorry, that does not exist')
|
186
204
|
end
|
187
205
|
end
|
188
206
|
|
@@ -191,8 +209,8 @@ describe Lita::Handlers::Locker, lita_handler: true do
|
|
191
209
|
send_command('locker label create foobar')
|
192
210
|
send_command('locker label create bazbat')
|
193
211
|
send_command('locker label list')
|
194
|
-
expect(replies.include?('Label: foobar')).to eq(true)
|
195
|
-
expect(replies.include?('Label: bazbat')).to eq(true)
|
212
|
+
expect(replies.include?('Label: foobar, state: unlocked')).to eq(true)
|
213
|
+
expect(replies.include?('Label: bazbat, state: unlocked')).to eq(true)
|
196
214
|
end
|
197
215
|
end
|
198
216
|
|
@@ -224,7 +242,8 @@ describe Lita::Handlers::Locker, lita_handler: true do
|
|
224
242
|
|
225
243
|
it 'shows a warning when <name> does not exist' do
|
226
244
|
send_command('locker label delete foobar')
|
227
|
-
expect(replies.last).to eq('Label foobar does not exist'
|
245
|
+
expect(replies.last).to eq('Label foobar does not exist. To create ' \
|
246
|
+
'it: "!locker label create foobar"')
|
228
247
|
end
|
229
248
|
end
|
230
249
|
|
@@ -245,7 +264,8 @@ describe Lita::Handlers::Locker, lita_handler: true do
|
|
245
264
|
|
246
265
|
it 'shows an error if the label does not exist' do
|
247
266
|
send_command('locker label show foobar')
|
248
|
-
expect(replies.last).to eq('Label foobar does not exist'
|
267
|
+
expect(replies.last).to eq('Label foobar does not exist. To create ' \
|
268
|
+
'it: "!locker label create foobar"')
|
249
269
|
end
|
250
270
|
end
|
251
271
|
|
@@ -266,12 +286,13 @@ describe Lita::Handlers::Locker, lita_handler: true do
|
|
266
286
|
send_command('locker label add foo to bar')
|
267
287
|
send_command('locker label add baz to bar')
|
268
288
|
send_command('locker label show bar')
|
269
|
-
expect(replies.last).to eq('Label bar has:
|
289
|
+
expect(replies.last).to eq('Label bar has: foo, baz')
|
270
290
|
end
|
271
291
|
|
272
292
|
it 'shows an error if the label does not exist' do
|
273
293
|
send_command('locker label add foo to bar')
|
274
|
-
expect(replies.last).to eq('Label bar does not exist'
|
294
|
+
expect(replies.last).to eq('Label bar does not exist. To create ' \
|
295
|
+
'it: "!locker label create bar"')
|
275
296
|
end
|
276
297
|
|
277
298
|
it 'shows an error if the resource does not exist' do
|
@@ -300,7 +321,8 @@ describe Lita::Handlers::Locker, lita_handler: true do
|
|
300
321
|
|
301
322
|
it 'shows an error if the label does not exist' do
|
302
323
|
send_command('locker label add foo to bar')
|
303
|
-
expect(replies.last).to eq('Label bar does not exist'
|
324
|
+
expect(replies.last).to eq('Label bar does not exist. To create ' \
|
325
|
+
'it: "!locker label create bar"')
|
304
326
|
end
|
305
327
|
|
306
328
|
it 'shows an error if the resource does not exist' do
|
@@ -315,8 +337,8 @@ describe Lita::Handlers::Locker, lita_handler: true do
|
|
315
337
|
send_command('locker resource create foobar')
|
316
338
|
send_command('locker resource create bazbat')
|
317
339
|
send_command('locker resource list')
|
318
|
-
expect(replies.
|
319
|
-
expect(replies.
|
340
|
+
expect(replies.last).to match(/Resource: foobar, state: unlocked/)
|
341
|
+
expect(replies.last).to match(/Resource: bazbat, state: unlocked/)
|
320
342
|
end
|
321
343
|
end
|
322
344
|
|
@@ -357,9 +379,6 @@ describe Lita::Handlers::Locker, lita_handler: true do
|
|
357
379
|
send_command('locker resource create foobar')
|
358
380
|
send_command('locker resource show foobar')
|
359
381
|
expect(replies.last).to eq('Resource: foobar, state: unlocked')
|
360
|
-
send_command('lock foobar')
|
361
|
-
send_command('locker resource show foobar')
|
362
|
-
expect(replies.last).to eq('Resource: foobar, state: locked')
|
363
382
|
end
|
364
383
|
|
365
384
|
it 'shows a warning when <name> does not exist' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lita-locker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Sigler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lita
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- LICENSE
|
123
123
|
- README.md
|
124
124
|
- Rakefile
|
125
|
+
- TODO.md
|
125
126
|
- lib/lita-locker.rb
|
126
127
|
- lib/lita/handlers/locker.rb
|
127
128
|
- lita-locker.gemspec
|