hanami_id 0.1.0 → 0.2.1
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/CODE_OF_CONDUCT.md +5 -5
- data/README.md +72 -7
- data/lib/hanami_id.rb +64 -2
- data/lib/hanami_id/authentication.rb +30 -0
- data/lib/hanami_id/version.rb +3 -1
- data/lib/hanami_id/warden/app_helper.rb +27 -0
- data/lib/hanami_id/warden/strategy.rb +12 -0
- data/locales/hanam_id.en.yml +3 -0
- metadata +140 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f21d850b87ca9ce2161c771638c6ae7b0d5847f88267ebaf0a72269ce46741c
|
|
4
|
+
data.tar.gz: e4cac524ec868de6ddc432c2d70d885d8c65d8f7eb7ec578bb24fd979eb53026
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 181fa05adabf48e2c04720213bbf096d153558f51f61d9ff063701dbd9c1f17a3337f9fd37821426eb009c5074e8cec4fbb7616913baa25b8c0475444460048f
|
|
7
|
+
data.tar.gz: 2dff55118101a7ba4e4089c70af7ba421e86fd287741cb0651b3c32a1017b8864d7fc378622b70f61515aa02d8cec84afa070afc1faa6c2e1dc551f694f7375c
|
data/CODE_OF_CONDUCT.md
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
In the interest of fostering an open and welcoming environment, we as
|
|
6
6
|
contributors and maintainers pledge to making participation in our project and
|
|
7
7
|
our community a harassment-free experience for everyone, regardless of age, body
|
|
8
|
-
size, disability, ethnicity, gender identity and expression, level of
|
|
9
|
-
nationality, personal appearance, race, religion, or sexual identity
|
|
10
|
-
orientation.
|
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of
|
|
9
|
+
experience,nationality, personal appearance, race, religion, or sexual identity
|
|
10
|
+
and orientation.
|
|
11
11
|
|
|
12
12
|
## Our Standards
|
|
13
13
|
|
|
@@ -67,8 +67,8 @@ members of the project's leadership.
|
|
|
67
67
|
|
|
68
68
|
## Attribution
|
|
69
69
|
|
|
70
|
-
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
71
|
-
available at [http://contributor-covenant.org/version/1/4][version]
|
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
71
|
+
version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
|
72
72
|
|
|
73
73
|
[homepage]: http://contributor-covenant.org
|
|
74
74
|
[version]: http://contributor-covenant.org/version/1/4/
|
data/README.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# HanamiId
|
|
2
2
|
|
|
3
|
-
Authentication solution for Hanami framework. Based on Warden and Bcrypt.
|
|
3
|
+
Authentication solution for [Hanami](https://github.com/hanami/hanami) framework. Based on [Warden](https://github.com/wardencommunity/warden) and [Bcrypt](https://github.com/codahale/bcrypt-ruby).
|
|
4
|
+
|
|
5
|
+
HanamiId tries to be a plug-n-play solution like Devise is for Rails. But
|
|
6
|
+
instead of magic intervention, it generates a separate app with controllers, views, templates full of working code that you can easily change to your liking.
|
|
7
|
+
HanamiId doesn't monkey patch anything, doesn't mess with your app configuration
|
|
8
|
+
and acts completely isolated.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## Status
|
|
4
12
|
|
|
5
13
|
[](https://travis-ci.org/leemour/hanami_id)
|
|
6
14
|
[](http://rubygems.org/gems/hanami_id "View this project in Rubygems")
|
|
@@ -13,23 +21,80 @@ Authentication solution for Hanami framework. Based on Warden and Bcrypt.
|
|
|
13
21
|
|
|
14
22
|
## Installation
|
|
15
23
|
|
|
16
|
-
Add this
|
|
24
|
+
Add this lines to your application's Gemfile:
|
|
17
25
|
|
|
18
26
|
```ruby
|
|
19
|
-
gem
|
|
27
|
+
gem "hanami_id"
|
|
28
|
+
|
|
29
|
+
group :plugins do
|
|
30
|
+
gem "hanami_id-generators"
|
|
31
|
+
end
|
|
20
32
|
```
|
|
21
33
|
|
|
22
34
|
And then execute:
|
|
23
35
|
|
|
24
36
|
$ bundle
|
|
25
37
|
|
|
26
|
-
|
|
38
|
+
Run generator:
|
|
39
|
+
|
|
40
|
+
$ hanami g auth --app auth --model user
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
Use `--help` to see all available options and defaults. They are:
|
|
44
|
+
|
|
45
|
+
- --modules
|
|
46
|
+
- --id_type
|
|
47
|
+
- --login_column
|
|
48
|
+
- --password_column
|
|
27
49
|
|
|
28
|
-
|
|
50
|
+
The above command is using Hanami CLI under the hood and will generate an
|
|
51
|
+
application with all controller actions, entity, repository and all relevant
|
|
52
|
+
specs (RSpec).
|
|
29
53
|
|
|
30
54
|
## Usage
|
|
31
55
|
|
|
32
|
-
|
|
56
|
+
For project-wide usage add Warden Rack middleware to your project:
|
|
57
|
+
```ruby
|
|
58
|
+
# config/environment.rb
|
|
59
|
+
Hanami.configure do
|
|
60
|
+
# ...
|
|
61
|
+
use Rack::Session::Cookie, secret: "replace this with some secret key"
|
|
62
|
+
include HanamiId::Warden::AppHelper
|
|
63
|
+
end
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
For usage in a specific app add Warden Rack middleware to that particular app:
|
|
67
|
+
```ruby
|
|
68
|
+
# apps/web/application.rb
|
|
69
|
+
module Web
|
|
70
|
+
class Application < Hanami::Application
|
|
71
|
+
configure do
|
|
72
|
+
# ...
|
|
73
|
+
sessions :cookie, secret: ENV["WEB_SESSIONS_SECRET"]
|
|
74
|
+
include HanamiId::Warden::AppHelper
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For usage in single controller action add Warden Rack middleware to that action:
|
|
81
|
+
```ruby
|
|
82
|
+
# apps/web/controllers/dashboard/show.rb
|
|
83
|
+
module Web
|
|
84
|
+
module Controllers
|
|
85
|
+
module Dashboard
|
|
86
|
+
class Show
|
|
87
|
+
include Web::Action
|
|
88
|
+
include HanamiId::Warden::ActionHelper
|
|
89
|
+
|
|
90
|
+
def call(params)
|
|
91
|
+
# ...
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
```
|
|
33
98
|
|
|
34
99
|
## Development
|
|
35
100
|
|
data/lib/hanami_id.rb
CHANGED
|
@@ -1,6 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bcrypt"
|
|
4
|
+
require "i18n"
|
|
5
|
+
require "logger"
|
|
6
|
+
# TODO: remove pry
|
|
7
|
+
# require "pry-byebug"
|
|
8
|
+
require "warden"
|
|
9
|
+
|
|
1
10
|
require "hanami_id/version"
|
|
11
|
+
require "hanami_id/warden/strategy"
|
|
12
|
+
require "hanami_id/warden/app_helper"
|
|
2
13
|
|
|
3
14
|
module HanamiId
|
|
4
|
-
|
|
5
|
-
|
|
15
|
+
MODES = %w[standalone project].freeze
|
|
16
|
+
MODULES = %w[sessions registrations].freeze
|
|
17
|
+
|
|
18
|
+
class AuthError < StandardError; end
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
attr_accessor :logger
|
|
22
|
+
attr_accessor :model_name
|
|
23
|
+
attr_accessor :app_name
|
|
24
|
+
attr_accessor :failure_app
|
|
25
|
+
attr_accessor :default_modules
|
|
26
|
+
|
|
27
|
+
def configure
|
|
28
|
+
yield self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def model
|
|
32
|
+
@model ||= Module.const_get(classify(@model_name))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def repository_name
|
|
36
|
+
@repository_name ||= "#{@model_name}_repository"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def repository
|
|
40
|
+
@repository ||= Module.const_get("#{classify @model_name}Repository")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def classify(string)
|
|
44
|
+
Hanami::Utils::String.classify string
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def app
|
|
48
|
+
@app ||= Module.const_get(@app_name)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Defaults
|
|
53
|
+
@logger = ::Logger.new(STDOUT)
|
|
54
|
+
@model_name = "user"
|
|
55
|
+
@app_name = "Auth"
|
|
56
|
+
@failure_app = lambda do |env|
|
|
57
|
+
HanamiId.app::Controllers::Session::New.new(
|
|
58
|
+
login_failed_with: env["warden"].message
|
|
59
|
+
).call(env)
|
|
60
|
+
end
|
|
61
|
+
@default_modules = %w[sessions registrations].freeze
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
I18n.tap do |i18n|
|
|
65
|
+
i18n.load_path << Dir[File.join File.expand_path("locales"), "*.yml"]
|
|
66
|
+
i18n.enforce_available_locales = false
|
|
67
|
+
i18n.default_locale = :en
|
|
6
68
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HanamiId
|
|
4
|
+
module Authentication
|
|
5
|
+
model = HanamiId.model_name
|
|
6
|
+
|
|
7
|
+
attr_reader :"current_#{model}"
|
|
8
|
+
|
|
9
|
+
def self.included(action)
|
|
10
|
+
action.class_eval do
|
|
11
|
+
before :"authenticate_#{model}!"
|
|
12
|
+
expose :"current_#{model}"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
define_method "authenticate_#{model}!" do
|
|
19
|
+
instance_variable_set(
|
|
20
|
+
"@current_#{model}",
|
|
21
|
+
HanamiId.repostiory.new.find(session["#{model}_id"])
|
|
22
|
+
)
|
|
23
|
+
halt 401 unless send("#{model}_signed_in?")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
define_method "#{model}_signed_in?" do
|
|
27
|
+
!!send("current_#{model}")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/hanami_id/version.rb
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HanamiId
|
|
4
|
+
module Warden
|
|
5
|
+
module AppHelper
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.configure do
|
|
8
|
+
middleware.use ::Warden::Manager do |manager|
|
|
9
|
+
manager.default_strategies :password
|
|
10
|
+
manager.failure_app = HanamiId.failure_app
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module ActionHelper
|
|
17
|
+
def self.included(base)
|
|
18
|
+
base.configure do
|
|
19
|
+
use ::Warden::Manager do |manager|
|
|
20
|
+
manager.default_strategies :password
|
|
21
|
+
manager.failure_app = HanamiId.failure_app
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Warden::Strategies.add(:password) do
|
|
4
|
+
def valid?
|
|
5
|
+
params[:login] || params[:password]
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def authenticate!
|
|
9
|
+
user = HanamiId.repository.authenticate(params[:login], params[:password])
|
|
10
|
+
user.nil? ? fail!(I18n.t("errors.authentication_failed")) : success!(user)
|
|
11
|
+
end
|
|
12
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hanami_id
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Viacheslav Ptsarev
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-05-
|
|
11
|
+
date: 2019-05-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bcrypt
|
|
@@ -24,6 +24,34 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '3.1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: hanami_id-generators
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.1'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0.1'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: i18n
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.6'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.6'
|
|
27
55
|
- !ruby/object:Gem::Dependency
|
|
28
56
|
name: warden
|
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -44,14 +72,56 @@ dependencies:
|
|
|
44
72
|
requirements:
|
|
45
73
|
- - "~>"
|
|
46
74
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
75
|
+
version: '2'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '2'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: hanami
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '1.3'
|
|
48
90
|
type: :development
|
|
49
91
|
prerelease: false
|
|
50
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
93
|
requirements:
|
|
52
94
|
- - "~>"
|
|
53
95
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '1.
|
|
96
|
+
version: '1.3'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: hanami-model
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '1.3'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '1.3'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: pry-byebug
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '3.7'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '3.7'
|
|
55
125
|
- !ruby/object:Gem::Dependency
|
|
56
126
|
name: rake
|
|
57
127
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,7 +150,66 @@ dependencies:
|
|
|
80
150
|
- - "~>"
|
|
81
151
|
- !ruby/object:Gem::Version
|
|
82
152
|
version: '3.0'
|
|
83
|
-
|
|
153
|
+
- !ruby/object:Gem::Dependency
|
|
154
|
+
name: rubocop-md
|
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
|
156
|
+
requirements:
|
|
157
|
+
- - "~>"
|
|
158
|
+
- !ruby/object:Gem::Version
|
|
159
|
+
version: '0.3'
|
|
160
|
+
type: :development
|
|
161
|
+
prerelease: false
|
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
+
requirements:
|
|
164
|
+
- - "~>"
|
|
165
|
+
- !ruby/object:Gem::Version
|
|
166
|
+
version: '0.3'
|
|
167
|
+
- !ruby/object:Gem::Dependency
|
|
168
|
+
name: rubocop-performance
|
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
|
170
|
+
requirements:
|
|
171
|
+
- - "~>"
|
|
172
|
+
- !ruby/object:Gem::Version
|
|
173
|
+
version: '1.3'
|
|
174
|
+
type: :development
|
|
175
|
+
prerelease: false
|
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
177
|
+
requirements:
|
|
178
|
+
- - "~>"
|
|
179
|
+
- !ruby/object:Gem::Version
|
|
180
|
+
version: '1.3'
|
|
181
|
+
- !ruby/object:Gem::Dependency
|
|
182
|
+
name: rubocop-rspec
|
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
|
184
|
+
requirements:
|
|
185
|
+
- - "~>"
|
|
186
|
+
- !ruby/object:Gem::Version
|
|
187
|
+
version: '1.3'
|
|
188
|
+
type: :development
|
|
189
|
+
prerelease: false
|
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
191
|
+
requirements:
|
|
192
|
+
- - "~>"
|
|
193
|
+
- !ruby/object:Gem::Version
|
|
194
|
+
version: '1.3'
|
|
195
|
+
- !ruby/object:Gem::Dependency
|
|
196
|
+
name: simplecov
|
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
|
198
|
+
requirements:
|
|
199
|
+
- - "~>"
|
|
200
|
+
- !ruby/object:Gem::Version
|
|
201
|
+
version: '0.16'
|
|
202
|
+
type: :development
|
|
203
|
+
prerelease: false
|
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
205
|
+
requirements:
|
|
206
|
+
- - "~>"
|
|
207
|
+
- !ruby/object:Gem::Version
|
|
208
|
+
version: '0.16'
|
|
209
|
+
description: |
|
|
210
|
+
Fully-fledged flexible authentication solution based on Bcrypt and Warden.
|
|
211
|
+
Instead of magic intervention it acts isolated and generates a new
|
|
212
|
+
authentication app with all the code you need. I fully supports I18n.
|
|
84
213
|
email:
|
|
85
214
|
- leemour@gmail.com
|
|
86
215
|
executables: []
|
|
@@ -92,7 +221,11 @@ files:
|
|
|
92
221
|
- LICENSE.txt
|
|
93
222
|
- README.md
|
|
94
223
|
- lib/hanami_id.rb
|
|
224
|
+
- lib/hanami_id/authentication.rb
|
|
95
225
|
- lib/hanami_id/version.rb
|
|
226
|
+
- lib/hanami_id/warden/app_helper.rb
|
|
227
|
+
- lib/hanami_id/warden/strategy.rb
|
|
228
|
+
- locales/hanam_id.en.yml
|
|
96
229
|
homepage: https://github.com/leemour/hanami_id
|
|
97
230
|
licenses:
|
|
98
231
|
- MIT
|
|
@@ -109,15 +242,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
109
242
|
requirements:
|
|
110
243
|
- - "~>"
|
|
111
244
|
- !ruby/object:Gem::Version
|
|
112
|
-
version: '2'
|
|
245
|
+
version: '2.3'
|
|
113
246
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
247
|
requirements:
|
|
115
248
|
- - ">="
|
|
116
249
|
- !ruby/object:Gem::Version
|
|
117
250
|
version: '0'
|
|
118
251
|
requirements: []
|
|
119
|
-
|
|
120
|
-
rubygems_version: 2.7.6
|
|
252
|
+
rubygems_version: 3.0.3
|
|
121
253
|
signing_key:
|
|
122
254
|
specification_version: 4
|
|
123
255
|
summary: Authentication for Hanami framework
|