lita 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -3
- data/lib/lita/authorization.rb +17 -0
- data/lib/lita/handler.rb +12 -4
- data/lib/lita/handlers/authorization.rb +38 -0
- data/lib/lita/rspec.rb +2 -0
- data/lib/lita/version.rb +1 -1
- data/lita.gemspec +1 -1
- data/spec/lita/authorization_spec.rb +38 -0
- data/spec/lita/handler_spec.rb +14 -1
- data/spec/lita/handlers/authorization_spec.rb +42 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73a99962e90c5ed2aa41e8d8a728abdd0a707051
|
4
|
+
data.tar.gz: 1b9026e1e1d32e693d67d13a40fe1fa412982930
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5abc300962d3cdfbe95a1d2882acc8c79cdd4b259819badc7d396ca8b2a83aed37176a4c8c92721926810706bb3cd9a27cbf4d3cf2613aa3f166d53e5420e34b
|
7
|
+
data.tar.gz: b48afb57c7cb94f560ebb4ff0a7a88ba390759720020c8085868d6a748e541c338317bbb0837902183f61a95c1a4ca9e7c50677ce3478511bee80204bc97723a
|
data/README.md
CHANGED
@@ -27,8 +27,8 @@ Lita draws much inspiration from GitHub's fantastic [Hubot](http://hubot.github.
|
|
27
27
|
|
28
28
|
* It's written in Ruby.
|
29
29
|
* It exposes the full power of Redis rather than using it to serialize JSON.
|
30
|
-
*
|
31
|
-
* It uses
|
30
|
+
* It's easy to develop and test plugins for with the provied [RSpec](https://github.com/rspec/rspec) extras. Lita strongly encourages thorough testing of plugins.
|
31
|
+
* It uses the Ruby ecosystem's standard tools (RubyGems and Bundler) for plugin installation and loading.
|
32
32
|
* It's thoroughly documented.
|
33
33
|
|
34
34
|
## Is it any good?
|
@@ -115,6 +115,14 @@ Lita: auth remove joe committers
|
|
115
115
|
|
116
116
|
The first command adds a user whose ID or name is "joe" to the authorization group "committers." If the group doesn't yet exist, it is created. The second command removes joe from the group. Handlers can specify that a route (a method that matches an incoming message) requires that the user sending the message be in a certain authorization group. See the section on writing handlers for more details.
|
117
117
|
|
118
|
+
To list all the authorization groups and the names of the users in them, send Lita this command:
|
119
|
+
|
120
|
+
```
|
121
|
+
Lita: auth list
|
122
|
+
```
|
123
|
+
|
124
|
+
You can optionally suffix the command with the name of a group if you're only interested in the memebers of one group.
|
125
|
+
|
118
126
|
## Online help
|
119
127
|
|
120
128
|
Message Lita `help` for a list of commands it knows about. You can also message it `help FOO` to list only commands beginning with FOO.
|
@@ -208,6 +216,8 @@ Additionally, handlers have access to these top-level methods:
|
|
208
216
|
* `redis` - A `Redis::Namespace` object which provides each handler with its own isolated Redis store, suitable for many data persistence and manipulation tasks.
|
209
217
|
* `http` - A `Faraday::Connection` object for making HTTP requests. Takes an optional hash of options and optional block which are passed on to [Faraday](https://github.com/lostisland/faraday).
|
210
218
|
|
219
|
+
If a handler method crashes, the backtrace will be output to Lita's log with the `:error` level, but it will not crash the robot itself.
|
220
|
+
|
211
221
|
### HTTP routes
|
212
222
|
|
213
223
|
In addition to chat routes, handlers can also define HTTP routes for the built-in web server. This is done with the class-level `http` method. `http` returns a `Lita::HTTPRoute` object, which has methods for the most common HTTP methods. These methods take two arguments: the path for the route, and the name of the method that it will invoke as a symbol. The callback method takes two arguments: a `Rack::Request` and a `Rack::Response`. For example:
|
@@ -382,11 +392,12 @@ There are a few things worth mentioning when deploying an instance of Lita to He
|
|
382
392
|
|
383
393
|
1. Your Procfile should contain one process: `web: bundle exec lita`.
|
384
394
|
|
385
|
-
1. To use the Redis To Go add-on, configure Lita
|
395
|
+
1. To use the Redis To Go add-on and the HTTP port set by Heroku, configure Lita like this:
|
386
396
|
|
387
397
|
``` ruby
|
388
398
|
Lita.configure do |config|
|
389
399
|
config.redis.url = ENV["REDISTOGO_URL"]
|
400
|
+
config.http.port = ENV["PORT"]
|
390
401
|
end
|
391
402
|
```
|
392
403
|
|
@@ -396,6 +407,10 @@ There are a few things worth mentioning when deploying an instance of Lita to He
|
|
396
407
|
|
397
408
|
Complete documentation for all of Lita's classes and methods can be found at [rdoc.info](http://rdoc.info/gems/lita/frames).
|
398
409
|
|
410
|
+
## Try it out
|
411
|
+
|
412
|
+
You can chat with an instance of Lita on the Freenode IRC network in the channel `#litabot`. The bot's name is also *Litabot*.
|
413
|
+
|
399
414
|
## History
|
400
415
|
|
401
416
|
For a history of releases, see the [Releases](https://github.com/jimmycuadra/lita/releases) page.
|
data/lib/lita/authorization.rb
CHANGED
@@ -41,6 +41,23 @@ module Lita
|
|
41
41
|
Array(Lita.config.robot.admins).include?(user.id)
|
42
42
|
end
|
43
43
|
|
44
|
+
# Returns a list of all authorization groups.
|
45
|
+
# @return [Array<Symbol>] The names of all authorization groups.
|
46
|
+
def groups
|
47
|
+
redis.keys("*").map(&:to_sym)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns a hash of authorization group names and the users in them.
|
51
|
+
# @return [Hash] A map of +Symbol+ group names to +Lita::User+ objects.
|
52
|
+
def groups_with_users
|
53
|
+
groups.inject({}) do |list, group|
|
54
|
+
list[group] = redis.smembers(group).map do |user_id|
|
55
|
+
User.find_by_id(user_id)
|
56
|
+
end
|
57
|
+
list
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
44
61
|
private
|
45
62
|
|
46
63
|
# Ensures that group names are stored consistently in Redis.
|
data/lib/lita/handler.rb
CHANGED
@@ -56,10 +56,18 @@ module Lita
|
|
56
56
|
Lita.logger.debug <<-LOG.chomp
|
57
57
|
Dispatching message to #{self}##{route.method_name}.
|
58
58
|
LOG
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
begin
|
60
|
+
new(robot).public_send(route.method_name, Response.new(
|
61
|
+
message,
|
62
|
+
matches: message.match(route.pattern)
|
63
|
+
))
|
64
|
+
rescue Exception => e
|
65
|
+
Lita.logger.error <<-ERROR.chomp
|
66
|
+
#{name} crashed. The exception was:
|
67
|
+
#{e.message}
|
68
|
+
#{e.backtrace.join("\n")}
|
69
|
+
ERROR
|
70
|
+
end
|
63
71
|
end
|
64
72
|
end
|
65
73
|
end
|
@@ -8,6 +8,12 @@ module Lita
|
|
8
8
|
route(/^auth\s+remove/, :remove, command: true, help: {
|
9
9
|
"auth remove USER GROUP" => "Remove USER from authorization group GROUP. Requires admin privileges."
|
10
10
|
})
|
11
|
+
route(/^auth\s+list/, :list, command: true, help: {
|
12
|
+
"auth list [GROUP]" => <<-HELP
|
13
|
+
List authorization groups and the users in them. If GROUP is supplied, only \
|
14
|
+
lists that group."
|
15
|
+
HELP
|
16
|
+
})
|
11
17
|
|
12
18
|
# Adds a user to an authorization group.
|
13
19
|
# @param response [Lita::Response] The response object.
|
@@ -45,8 +51,40 @@ module Lita
|
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
54
|
+
# Lists all authorization groups (or only the specified group) and the
|
55
|
+
# names of their members.
|
56
|
+
# @param response [Lita::Response] The response object.
|
57
|
+
# @return [void]
|
58
|
+
def list(response)
|
59
|
+
requested_group = response.args[1]
|
60
|
+
output = get_groups_list(requested_group)
|
61
|
+
if output.empty?
|
62
|
+
if requested_group
|
63
|
+
response.reply(
|
64
|
+
"There is no authorization group named #{requested_group}."
|
65
|
+
)
|
66
|
+
else
|
67
|
+
response.reply("There are no authorization groups yet.")
|
68
|
+
end
|
69
|
+
else
|
70
|
+
response.reply(output.join("\n"))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
48
74
|
private
|
49
75
|
|
76
|
+
def get_groups_list(requested_group)
|
77
|
+
groups_with_users = Lita::Authorization.groups_with_users
|
78
|
+
if requested_group
|
79
|
+
requested_group = requested_group.downcase.strip.to_sym
|
80
|
+
groups_with_users.select! { |group, _| group == requested_group }
|
81
|
+
end
|
82
|
+
groups_with_users.map do |group, users|
|
83
|
+
user_names = users.map { |u| u.name }.join(", ")
|
84
|
+
"#{group}: #{user_names}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
50
88
|
# Validates that incoming messages have the right format and a valid user.
|
51
89
|
# Also assigns the user and group to instance variables for the main
|
52
90
|
# methods to use later.
|
data/lib/lita/rspec.rb
CHANGED
data/lib/lita/version.rb
CHANGED
data/lita.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_runtime_dependency "thor", "~> 0.18.1"
|
30
30
|
|
31
31
|
spec.add_development_dependency "rake"
|
32
|
-
spec.add_development_dependency "rspec", "
|
32
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
33
33
|
spec.add_development_dependency "simplecov"
|
34
34
|
spec.add_development_dependency "coveralls"
|
35
35
|
spec.add_development_dependency "pry"
|
@@ -73,4 +73,42 @@ describe Lita::Authorization, lita: true do
|
|
73
73
|
expect(described_class.user_is_admin?(user)).to be_false
|
74
74
|
end
|
75
75
|
end
|
76
|
+
|
77
|
+
describe ".groups" do
|
78
|
+
before do
|
79
|
+
%i{foo bar baz}.each do |group|
|
80
|
+
described_class.add_user_to_group(requesting_user, user, group)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it "returns a list of all authorization groups" do
|
85
|
+
expect(described_class.groups).to match_array(%i{foo bar baz})
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe ".groups_with_users" do
|
90
|
+
before do
|
91
|
+
%i{foo bar baz}.each do |group|
|
92
|
+
described_class.add_user_to_group(requesting_user, user, group)
|
93
|
+
described_class.add_user_to_group(
|
94
|
+
requesting_user,
|
95
|
+
requesting_user,
|
96
|
+
group
|
97
|
+
)
|
98
|
+
end
|
99
|
+
allow(Lita::User).to receive(:find_by_id).with("1").and_return(
|
100
|
+
requesting_user
|
101
|
+
)
|
102
|
+
allow(Lita::User).to receive(:find_by_id).with("2").and_return(user)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "returns a hash of all authorization groups and their members" do
|
106
|
+
groups = %i{foo bar baz}
|
107
|
+
groups_with_users = described_class.groups_with_users
|
108
|
+
expect(groups_with_users.keys).to match_array(groups)
|
109
|
+
groups.each do |group|
|
110
|
+
expect(groups_with_users[group]).to match_array([user, requesting_user])
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
76
114
|
end
|
data/spec/lita/handler_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Lita::Handler do
|
3
|
+
describe Lita::Handler, lita: true do
|
4
4
|
let(:robot) { double("Lita::Robot", name: "Lita") }
|
5
5
|
let(:user) { double("Lita::User") }
|
6
6
|
|
@@ -15,6 +15,7 @@ describe Lita::Handler do
|
|
15
15
|
route(/\w{3}/, :foo)
|
16
16
|
route(/\w{4}/, :blah, command: true)
|
17
17
|
route(/secret/, :secret, restrict_to: :admins)
|
18
|
+
route(/danger/, :danger)
|
18
19
|
|
19
20
|
http.get "web", :web
|
20
21
|
|
@@ -30,6 +31,10 @@ describe Lita::Handler do
|
|
30
31
|
def web(request, response)
|
31
32
|
end
|
32
33
|
|
34
|
+
def danger(response)
|
35
|
+
raise "The developer of this handler's got a bug in their code!"
|
36
|
+
end
|
37
|
+
|
33
38
|
def self.name
|
34
39
|
"Lita::Handlers::Test"
|
35
40
|
end
|
@@ -85,6 +90,14 @@ describe Lita::Handler do
|
|
85
90
|
expect_any_instance_of(handler_class).not_to receive(:secret)
|
86
91
|
handler_class.dispatch(robot, message)
|
87
92
|
end
|
93
|
+
|
94
|
+
it "logs exceptions but doesn't crash the bot" do
|
95
|
+
allow(message).to receive(:body).and_return("#{robot.name}: danger")
|
96
|
+
expect(Lita.logger).to receive(:error).with(
|
97
|
+
%r{Lita::Handlers::Test crashed}
|
98
|
+
)
|
99
|
+
expect { handler_class.dispatch(robot, message) }.not_to raise_error
|
100
|
+
end
|
88
101
|
end
|
89
102
|
|
90
103
|
describe ".namespace" do
|
@@ -13,6 +13,8 @@ describe Lita::Handlers::Authorization, lita_handler: true do
|
|
13
13
|
it { routes_command("auth add foo@bar.com baz").to(:add) }
|
14
14
|
it { routes_command("auth remove foo bar").to(:remove) }
|
15
15
|
it { routes_command("auth remove foo@bar.com baz").to(:remove) }
|
16
|
+
it { routes_command("auth list").to(:list) }
|
17
|
+
it { routes_command("auth list foo").to(:list) }
|
16
18
|
|
17
19
|
describe "#add" do
|
18
20
|
it "replies with the proper format if the require commands are missing" do
|
@@ -73,4 +75,44 @@ describe Lita::Handlers::Authorization, lita_handler: true do
|
|
73
75
|
expect(replies.last).to match(/Only administrators can remove/)
|
74
76
|
end
|
75
77
|
end
|
78
|
+
|
79
|
+
describe "#list" do
|
80
|
+
context "when there are populated groups" do
|
81
|
+
let(:groups) { %i{foo bar} }
|
82
|
+
let(:user1) { Lita::User.create(3, name: "Bongo") }
|
83
|
+
let(:user2) { Lita::User.create(4, name: "Carl") }
|
84
|
+
|
85
|
+
before do
|
86
|
+
groups.each do |group|
|
87
|
+
Lita::Authorization.add_user_to_group(user, user1, group)
|
88
|
+
Lita::Authorization.add_user_to_group(user, user2, group)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it "lists all authorization groups and their members" do
|
93
|
+
send_command("auth list")
|
94
|
+
groups.each do |group|
|
95
|
+
expect(replies.last).to include(
|
96
|
+
"#{group}: #{user1.name}, #{user2.name}"
|
97
|
+
)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "lists only the requested group" do
|
102
|
+
send_command("auth list foo")
|
103
|
+
expect(replies.last).to include("foo")
|
104
|
+
expect(replies.last).not_to include("bar")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it "replies that there are no groups" do
|
109
|
+
send_command("auth list")
|
110
|
+
expect(replies.last).to include("no authorization groups yet")
|
111
|
+
end
|
112
|
+
|
113
|
+
it "replies that the specified group doesn't exist" do
|
114
|
+
send_command("auth list nothing")
|
115
|
+
expect(replies.last).to include("no authorization group named nothing")
|
116
|
+
end
|
117
|
+
end
|
76
118
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lita
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jimmy Cuadra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-07-
|
11
|
+
date: 2013-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -126,16 +126,16 @@ dependencies:
|
|
126
126
|
name: rspec
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- -
|
129
|
+
- - ~>
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: 2.14
|
131
|
+
version: '2.14'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- -
|
136
|
+
- - ~>
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 2.14
|
138
|
+
version: '2.14'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: simplecov
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|