grape-slack-bot 1.3.0 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 669dbf492365849f4628ed362f0a047e70d15cb80a62a236260be26d76fbaacc
4
- data.tar.gz: e17819f3afa4096b5623c4a8d19f6443522c2010d528ac6a14fefc17fb3c3309
3
+ metadata.gz: 2d248818a6772bc6b90aaaff5e6a32f34ed8f1be71d3865435929e018f30d48b
4
+ data.tar.gz: 8719e28b6995efa871e4a834aa5ac884cbda4133034805e256ddf53786c1fdb2
5
5
  SHA512:
6
- metadata.gz: 05de3c891473d52722c368bd587e7a90b7d8e9eaa96c4f6bd59bd4bbb5f867c265e2fab1b2e95076abd8b75c0dd9460a51ea460909afd538e9c0c0962fe8250c
7
- data.tar.gz: c80d3a362202a526df44c32dad70270109ef344180d7d83d27cca9a24c9f308d422c7f8f91215a0a31b357ef2e86d14771b048f344051a7bc48ca27f80fa73d1
6
+ metadata.gz: 3a20d2e0f603d9f5a1cbfc24d8e08e9907b12d6d677442d63160cf0a5f57b3dc56234bd65b0d979749574e290a3a3fb00b8f014bf219c8bf969e2c4d1cd7f7f3
7
+ data.tar.gz: f3401998a0b1cd270e952107d86f2da78de98cc45b4260d7205998ff173e00f356d09185d08f50416bebe5b38593fe9cb40e829b2f4a4454bc3dafd53414227b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 1.5.0
2
+
3
+ * Complete upgrade of callback storage logic
4
+
5
+ # 1.4.0
6
+
7
+ * Allow setting callback expiration time on save and update
8
+
1
9
  # 1.3.0
2
10
 
3
11
  * Clean up callback arguments, remove unused `method_name`
@@ -3,42 +3,53 @@ require 'active_support/core_ext/numeric/time'
3
3
 
4
4
  module SlackBot
5
5
  class Callback
6
- CALLBACK_CACHE_KEY = "slack-bot-callback".freeze
6
+ CALLBACK_KEY_PREFIX = "slack-bot-callback".freeze
7
+ CALLBACK_RECORD_EXPIRES_IN = 15.minutes.freeze
7
8
 
8
- def self.find(id, config: nil)
9
+ def self.find(id, user: nil, config: nil)
9
10
  return if id.blank?
10
11
 
11
- callback = new(id: id, config: config)
12
+ callback = new(id: id, user: user, config: config)
12
13
  callback.reload
13
14
  rescue SlackBot::Errors::CallbackNotFound
14
15
  nil
15
16
  end
16
17
 
17
- def self.create(class_name:, user:, channel_id: nil, config: nil)
18
+ def self.create(class_name:, user:, channel_id: nil, config: nil, payload: nil, expires_in: nil, user_scope: nil)
18
19
  callback =
19
- new(class_name: class_name, user: user, channel_id: channel_id, config: config)
20
+ new(class_name: class_name, user: user, channel_id: channel_id, payload: payload, config: config, expires_in: expires_in, user_scope: user_scope)
20
21
  callback.save
21
22
  callback
22
23
  end
23
24
 
24
- attr_reader :id, :data, :args, :config
25
- def initialize(id: nil, class_name: nil, user: nil, channel_id: nil, extra: nil, config: nil)
25
+ def self.find_or_create(id:, class_name:, user:, channel_id: nil, config: nil, payload: nil, expires_in: nil, user_scope: nil)
26
+ callback = find(id, user: user, config: config)
27
+ return callback if callback.present?
28
+
29
+ create(class_name: class_name, user: user, channel_id: channel_id, payload: payload, config: config, expires_in: expires_in, user_scope: user_scope)
30
+ end
31
+
32
+ attr_reader :id, :data, :args, :config, :expires_in, :user_scope
33
+ def initialize(id: nil, class_name: nil, user: nil, channel_id: nil, payload: nil, config: nil, expires_in: nil, user_scope: nil)
26
34
  @id = id
27
35
  @data = {
28
36
  class_name: class_name,
29
37
  user_id: user&.id,
30
38
  channel_id: channel_id,
31
- extra: extra
39
+ payload: payload
32
40
  }
33
41
  @args = SlackBot::Args.new
34
42
  @config = config || SlackBot::Config.current_instance
43
+ @expires_in = expires_in || CALLBACK_RECORD_EXPIRES_IN
44
+ @user_scope = user_scope.nil? ? true : user_scope
35
45
  end
36
46
 
37
47
  def reload
38
- @data = read_data
39
- SlackBot::DevConsole.log_check("SlackBot::Callback#read_data: #{id} | #{data}")
40
- raise SlackBot::Errors::CallbackNotFound if data.nil?
48
+ cached_data = read_data
49
+ SlackBot::DevConsole.log_check("SlackBot::Callback#read_data: #{id} | #{cached_data}")
50
+ raise SlackBot::Errors::CallbackNotFound if cached_data.nil?
41
51
 
52
+ @data = cached_data
42
53
  parse_args
43
54
  self
44
55
  end
@@ -55,7 +66,12 @@ module SlackBot
55
66
  return if id.blank?
56
67
  return if data.blank?
57
68
 
58
- @data = data.merge(payload)
69
+ if @data[:payload].is_a?(Hash)
70
+ @data[:payload] = @data[:payload].merge(payload)
71
+ else
72
+ @data[:payload] = payload
73
+ end
74
+
59
75
  save
60
76
  end
61
77
 
@@ -72,6 +88,23 @@ module SlackBot
72
88
  end
73
89
  end
74
90
 
91
+ def user=(user)
92
+ @user = user
93
+ @data[:user_id] = user&.id
94
+ end
95
+
96
+ def class_name=(class_name)
97
+ @data[:class_name] = class_name
98
+ end
99
+
100
+ def channel_id=(channel_id)
101
+ @data[:channel_id] = channel_id
102
+ end
103
+
104
+ def payload=(payload)
105
+ @data[:payload] = payload
106
+ end
107
+
75
108
  def handler_class
76
109
  return if class_name.blank?
77
110
 
@@ -80,6 +113,7 @@ module SlackBot
80
113
 
81
114
  def method_missing(method_name, *args, &block)
82
115
  return data[method_name.to_sym] if data.key?(method_name.to_sym)
116
+ return data[:payload][method_name.to_s] if data[:payload].is_a?(Hash) && data[:payload].key?(method_name.to_s)
83
117
 
84
118
  super
85
119
  end
@@ -91,23 +125,34 @@ module SlackBot
91
125
  end
92
126
 
93
127
  def serialize_args
94
- data[:args] = args.to_s
128
+ @data[:args] = args.to_s
95
129
  end
96
130
 
97
131
  def generate_id
98
- SecureRandom.uuid
132
+ SecureRandom.hex(10)
133
+ end
134
+
135
+ def storage_key
136
+ if user_scope
137
+ raise "User is required for scoped callback" if user.blank?
138
+
139
+ "#{CALLBACK_KEY_PREFIX}:u#{user.id}:#{id}"
140
+ else
141
+ "#{CALLBACK_KEY_PREFIX}:#{id}"
142
+ end
99
143
  end
100
144
 
101
145
  def read_data
102
- config.callback_storage_instance.read("#{CALLBACK_CACHE_KEY}:#{id}")
146
+ config.callback_storage_instance.read(storage_key)
103
147
  end
104
148
 
105
- def write_data(data)
106
- config.callback_storage_instance.write("#{CALLBACK_CACHE_KEY}:#{id}", data, expires_in: 1.hour)
149
+ def write_data(data, expires_in: nil)
150
+ expires_in ||= CALLBACK_RECORD_EXPIRES_IN
151
+ config.callback_storage_instance.write(storage_key, data, expires_in: expires_in)
107
152
  end
108
153
 
109
154
  def delete_data
110
- config.callback_storage_instance.delete("#{CALLBACK_CACHE_KEY}:#{id}")
155
+ config.callback_storage_instance.delete(storage_key)
111
156
  end
112
157
  end
113
158
  end
@@ -88,7 +88,7 @@ module SlackBot
88
88
  callback = SlackBot::Callback.find(callback_id, config: config)
89
89
  raise SlackBot::Errors::CallbackNotFound.new if callback.blank?
90
90
 
91
- SlackBot::DevConsole.log_check "SlackApi::Interactions##{__method__}: #{callback.id} #{callback.extra} #{callback.user_id} #{user&.id}"
91
+ SlackBot::DevConsole.log_check "SlackApi::Interactions##{__method__}: #{callback.id} #{callback.payload} #{callback.user_id} #{user&.id}"
92
92
 
93
93
  if callback.user_id != user.id
94
94
  raise "Callback user is not equal to action user"
data/lib/slack_bot.rb CHANGED
@@ -22,5 +22,5 @@ require 'slack_bot/pager'
22
22
  require 'slack_bot/grape_extension'
23
23
 
24
24
  module SlackBot
25
- VERSION = '1.3.0'.freeze
25
+ VERSION = '1.5.1'.freeze
26
26
  end
@@ -6,7 +6,7 @@ describe SlackBot::Callback do
6
6
  class_name: "Test",
7
7
  user: user,
8
8
  channel_id: "test_channel_id",
9
- extra: { test: "test" },
9
+ payload: { test: "test" },
10
10
  config: config
11
11
  )
12
12
  }
@@ -26,174 +26,115 @@ describe SlackBot::Callback do
26
26
  let(:callback_id) { "test_callback_id" }
27
27
 
28
28
  describe ".find" do
29
- subject(:find) { described_class.find(callback_id, config: config) }
29
+ subject(:find) { described_class.find(callback_id, user: user, config: config) }
30
30
 
31
- before do
32
- allow(callback_storage_instance).to receive(:read).with("slack-bot-callback:test_callback_id").and_return(data)
33
- end
34
-
35
- context "when callback is found" do
36
- let(:data) { { class_name: "Test", user_id: 1, channel_id: "test_channel_id", extra: { test: "test" }, args: "" } }
37
-
38
- it "returns callback" do
39
- expect(find).to be_a(described_class)
40
- expect(find.id).to eq(callback_id)
41
- expect(find.class_name).to eq("Test")
42
- expect(find.user).to eq(user)
43
- expect(find.user_id).to eq(1)
44
- expect(find.channel_id).to eq("test_channel_id")
45
- expect(find.extra).to eq({ test: "test" })
46
- end
47
- end
48
-
49
- context "when callback is not found" do
50
- let(:data) { nil }
51
-
52
- it "returns nil" do
53
- expect(find).to eq(nil)
54
- end
55
- end
56
- end
57
-
58
- describe ".create" do
59
- subject(:create) { described_class.create(class_name: "Test", user: user, channel_id: "test_channel_id", config: config) }
60
-
61
- before do
62
- allow_any_instance_of(described_class).to receive(:generate_id).and_return("test_callback_id")
63
- allow(callback_storage_instance).to receive(:write).with("slack-bot-callback:test_callback_id", {
64
- args: "",
65
- class_name: "Test",
66
- user_id: 1,
67
- channel_id: "test_channel_id",
68
- extra: nil
69
- }, expires_in: 1.hour)
70
- end
71
-
72
- let(:data) { { class_name: "Test", user_id: 1, channel_id: "test_channel_id", extra: nil } }
73
-
74
- it "returns callback" do
75
- expect(create).to be_a(described_class)
76
- expect(create.id).to eq("test_callback_id")
77
- expect(create.class_name).to eq("Test")
78
- expect(create.user).to eq(user)
79
- expect(create.user_id).to eq(1)
80
- expect(create.channel_id).to eq("test_channel_id")
81
- expect(create.extra).to eq(nil)
82
- end
83
- end
84
-
85
- describe "#reload" do
86
- subject(:reload) { callback.reload }
87
- let(:callback) {
88
- described_class.new(id: "test_callback_id", config: config)
89
- }
90
- let(:data) {
31
+ let(:cached_data) {
91
32
  {
92
33
  class_name: "Test",
93
- user_id: 1,
34
+ user_id: user.id,
94
35
  channel_id: "test_channel_id",
95
- extra: { test: "test" },
96
- args: ""
36
+ payload: { test: "test" },
37
+ args: "test"
97
38
  }
98
39
  }
99
40
 
100
41
  before do
101
- allow(callback_storage_instance).to receive(:read).with("slack-bot-callback:test_callback_id").and_return(data)
42
+ allow(callback_storage_instance).to receive(:read).with("#{SlackBot::Callback::CALLBACK_KEY_PREFIX}:u#{user.id}:#{callback_id}").and_return(cached_data)
102
43
  end
103
44
 
104
45
  it "returns callback" do
105
- expect(reload).to be_a(described_class)
106
- expect(reload.id).to eq("test_callback_id")
107
- expect(reload.class_name).to eq("Test")
108
- expect(reload.user).to eq(user)
109
- expect(reload.user_id).to eq(1)
110
- expect(reload.channel_id).to eq("test_channel_id")
111
- expect(reload.extra).to eq({ test: "test" })
46
+ expect(find).to be_a(described_class)
47
+ expect(find.id).to eq(callback_id)
48
+ expect(find.class_name).to eq("Test")
49
+ expect(find.user).to eq(user)
50
+ expect(find.channel_id).to eq("test_channel_id")
51
+ expect(find.payload).to eq({ test: "test" })
52
+ expect(find.args).to be_a(SlackBot::Args)
112
53
  end
113
54
 
114
55
  context "when callback is not found" do
115
- let(:data) { nil }
56
+ let(:cached_data) { nil }
116
57
 
117
- it "raises error" do
118
- expect { reload }.to raise_error(SlackBot::Errors::CallbackNotFound)
58
+ it "returns nil" do
59
+ expect(find).to be_nil
119
60
  end
120
61
  end
121
62
  end
122
63
 
123
- describe "#save" do
124
- subject(:save) { callback.save }
125
- let(:callback) {
126
- described_class.new(
64
+ describe ".create" do
65
+ subject(:create) {
66
+ described_class.create(
127
67
  class_name: "Test",
128
68
  user: user,
129
69
  channel_id: "test_channel_id",
130
- extra: { test: "test" },
70
+ payload: { test: "test" },
131
71
  config: config
132
72
  )
133
73
  }
134
74
 
135
- before do
136
- allow_any_instance_of(described_class).to receive(:generate_id).and_return("test_callback_id")
137
- allow(callback_storage_instance).to receive(:write).with("slack-bot-callback:test_callback_id", {
138
- args: "",
75
+ let(:cached_data) {
76
+ {
139
77
  class_name: "Test",
140
- user_id: 1,
78
+ user_id: user.id,
141
79
  channel_id: "test_channel_id",
142
- extra: { test: "test" }
143
- }, expires_in: 1.hour)
80
+ payload: { test: "test" },
81
+ args: ""
82
+ }
83
+ }
84
+
85
+ before do
86
+ allow_any_instance_of(described_class).to receive(:generate_id).and_return(callback_id)
87
+ allow(callback_storage_instance).to receive(:write).with("#{SlackBot::Callback::CALLBACK_KEY_PREFIX}:u#{user.id}:#{callback_id}", cached_data, expires_in: SlackBot::Callback::CALLBACK_RECORD_EXPIRES_IN).and_return(cached_data)
88
+ allow(callback_storage_instance).to receive(:read).with("#{SlackBot::Callback::CALLBACK_KEY_PREFIX}:u#{user.id}:#{callback_id}").and_return(cached_data)
144
89
  end
145
90
 
146
- it "returns callback" do
147
- expect { save }.not_to raise_error
148
- expect(callback).to be_a(described_class)
149
- expect(callback.id).to eq("test_callback_id")
150
- expect(callback.args).to be_a(SlackBot::Args)
91
+ it "creates callback" do
92
+ expect(create).to be_a(described_class)
93
+ expect(create.id).to be_present
94
+ expect(create.class_name).to eq("Test")
95
+ expect(create.user).to eq(user)
96
+ expect(create.channel_id).to eq("test_channel_id")
97
+ expect(create.payload).to eq({ test: "test" })
98
+ expect(create.args).to be_a(SlackBot::Args)
151
99
  end
152
100
  end
153
101
 
154
- describe "#update" do
155
- subject(:update) { callback.update(payload) }
156
- let(:callback) {
157
- described_class.new(
158
- id: "test_callback_id",
102
+ describe ".find_or_create" do
103
+ subject(:find_or_create) {
104
+ described_class.find_or_create(
105
+ id: callback_id,
159
106
  class_name: "Test",
160
107
  user: user,
161
108
  channel_id: "test_channel_id",
162
- extra: { test: "test" },
109
+ payload: { test: "test" },
163
110
  config: config
164
111
  )
165
112
  }
166
113
 
167
- before do
168
- allow(callback_storage_instance).to receive(:write).with("slack-bot-callback:test_callback_id", {
169
- args: "",
114
+ let(:cached_data) {
115
+ {
170
116
  class_name: "Test",
171
- user_id: 1,
117
+ user_id: user.id,
172
118
  channel_id: "test_channel_id",
173
- extra: { test: "test" },
174
- test: "test"
175
- }, expires_in: 1.hour)
176
- end
177
-
178
- let(:payload) { { test: "test" } }
119
+ payload: { test: "test" },
120
+ args: ""
121
+ }
122
+ }
179
123
 
180
- it "returns callback" do
181
- expect { update }.not_to raise_error
182
- expect(callback).to be_a(described_class)
183
- expect(callback.id).to eq("test_callback_id")
184
- expect(callback.args).to be_a(SlackBot::Args)
124
+ before do
125
+ allow_any_instance_of(described_class).to receive(:generate_id).and_return(callback_id)
126
+ allow(callback_storage_instance).to receive(:write).with("#{SlackBot::Callback::CALLBACK_KEY_PREFIX}:u#{user.id}:#{callback_id}", cached_data, expires_in: SlackBot::Callback::CALLBACK_RECORD_EXPIRES_IN).and_return(cached_data)
127
+ allow(callback_storage_instance).to receive(:read).with("#{SlackBot::Callback::CALLBACK_KEY_PREFIX}:u#{user.id}:#{callback_id}").and_return(cached_data)
185
128
  end
186
- end
187
-
188
- describe "#destroy" do
189
-
190
- end
191
-
192
- describe "#user" do
193
-
194
- end
195
-
196
- describe "#handler_class" do
197
129
 
130
+ it "finds or creates callback" do
131
+ expect(find_or_create).to be_a(described_class)
132
+ expect(find_or_create.id).to eq(callback_id)
133
+ expect(find_or_create.class_name).to eq("Test")
134
+ expect(find_or_create.user).to eq(user)
135
+ expect(find_or_create.channel_id).to eq("test_channel_id")
136
+ expect(find_or_create.payload).to eq({ test: "test" })
137
+ expect(find_or_create.args).to be_a(SlackBot::Args)
138
+ end
198
139
  end
199
140
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-slack-bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Makarov