signinable 2.0.11 → 2.0.12
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/Rakefile +6 -4
- data/app/models/signin.rb +12 -2
- data/config/routes.rb +2 -0
- data/db/migrate/20140103165607_create_signins.rb +7 -5
- data/db/migrate/20180530131006_add_custom_data_to_sigins.rb +5 -5
- data/lib/signinable/engine.rb +4 -9
- data/lib/signinable/model_additions.rb +77 -51
- data/lib/signinable/version.rb +3 -1
- data/lib/signinable.rb +3 -1
- data/spec/dummy/Rakefile +3 -1
- data/spec/dummy/app/models/user.rb +2 -0
- data/spec/dummy/bin/bundle +3 -1
- data/spec/dummy/bin/rails +3 -1
- data/spec/dummy/bin/rake +2 -0
- data/spec/dummy/config/application.rb +5 -20
- data/spec/dummy/config/boot.rb +5 -3
- data/spec/dummy/config/environment.rb +3 -1
- data/spec/dummy/config/environments/development.rb +4 -2
- data/spec/dummy/config/environments/production.rb +2 -0
- data/spec/dummy/config/environments/test.rb +4 -2
- data/spec/dummy/config/initializers/backtrace_silencers.rb +1 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +2 -0
- data/spec/dummy/config/initializers/inflections.rb +1 -0
- data/spec/dummy/config/initializers/mime_types.rb +1 -0
- data/spec/dummy/config/initializers/secret_token.rb +2 -0
- data/spec/dummy/config/initializers/session_store.rb +2 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
- data/spec/dummy/config/routes.rb +2 -0
- data/spec/dummy/config.ru +3 -1
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20140103165606_create_users.rb +3 -1
- data/spec/dummy/db/schema.rb +23 -24
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +427 -0
- data/spec/dummy/log/test.log +8192 -0
- data/spec/factories/signins.rb +8 -0
- data/spec/factories/users.rb +7 -0
- data/spec/models/signin_spec.rb +25 -23
- data/spec/models/user_spec.rb +71 -72
- data/spec/rails_helper.rb +20 -0
- data/spec/spec_helper.rb +11 -12
- data/spec/support/utilities.rb +2 -0
- metadata +39 -14
- data/spec/factories/signin.rb +0 -8
- data/spec/factories/user.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dcefec413ade50e4c25e5092ce23033646cb6ed3b7e19bbe473011ecbf4bb649
|
4
|
+
data.tar.gz: e9c6374287e726ce2007b3a6654063d017138161cfaf51cb2076167e629708d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '07509bfee44ecffa2072e9c7730c8b9aa557c60bf1d3d599366f9b793b77b7a4934f7de800a77157bfdba2773be1e7908343ef11d90550a6d52fccb8d8982786'
|
7
|
+
data.tar.gz: ecd7ec4b2e43ff9d6a219d255674a8ee0663d190549123af5998300ba1ce52d4c972b9636b433fe685fa43d9da6159303a650c9f2937453c01e40b35719da91f
|
data/Rakefile
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'bundler/setup'
|
3
5
|
rescue LoadError
|
4
6
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
7
|
end
|
6
8
|
|
7
|
-
APP_RAKEFILE = File.expand_path(
|
9
|
+
APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
|
8
10
|
load 'rails/tasks/engine.rake'
|
9
11
|
|
10
12
|
Bundler::GemHelper.install_tasks
|
@@ -12,7 +14,7 @@ Bundler::GemHelper.install_tasks
|
|
12
14
|
require 'rspec/core'
|
13
15
|
require 'rspec/core/rake_task'
|
14
16
|
|
15
|
-
desc
|
16
|
-
RSpec::Core::RakeTask.new(:
|
17
|
+
desc 'Run all specs in spec directory (excluding plugin specs)'
|
18
|
+
RSpec::Core::RakeTask.new(spec: 'app:db:test:prepare')
|
17
19
|
|
18
|
-
task :
|
20
|
+
task default: :spec
|
data/app/models/signin.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'resolv'
|
2
4
|
|
3
5
|
class Signin < ActiveRecord::Base
|
@@ -13,11 +15,19 @@ class Signin < ActiveRecord::Base
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def expire!
|
16
|
-
|
18
|
+
renew!(0)
|
17
19
|
end
|
18
20
|
|
19
21
|
def expired?
|
20
|
-
|
22
|
+
expireable? && expiration_time.past?
|
23
|
+
end
|
24
|
+
|
25
|
+
def expireable?
|
26
|
+
!expiration_time.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
def renew!(period)
|
30
|
+
update!(expiration_time: (Time.zone.now + period))
|
21
31
|
end
|
22
32
|
|
23
33
|
serialize :custom_data if ActiveRecord::Base.connection.instance_values['config'][:adapter].match('mysql')
|
data/config/routes.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
migration_kls = Rails::VERSION::MAJOR > 4 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
|
2
4
|
class CreateSignins < migration_kls
|
3
5
|
def self.up
|
@@ -5,18 +7,18 @@ class CreateSignins < migration_kls
|
|
5
7
|
t.integer :signinable_id, null: false
|
6
8
|
t.string :signinable_type, null: false
|
7
9
|
t.string :token, null: false
|
8
|
-
t.string :referer, default:
|
9
|
-
t.string :user_agent, default:
|
10
|
+
t.string :referer, default: ''
|
11
|
+
t.string :user_agent, default: ''
|
10
12
|
t.string :ip, null: false
|
11
13
|
t.datetime :expiration_time
|
12
14
|
t.timestamps
|
13
15
|
end
|
14
16
|
|
15
|
-
if ActiveRecord::Base.connection.instance_values[
|
16
|
-
execute
|
17
|
+
if ActiveRecord::Base.connection.instance_values['config'][:adapter] == 'postgresql'
|
18
|
+
execute 'ALTER TABLE signins ALTER COLUMN ip TYPE inet USING ip::inet'
|
17
19
|
end
|
18
20
|
|
19
|
-
add_index :signins, [
|
21
|
+
add_index :signins, %i[signinable_id signinable_type]
|
20
22
|
add_index :signins, :token
|
21
23
|
end
|
22
24
|
|
@@ -1,13 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
migration_kls = Rails::VERSION::MAJOR > 4 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
|
2
4
|
|
3
5
|
class AddCustomDataToSigins < migration_kls
|
4
6
|
def change
|
5
|
-
|
6
|
-
|
7
|
-
add_column :signins, :custom_data, :jsonb, null:false, default: {}
|
7
|
+
if ActiveRecord::Base.connection.instance_values['config'][:adapter] == 'postgresql'
|
8
|
+
add_column :signins, :custom_data, :jsonb, null: false, default: {}
|
8
9
|
else
|
9
|
-
add_column :signins, :custom_data, :string, null:false, default: {}.to_json
|
10
|
+
add_column :signins, :custom_data, :string, null: false, default: {}.to_json
|
10
11
|
end
|
11
|
-
|
12
12
|
end
|
13
13
|
end
|
data/lib/signinable/engine.rb
CHANGED
@@ -1,18 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Signinable
|
2
4
|
class Engine < ::Rails::Engine
|
3
5
|
initializer :append_migrations do |app|
|
4
6
|
unless app.root.to_s.match(root.to_s)
|
5
|
-
config.paths[
|
6
|
-
app.config.paths[
|
7
|
+
config.paths['db/migrate'].expanded.each do |path|
|
8
|
+
app.config.paths['db/migrate'] << path
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
10
|
-
|
11
|
-
config.generators do |g|
|
12
|
-
g.test_framework :rspec, :fixture => false
|
13
|
-
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
|
14
|
-
g.assets false
|
15
|
-
g.helper false
|
16
|
-
end
|
17
12
|
end
|
18
13
|
end
|
@@ -1,87 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Signinable
|
2
4
|
module ModelAdditions
|
3
5
|
extend ActiveSupport::Concern
|
4
6
|
|
5
7
|
module ClassMethods
|
8
|
+
ALLOWED_RESTRICTIONS = %i[ip user_agent].freeze
|
9
|
+
DEFAULT_EXPIRATION = 7200
|
10
|
+
|
11
|
+
cattr_reader :signin_expiration
|
12
|
+
cattr_reader :simultaneous_signings
|
13
|
+
cattr_reader :signin_restrictions
|
14
|
+
|
6
15
|
def signinable(options = {})
|
7
|
-
|
8
|
-
|
9
|
-
cattr_accessor :signin_restrictions
|
10
|
-
self.signin_expiration = options.fetch(:expiration, 2.hours)
|
11
|
-
self.signin_simultaneous = options.fetch(:simultaneous, true)
|
16
|
+
self.signin_expiration = options.fetch(:expiration, DEFAULT_EXPIRATION)
|
17
|
+
self.simultaneous_signings = options.fetch(:simultaneous, true)
|
12
18
|
self.signin_restrictions = options[:restrictions]
|
13
19
|
|
14
20
|
has_many :signins, as: :signinable, dependent: :destroy
|
15
21
|
end
|
16
22
|
|
17
|
-
def authenticate_with_token(token, ip, user_agent, skip_restrictions
|
18
|
-
|
19
|
-
if self.signin_expiration.respond_to?(:call)
|
20
|
-
self.signin_expiration = self.signin_expiration.call(signin.signinable)
|
21
|
-
end
|
23
|
+
def authenticate_with_token(token, ip, user_agent, skip_restrictions: [])
|
24
|
+
signin = Signin.find_by(token: token)
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
+
return unless signin
|
27
|
+
return nil if signin.expired?
|
28
|
+
return nil unless check_simultaneous_signings(signin)
|
29
|
+
return nil unless check_signin_permission(signin, { ip: ip, user_agent: user_agent }, skip_restrictions)
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
31
|
+
signin.renew!(expiration_period) if signin.expireable?
|
32
|
+
signin.signinable
|
33
|
+
end
|
30
34
|
|
31
|
-
|
32
|
-
|
33
|
-
signin.signinable
|
34
|
-
end
|
35
|
+
def check_signin_permission(signin, restrictions_to_check, skip_restrictions)
|
36
|
+
signin_permitted?(signin, restrictions_to_check, skip_restrictions)
|
35
37
|
end
|
36
38
|
|
37
|
-
def
|
38
|
-
|
39
|
+
def expiration_period
|
40
|
+
return signin_expiration.call if signin_expiration.respond_to?(:call)
|
41
|
+
|
42
|
+
signin_expiration
|
39
43
|
end
|
40
44
|
|
41
45
|
private
|
42
|
-
def signin_permitted?(signin, ip, user_agent, skip_restrictions)
|
43
|
-
restriction_fields = case
|
44
|
-
when self.signin_restrictions.respond_to?(:call)
|
45
|
-
self.signin_restrictions.call(signin.signinable)
|
46
|
-
when self.signin_restrictions.is_a?(Array)
|
47
|
-
self.signin_restrictions
|
48
|
-
else
|
49
|
-
[]
|
50
|
-
end
|
51
46
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
47
|
+
cattr_writer :signin_expiration
|
48
|
+
cattr_writer :simultaneous_signings
|
49
|
+
cattr_writer :signin_restrictions
|
50
|
+
|
51
|
+
def signin_permitted?(signin, restrictions_to_check, skip_restrictions)
|
52
|
+
restriction_fields = signin_restriction_fields(signin, skip_restrictions)
|
53
|
+
|
54
|
+
restrictions_to_check.slice(*restriction_fields).each do |field, value|
|
55
|
+
return false unless signin.send(field) == value
|
56
56
|
end
|
57
57
|
|
58
|
-
|
58
|
+
true
|
59
59
|
end
|
60
|
-
end
|
61
60
|
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
def signin_restriction_fields(signin, skip_restrictions)
|
62
|
+
fields = if signin_restrictions.respond_to?(:call)
|
63
|
+
signin_restrictions.call(signin.signinable)
|
64
|
+
elsif signin_restrictions.is_a?(Array)
|
65
|
+
signin_restrictions
|
66
|
+
else
|
67
|
+
[]
|
68
|
+
end
|
69
|
+
(fields - skip_restrictions) & ALLOWED_RESTRICTIONS
|
65
70
|
end
|
66
|
-
expiration_time = (self.class.signin_expiration == 0 || permanent) ? nil : (Time.zone.now + self.class.signin_expiration)
|
67
|
-
Signin.create!(custom_data: custom_data, signinable: self, ip: ip, referer: referer, user_agent: user_agent, expiration_time: expiration_time).token
|
68
|
-
end
|
69
71
|
|
70
|
-
|
71
|
-
|
72
|
-
return nil unless self.class.check_signin_permission(signin, ip, user_agent, skip_restrictions)
|
73
|
-
signin.expire!
|
72
|
+
def check_simultaneous_signings(signin)
|
73
|
+
return true if simultaneous_signings
|
74
74
|
|
75
|
-
|
75
|
+
signin == signin.signinable.last_signin
|
76
76
|
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def signin(ip, user_agent, referer, permanent: false, custom_data: {})
|
80
|
+
expires_in = self.class.expiration_period
|
81
|
+
expiration_time = expires_in.zero? || permanent ? nil : expires_in.seconds.from_now
|
82
|
+
Signin.create!(
|
83
|
+
signinable: self,
|
84
|
+
ip: ip,
|
85
|
+
referer: referer,
|
86
|
+
user_agent: user_agent,
|
87
|
+
expiration_time: expiration_time,
|
88
|
+
custom_data: custom_data
|
89
|
+
).token
|
90
|
+
end
|
91
|
+
|
92
|
+
def signout(token, ip, user_agent, skip_restrictions: [])
|
93
|
+
signin = Signin.find_by_token(token)
|
94
|
+
|
95
|
+
return unless signin
|
96
|
+
return unless self.class.check_signin_permission(
|
97
|
+
signin,
|
98
|
+
{ ip: ip, user_agent: user_agent },
|
99
|
+
skip_restrictions
|
100
|
+
)
|
101
|
+
|
102
|
+
signin.expire!
|
77
103
|
|
78
|
-
|
104
|
+
true
|
79
105
|
end
|
80
106
|
|
81
107
|
def last_signin
|
82
|
-
signins.last
|
108
|
+
signins.last
|
83
109
|
end
|
84
110
|
end
|
85
111
|
end
|
86
112
|
|
87
|
-
ActiveRecord::Base.
|
113
|
+
ActiveRecord::Base.include Signinable::ModelAdditions
|
data/lib/signinable/version.rb
CHANGED
data/lib/signinable.rb
CHANGED
data/spec/dummy/Rakefile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
4
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
5
|
|
4
|
-
require File.expand_path('
|
6
|
+
require File.expand_path('config/application', __dir__)
|
5
7
|
|
6
8
|
Dummy::Application.load_tasks
|
data/spec/dummy/bin/bundle
CHANGED
data/spec/dummy/bin/rails
CHANGED
data/spec/dummy/bin/rake
CHANGED
@@ -1,28 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
require
|
6
|
-
require "action_mailer/railtie"
|
7
|
-
require "sprockets/railtie"
|
8
|
-
# require "rails/test_unit/railtie"
|
3
|
+
require File.expand_path('boot', __dir__)
|
4
|
+
|
5
|
+
require 'active_record/railtie'
|
9
6
|
|
10
7
|
Bundler.require(*Rails.groups)
|
11
|
-
require
|
8
|
+
require 'signinable'
|
12
9
|
|
13
10
|
module Dummy
|
14
11
|
class Application < Rails::Application
|
15
|
-
# Settings in config/environments/* take precedence over those specified here.
|
16
|
-
# Application configuration should go into files in config/initializers
|
17
|
-
# -- all .rb files in that directory are automatically loaded.
|
18
|
-
|
19
|
-
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
20
|
-
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
21
|
-
# config.time_zone = 'Central Time (US & Canada)'
|
22
|
-
|
23
|
-
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
24
|
-
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
25
|
-
# config.i18n.default_locale = :de
|
26
12
|
end
|
27
13
|
end
|
28
|
-
|
data/spec/dummy/config/boot.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Set up gems listed in the Gemfile.
|
2
|
-
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('
|
4
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__)
|
3
5
|
|
4
|
-
require 'bundler/setup' if File.
|
5
|
-
$LOAD_PATH.unshift File.expand_path('
|
6
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
7
|
+
$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
Dummy::Application.configure do
|
2
4
|
# Settings specified here will take precedence over those in config/application.rb.
|
3
5
|
|
@@ -14,7 +16,7 @@ Dummy::Application.configure do
|
|
14
16
|
config.action_controller.perform_caching = false
|
15
17
|
|
16
18
|
# Don't care if the mailer can't send.
|
17
|
-
config.action_mailer.raise_delivery_errors = false
|
19
|
+
# config.action_mailer.raise_delivery_errors = false
|
18
20
|
|
19
21
|
# Print deprecation notices to the Rails logger.
|
20
22
|
config.active_support.deprecation = :log
|
@@ -25,5 +27,5 @@ Dummy::Application.configure do
|
|
25
27
|
# Debug mode disables concatenation and preprocessing of assets.
|
26
28
|
# This option may cause significant delays in view rendering with a large
|
27
29
|
# number of complex assets.
|
28
|
-
config.assets.debug = true
|
30
|
+
# config.assets.debug = true
|
29
31
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
Dummy::Application.configure do
|
2
4
|
# Settings specified here will take precedence over those in config/application.rb.
|
3
5
|
|
@@ -14,7 +16,7 @@ Dummy::Application.configure do
|
|
14
16
|
|
15
17
|
# Configure static asset server for tests with Cache-Control for performance.
|
16
18
|
config.serve_static_assets = true
|
17
|
-
config.static_cache_control =
|
19
|
+
config.static_cache_control = 'public, max-age=3600'
|
18
20
|
|
19
21
|
# Show full error reports and disable caching.
|
20
22
|
config.consider_all_requests_local = true
|
@@ -29,7 +31,7 @@ Dummy::Application.configure do
|
|
29
31
|
# Tell Action Mailer not to deliver emails to the real world.
|
30
32
|
# The :test delivery method accumulates sent emails in the
|
31
33
|
# ActionMailer::Base.deliveries array.
|
32
|
-
config.action_mailer.delivery_method = :test
|
34
|
+
# config.action_mailer.delivery_method = :test
|
33
35
|
|
34
36
|
# Print deprecation notices to the stderr.
|
35
37
|
config.active_support.deprecation = :stderr
|
data/spec/dummy/config/routes.rb
CHANGED
data/spec/dummy/config.ru
CHANGED
File without changes
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -1,35 +1,34 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
# This file is auto-generated from the current state of the database. Instead
|
3
4
|
# of editing this file, please use the migrations feature of Active Record to
|
4
5
|
# incrementally modify your database, and then regenerate this schema definition.
|
5
6
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# from scratch.
|
10
|
-
#
|
7
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
8
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
9
|
+
# be faster and is potentially less error prone than running all of your
|
10
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
11
|
+
# migrations use external dependencies or application code.
|
11
12
|
#
|
12
13
|
# It's strongly recommended that you check this file into your version control system.
|
13
14
|
|
14
|
-
ActiveRecord::Schema.define(version:
|
15
|
-
|
16
|
-
|
17
|
-
t.
|
18
|
-
t.string
|
19
|
-
t.string
|
20
|
-
t.string
|
21
|
-
t.string
|
22
|
-
t.
|
23
|
-
t.datetime
|
24
|
-
t.datetime
|
25
|
-
t.
|
15
|
+
ActiveRecord::Schema.define(version: 20_180_530_131_006) do
|
16
|
+
create_table 'signins', force: :cascade do |t|
|
17
|
+
t.integer 'signinable_id', null: false
|
18
|
+
t.string 'signinable_type', null: false
|
19
|
+
t.string 'token', null: false
|
20
|
+
t.string 'referer', default: ''
|
21
|
+
t.string 'user_agent', default: ''
|
22
|
+
t.string 'ip', null: false
|
23
|
+
t.datetime 'expiration_time'
|
24
|
+
t.datetime 'created_at', null: false
|
25
|
+
t.datetime 'updated_at', null: false
|
26
|
+
t.string 'custom_data', default: '{}', null: false
|
27
|
+
t.index %w[signinable_id signinable_type], name: 'index_signins_on_signinable_id_and_signinable_type'
|
28
|
+
t.index ['token'], name: 'index_signins_on_token'
|
26
29
|
end
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
create_table "users", force: true do |t|
|
32
|
-
t.string "name"
|
31
|
+
create_table 'users', force: :cascade do |t|
|
32
|
+
t.string 'name'
|
33
33
|
end
|
34
|
-
|
35
34
|
end
|
Binary file
|