lita-locker 0.4.0 → 0.5.0
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.
- 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
|