groot 1.0.0.beta

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6d417b0a6033a346014fa1da80643f88d33782e5
4
+ data.tar.gz: 416dfd442d194ac7c3413b716b1cf6cf34dbe7ec
5
+ SHA512:
6
+ metadata.gz: c01092415acfe65c21a32192b0cf463d425db972d77ab27acd098ca66cf0e7fddefcb6c4f972576368f41a28e62fe083d711b6eb827bfef39f5c9ec6887dd386
7
+ data.tar.gz: f8c04a188fcb95c80bd9d1c8cf6ae16e7e4b4676948caa8e6363961be5f986942b07ece7afe887990e5968284bc184a6d47710277379d46c58d26e72c6abecc5
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ /Gemfile.lock
5
+ spec/dummy/db/*.sqlite3
6
+ spec/dummy/db/*.sqlite3-journal
7
+ spec/dummy/log/*.log
8
+ spec/dummy/tmp/
9
+ *.gem
10
+
11
+
12
+
13
+
14
+ .DS_Store
15
+ dump.rdb
16
+
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Declare your gem's dependencies in groot.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # Declare any dependencies that are still in development here instead of in
9
+ # your gemspec. These might include edge Rails or gems from your path or
10
+ # Git. Remember to move these dependencies to your gemspec before releasing
11
+ # your gem to rubygems.org.
12
+
13
+ # To use a debugger
14
+ # gem 'byebug', group: [:development, :test]
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Alisson Bruno
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # Groot
2
+ Groot is a simple gem to help you authenticate using [JWT](https://github.com/jwt/ruby-jwt).
3
+ ## Installation
4
+
5
+ Add it to your Gemfile:
6
+
7
+ ```ruby
8
+ gem 'groot'
9
+ ```
10
+
11
+ Run the following command to install it:
12
+ ```console
13
+ bundle install
14
+ ```
15
+
16
+ Run the generator:
17
+ ```console
18
+ rails generate groot:install
19
+ ```
20
+
21
+ ## Usage
22
+ In the following command you should replace MODEL with your user application class
23
+ ```console
24
+ rails generate groot:auth MODEL
25
+ ```
26
+ Take a look at the MODEL and if you want, you can add any additional configuration to it.
27
+ Add the following line to your routes.rb file (assuming your model is 'Admin'):
28
+ ```console
29
+ auth_for :admins
30
+ ```
31
+ It will create the routes to Groot controllers.
32
+
33
+
34
+ ### Filter and Helpers
35
+ Groot will create a filter for user authentication, to configure it just add the following line to your controller: (assuming again that your model is Admin):
36
+
37
+ ```ruby
38
+ before_action :authenticate_admin!
39
+ ```
40
+ Groot will also create some helpers to make your life easier.
41
+
42
+ To get the current signed-in user:
43
+ ```ruby
44
+ current_admin
45
+ ```
46
+ To verify if there is a user signed in:
47
+ ```ruby
48
+ admin_signed_in?
49
+ ```
50
+ ## ORMs
51
+ So far Groot only supports ActiveRecord.
52
+
53
+ ## Contributing
54
+ Bug reports and pull requests are welcome on GitHub at https://github.com/alissonbrunosa/groot.
55
+
56
+ ## License
57
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Groot'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ require 'bundler/gem_tasks'
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task default: :test
@@ -0,0 +1,28 @@
1
+ module Groot
2
+ class AuthController < ApplicationController
3
+
4
+ # TODO Do something to get the real model
5
+ def create
6
+ user = resource_class.find_by(email: params[:email])
7
+ if(user && user.authenticate(params[:password]))
8
+ render json: { user: user, access_token: encode(user) } , status: :ok
9
+ else
10
+ render json: { message: 'Email/Password incorrect.' }, status: :forbidden
11
+ end
12
+ end
13
+
14
+ def destroy
15
+ raise NotImplementedError
16
+ end
17
+
18
+
19
+ private
20
+ def resource_class
21
+ mapping.clazz
22
+ end
23
+
24
+ def mapping
25
+ @mapping ||= request.env['groot.mapping']
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,4 @@
1
+ module Groot
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Groot
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Groot
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Groot</title>
5
+ <%= stylesheet_link_tag "groot/application", media: "all" %>
6
+ <%= javascript_include_tag "groot/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/bin/rails ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
6
+ ENGINE_PATH = File.expand_path('../../lib/groot/engine', __FILE__)
7
+
8
+ # Set up gems listed in the Gemfile.
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
10
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
11
+
12
+ require 'rails/all'
13
+ require 'rails/engine/commands'
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Groot::Engine.routes.draw do
2
+ end
data/groot.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ # Maintain your gem"s version:
6
+ require "groot/version"
7
+
8
+ # Describe your gem and declare its dependencies:
9
+ Gem::Specification.new do |spec|
10
+ spec.name = "groot"
11
+ spec.version = Groot::VERSION
12
+ spec.authors = ["Alisson Bruno"]
13
+ spec.email = ["alissonbruno.sa@gmail.com"]
14
+
15
+ spec.summary = "Simple token authentication and authorization"
16
+ spec.description = "Simple token authentication and authorization solution for Rails with JWT."
17
+ spec.homepage = "https://github.com/alissonbrunosa/groot"
18
+ spec.license = "MIT"
19
+
20
+ # spec.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
21
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
22
+ f.match(%r{^(test|spec|features)/})
23
+ end
24
+ spec.add_dependency "rails", "~> 5.0", ">= 5.0.0"
25
+ spec.add_dependency "jwt", "~> 1.5", ">= 1.5.6"
26
+ spec.add_dependency "bcrypt", "~> 3.1", ">= 3.1.7"
27
+
28
+ spec.add_development_dependency "sqlite3", "~> 1.3"
29
+ end
@@ -0,0 +1,54 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ module ActiveRecord
4
+ module Generators
5
+ class AuthGenerator < ActiveRecord::Generators::Base
6
+ namespace "groot:auth"
7
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
8
+ source_root File.expand_path("../templates", __FILE__)
9
+
10
+ class_option :parent, type: :string, desc: "The parent class for the generated model"
11
+
12
+ def create_migration_file
13
+ if(model_exists?)
14
+ migration_template "../templates/migration/migration_existing.rb", "db/migrate/add_groot_to_#{table_name}.rb"
15
+ else
16
+ migration_template "../templates/migration/create_migration.rb", "db/migrate/create_#{table_name}.rb"
17
+ end
18
+ end
19
+
20
+ def create_model_file
21
+ template "model.rb", model_path unless model_exists?
22
+ end
23
+
24
+
25
+ private
26
+
27
+ def attributes_auth
28
+ <<RUBY
29
+ t.string :email, null: false, default: ""
30
+ t.string :password_digest, null: false, default: ""
31
+
32
+ t.string :reset_password_token
33
+ t.datetime :reset_password_sent_at
34
+ RUBY
35
+ end
36
+
37
+ def attributes_with_index
38
+ attributes.select { |a| !a.reference? && a.has_index? }
39
+ end
40
+
41
+ def model_exists?
42
+ File.exist?(File.join(destination_root, model_path))
43
+ end
44
+
45
+ def model_path
46
+ @model_path ||= File.join("app", "models", "#{file_path}.rb")
47
+ end
48
+
49
+ def parent_class_name
50
+ options[:parent] || "ApplicationRecord"
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,12 @@
1
+ module Groot
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ # namespace "groot:install"
5
+ source_root File.expand_path("../templates", __FILE__)
6
+
7
+ def copy_initializer_file
8
+ template "config.rb", "config/initializers/groot.rb"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ Groot.setup do |config|
2
+ config.hmac_secret = "<%= SecureRandom.hex(64) %>"
3
+ end
@@ -0,0 +1,14 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :<%= table_name %><%= primary_key_type %> do |t|
4
+ <%= attributes_auth -%>
5
+
6
+ <% attributes.each do |attribute| -%>
7
+ t.<%= attribute.type %> :<%= attribute.name %>
8
+ <% end -%>
9
+ end
10
+
11
+ add_index :<%= table_name %>, :email, unique: true
12
+ add_index :<%= table_name %>, :reset_password_token, unique: true
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ class AddGrootTo<%= table_name.camelize %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def self.up
3
+ change_table :<%= table_name %> do |t|
4
+ <%= attributes_auth -%>
5
+
6
+ <% attributes.each do |attribute| -%>
7
+ t.<%= attribute.type %> :<%= attribute.name %>
8
+ <% end -%>
9
+ end
10
+
11
+ add_index :<%= table_name %>, :email, unique: true
12
+ add_index :<%= table_name %>, :reset_password_token, unique: true
13
+ end
14
+
15
+ def self.down
16
+ # By default, we don't want to make any assumption about how to roll back a migration when your
17
+ # model already existed. Please edit below which fields you would like to remove in this migration.
18
+ raise ActiveRecord::IrreversibleMigration
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %> < <%= parent_class_name.classify %>
3
+ <% attributes.select(&:reference?).each do |attribute| -%>
4
+ belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %><%= ', required: true' if attribute.required? %>
5
+ <% end -%>
6
+ <% attributes.select(&:token?).each do |attribute| -%>
7
+ has_secure_token<% if attribute.name != "token" %> :<%= attribute.name %><% end %>
8
+ <% end -%>
9
+ has_secure_password
10
+ end
11
+ <% end -%>
data/lib/groot.rb ADDED
@@ -0,0 +1,27 @@
1
+ require "groot/engine"
2
+
3
+ module Groot
4
+ extend ActiveSupport::Autoload
5
+
6
+ autoload :Mapping
7
+
8
+ module Controllers
9
+ autoload :Helpers, 'groot/controllers/helpers'
10
+ end
11
+
12
+
13
+
14
+
15
+ mattr_accessor :hmac_secret
16
+ @@hmac_secret = nil
17
+
18
+ def self.setup
19
+ yield self
20
+ end
21
+
22
+ def self.mapping(resource)
23
+ mapping = Mapping.new(resource)
24
+ Controllers::Helpers.define_method(mapping)
25
+ mapping
26
+ end
27
+ end
@@ -0,0 +1,58 @@
1
+ require 'jwt'
2
+
3
+ module Groot
4
+ module Controllers
5
+ module Helpers
6
+ def self.define_method(mapping)
7
+ name = mapping.name
8
+ class_eval <<-METHODS, __FILE__, __LINE__ + 1
9
+ def authenticate_#{name}!
10
+ decode(http_token)
11
+ end
12
+ def #{name}_signed_in?
13
+ !!current_user
14
+ end
15
+ def current_#{name}
16
+ payload = decode(http_token)
17
+ @current_user ||= #{mapping.clazz}.find(payload["id"])
18
+ end
19
+ METHODS
20
+
21
+ ActiveSupport.on_load(:action_controller) do
22
+ if respond_to?(:helper_method)
23
+ helper_method "current_#{name}", "#{name}_signed_in?"
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def http_token
31
+ @http_token ||= request.headers['Authorization'].split(' ').last if request.headers['Authorization'].present?
32
+ end
33
+
34
+ def encode(resource)
35
+ payload = {
36
+ id: resource.id,
37
+ exp: (Time.now + 24.hours).to_i
38
+ }
39
+ JWT.encode(payload, Groot.hmac_secret, 'HS256')
40
+ end
41
+
42
+ def decode(token)
43
+ begin
44
+ options = {
45
+ algorithm: 'HS256'
46
+ }
47
+ JWT.decode(token, Groot.hmac_secret, true, options).first
48
+ rescue JWT::ExpiredSignature
49
+ render json: { message: 'The token has expired.' }, status: :forbidden
50
+ rescue JWT::VerificationError
51
+ render json: { message: 'Invalid access token.' }, status: :forbidden
52
+ rescue JWT::DecodeError
53
+ render json: { message: 'Invalid access token.' }, status: :forbidden
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,12 @@
1
+ require 'groot/rails/routes'
2
+ module Groot
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace Groot
5
+
6
+ initializer "groot.add_helpers" do
7
+ ActiveSupport.on_load(:action_controller) do
8
+ include Controllers::Helpers
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ module Groot
2
+ class Mapping
3
+ attr_accessor :resource, :class_name, :path_names
4
+ def initialize(resource)
5
+ @resource = resource
6
+ @path_names = Hash.new { |h,k| h[k] = k.to_s }
7
+ end
8
+
9
+ def singular
10
+ resource.to_s.singularize
11
+ end
12
+ alias :name :singular
13
+
14
+ def class_name
15
+ @class_name ||= singular.classify
16
+ end
17
+
18
+ def clazz
19
+ @clazz ||= class_name.constantize
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module ActionDispatch::Routing
2
+ class Mapper
3
+ def auth_for(resource)
4
+ mapping = Groot.mapping(resource)
5
+ constraint = lambda do |request|
6
+ request.env['groot.mapping'] = mapping
7
+ true
8
+ end
9
+ constraints(constraint) do
10
+ auth_routes(mapping)
11
+ end
12
+ end
13
+
14
+ private
15
+ def auth_routes(mapping) #:nodoc:
16
+ resource mapping.resource, only: [], controller: 'groot/auth' do
17
+ post :create, path: mapping.path_names[:login]
18
+ delete :destroy, path: mapping.path_names[:logout]
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Groot
2
+ VERSION = '1.0.0.beta'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :groot do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: groot
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.beta
5
+ platform: ruby
6
+ authors:
7
+ - Alisson Bruno
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 5.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '5.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 5.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: jwt
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.5'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.5.6
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.5'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.5.6
53
+ - !ruby/object:Gem::Dependency
54
+ name: bcrypt
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.1'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 3.1.7
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.1'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 3.1.7
73
+ - !ruby/object:Gem::Dependency
74
+ name: sqlite3
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '1.3'
80
+ type: :development
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: '1.3'
87
+ description: Simple token authentication and authorization solution for Rails with
88
+ JWT.
89
+ email:
90
+ - alissonbruno.sa@gmail.com
91
+ executables: []
92
+ extensions: []
93
+ extra_rdoc_files: []
94
+ files:
95
+ - ".gitignore"
96
+ - Gemfile
97
+ - MIT-LICENSE
98
+ - README.md
99
+ - Rakefile
100
+ - app/controllers/groot/auth_controller.rb
101
+ - app/helpers/groot/application_helper.rb
102
+ - app/jobs/groot/application_job.rb
103
+ - app/mailers/groot/application_mailer.rb
104
+ - app/views/layouts/groot/application.html.erb
105
+ - bin/rails
106
+ - config/routes.rb
107
+ - groot.gemspec
108
+ - lib/generators/.DS_Store
109
+ - lib/generators/groot/auth_generator.rb
110
+ - lib/generators/groot/install_generator.rb
111
+ - lib/generators/groot/templates/.DS_Store
112
+ - lib/generators/groot/templates/config.rb
113
+ - lib/generators/groot/templates/migration/create_migration.rb
114
+ - lib/generators/groot/templates/migration/migration_existing.rb
115
+ - lib/generators/groot/templates/model.rb
116
+ - lib/groot.rb
117
+ - lib/groot/controllers/helpers.rb
118
+ - lib/groot/engine.rb
119
+ - lib/groot/mapping.rb
120
+ - lib/groot/rails/routes.rb
121
+ - lib/groot/version.rb
122
+ - lib/tasks/groot_tasks.rake
123
+ homepage: https://github.com/alissonbrunosa/groot
124
+ licenses:
125
+ - MIT
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">"
139
+ - !ruby/object:Gem::Version
140
+ version: 1.3.1
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.5.1
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Simple token authentication and authorization
147
+ test_files: []