hobby-auth 0.0.1 → 0.0.2

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
  SHA1:
3
- metadata.gz: a695f776bd20babf3742458ff066a82b5afafe90
4
- data.tar.gz: 625b7448fe38eb6e59abb4b29f6dac9f75113694
3
+ metadata.gz: 0fd7308d5de3ee1087bf4829558efeb555f18433
4
+ data.tar.gz: 383fd2c09d0fc8a72d63e0f6f6857df11439b690
5
5
  SHA512:
6
- metadata.gz: cb4684a95506dead682cb9b696f41f2a980723e69aa420dcc9d9b188135fdbc4aa80fffd1e9a31e965eae2f04e082809ccde27a98bcd33827a12d97638fa1ace
7
- data.tar.gz: e72b29085e987c5c16ce5a83b2e0839baa3f716a0ecde1cf4bec877e10f0ed7eb5672cecbb762958a8528a31a58063d9ce2119d53ae74870410fe657e0ad6e09
6
+ metadata.gz: bfc2f279d0e4f7979ea66adb086067c19f5e4320ea0a9aea0a7cb865ae6a9c4b5939e2e305902db56b222f0567b707c5c8ef3d14790d9bbc4f6e9492d9639345
7
+ data.tar.gz: c57175fc1f465f1524d0000342b36c2f1a192dfd37da8c5a78167ed409ab42d93a5487895eedfd0d9be4f3b33ce1ca715ae9c53340c9c2787979aa359e9e82b5
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  Gemfile.lock
2
+ *.gem
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'hobby-devtools', '>=0.0.7'
3
+ gem 'hobby-devtools', '>=0.0.11'
@@ -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.1'
5
- g.summary = 'Authorize Hobby routes'
4
+ g.version = '0.0.2'
5
+ g.summary = 'A Hobby extension to authorize routes.'
6
6
  g.authors = ['Anatoly Chernow']
7
7
  end
@@ -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
- user_models.each do |user_model|
7
- app.define_singleton_method short_name_of user_model do |route|
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 # Ends should be optional. Block nesting can be inferred from two-space indent.
55
+ end
@@ -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
@@ -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.1
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-01-03 00:00:00.000000000 Z
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.5.2
50
+ rubygems_version: 2.6.11
48
51
  signing_key:
49
52
  specification_version: 4
50
- summary: Authorize Hobby routes
53
+ summary: A Hobby extension to authorize routes.
51
54
  test_files: []