lita-locker 0.5.3 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c8c1387e7b5b34330a06b4b423c09baf6a07c910
4
- data.tar.gz: 7aff63b7b66afb89c1b4409be77a1e1902d4be49
3
+ metadata.gz: c652f7dfc79a47babe632a2f9516bfeedf1b4781
4
+ data.tar.gz: d4f5f7802f48182a08fab5f573f44b35ecac6b90
5
5
  SHA512:
6
- metadata.gz: 3dd3c6ae9eaa86fd70333347c288509022b7cd056db2daab328d185210dd4ec5e02e9bd2ff1028094aa361f9ddd0acf61b7ae83f8b7b2cf0e544f1d0157d23ee
7
- data.tar.gz: d2da98d29c48a71b87795a41e7377b11f00aba25e95234bf4e05d4311fa1a2669dc70e1bc7ca84995644d949603be2d26a3e8c9dfc6f5a3b7b6cb99e8482d2f9
6
+ metadata.gz: c9113338335470eca38f6b2b947618b115c624ffeea5dc81acf94e43636bb1aaecc359f00128653784aace1ed48647e2da0ec5dad5318d90b533e361d66a5fe5
7
+ data.tar.gz: 2acb94c1f70b702c67baedb3e2cd8095a68c79517c1ec46e57558e8d755e18a203bc5d6987181301999ce1e67aada7cb028fe91289291e0a55bf650b50dad748
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  *.gem
2
2
  *.rbc
3
+ *.swp
3
4
  .bundle
4
5
  .config
5
6
  .yardoc
data/.rubocop.yml CHANGED
@@ -1,26 +1,21 @@
1
- BlockNesting:
2
- Max: 5
3
-
4
1
  ClassLength:
5
- Max: 500
2
+ Max: 103
6
3
 
7
4
  CyclomaticComplexity:
8
- Max: 8
9
-
10
- Documentation:
11
- Exclude:
12
- - lib/lita/handlers/locker.rb
5
+ Max: 7
13
6
 
14
7
  FileName:
15
8
  Exclude:
16
9
  - lib/lita-locker.rb
17
10
 
18
11
  MethodLength:
19
- Max: 200
12
+ Max: 31
13
+
14
+ PerceivedComplexity:
15
+ Max: 12
20
16
 
21
17
  LineLength:
22
- Max: 85
18
+ Max: 120
23
19
 
24
- GuardClause:
25
- Exclude:
26
- - lib/lita/handlers/locker.rb
20
+ AbcSize:
21
+ Max: 49
data/.travis.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.0.0
3
+ - 2.1
4
4
  script: bundle exec rake
5
5
  before_install:
6
6
  - gem update --system
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,9 @@
1
+ Pull requests are awesome! Pull requests with tests are even more awesome!
2
+
3
+ ## Quick steps
4
+
5
+ 1. Fork the repo.
6
+ 2. Run the tests: `bundle && rake`
7
+ 3. Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, it needs a test!
8
+ 4. Make the test pass.
9
+ 5. Push to your fork and submit a pull request.
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
data/lib/lita-locker.rb CHANGED
@@ -4,4 +4,14 @@ Lita.load_locales Dir[File.expand_path(
4
4
  File.join('..', '..', 'locales', '*.yml'), __FILE__
5
5
  )]
6
6
 
7
+ require 'locker/label'
8
+ require 'locker/misc'
9
+ require 'locker/regex'
10
+ require 'locker/resource'
11
+
12
+ require 'lita/handlers/locker_events'
13
+ require 'lita/handlers/locker_http'
14
+ require 'lita/handlers/locker_labels'
15
+ require 'lita/handlers/locker_misc'
16
+ require 'lita/handlers/locker_resources'
7
17
  require 'lita/handlers/locker'
@@ -1,20 +1,20 @@
1
1
  module Lita
2
+ # Handy, isn't it?
2
3
  module Handlers
4
+ # Top-level class for Locker
3
5
  class Locker < Handler
4
- http.get '/locker/label/:name', :http_label_show
5
- http.get '/locker/resource/:name', :http_resource_show
6
-
7
- LABEL_REGEX = /([\.\w\s-]+)/
8
- RESOURCE_REGEX = /([\.\w-]+)/
9
- COMMENT_REGEX = /(\s\#.+)?/
6
+ include ::Locker::Label
7
+ include ::Locker::Misc
8
+ include ::Locker::Regex
9
+ include ::Locker::Resource
10
10
 
11
11
  route(
12
- /^\(lock\)\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
12
+ /^#{LOCK_REGEX}#{LABEL_REGEX}#{COMMENT_REGEX}$/,
13
13
  :lock
14
14
  )
15
15
 
16
16
  route(
17
- /^(?:\(unlock\)|\(release\))\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
17
+ /^#{UNLOCK_REGEX}#{LABEL_REGEX}#{COMMENT_REGEX}$/,
18
18
  :unlock
19
19
  )
20
20
 
@@ -39,435 +39,84 @@ module Lita
39
39
  help: { t('help.steal.syntax') => t('help.steal.desc') }
40
40
  )
41
41
 
42
- route(
43
- /^locker\sstatus\s#{LABEL_REGEX}$/,
44
- :status,
45
- command: true,
46
- help: { t('help.status.syntax') => t('help.status.desc') }
47
- )
48
-
49
- route(
50
- /^locker\sresource\slist$/,
51
- :resource_list,
52
- command: true,
53
- help: { t('help.resource.list.syntax') => t('help.resource.list.desc') }
54
- )
55
-
56
- route(
57
- /^locker\sresource\screate\s#{RESOURCE_REGEX}$/,
58
- :resource_create,
59
- command: true,
60
- restrict_to: [:locker_admins],
61
- help: {
62
- t('help.resource.create.syntax') => t('help.resource.create.desc')
63
- }
64
- )
65
-
66
- route(
67
- /^locker\sresource\sdelete\s#{RESOURCE_REGEX}$/,
68
- :resource_delete,
69
- command: true,
70
- restrict_to: [:locker_admins],
71
- help: {
72
- t('help.resource.delete.syntax') => t('help.resource.delete.desc')
73
- }
74
- )
75
-
76
- route(
77
- /^locker\sresource\sshow\s#{RESOURCE_REGEX}$/,
78
- :resource_show,
79
- command: true,
80
- help: { t('help.resource.show.syntax') => t('help.resource.show.desc') }
81
- )
82
-
83
- route(
84
- /^locker\slabel\slist$/,
85
- :label_list,
86
- command: true,
87
- help: { t('help.label.list.syntax') => t('help.label.list.desc') }
88
- )
89
-
90
- route(
91
- /^locker\slabel\screate\s#{LABEL_REGEX}$/,
92
- :label_create,
93
- command: true,
94
- help: { t('help.label.create.syntax') => t('help.label.create.desc') }
95
- )
96
-
97
- route(
98
- /^locker\slabel\sdelete\s#{LABEL_REGEX}$/,
99
- :label_delete,
100
- command: true,
101
- help: { t('help.label.delete.syntax') => t('help.label.delete.desc') }
102
- )
103
-
104
- route(
105
- /^locker\slabel\sshow\s#{LABEL_REGEX}$/,
106
- :label_show,
107
- command: true,
108
- help: { t('help.label.show.syntax') => t('help.label.show.desc') }
109
- )
110
-
111
- route(
112
- /^locker\slabel\sadd\s#{RESOURCE_REGEX}\sto\s#{LABEL_REGEX}$/,
113
- :label_add,
114
- command: true,
115
- help: { t('help.label.add.syntax') => t('help.label.add.desc') }
116
- )
117
-
118
- route(
119
- /^locker\slabel\sremove\s#{RESOURCE_REGEX}\sfrom\s#{LABEL_REGEX}$/,
120
- :label_remove,
121
- command: true,
122
- help: { t('help.label.remove.syntax') => t('help.label.remove.desc') }
123
- )
124
-
125
- def http_label_show(request, response)
126
- name = request.env['router.params'][:name]
127
- response.headers['Content-Type'] = 'application/json'
128
- response.write(label(name).to_json)
129
- end
130
-
131
- def http_resource_show(request, response)
132
- name = request.env['router.params'][:name]
133
- response.headers['Content-Type'] = 'application/json'
134
- response.write(resource(name).to_json)
135
- end
136
-
137
42
  def lock(response)
138
43
  name = response.matches[0][0]
139
44
 
140
- if label_exists?(name)
141
- m = label_membership(name)
142
- if m.count > 0
143
- if lock_label!(name, response.user, nil)
144
- response.reply('(successful) ' + t('label.lock', name: name))
145
- else
146
- l = label(name)
147
- if l['state'] == 'locked'
148
- o = Lita::User.find_by_id(l['owner_id'])
149
- if o.mention_name
150
- response.reply('(failed) ' + t('label.owned_mention',
151
- name: name,
152
- owner_name: o.name,
153
- owner_mention: o.mention_name))
154
- else
155
- response.reply('(failed) ' + t('label.owned',
156
- name: name,
157
- owner_name: o.name))
158
- end
159
- else
160
- response.reply('(failed) ' + t('label.dependency'))
161
- end
162
- end
45
+ return response.reply('(failed) ' + t('label.does_not_exist', name: name)) unless label_exists?(name)
46
+ m = label_membership(name)
47
+ return response.reply('(failed) ' + t('label.no_resources', name: name)) unless m.count > 0
48
+ return response.reply('(successful) ' + t('label.lock', name: name)) if lock_label!(name, response.user, nil)
49
+
50
+ l = label(name)
51
+ if l['state'] == 'locked'
52
+ o = Lita::User.find_by_id(l['owner_id'])
53
+ if o.mention_name
54
+ response.reply('(failed) ' + t('label.owned_mention',
55
+ name: name,
56
+ owner_name: o.name,
57
+ owner_mention: o.mention_name))
163
58
  else
164
- response.reply('(failed) ' + t('label.no_resources', name: name))
59
+ response.reply('(failed) ' + t('label.owned',
60
+ name: name,
61
+ owner_name: o.name))
165
62
  end
166
63
  else
167
- response.reply('(failed) ' + t('label.does_not_exist', name: name))
168
- end
169
- end
170
-
171
- def unlock(response)
172
- name = response.matches[0][0]
173
- if label_exists?(name)
174
- l = label(name)
175
- if l['state'] == 'unlocked'
176
- response.reply('(successful) ' + t('label.is_unlocked',
177
- name: name))
178
- else
179
- if response.user.id == l['owner_id']
180
- unlock_label!(name)
181
- response.reply('(successful) ' + t('label.unlock', name: name))
182
- else
183
- o = Lita::User.find_by_id(l['owner_id'])
184
- if o.mention_name
185
- response.reply('(failed) ' + t('label.owned_mention',
186
- name: name,
187
- owner_name: o.name,
188
- owner_mention: o.mention_name))
189
- else
190
- response.reply('(failed) ' + t('label.owned',
191
- name: name,
192
- owner_name: o.name))
193
- end
64
+ msg = '(failed) ' + t('label.dependency') + "\n"
65
+ deps = []
66
+ label_membership(name).each do |resource_name|
67
+ resource = resource(resource_name)
68
+ u = Lita::User.find_by_id(resource['owner_id'])
69
+ if resource['state'] == 'locked'
70
+ deps.push "#{resource_name} - #{u.name}"
194
71
  end
195
72
  end
196
- else
197
- response.reply('(failed) ' + t('subject.does_not_exist', name: name))
73
+ msg += deps.join("\n")
74
+ response.reply(msg)
198
75
  end
199
76
  end
200
77
 
201
- def steal(response)
78
+ def unlock(response)
202
79
  name = response.matches[0][0]
203
- if label_exists?(name)
80
+ return response.reply('(failed) ' + t('subject.does_not_exist', name: name)) unless label_exists?(name)
81
+ l = label(name)
82
+ return response.reply('(successful) ' + t('label.is_unlocked', name: name)) if l['state'] == 'unlocked'
83
+
84
+ if response.user.id == l['owner_id']
204
85
  unlock_label!(name)
205
86
  response.reply('(successful) ' + t('label.unlock', name: name))
206
- # FIXME: Handle the case where things can't be unlocked?
207
- else
208
- response.reply('(failed) ' + t('subject.does_not_exist', name: name))
209
- end
210
- end
211
-
212
- def status(response)
213
- name = response.matches[0][0]
214
- if label_exists?(name)
215
- l = label(name)
216
- if l['owner_id'] && l['owner_id'] != ''
217
- o = Lita::User.find_by_id(l['owner_id'])
218
- response.reply(t('label.desc_owner', name: name,
219
- state: l['state'],
220
- owner_name: o.name))
221
- else
222
- response.reply(t('label.desc', name: name, state: l['state']))
223
- end
224
- elsif resource_exists?(name)
225
- r = resource(name)
226
- response.reply(t('resource.desc', name: name, state: r['state']))
227
- else
228
- response.reply(t('subject.does_not_exist', name: name))
229
- end
230
- end
231
-
232
- def label_list(response)
233
- labels.each do |n|
234
- name = n.sub('label_', '')
235
- l = label(name)
236
- response.reply(t('label.desc', name: name, state: l['state']))
237
- end
238
- end
239
-
240
- def label_create(response)
241
- name = response.matches[0][0]
242
- if create_label(name)
243
- response.reply(t('label.created', name: name))
244
- else
245
- response.reply(t('label.exists', name: name))
246
- end
247
- end
248
-
249
- def label_delete(response)
250
- name = response.matches[0][0]
251
- if delete_label(name)
252
- response.reply(t('label.deleted', name: name))
253
- else
254
- response.reply(t('label.does_not_exist', name: name))
255
- end
256
- end
257
-
258
- def label_show(response)
259
- name = response.matches[0][0]
260
- if label_exists?(name)
261
- members = label_membership(name)
262
- if members.count > 0
263
- response.reply(t('label.resources', name: name,
264
- resources: members.join(', ')))
265
- else
266
- response.reply(t('label.has_no_resources', name: name))
267
- end
268
87
  else
269
- response.reply(t('label.does_not_exist', name: name))
270
- end
271
- end
272
-
273
- def label_add(response)
274
- resource_name = response.matches[0][0]
275
- label_name = response.matches[0][1]
276
- if label_exists?(label_name)
277
- if resource_exists?(resource_name)
278
- add_resource_to_label(label_name, resource_name)
279
- response.reply(t('label.resource_added', label: label_name,
280
- resource: resource_name))
88
+ o = Lita::User.find_by_id(l['owner_id'])
89
+ if o.mention_name
90
+ response.reply('(failed) ' + t('label.owned_mention',
91
+ name: name,
92
+ owner_name: o.name,
93
+ owner_mention: o.mention_name))
281
94
  else
282
- response.reply(t('resource.does_not_exist', name: resource_name))
95
+ response.reply('(failed) ' + t('label.owned',
96
+ name: name,
97
+ owner_name: o.name))
283
98
  end
284
- else
285
- response.reply(t('label.does_not_exist', name: label_name))
286
99
  end
287
100
  end
288
101
 
289
- def label_remove(response)
290
- resource_name = response.matches[0][0]
291
- label_name = response.matches[0][1]
292
- if label_exists?(label_name)
293
- if resource_exists?(resource_name)
294
- members = label_membership(label_name)
295
- if members.include?(resource_name)
296
- remove_resource_from_label(label_name, resource_name)
297
- response.reply(t('label.resource_removed',
298
- label: label_name, resource: resource_name))
299
- else
300
- response.reply(t('label.does_not_have_resource',
301
- label: label_name, resource: resource_name))
302
- end
303
- else
304
- response.reply(t('resource.does_not_exist', name: resource_name))
305
- end
306
- else
307
- response.reply(t('label.does_not_exist', name: label_name))
308
- end
309
- end
310
-
311
- def resource_list(response)
312
- output = ''
313
- resources.each do |r|
314
- r_name = r.sub('resource_', '')
315
- res = resource(r_name)
316
- output += t('resource.desc', name: r_name, state: res['state'])
317
- end
318
- response.reply(output)
319
- end
320
-
321
- def resource_create(response)
322
- name = response.matches[0][0]
323
- if create_resource(name)
324
- response.reply(t('resource.created', name: name))
325
- else
326
- response.reply(t('resource.exists', name: name))
327
- end
328
- end
329
-
330
- def resource_delete(response)
331
- name = response.matches[0][0]
332
- if delete_resource(name)
333
- response.reply(t('resource.deleted', name: name))
334
- else
335
- response.reply(t('resource.does_not_exist', name: name))
336
- end
337
- end
338
-
339
- def resource_show(response)
102
+ def steal(response)
340
103
  name = response.matches[0][0]
341
- if resource_exists?(name)
342
- r = resource(name)
343
- response.reply(t('resource.desc', name: name, state: r['state']))
344
- else
345
- response.reply(t('resource.does_not_exist', name: name))
346
- end
347
- end
348
-
349
- private
350
-
351
- def create_label(name)
352
- label_key = "label_#{name}"
353
- redis.hset(label_key, 'state', 'unlocked') unless
354
- resource_exists?(name) || label_exists?(name)
355
- end
356
-
357
- def delete_label(name)
358
- label_key = "label_#{name}"
359
- redis.del(label_key) if label_exists?(name)
360
- end
361
-
362
- def label_exists?(name)
363
- redis.exists("label_#{name}")
364
- end
365
-
366
- def label_membership(name)
367
- redis.smembers("membership_#{name}")
368
- end
369
-
370
- def add_resource_to_label(label, resource)
371
- if label_exists?(label) && resource_exists?(resource)
372
- redis.sadd("membership_#{label}", resource)
373
- end
374
- end
375
-
376
- def remove_resource_from_label(label, resource)
377
- if label_exists?(label) && resource_exists?(resource)
378
- redis.srem("membership_#{label}", resource)
379
- end
380
- end
381
-
382
- def create_resource(name)
383
- resource_key = "resource_#{name}"
384
- redis.hset(resource_key, 'state', 'unlocked') unless
385
- resource_exists?(name) || label_exists?(name)
386
- end
387
-
388
- def delete_resource(name)
389
- resource_key = "resource_#{name}"
390
- redis.del(resource_key) if resource_exists?(name)
391
- end
392
-
393
- def resource_exists?(name)
394
- redis.exists("resource_#{name}")
395
- end
396
-
397
- def lock_resource!(name, owner, time_until)
398
- if resource_exists?(name)
399
- resource_key = "resource_#{name}"
400
- value = redis.hget(resource_key, 'state')
401
- if value == 'unlocked'
402
- # FIXME: Race condition!
403
- redis.hset(resource_key, 'state', 'locked')
404
- redis.hset(resource_key, 'owner_id', owner.id)
405
- redis.hset(resource_key, 'until', time_until)
406
- true
407
- else
408
- false
409
- end
410
- else
411
- false
412
- end
413
- end
414
-
415
- def lock_label!(name, owner, time_until)
416
- if label_exists?(name)
417
- key = "label_#{name}"
418
- members = label_membership(name)
419
- members.each do |m|
420
- return false unless lock_resource!(m, owner, time_until)
421
- end
422
- redis.hset(key, 'state', 'locked')
423
- redis.hset(key, 'owner_id', owner.id)
424
- redis.hset(key, 'until', time_until)
425
- true
426
- else
427
- false
428
- end
429
- end
430
-
431
- def unlock_resource!(name)
432
- if resource_exists?(name)
433
- key = "resource_#{name}"
434
- redis.hset(key, 'state', 'unlocked')
435
- redis.hset(key, 'owner_id', '')
436
- else
437
- false
438
- end
439
- end
440
-
441
- def unlock_label!(name)
442
- if label_exists?(name)
443
- key = "label_#{name}"
444
- members = label_membership(name)
445
- members.each do |m|
446
- unlock_resource!(m)
447
- end
448
- redis.hset(key, 'state', 'unlocked')
449
- redis.hset(key, 'owner_id', '')
450
- true
104
+ return response.reply('(failed) ' + t('subject.does_not_exist', name: name)) unless label_exists?(name)
105
+ l = label(name)
106
+ return response.reply(t('steal.already_unlocked', label: name)) unless l['state'] == 'locked'
107
+ o = Lita::User.find_by_id(l['owner_id'])
108
+ if o.id != response.user.id
109
+ unlock_label!(name)
110
+ lock_label!(name, response.user, nil)
111
+ mention = o.mention_name ? "(@#{o.mention_name})" : ''
112
+ response.reply('(successful) ' + t('steal.stolen',
113
+ label: name,
114
+ old_owner: o.name,
115
+ mention: mention))
451
116
  else
452
- false
117
+ response.reply(t('steal.self'))
453
118
  end
454
119
  end
455
-
456
- def resource(name)
457
- redis.hgetall("resource_#{name}")
458
- end
459
-
460
- def resources
461
- redis.keys('resource_*')
462
- end
463
-
464
- def label(name)
465
- redis.hgetall("label_#{name}")
466
- end
467
-
468
- def labels
469
- redis.keys('label_*')
470
- end
471
120
  end
472
121
 
473
122
  Lita.register_handler(Locker)