tiddle 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bcae34825a51917726a62d76e0c12f219c3bdaff
4
+ data.tar.gz: 7a63e0436d50cdddfa99407d87ef89101491043f
5
+ SHA512:
6
+ metadata.gz: 0506dea0acf421a88fe9b7d225851a095e1095c0d4c69e7e04a0055b92ba2e2945c69f8cf729fe7efdd0c00f3edbad33caebc3c0ef1d2d30977d9bbff3863484
7
+ data.tar.gz: df27a7199bf7690edd4c6a988e86a9358489ae36f24b07b53f8d8a1121db8069f872ea5a7e9d498744a32848ea9993381b4a3c96f81934b26ffaa0b1648651aa
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .ruby-gemset
16
+ .ruby-version
17
+ *.sqlite3
18
+ *.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tiddle.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Adam Niedzielski
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,76 @@
1
+ # Tiddle
2
+
3
+ Tiddle provides Devise strategy for token authentication in API-only Ruby on Rails applications. Its main feature is **support for multiple tokens per user**.
4
+
5
+ Tiddle is lightweight and non-configurable. It does what it has to do and leaves some manual implementation to you.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'tiddle'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+
20
+ ## Usage
21
+
22
+ 1) Add ```:token_authenticatable``` inside your Devise-enabled model:
23
+
24
+ ```ruby
25
+ class User < ActiveRecord::Base
26
+ devise :database_authenticatable, :registerable,
27
+ :recoverable, :trackable, :validatable,
28
+ :token_authenticatable
29
+ end
30
+ ```
31
+
32
+ 2) Generate the model which stores authentication tokens. The model name is not important, but the Devise-enabled model should have association called ```authentication_tokens```.
33
+
34
+ ```
35
+ rails g model AuthenticationToken body:string user:references last_used_at:datetime ip_address:string user_agent:string
36
+ ```
37
+
38
+ ```ruby
39
+ class User < ActiveRecord::Base
40
+ has_many :authentication_tokens
41
+ end
42
+ ```
43
+
44
+ ```body```, ```last_used_at```, ```ip_address``` and ```user_agent``` fields are required.
45
+
46
+ 3) Customize ```Devise::SessionsController```. You need to create and return token in ```#create``` and expire the token in ```#destroy```.
47
+
48
+ ```ruby
49
+ class Users::SessionsController < Devise::SessionsController
50
+
51
+ def create
52
+ [...]
53
+ token = Tiddle.create_and_return_token(resource)
54
+ render json: { authentication_token: token }
55
+ end
56
+
57
+ def destroy
58
+ Tiddle.expire_token(current_user, request)
59
+ render json: {}
60
+ end
61
+ end
62
+ ```
63
+
64
+ 4) Require authentication for some controller:
65
+
66
+ ```ruby
67
+ class PostsController < ApplicationController
68
+ before_action :authenticate_user!
69
+
70
+ def index
71
+ render json: Post.all
72
+ end
73
+ end
74
+ ```
75
+
76
+ 5) Send ```X-USER-EMAIL``` and ```X-USER-TOKEN``` as headers of every request which requires authentication.
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ task :default => :spec
@@ -0,0 +1,4 @@
1
+ en:
2
+ devise:
3
+ failure:
4
+ invalid_token: "Invalid email or token"
@@ -0,0 +1,24 @@
1
+ require "tiddle/version"
2
+ require "tiddle/strategy"
3
+ require "tiddle/rails"
4
+ require "tiddle/token_issuer"
5
+
6
+ module Tiddle
7
+
8
+ def self.create_and_return_token(resource, request)
9
+ TokenIssuer.build.create_and_return_token(resource, request)
10
+ end
11
+
12
+ def self.expire_token(resource, request)
13
+ TokenIssuer.build.expire_token(resource, request)
14
+ end
15
+
16
+ def self.purge_old_tokens(resource)
17
+ TokenIssuer.build.purge_old_tokens(resource)
18
+ end
19
+ end
20
+
21
+ Devise::add_module :token_authenticatable,
22
+ model: 'tiddle/model',
23
+ strategy: true,
24
+ no_input: true
@@ -0,0 +1,6 @@
1
+ module Devise
2
+ module Models
3
+ module TokenAuthenticatable
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ module Tiddle
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,52 @@
1
+ require 'devise/strategies/authenticatable'
2
+
3
+ module Devise
4
+ module Strategies
5
+ class TokenAuthenticatable < Authenticatable
6
+
7
+ def authenticate!
8
+ env["devise.skip_trackable"] = true
9
+
10
+ resource = mapping.to.find_for_authentication(email: email_from_headers)
11
+ return fail(:invalid_token) unless resource
12
+
13
+ resource.authentication_tokens.each do |token|
14
+ if Devise.secure_compare(token.body, token_from_headers)
15
+ touch_token(token)
16
+ return success!(resource)
17
+ end
18
+ end
19
+
20
+ fail(:invalid_token)
21
+ end
22
+
23
+ def valid?
24
+ email_from_headers.present? && token_from_headers.present?
25
+ end
26
+
27
+ def store?
28
+ false
29
+ end
30
+
31
+ private
32
+
33
+ def email_from_headers
34
+ env["HTTP_X_#{model_name}_EMAIL"]
35
+ end
36
+
37
+ def token_from_headers
38
+ env["HTTP_X_#{model_name}_TOKEN"]
39
+ end
40
+
41
+ def model_name
42
+ mapping.to.model_name.to_s.underscore.upcase
43
+ end
44
+
45
+ def touch_token(token)
46
+ token.update_attribute(:last_used_at, DateTime.current) if token.last_used_at < 1.hour.ago
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ Warden::Strategies.add(:token_authenticatable, Devise::Strategies::TokenAuthenticatable)
@@ -0,0 +1,38 @@
1
+ module Tiddle
2
+ class TokenIssuer
3
+ MAXIMUM_TOKENS_PER_USER = 20
4
+
5
+ def self.build
6
+ new(MAXIMUM_TOKENS_PER_USER)
7
+ end
8
+
9
+ def initialize(maximum_tokens_per_user)
10
+ self.maximum_tokens_per_user = maximum_tokens_per_user
11
+ end
12
+
13
+ def create_and_return_token(resource, request)
14
+ token = resource.authentication_tokens.
15
+ create! body: generate_token,
16
+ last_used_at: DateTime.current,
17
+ ip_address: request.remote_ip,
18
+ user_agent: request.user_agent
19
+
20
+ token.body
21
+ end
22
+
23
+ def expire_token(resource, request)
24
+ resource.authentication_tokens.where(body: request.headers["X-#{resource.model_name.to_s.upcase}-TOKEN"]).take!.destroy
25
+ end
26
+
27
+ def purge_old_tokens(resource)
28
+ resource.authentication_tokens.order(last_used_at: :desc).offset(maximum_tokens_per_user).destroy_all
29
+ end
30
+
31
+ private
32
+ attr_accessor :maximum_tokens_per_user
33
+
34
+ def generate_token
35
+ Devise.friendly_token
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module Tiddle
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+ end
@@ -0,0 +1,7 @@
1
+ class SecretsController < ApplicationController
2
+ before_action :authenticate_user!
3
+
4
+ def index
5
+ head :ok
6
+ end
7
+ end
@@ -0,0 +1,2 @@
1
+ class AuthenticationToken < ActiveRecord::Base
2
+ end
@@ -0,0 +1,7 @@
1
+ class User < ActiveRecord::Base
2
+ devise :database_authenticatable, :registerable,
3
+ :recoverable, :trackable, :validatable,
4
+ :token_authenticatable
5
+
6
+ has_many :authentication_tokens
7
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "active_model/railtie"
4
+ require "active_job/railtie"
5
+ require "active_record/railtie"
6
+ require "action_controller/railtie"
7
+ require "action_mailer/railtie"
8
+ require "action_view/railtie"
9
+
10
+ module RailsApp
11
+ class Application < Rails::Application
12
+ config.eager_load = true
13
+ config.root = File.expand_path('../../.', __FILE__)
14
+ end
15
+ end
16
+
@@ -0,0 +1,2 @@
1
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('../../../../Gemfile', __FILE__)
2
+ require 'bundler/setup'
@@ -0,0 +1,5 @@
1
+ # Load the Rails application.
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the Rails application.
5
+ Rails.application.initialize!
@@ -0,0 +1,4 @@
1
+ Rails.application.routes.draw do
2
+ devise_for :users
3
+ resources :secrets, only: [:index], defaults: { format: 'json' }
4
+ end
@@ -0,0 +1,2 @@
1
+ test:
2
+ secret_key_base: 01c37cff57639eef8aa511ae6ab64298c1da89dc32dfdda363473716f49e25d2473e48b6253c69d17c8ae8c9b6a027ec5a4ac0ffbd6c06defe1b70dd2ef32df8
@@ -0,0 +1,35 @@
1
+ class CreateTables < ActiveRecord::Migration
2
+ def change
3
+ create_table(:users) do |t|
4
+ ## Database authenticatable
5
+ t.string :email, null: false, default: ""
6
+ t.string :encrypted_password, null: false, default: ""
7
+
8
+ ## Recoverable
9
+ t.string :reset_password_token
10
+ t.datetime :reset_password_sent_at
11
+
12
+ ## Trackable
13
+ t.integer :sign_in_count, default: 0, null: false
14
+ t.datetime :current_sign_in_at
15
+ t.datetime :last_sign_in_at
16
+ t.string :current_sign_in_ip
17
+ t.string :last_sign_in_ip
18
+
19
+ t.timestamps null: false
20
+ end
21
+
22
+ add_index :users, :email, unique: true
23
+ add_index :users, :reset_password_token, unique: true
24
+ end
25
+
26
+ create_table :authentication_tokens do |t|
27
+ t.string :body, null: false
28
+ t.references :user, index: true, null: false
29
+ t.datetime :last_used_at, null: false
30
+ t.string :ip_address
31
+ t.string :user_agent
32
+
33
+ t.timestamps null: false
34
+ end
35
+ end
@@ -0,0 +1,111 @@
1
+ ENV["RAILS_ENV"] = 'test'
2
+ ENV["DATABASE_URL"] = "sqlite3:db/test.sqlite3"
3
+
4
+ require 'rails/all'
5
+ require 'rspec/rails'
6
+ require 'devise'
7
+ require 'devise/orm/active_record'
8
+ require 'tiddle'
9
+
10
+ require 'rails_app/config/environment'
11
+
12
+ Dir[__dir__ + "/support/**/*.rb"].each { |f| require f }
13
+
14
+ # This file was generated by the `rspec --init` command. Conventionally, all
15
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
16
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
17
+ # this file to always be loaded, without a need to explicitly require it in any
18
+ # files.
19
+ #
20
+ # Given that it is always loaded, you are encouraged to keep this file as
21
+ # light-weight as possible. Requiring heavyweight dependencies from this file
22
+ # will add to the boot time of your test suite on EVERY test run, even for an
23
+ # individual file that may not need all of that loaded. Instead, consider making
24
+ # a separate helper file that requires the additional dependencies and performs
25
+ # the additional setup, and require it from the spec files that actually need
26
+ # it.
27
+ #
28
+ # The `.rspec` file also contains a few flags that are not defaults but that
29
+ # users commonly want.
30
+ #
31
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
32
+ RSpec.configure do |config|
33
+ # rspec-expectations config goes here. You can use an alternate
34
+ # assertion/expectation library such as wrong or the stdlib/minitest
35
+ # assertions if you prefer.
36
+ config.expect_with :rspec do |expectations|
37
+ # This option will default to `true` in RSpec 4. It makes the `description`
38
+ # and `failure_message` of custom matchers include text for helper methods
39
+ # defined using `chain`, e.g.:
40
+ # be_bigger_than(2).and_smaller_than(4).description
41
+ # # => "be bigger than 2 and smaller than 4"
42
+ # ...rather than:
43
+ # # => "be bigger than 2"
44
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
45
+ end
46
+
47
+ # rspec-mocks config goes here. You can use an alternate test double
48
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
49
+ config.mock_with :rspec do |mocks|
50
+ # Prevents you from mocking or stubbing a method that does not exist on
51
+ # a real object. This is generally recommended, and will default to
52
+ # `true` in RSpec 4.
53
+ mocks.verify_partial_doubles = true
54
+ end
55
+
56
+ config.before(:suite) do
57
+ # Do initial migration
58
+ ActiveRecord::Migrator.migrate(File.expand_path("rails_app/db/migrate/", File.dirname(__FILE__)))
59
+ end
60
+
61
+ config.use_transactional_fixtures = true
62
+
63
+ # The settings below are suggested to provide a good initial experience
64
+ # with RSpec, but feel free to customize to your heart's content.
65
+ =begin
66
+ # These two settings work together to allow you to limit a spec run
67
+ # to individual examples or groups you care about by tagging them with
68
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
69
+ # get run.
70
+ config.filter_run :focus
71
+ config.run_all_when_everything_filtered = true
72
+
73
+ # Limits the available syntax to the non-monkey patched syntax that is
74
+ # recommended. For more details, see:
75
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
76
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
77
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
78
+ config.disable_monkey_patching!
79
+
80
+ # This setting enables warnings. It's recommended, but in some cases may
81
+ # be too noisy due to issues in dependencies.
82
+ config.warnings = true
83
+
84
+ # Many RSpec users commonly either run the entire suite or an individual
85
+ # file, and it's useful to allow more verbose output when running an
86
+ # individual spec file.
87
+ if config.files_to_run.one?
88
+ # Use the documentation formatter for detailed output,
89
+ # unless a formatter has already been configured
90
+ # (e.g. via a command-line flag).
91
+ config.default_formatter = 'doc'
92
+ end
93
+
94
+ # Print the 10 slowest examples and example groups at the
95
+ # end of the spec run, to help surface which specs are running
96
+ # particularly slow.
97
+ config.profile_examples = 10
98
+
99
+ # Run specs in random order to surface order dependencies. If you find an
100
+ # order dependency and want to debug it, you can fix the order by providing
101
+ # the seed, which is printed after each run.
102
+ # --seed 1234
103
+ config.order = :random
104
+
105
+ # Seed global randomization in this process using the `--seed` CLI option.
106
+ # Setting this allows you to use `--seed` to deterministically reproduce
107
+ # test failures related to randomization by passing the same `--seed` value
108
+ # as the one that triggered the failure.
109
+ Kernel.srand config.seed
110
+ =end
111
+ end
@@ -0,0 +1,68 @@
1
+ describe "Authentication using Tiddle strategy", type: :request do
2
+
3
+ before do
4
+ @user = User.create!(email: "test@example.com", password: "12345678")
5
+ @token = Tiddle.create_and_return_token(@user, FakeRequest.new)
6
+ end
7
+
8
+ context "with valid email and token" do
9
+
10
+ it "allows to access endpoints which require authentication" do
11
+ get secrets_path, {}, { "X-USER-EMAIL" => "test@example.com", "X-USER-TOKEN" => @token }
12
+ expect(response.status).to eq 200
13
+ end
14
+
15
+ describe "touching token" do
16
+
17
+ context "when token was last used more than hour ago" do
18
+
19
+ before do
20
+ @user.authentication_tokens.last.update_attribute(:last_used_at, 2.hours.ago)
21
+ end
22
+
23
+ it "updates last_used_at field" do
24
+ expect do
25
+ get secrets_path, {}, { "X-USER-EMAIL" => "test@example.com", "X-USER-TOKEN" => @token }
26
+ end.to change { @user.authentication_tokens.last.last_used_at }
27
+ end
28
+ end
29
+
30
+ context "when token was last used less than hour ago" do
31
+
32
+ before do
33
+ @user.authentication_tokens.last.update_attribute(:last_used_at, 30.minutes.ago)
34
+ end
35
+
36
+ it "does not update last_used_at field" do
37
+ expect do
38
+ get secrets_path, {}, { "X-USER-EMAIL" => "test@example.com", "X-USER-TOKEN" => @token }
39
+ end.not_to change { @user.authentication_tokens.last.last_used_at }
40
+ end
41
+ end
42
+ end
43
+
44
+ context "when email contains uppercase letters" do
45
+
46
+ it "converts email to lower case and authenticates user" do
47
+ get secrets_path, {}, { "X-USER-EMAIL" => "TEST@example.com", "X-USER-TOKEN" => @token }
48
+ expect(response.status).to eq 200
49
+ end
50
+ end
51
+ end
52
+
53
+ context "with invalid email and valid token" do
54
+
55
+ it "does not allow to access endpoints which require authentication" do
56
+ get secrets_path, {}, { "X-USER-EMAIL" => "wrong@example.com", "X-USER-TOKEN" => @token }
57
+ expect(response.status).to eq 401
58
+ end
59
+ end
60
+
61
+ context "with valid email and invalid token" do
62
+
63
+ it "does not allow to access endpoints which require authentication" do
64
+ get secrets_path, {}, { "X-USER-EMAIL" => "test@example.com", "X-USER-TOKEN" => "wrong" }
65
+ expect(response.status).to eq 401
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,16 @@
1
+ class FakeRequest
2
+
3
+ def initialize(
4
+ remote_ip: "23.12.54.111",
5
+ user_agent: "I am not a bot",
6
+ headers: {}
7
+ )
8
+ self.remote_ip = remote_ip
9
+ self.user_agent = user_agent
10
+ self.headers = headers
11
+ end
12
+
13
+ attr_accessor :remote_ip
14
+ attr_accessor :user_agent
15
+ attr_accessor :headers
16
+ end
@@ -0,0 +1,70 @@
1
+ describe Tiddle do
2
+
3
+ before do
4
+ @user = User.create!(email: "test@example.com", password: "12345678")
5
+ end
6
+
7
+ describe "create_and_return_token" do
8
+
9
+ it "returns string with token" do
10
+ result = Tiddle.create_and_return_token(@user, FakeRequest.new)
11
+ expect(result).to be_present
12
+ end
13
+
14
+ it "creates new token in the database" do
15
+ expect do
16
+ Tiddle.create_and_return_token(@user, FakeRequest.new)
17
+ end.to change { @user.authentication_tokens.count }.by(1)
18
+ end
19
+
20
+ it "sets last_used_at field" do
21
+ Tiddle.create_and_return_token(@user, FakeRequest.new)
22
+ expect(@user.authentication_tokens.last.last_used_at).to be_within(1).of(DateTime.current)
23
+ end
24
+
25
+ it "saves ip address" do
26
+ Tiddle.create_and_return_token(@user, FakeRequest.new(remote_ip: "123.101.54.1"))
27
+ expect(@user.authentication_tokens.last.ip_address).to eq "123.101.54.1"
28
+ end
29
+
30
+ it "saves user agent" do
31
+ Tiddle.create_and_return_token(@user, FakeRequest.new(user_agent: "Internet Explorer 4.0"))
32
+ expect(@user.authentication_tokens.last.user_agent).to eq "Internet Explorer 4.0"
33
+ end
34
+ end
35
+
36
+ describe "expire_token" do
37
+
38
+ before do
39
+ token = Tiddle.create_and_return_token(@user, FakeRequest.new)
40
+ @request = FakeRequest.new(headers: { "X-USER-TOKEN" => token })
41
+ end
42
+
43
+ it "deletes token from the database" do
44
+ expect do
45
+ Tiddle.expire_token(@user, @request)
46
+ end.to change { @user.authentication_tokens.count }.by(-1)
47
+ end
48
+ end
49
+
50
+ describe "purge_old_tokens" do
51
+
52
+ before do
53
+ Tiddle.create_and_return_token(@user, FakeRequest.new)
54
+ @old = @user.authentication_tokens.last
55
+ @old.update_attribute(:last_used_at, 2.hours.ago)
56
+
57
+ Tiddle.create_and_return_token(@user, FakeRequest.new)
58
+ @new = @user.authentication_tokens.last
59
+ @new.update_attribute(:last_used_at, 10.minutes.ago)
60
+ end
61
+
62
+ it "deletes old tokens which are over the limit" do
63
+ expect do
64
+ Tiddle::TokenIssuer.new(1).purge_old_tokens(@user)
65
+ end.to change { @user.authentication_tokens.count }.from(2).to(1)
66
+
67
+ expect(@user.authentication_tokens.last).to eq @new
68
+ end
69
+ end
70
+ end
@@ -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
+ require 'tiddle/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tiddle"
8
+ spec.version = Tiddle::VERSION
9
+ spec.authors = ["Adam Niedzielski"]
10
+ spec.email = ["adamsunday@gmail.com"]
11
+ spec.summary = %q{Token authentication for Devise which supports multiple tokens per model}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.required_ruby_version = '~> 2.2.0'
21
+
22
+ spec.add_dependency "devise", "~> 3.4.1"
23
+ spec.add_dependency "activerecord", "~> 4.2.0"
24
+ spec.add_development_dependency "bundler", "~> 1.7"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec-rails"
27
+ spec.add_development_dependency "rails", "~> 4.2.0"
28
+ spec.add_development_dependency "sqlite3"
29
+ end
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tiddle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Adam Niedzielski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: devise
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.4.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.4.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 4.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 4.2.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 4.2.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 4.2.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: sqlite3
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description:
112
+ email:
113
+ - adamsunday@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - config/locales/en.yml
125
+ - lib/tiddle.rb
126
+ - lib/tiddle/model.rb
127
+ - lib/tiddle/rails.rb
128
+ - lib/tiddle/strategy.rb
129
+ - lib/tiddle/token_issuer.rb
130
+ - lib/tiddle/version.rb
131
+ - spec/rails_app/app/controllers/application_controller.rb
132
+ - spec/rails_app/app/controllers/secrets_controller.rb
133
+ - spec/rails_app/app/models/authentication_token.rb
134
+ - spec/rails_app/app/models/user.rb
135
+ - spec/rails_app/config/application.rb
136
+ - spec/rails_app/config/boot.rb
137
+ - spec/rails_app/config/environment.rb
138
+ - spec/rails_app/config/routes.rb
139
+ - spec/rails_app/config/secrets.yml
140
+ - spec/rails_app/db/migrate/20150217000000_create_tables.rb
141
+ - spec/spec_helper.rb
142
+ - spec/strategy_spec.rb
143
+ - spec/support/fake_request.rb
144
+ - spec/tiddle_spec.rb
145
+ - tiddle.gemspec
146
+ homepage: ''
147
+ licenses:
148
+ - MIT
149
+ metadata: {}
150
+ post_install_message:
151
+ rdoc_options: []
152
+ require_paths:
153
+ - lib
154
+ required_ruby_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: 2.2.0
159
+ required_rubygems_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ requirements: []
165
+ rubyforge_project:
166
+ rubygems_version: 2.4.5
167
+ signing_key:
168
+ specification_version: 4
169
+ summary: Token authentication for Devise which supports multiple tokens per model
170
+ test_files:
171
+ - spec/rails_app/app/controllers/application_controller.rb
172
+ - spec/rails_app/app/controllers/secrets_controller.rb
173
+ - spec/rails_app/app/models/authentication_token.rb
174
+ - spec/rails_app/app/models/user.rb
175
+ - spec/rails_app/config/application.rb
176
+ - spec/rails_app/config/boot.rb
177
+ - spec/rails_app/config/environment.rb
178
+ - spec/rails_app/config/routes.rb
179
+ - spec/rails_app/config/secrets.yml
180
+ - spec/rails_app/db/migrate/20150217000000_create_tables.rb
181
+ - spec/spec_helper.rb
182
+ - spec/strategy_spec.rb
183
+ - spec/support/fake_request.rb
184
+ - spec/tiddle_spec.rb