clavem 1.0.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.
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <%
3
+ # encoding: utf-8
4
+ #
5
+ # This file is part of the clavem gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
6
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
7
+ #
8
+ %>
9
+ <html>
10
+ <head>
11
+ <title><%= @title %></title>
12
+ <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap.no-icons.min.css"/>
13
+ <script type="text/javascript"> close_window = (function(){ window.open("", "_self", ""); window.close(); })(); </script>
14
+ </head>
15
+ <body>
16
+ <div class="container">
17
+ <br/>
18
+ <div class="alert alert-<%= @status == :success ? "success" : "error" %>">
19
+ <h4><%= @title %></h4>
20
+ <h1><%= @i18n.send(@status == :success ? :header_success : :header_failure) %></h1>
21
+ <p><%= @i18n.close_message %></p>
22
+ </div>
23
+ </div>
24
+ </body>
25
+ </html>
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the clavem gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ module Clavem
8
+ # The current version of clavem, according to semantic versioning.
9
+ #
10
+ # @see http://semver.org
11
+ module Version
12
+ # The major version.
13
+ MAJOR = 1
14
+
15
+ # The minor version.
16
+ MINOR = 0
17
+
18
+ # The patch version.
19
+ PATCH = 0
20
+
21
+ # The current version of clavem.
22
+ STRING = [MAJOR, MINOR, PATCH].compact.join(".")
23
+ end
24
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the clavem gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+ ---
7
+ header_success: "Authentication succeded!"
8
+ header_failure: "Authentication failed!"
9
+ close_message: "This window should close immediately. Alternatively you can close it by <a href=\"javascript:close_window();\">clicking here</a>."
data/locales/it.yml ADDED
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the clavem gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+ ---
7
+ header_success: "Autenticazione riuscita!"
8
+ header_failure: "Autenticazione fallita!"
9
+ close_message: "Questa finestra dovrebbe chiudersi immediatamente. Alternativamente puoi chiuderla <a href=\"javascript:close_window();\">cliccando qui</a>."
@@ -0,0 +1,334 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the clavem gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ require "spec_helper"
8
+
9
+ class ClavemDummyServer
10
+ attr_accessor :started
11
+
12
+ def start
13
+ self.started = true
14
+ end
15
+
16
+ def shutdown
17
+ self.started = false
18
+ end
19
+
20
+ def mount_proc(path, &handler)
21
+
22
+ end
23
+ end
24
+
25
+ class ClavemDummyRequest
26
+ attr_reader :query
27
+
28
+ def initialize(token = nil)
29
+ @query = {"oauth_token" => token}
30
+ end
31
+ end
32
+
33
+ class ClavemDummyResponse
34
+ attr_accessor :status
35
+ attr_accessor :body
36
+ end
37
+
38
+ describe Clavem::Authorizer do
39
+ let(:instance){::Clavem::Authorizer.new}
40
+
41
+ describe ".instance" do
42
+ it("should call .new with the passed arguments") do
43
+ ::Clavem::Authorizer.should_receive(:new).with("IP", "PORT", "COMMAND", "TITLE", "TEMPLATE", "TIMEOUT")
44
+ ::Clavem::Authorizer.instance("IP", "PORT", "COMMAND", "TITLE", "TEMPLATE", "TIMEOUT")
45
+ end
46
+
47
+ it("should return the same instance") do
48
+ ::Clavem::Authorizer.stub(:new) do Time.now end
49
+ authorizer = ::Clavem::Authorizer.instance("FIRST")
50
+ expect(::Clavem::Authorizer.instance("SECOND")).to be(authorizer)
51
+ end
52
+
53
+ it("should return a new instance if requested to") do
54
+ ::Clavem::Authorizer.stub(:new) do Time.now end
55
+ authorizer = ::Clavem::Authorizer.instance("FIRST")
56
+ expect(::Clavem::Authorizer.instance("IP", "PORT", "COMMAND", "TITLE", "TEMPLATE", "TIMEOUT", true)).not_to be(authorizer)
57
+ end
58
+ end
59
+
60
+ describe "#initialize" do
61
+ it("should handle default arguments") do
62
+ authorizer = ::Clavem::Authorizer.new
63
+ expect(authorizer.ip).to eq("127.0.0.1")
64
+ expect(authorizer.port).to eq(2501)
65
+ expect(authorizer.command).to eq("open \"{{URL}}\"")
66
+ expect(authorizer.title).to eq("Clavem Authorization")
67
+ expect(authorizer.template).to eq(File.read(File.dirname(__FILE__) + "/../../lib/clavem/template.html.erb"))
68
+ expect(authorizer.timeout).to eq(0)
69
+ expect(authorizer.response_handler).to be_nil
70
+ end
71
+
72
+ it("should assign arguments") do
73
+ authorizer = ::Clavem::Authorizer.new("IP", 2511, "COMMAND", "TITLE", "TEMPLATE", 2) do end
74
+ expect(authorizer.ip).to eq("IP")
75
+ expect(authorizer.port).to eq(2511)
76
+ expect(authorizer.command).to eq("COMMAND")
77
+ expect(authorizer.title).to eq("TITLE")
78
+ expect(authorizer.template).to eq("TEMPLATE")
79
+ expect(authorizer.timeout).to eq(2)
80
+ expect(authorizer.response_handler).to be_a(Proc)
81
+ end
82
+
83
+ it("should correct wrong arguments") do
84
+ authorizer = ::Clavem::Authorizer.new("IP", -10, nil, nil, "", -1)
85
+ expect(authorizer.port).to eq(2501)
86
+ expect(authorizer.timeout).to eq(0)
87
+ end
88
+
89
+ it("should setup internal status") do
90
+ authorizer = ::Clavem::Authorizer.new
91
+ expect(authorizer.token).to be_nil
92
+ expect(authorizer.status).to eq(:waiting)
93
+ end
94
+
95
+ it("should return self") do
96
+ expect(::Clavem::Authorizer.new).to be_a(::Clavem::Authorizer)
97
+ end
98
+ end
99
+
100
+ describe "#authorize" do
101
+ it("should call the correct authorize sequence and then return self") do
102
+ sequence = []
103
+ instance = ::Clavem::Authorizer.new
104
+ server = ::ClavemDummyServer.new
105
+
106
+ # Setup stuff
107
+ instance.stub(:setup_webserver) do sequence << 1 end
108
+
109
+ instance.instance_variable_set(:@server, server)
110
+ instance.stub(:setup_interruptions_handling) do sequence << 2 end
111
+ instance.stub(:setup_timeout_handling) do sequence << 3 end
112
+ instance.stub(:open_endpoint) do sequence << 4 end
113
+
114
+ server.should_receive(:start)
115
+ expect(instance.authorize("URL")).to be(instance)
116
+ expect(sequence).to eq([1, 2, 3, 4])
117
+ end
118
+
119
+ it("should raise an exception in case of timeout") do
120
+ instance = ::Clavem::Authorizer.new
121
+ instance.stub(:setup_webserver).and_raise(::Clavem::Exceptions::Timeout)
122
+ expect { instance.authorize("URL") }.to raise_error(::Clavem::Exceptions::Timeout)
123
+ expect(instance.status).to eq(:failure)
124
+ end
125
+
126
+ it("should raise an exception in case of errors") do
127
+ instance = ::Clavem::Authorizer.new
128
+ instance.stub(:setup_webserver).and_raise(ArgumentError)
129
+ expect { instance.authorize("URL") }.to raise_error(::Clavem::Exceptions::Failure)
130
+ expect(instance.status).to eq(:failure)
131
+ end
132
+
133
+ it("should always run #cleanup") do
134
+ cleaned = false
135
+ instance = ::Clavem::Authorizer.new
136
+ instance.stub(:cleanup) do cleaned = true end
137
+ instance.stub(:open_endpoint) do end
138
+ instance.stub(:setup_webserver) do
139
+ instance.instance_variable_set(:@server, ::ClavemDummyServer.new)
140
+ end
141
+
142
+ cleaned = false
143
+ instance.authorize("URL")
144
+ expect(cleaned).to be_true
145
+
146
+ cleaned = false
147
+ instance.stub(:setup_webserver).and_raise(ArgumentError)
148
+ expect { instance.authorize("URL") }.to raise_error(::Clavem::Exceptions::Failure)
149
+ expect(cleaned).to be_true
150
+
151
+ cleaned = false
152
+ instance.stub(:setup_webserver).and_raise(::Clavem::Exceptions::Timeout)
153
+ expect { instance.authorize("URL") }.to raise_error(::Clavem::Exceptions::Timeout)
154
+ expect(cleaned).to be_true
155
+ end
156
+ end
157
+
158
+ describe "#callback_url" do
159
+ it("should return the correct callback") do
160
+ expect(::Clavem::Authorizer.new.callback_url).to eq("http://127.0.0.1:2501/")
161
+ expect(::Clavem::Authorizer.new("10.0.0.1", "80").callback_url).to eq("http://10.0.0.1:80/")
162
+ end
163
+ end
164
+
165
+ describe "#default_response_handler" do
166
+ it("should return the token") do
167
+ instance = ::Clavem::Authorizer.new
168
+ expect(instance.default_response_handler(instance, ::ClavemDummyRequest.new("TOKEN"), nil)).to eq("TOKEN")
169
+ end
170
+
171
+ it("should return an empty string by default") do
172
+ instance = ::Clavem::Authorizer.new
173
+ expect(instance.default_response_handler(instance, ::ClavemDummyRequest.new(nil), nil)).to eq("")
174
+ end
175
+ end
176
+
177
+ # PRIVATE
178
+ describe "#open_endpoint" do
179
+ it("should call system with the right command") do
180
+ Kernel.should_receive(:system).with("open \"URL\"")
181
+ instance.instance_variable_set(:@url, "URL")
182
+ instance.send(:open_endpoint)
183
+
184
+ Kernel.should_receive(:system).with("COMMAND")
185
+ ::Clavem::Authorizer.new("IP", "PORT", "COMMAND").send(:open_endpoint)
186
+ end
187
+
188
+ it("should raise exception in case of failures") do
189
+ Kernel.stub(:system).and_raise(RuntimeError)
190
+ expect { instance.send(:open_endpoint) }.to raise_error(::Clavem::Exceptions::Failure)
191
+ end
192
+ end
193
+
194
+ describe "#setup_interruptions_handling" do
195
+ it("should add handler for SIGINT, SIGTERM, SIGKILL") do
196
+ Kernel.should_receive(:trap).with("USR2")
197
+ Kernel.should_receive(:trap).with("INT")
198
+ Kernel.should_receive(:trap).with("TERM")
199
+ Kernel.should_receive(:trap).with("KILL")
200
+ instance.send(:setup_interruptions_handling)
201
+ end
202
+ end
203
+
204
+ describe "#setup_timeout_handling" do
205
+ it("should not set a timeout handler by default") do
206
+ authorizer = ::Clavem::Authorizer.new
207
+ authorizer.stub(:open_endpoint) do end
208
+ authorizer.stub(:setup_webserver) do authorizer.instance_variable_set(:@server, ::ClavemDummyServer.new) end
209
+ authorizer.authorize("URL")
210
+ expect(authorizer.instance_variable_get(:@timeout_handler)).to be_nil
211
+ end
212
+
213
+ it("should set and execute a timeout handler") do
214
+ Process.should_receive(:kill).with("USR2", 0)
215
+ Kernel.should_receive(:sleep).with(0.5)
216
+
217
+ server = ::ClavemDummyServer.new
218
+ server.stub(:start) do sleep(1) end
219
+
220
+ authorizer = ::Clavem::Authorizer.new("IP", "PORT", "COMMAND", "TITLE", "TEMPLATE", 500)
221
+ authorizer.stub(:open_endpoint) do end
222
+ authorizer.stub(:setup_webserver) do authorizer.instance_variable_set(:@server, server) end
223
+ expect { authorizer.authorize("URL") }.to raise_error(::Clavem::Exceptions::Timeout)
224
+
225
+ thread = authorizer.instance_variable_get(:@timeout_thread)
226
+ expect(thread).to be_a(Thread)
227
+ expect(thread.stop?).to be_true
228
+ expect(authorizer.instance_variable_get(:@timeout_expired)).to be_true
229
+ end
230
+ end
231
+
232
+ describe "#setup_webserver" do
233
+ it "should initialize a web server with correct arguments" do
234
+ logger = WEBrick::Log.new("/dev/null")
235
+ WEBrick::Log.stub(:new).and_return(logger)
236
+
237
+ ::WEBrick::HTTPServer.should_receive(:new).with(BindAddress: "10.0.0.1", Port: 80, Logger: logger, AccessLog: [nil, nil]).and_return(::ClavemDummyServer.new)
238
+ authorizer = ::Clavem::Authorizer.new("10.0.0.1", 80)
239
+ authorizer.send(:setup_webserver)
240
+ end
241
+
242
+ it "should setup a single request handler on /" do
243
+ server = ::ClavemDummyServer.new
244
+ ::WEBrick::HTTPServer.stub(:new).and_return(server)
245
+ authorizer = ::Clavem::Authorizer.new("IP", "PORT")
246
+ server.should_receive(:mount_proc).with("/")
247
+ authorizer.send(:setup_webserver)
248
+ end
249
+ end
250
+
251
+ describe "#dispatch_request" do
252
+ let(:request) { ::ClavemDummyRequest.new }
253
+ let(:response) { ::ClavemDummyResponse.new }
254
+ let(:server) { ::ClavemDummyServer.new }
255
+
256
+ it "should call the correct handler" do
257
+ instance.instance_variable_set(:@server, ::ClavemDummyServer.new)
258
+ instance.should_receive(:default_response_handler).with(instance, request, response)
259
+ instance.send(:dispatch_request, request, response)
260
+
261
+ authorizer = ::Clavem::Authorizer.new do end
262
+ authorizer.instance_variable_set(:@server, ::ClavemDummyServer.new)
263
+ authorizer.response_handler.should_receive(:call).with(authorizer, request, response)
264
+ authorizer.send(:dispatch_request, request, response)
265
+ end
266
+
267
+ it "should handle request only if the status is still :waiting" do
268
+ authorizer = ::Clavem::Authorizer.new
269
+ authorizer.instance_variable_set(:@server, server)
270
+ authorizer.status = :waiting
271
+ server.should_receive(:shutdown)
272
+ authorizer.send(:dispatch_request, request, response)
273
+
274
+ authorizer = ::Clavem::Authorizer.new
275
+ authorizer.instance_variable_set(:@server, server)
276
+ authorizer.status = :success
277
+ server.should_not_receive(:shutdown)
278
+ authorizer.send(:dispatch_request, request, response)
279
+ end
280
+
281
+ it "should correctly set status" do
282
+ authorizer = ::Clavem::Authorizer.new
283
+ authorizer.instance_variable_set(:@server, server)
284
+ authorizer.send(:dispatch_request, ::ClavemDummyRequest.new("TOKEN"), response)
285
+ expect(authorizer.status).to eq(:success)
286
+ expect(response.status).to eq(200)
287
+
288
+ authorizer = ::Clavem::Authorizer.new
289
+ authorizer.instance_variable_set(:@server, server)
290
+ authorizer.send(:dispatch_request, request, response)
291
+ expect(authorizer.status).to eq(:denied)
292
+ expect(response.status).to eq(403)
293
+ end
294
+
295
+ it "should render the body of the response" do
296
+ authorizer = ::Clavem::Authorizer.new
297
+ authorizer.instance_variable_set(:@server, server)
298
+ authorizer.instance_variable_get(:@compiled_template).should_receive(:result).and_return("TEMPLATE")
299
+ authorizer.send(:dispatch_request, request, response)
300
+ expect(response.body).to eq("TEMPLATE")
301
+ end
302
+ end
303
+
304
+ describe "#cleanup" do
305
+ it "should shutdown the server and cleanup signal handling" do
306
+ server = ::ClavemDummyServer.new
307
+ server.stub(:start) do sleep(1) end
308
+
309
+ authorizer = ::Clavem::Authorizer.new("IP", "PORT", "COMMAND", "TITLE", "TEMPLATE")
310
+ authorizer.stub(:open_endpoint) do end
311
+ authorizer.stub(:setup_webserver) do authorizer.instance_variable_set(:@server, server) end
312
+ authorizer.authorize("URL")
313
+
314
+ Kernel.should_receive(:trap).with("USR2", "DEFAULT")
315
+ Kernel.should_receive(:trap).with("INT", "DEFAULT")
316
+ Kernel.should_receive(:trap).with("TERM", "DEFAULT")
317
+ Kernel.should_receive(:trap).with("KILL", "DEFAULT")
318
+ server.should_receive(:shutdown)
319
+ authorizer.send(:cleanup)
320
+ end
321
+
322
+ it "should exit timeout handling thread if active" do
323
+ thread = nil
324
+ server = ::ClavemDummyServer.new
325
+ server.stub(:start) do sleep(1) end
326
+
327
+ authorizer = ::Clavem::Authorizer.new("IP", "PORT", "COMMAND", "TITLE", "TEMPLATE", 5000)
328
+ authorizer.send(:setup_timeout_handling)
329
+ thread = authorizer.instance_variable_get(:@timeout_thread)
330
+ thread.should_receive(:exit)
331
+ authorizer.send(:cleanup)
332
+ end
333
+ end
334
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the clavem gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ require "pathname"
8
+
9
+ if ENV["CLAVEM_COVERAGE"] then
10
+ require "simplecov"
11
+ root = Pathname.new(File.dirname(__FILE__)) + ".."
12
+
13
+ SimpleCov.start do
14
+ add_filter do |src_file|
15
+ path = Pathname.new(src_file.filename).relative_path_from(root).to_s
16
+
17
+ # TODO: Add exclusions here
18
+ path !~ /^(bin|lib)/
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the clavem gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ require "rubygems"
8
+ require "coverage_helper"
9
+ require "bundler/setup"
10
+ require "clavem"
11
+
12
+ RSpec.configure do |config|
13
+ config.expect_with :rspec do |c|
14
+ c.syntax = :expect
15
+ end
16
+ end