hobby-auth 0.0.1 → 0.0.2
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/.gitignore +1 -0
- data/Gemfile +1 -1
- data/hobby-auth.gemspec +2 -2
- data/lib/hobby/auth.rb +32 -7
- data/readme.adoc +95 -0
- data/spec/http/getter_decorator.yml +22 -0
- data/spec/http_spec.rb +9 -0
- data/spec/name_shadowing_spec.rb +27 -0
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fd7308d5de3ee1087bf4829558efeb555f18433
|
4
|
+
data.tar.gz: 383fd2c09d0fc8a72d63e0f6f6857df11439b690
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfc2f279d0e4f7979ea66adb086067c19f5e4320ea0a9aea0a7cb865ae6a9c4b5939e2e305902db56b222f0567b707c5c8ef3d14790d9bbc4f6e9492d9639345
|
7
|
+
data.tar.gz: c57175fc1f465f1524d0000342b36c2f1a192dfd37da8c5a78167ed409ab42d93a5487895eedfd0d9be4f3b33ce1ca715ae9c53340c9c2787979aa359e9e82b5
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/hobby-auth.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |g|
|
2
2
|
g.name = 'hobby-auth'
|
3
3
|
g.files = `git ls-files`.split($/)
|
4
|
-
g.version = '0.0.
|
5
|
-
g.summary = '
|
4
|
+
g.version = '0.0.2'
|
5
|
+
g.summary = 'A Hobby extension to authorize routes.'
|
6
6
|
g.authors = ['Anatoly Chernow']
|
7
7
|
end
|
data/lib/hobby/auth.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
module Hobby
|
2
2
|
module Auth
|
3
3
|
def self.[] *user_models
|
4
|
+
pairs = find_pairs user_models
|
5
|
+
|
4
6
|
Module.new do
|
5
7
|
define_singleton_method :included do |app|
|
6
|
-
|
7
|
-
app.define_singleton_method
|
8
|
+
pairs.each do |name, user_model|
|
9
|
+
app.define_singleton_method name do |route|
|
8
10
|
action = route.action
|
9
11
|
route.action = -> do
|
10
12
|
if user = (user_model.find_by_token env['HTTP_AUTHORIZATION'])
|
@@ -19,12 +21,35 @@ module Hobby
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
22
|
-
def self.short_name_of user_model
|
23
|
-
user_model.name.split('::').last.downcase
|
24
|
-
end
|
25
|
-
|
26
24
|
attr_reader :user
|
27
25
|
end
|
28
26
|
end
|
27
|
+
|
28
|
+
class SameNames < StandardError
|
29
|
+
def initialize models, name
|
30
|
+
first, second = models
|
31
|
+
message = "The short names of #{first} and #{second} are the same: #{name}."
|
32
|
+
super message
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.find_pairs user_models
|
37
|
+
pairs = user_models.map { |um| [(short_name_of um), um] }
|
38
|
+
|
39
|
+
names = {}
|
40
|
+
pairs.each do |name, model|
|
41
|
+
if first_model_with_that_name = names[name]
|
42
|
+
fail SameNames.new [first_model_with_that_name, model], name
|
43
|
+
else
|
44
|
+
names[name] = model
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
pairs
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.short_name_of user_model
|
52
|
+
user_model.name.split('::').last.downcase
|
53
|
+
end
|
29
54
|
end
|
30
|
-
end
|
55
|
+
end
|
data/readme.adoc
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
= Hobby-Auth
|
2
|
+
|
3
|
+
This repository provides a https://github.com/ch1c0t/hobby[Hobby] extension
|
4
|
+
to authorize routes.
|
5
|
+
|
6
|
+
== Installation
|
7
|
+
|
8
|
+
[source,bash]
|
9
|
+
----
|
10
|
+
gem install hobby-auth
|
11
|
+
----
|
12
|
+
|
13
|
+
== Introduction
|
14
|
+
|
15
|
+
You are expected to pass your user models as arguments to `Hobby::Auth.[]`:
|
16
|
+
|
17
|
+
[source,ruby]
|
18
|
+
----
|
19
|
+
require 'hobby'
|
20
|
+
require 'hobby/auth'
|
21
|
+
|
22
|
+
class YourApp
|
23
|
+
include Hobby
|
24
|
+
include Auth[*array_of_user_models]
|
25
|
+
|
26
|
+
# some route defining logic goes here, after 'includes'
|
27
|
+
end
|
28
|
+
----
|
29
|
+
|
30
|
+
A user model is any object that responds to these two methods:
|
31
|
+
|
32
|
+
* `.name` which returns a `String` which might be in
|
33
|
+
https://ruby-doc.org/core/Module.html#method-i-name[Module#name].
|
34
|
+
* `.find_by_token` which takes one argument(a token `String`),
|
35
|
+
and returns `nil`(if no user were found) or a user(which
|
36
|
+
can be any object you would like to consider a user in your application).
|
37
|
+
|
38
|
+
You can access that user via `user` method.
|
39
|
+
|
40
|
+
Consider an example app where you need two user roles: managers and drivers.
|
41
|
+
You can define `Manager` class as follows:
|
42
|
+
|
43
|
+
[source,ruby]
|
44
|
+
----
|
45
|
+
class Manager
|
46
|
+
def self.find_by_token token
|
47
|
+
new if token == 'the only valid token at the moment'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
----
|
51
|
+
and `Driver` class similarly.
|
52
|
+
|
53
|
+
Then, you can use them in your app:
|
54
|
+
|
55
|
+
[source,ruby]
|
56
|
+
----
|
57
|
+
class App
|
58
|
+
include Hobby
|
59
|
+
include Auth[Manager, Driver]
|
60
|
+
|
61
|
+
manager post('/managers_route') {
|
62
|
+
# do something only managers can do
|
63
|
+
user # will return a `Manager` instance
|
64
|
+
}
|
65
|
+
|
66
|
+
driver get('/drivers_route') {
|
67
|
+
# do something only drivers can do
|
68
|
+
user # will return a `Driver` instance
|
69
|
+
}
|
70
|
+
end
|
71
|
+
----
|
72
|
+
|
73
|
+
The token is expected to be passed via
|
74
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization[Authorization header].
|
75
|
+
If no user were found, the response's status will be set to
|
76
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403[403].
|
77
|
+
|
78
|
+
NOTE: If your user models have names leading to the same decorator name
|
79
|
+
(for example, `Manager` and `SomeNamespace::Manager`),
|
80
|
+
a `Hobby::Auth::SameNames` error will be raised.
|
81
|
+
|
82
|
+
== Development
|
83
|
+
|
84
|
+
To run the specs:
|
85
|
+
|
86
|
+
[source,bash]
|
87
|
+
----
|
88
|
+
bundle exec rspec
|
89
|
+
----
|
90
|
+
|
91
|
+
To perform mutation analysis:
|
92
|
+
[source,bash]
|
93
|
+
----
|
94
|
+
bundle exec mutant --use rspec 'Hobby::Auth*'
|
95
|
+
----
|
@@ -0,0 +1,22 @@
|
|
1
|
+
- get:
|
2
|
+
path: /decorator
|
3
|
+
|
4
|
+
response:
|
5
|
+
status: 403
|
6
|
+
|
7
|
+
- get:
|
8
|
+
path: /decorator
|
9
|
+
headers:
|
10
|
+
Authorization: invalid token
|
11
|
+
|
12
|
+
response:
|
13
|
+
status: 403
|
14
|
+
|
15
|
+
- get:
|
16
|
+
path: /decorator
|
17
|
+
headers:
|
18
|
+
Authorization: first valid getter token
|
19
|
+
|
20
|
+
response:
|
21
|
+
status: 200
|
22
|
+
body: decorator append
|
data/spec/http_spec.rb
CHANGED
@@ -10,6 +10,15 @@ Hobby::Devtools::RSpec.describe do
|
|
10
10
|
|
11
11
|
getter get { 'oh my get' }
|
12
12
|
poster post { "the user's token is #{user.token}" }
|
13
|
+
|
14
|
+
|
15
|
+
def self.append_decorator route
|
16
|
+
action = route.action
|
17
|
+
route.action = -> { "#{instance_exec(&action)} append" }
|
18
|
+
route
|
19
|
+
end
|
20
|
+
|
21
|
+
append_decorator getter get('/decorator') { 'decorator' }
|
13
22
|
end.new
|
14
23
|
end
|
15
24
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class Same
|
4
|
+
def self.find_by_token _token
|
5
|
+
new
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Namespaced
|
10
|
+
class Same
|
11
|
+
def self.find_by_token _token
|
12
|
+
new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Hobby::Auth do
|
18
|
+
it 'raises an error when the short names are the same' do
|
19
|
+
expect {
|
20
|
+
Class.new do
|
21
|
+
include Hobby
|
22
|
+
include Hobby::Auth[Same, Namespaced::Same]
|
23
|
+
end
|
24
|
+
}.to raise_error Hobby::Auth::SameNames,
|
25
|
+
'The short names of Same and Namespaced::Same are the same: same.'
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hobby-auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anatoly Chernow
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -20,10 +20,13 @@ files:
|
|
20
20
|
- Gemfile
|
21
21
|
- hobby-auth.gemspec
|
22
22
|
- lib/hobby/auth.rb
|
23
|
+
- readme.adoc
|
23
24
|
- spec/helper.rb
|
24
25
|
- spec/http/getter.yml
|
26
|
+
- spec/http/getter_decorator.yml
|
25
27
|
- spec/http/poster.yml
|
26
28
|
- spec/http_spec.rb
|
29
|
+
- spec/name_shadowing_spec.rb
|
27
30
|
- spec/seed_users.rb
|
28
31
|
homepage:
|
29
32
|
licenses: []
|
@@ -44,8 +47,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
44
47
|
version: '0'
|
45
48
|
requirements: []
|
46
49
|
rubyforge_project:
|
47
|
-
rubygems_version: 2.
|
50
|
+
rubygems_version: 2.6.11
|
48
51
|
signing_key:
|
49
52
|
specification_version: 4
|
50
|
-
summary:
|
53
|
+
summary: A Hobby extension to authorize routes.
|
51
54
|
test_files: []
|