token_authenticate_me 0.4.3 → 0.5.0
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/{LICENSE → MIT-LICENSE} +1 -1
- data/Rakefile +27 -11
- data/app/controllers/token_authenticate_me/api/v1/base_controller.rb +9 -0
- data/app/controllers/token_authenticate_me/api/v1/invites_controller.rb +14 -0
- data/app/controllers/token_authenticate_me/api/v1/password_resets_controller.rb +11 -0
- data/app/controllers/token_authenticate_me/api/v1/sessions_controller.rb +11 -0
- data/app/controllers/token_authenticate_me/api/v1/users_controller.rb +17 -0
- data/app/controllers/token_authenticate_me/application_controller.rb +5 -0
- data/app/helpers/token_authenticate_me/application_helper.rb +4 -0
- data/app/mailers/token_authenticate_me_mailer.rb +16 -9
- data/app/models/token_authenticate_me/invite.rb +11 -0
- data/app/models/token_authenticate_me/session.rb +8 -0
- data/app/models/token_authenticate_me/user.rb +11 -0
- data/app/views/token_authenticate_me_mailer/invite_user_email.html.erb +0 -0
- data/config/routes.rb +23 -0
- data/db/migrate/20160620184327_create_token_authenticate_me_invites.rb +14 -0
- data/db/migrate/20160621211347_create_token_authenticate_me_users.rb +18 -0
- data/db/migrate/20160622203801_create_token_authenticate_me_sessions.rb +14 -0
- data/lib/generators/token_authenticate_me/controllers/controllers_generator.rb +1 -76
- data/lib/generators/token_authenticate_me/install/install_generator.rb +9 -3
- data/lib/generators/token_authenticate_me/models/models_generator.rb +1 -59
- data/lib/generators/token_authenticate_me/policies/policies_generator.rb +15 -0
- data/lib/generators/token_authenticate_me/policies/templates/invite_policy.rb +31 -0
- data/lib/generators/token_authenticate_me/policies/templates/user_policy.rb +23 -0
- data/lib/tasks/token_authenticate_me_tasks.rake +4 -0
- data/lib/token_authenticate_me.rb +11 -0
- data/lib/token_authenticate_me/concerns/controllers/invitable.rb +58 -0
- data/lib/token_authenticate_me/concerns/controllers/password_resetable.rb +97 -0
- data/lib/token_authenticate_me/concerns/controllers/sessionable.rb +55 -0
- data/lib/token_authenticate_me/concerns/controllers/token_authenticateable.rb +45 -0
- data/lib/token_authenticate_me/concerns/models/authenticatable.rb +102 -0
- data/lib/token_authenticate_me/concerns/models/invitable.rb +20 -0
- data/lib/token_authenticate_me/concerns/models/sessionable.rb +44 -0
- data/lib/token_authenticate_me/configuration.rb +16 -0
- data/lib/token_authenticate_me/engine.rb +2 -2
- data/lib/token_authenticate_me/models.rb +4 -0
- data/lib/token_authenticate_me/version.rb +1 -1
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/{spec/internal → test/dummy}/app/controllers/application_controller.rb +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +25 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +3 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/log/test.log +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/fixtures/token_authenticate_me/invites.yml +11 -0
- data/test/fixtures/token_authenticate_me/sessions.yml +11 -0
- data/test/fixtures/token_authenticate_me/users.yml +11 -0
- data/test/integration/navigation_test.rb +7 -0
- data/test/models/token_authenticate_me/invite_test.rb +9 -0
- data/test/models/token_authenticate_me/session_test.rb +9 -0
- data/test/models/token_authenticate_me/user_test.rb +9 -0
- data/test/test_helper.rb +21 -0
- data/test/token_authenticate_me_test.rb +7 -0
- metadata +129 -160
- data/.editorconfig +0 -41
- data/.gitignore +0 -4
- data/.rubocop.yml +0 -8
- data/CHANGELOG.md +0 -2
- data/Gemfile +0 -7
- data/config.ru +0 -7
- data/lib/generators/token_authenticate_me/controllers/templates/password_reset.rb +0 -6
- data/lib/generators/token_authenticate_me/controllers/templates/sessions.rb +0 -6
- data/lib/generators/token_authenticate_me/controllers/templates/users.rb +0 -8
- data/lib/generators/token_authenticate_me/models/templates/authentication_migration.rb +0 -20
- data/lib/generators/token_authenticate_me/models/templates/authentication_model.rb +0 -11
- data/lib/generators/token_authenticate_me/models/templates/session_migration.rb +0 -17
- data/lib/generators/token_authenticate_me/models/templates/session_model.rb +0 -12
- data/lib/token_authenticate_me/controllers/password_resetable.rb +0 -95
- data/lib/token_authenticate_me/controllers/sessionable.rb +0 -53
- data/lib/token_authenticate_me/controllers/token_authenticateable.rb +0 -52
- data/lib/token_authenticate_me/models/authenticatable.rb +0 -93
- data/lib/token_authenticate_me/models/sessionable.rb +0 -36
- data/spec/acceptance/password_reset_api_spec.rb +0 -111
- data/spec/acceptance/session_api_spec.rb +0 -95
- data/spec/acceptance/users_api_spec.rb +0 -70
- data/spec/internal/app/controllers/password_resets_controller.rb +0 -5
- data/spec/internal/app/controllers/sessions_controller.rb +0 -5
- data/spec/internal/app/controllers/users_controller.rb +0 -7
- data/spec/internal/app/models/session.rb +0 -11
- data/spec/internal/app/models/user.rb +0 -11
- data/spec/internal/app/policies/user_policy.rb +0 -29
- data/spec/internal/app/serializers/user_serializer.rb +0 -3
- data/spec/internal/config/database.yml +0 -3
- data/spec/internal/config/routes.rb +0 -13
- data/spec/internal/db/fixtures/users.rb +0 -11
- data/spec/internal/db/schema.rb +0 -19
- data/spec/spec_helper.rb +0 -38
- data/token_authenticate_me.gemspec +0 -32
data/.rubocop.yml
DELETED
data/CHANGELOG.md
DELETED
data/Gemfile
DELETED
data/config.ru
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
require 'token_authenticate_me/controllers/token_authenticateable'
|
|
2
|
-
|
|
3
|
-
class Api::V1::UsersController < ApplicationController
|
|
4
|
-
include ApiMe
|
|
5
|
-
include TokenAuthenticateMe::Controllers::TokenAuthenticateable
|
|
6
|
-
|
|
7
|
-
skip_before_action :authenticate, only: [:create]
|
|
8
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
class CreateUsers < ActiveRecord::Migration
|
|
2
|
-
def up
|
|
3
|
-
create_table :users do |t|
|
|
4
|
-
t.string :username, null: false
|
|
5
|
-
t.string :email, null: false
|
|
6
|
-
t.string :password_digest, null: false
|
|
7
|
-
t.string :reset_password_token
|
|
8
|
-
t.datetime :reset_password_token_exp
|
|
9
|
-
t.timestamps
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
add_index :users, :email, unique: true
|
|
13
|
-
add_index :users, :username, unique: true
|
|
14
|
-
add_index :users, :reset_password_token, unique: true
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def down
|
|
18
|
-
drop_table :users
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
require 'token_authenticate_me/models/authenticatable'
|
|
2
|
-
|
|
3
|
-
class User < ActiveRecord::Base
|
|
4
|
-
include TokenAuthenticateMe::Models::Authenticatable
|
|
5
|
-
|
|
6
|
-
has_many :<%= session_model_plural_name %>
|
|
7
|
-
|
|
8
|
-
def as_json(options=nil)
|
|
9
|
-
{ <%= authenticate_model_singular_name %>: super(options) }
|
|
10
|
-
end
|
|
11
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
class CreateSessions < ActiveRecord::Migration
|
|
2
|
-
def up
|
|
3
|
-
create_table :sessions do |t|
|
|
4
|
-
t.string :key, null: false
|
|
5
|
-
t.datetime :expiration
|
|
6
|
-
t.integer :user_id
|
|
7
|
-
|
|
8
|
-
t.timestamps
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
add_index :sessions, :key, unique: true
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def down
|
|
15
|
-
drop_table :sessions
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
require 'token_authenticate_me/models/sessionable'
|
|
2
|
-
|
|
3
|
-
class Session < ActiveRecord::Base
|
|
4
|
-
include TokenAuthenticateMe::Models::Sessionable
|
|
5
|
-
|
|
6
|
-
belongs_to :<%= authenticate_model_singular_name %>
|
|
7
|
-
|
|
8
|
-
def as_json(options={})
|
|
9
|
-
{ <%= session_model_singular_name %>: super({ include: :<%= authenticate_model_singular_name %> }.merge(options)) }
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
end
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
require 'active_support/concern'
|
|
2
|
-
|
|
3
|
-
require 'token_authenticate_me/controllers/token_authenticateable'
|
|
4
|
-
|
|
5
|
-
module TokenAuthenticateMe
|
|
6
|
-
module Controllers
|
|
7
|
-
module PasswordResetable
|
|
8
|
-
extend ActiveSupport::Concern
|
|
9
|
-
|
|
10
|
-
included do
|
|
11
|
-
include TokenAuthenticateMe::Controllers::TokenAuthenticateable
|
|
12
|
-
|
|
13
|
-
skip_before_action :authenticate, only: [:create, :update]
|
|
14
|
-
before_action :validate_reset_token, only: [:update]
|
|
15
|
-
|
|
16
|
-
# Send reset token to user with e-mail address
|
|
17
|
-
def create
|
|
18
|
-
@user = User.find_by_email(params[:email])
|
|
19
|
-
|
|
20
|
-
if @user
|
|
21
|
-
send_valid_reset_email(@user)
|
|
22
|
-
else
|
|
23
|
-
send_invalid_reset_email(params[:email])
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
render status: 204, nothing: true
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Allow user to reset password when the token is valid
|
|
30
|
-
# and not expired
|
|
31
|
-
def update
|
|
32
|
-
@user.update!(
|
|
33
|
-
password: params[:password],
|
|
34
|
-
password_confirmation: params[:password_confirmation],
|
|
35
|
-
reset_password_token: nil,
|
|
36
|
-
reset_password_token_exp: nil
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
render status: 204, nothing: true
|
|
40
|
-
rescue ActiveRecord::RecordInvalid => e
|
|
41
|
-
handle_errors(e)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
private
|
|
45
|
-
|
|
46
|
-
def send_valid_reset_email(user)
|
|
47
|
-
user.create_reset_token!
|
|
48
|
-
|
|
49
|
-
TokenAuthenticateMeMailer.valid_user_reset_password_email(
|
|
50
|
-
request.base_url,
|
|
51
|
-
user
|
|
52
|
-
).deliver
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def send_invalid_reset_email(email)
|
|
56
|
-
TokenAuthenticateMeMailer.invalid_user_reset_password_email(
|
|
57
|
-
request.base_url,
|
|
58
|
-
email
|
|
59
|
-
).deliver
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def session_params
|
|
63
|
-
params.permit(:password, :password_confirmation)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def render_errors(errors, status = 422)
|
|
67
|
-
render(json: { errors: errors }, status: status)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def handle_errors(e)
|
|
71
|
-
render_errors(e.record.errors.messages)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def validate_reset_token
|
|
75
|
-
valid_reset_token? || render_not_found
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def render_not_found
|
|
79
|
-
render status: 404, nothing: true
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def valid_reset_token?
|
|
83
|
-
# Check for
|
|
84
|
-
# https://github.com/rails/rails/commit/e8572cf2f94872d81e7145da31d55c6e1b074247
|
|
85
|
-
# security issue when config.action_dispatch.perform_deep_munge = false is set
|
|
86
|
-
# which is common for JSON APIs
|
|
87
|
-
return false if params[:id].class == Array || params[:id].nil?
|
|
88
|
-
|
|
89
|
-
@user = User.find_by_reset_password_token(params[:id])
|
|
90
|
-
@user && @user.reset_password_token_exp > DateTime.now
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
require 'active_support/concern'
|
|
2
|
-
|
|
3
|
-
require 'token_authenticate_me/controllers/token_authenticateable'
|
|
4
|
-
|
|
5
|
-
module TokenAuthenticateMe
|
|
6
|
-
module Controllers
|
|
7
|
-
module Sessionable
|
|
8
|
-
extend ActiveSupport::Concern
|
|
9
|
-
|
|
10
|
-
include TokenAuthenticateMe::Controllers::TokenAuthenticateable
|
|
11
|
-
|
|
12
|
-
included do
|
|
13
|
-
skip_before_action :authenticate, only: [:create]
|
|
14
|
-
after_action :cleanup_sessions, only: [:destroy]
|
|
15
|
-
|
|
16
|
-
def create
|
|
17
|
-
resource = User.where('username=? OR email=?', params[:username], params[:username]).first
|
|
18
|
-
if resource && resource.authenticate(params[:password])
|
|
19
|
-
@session = Session.create(user_id: resource.id)
|
|
20
|
-
render json: @session, status: 201
|
|
21
|
-
else
|
|
22
|
-
render json: { message: 'Bad credentials' }, status: 401
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def show
|
|
27
|
-
@session = authenticate_token
|
|
28
|
-
render json: @session
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def destroy
|
|
32
|
-
authenticate_token.destroy
|
|
33
|
-
|
|
34
|
-
render status: 204, nothing: true
|
|
35
|
-
rescue
|
|
36
|
-
render_unauthorized
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
private
|
|
40
|
-
|
|
41
|
-
def session_params
|
|
42
|
-
params.permit(:username, :email, :password)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def cleanup_sessions
|
|
46
|
-
ApiSession.where('expiration < ?', DateTime.now).delete_all
|
|
47
|
-
rescue
|
|
48
|
-
Rails.logger.warn 'Error cleaning up old authentication sessions'
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
require 'active_support/concern'
|
|
2
|
-
|
|
3
|
-
module TokenAuthenticateMe
|
|
4
|
-
module Controllers
|
|
5
|
-
module TokenAuthenticateable
|
|
6
|
-
extend ActiveSupport::Concern
|
|
7
|
-
|
|
8
|
-
included do
|
|
9
|
-
before_action :authenticate
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
protected
|
|
13
|
-
|
|
14
|
-
def authenticate
|
|
15
|
-
authenticate_token || render_unauthorized
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def current_user
|
|
19
|
-
if authenticate_token
|
|
20
|
-
@current_user ||= User.find_by_id(authenticate_token.user_id)
|
|
21
|
-
else
|
|
22
|
-
nil
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def authenticate_token
|
|
27
|
-
@session ||= (
|
|
28
|
-
authenticate_with_http_token(&method(:token_handler)) || authenticate_with_params
|
|
29
|
-
)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def authenticate_with_params
|
|
33
|
-
token = params[:authentication_token]
|
|
34
|
-
token_handler(token, {})
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def render_unauthorized
|
|
38
|
-
headers['WWW-Authenticate'] = 'Token realm="Application"'
|
|
39
|
-
render json: 'Bad credentials', status: 401
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def token_handler(token, _options)
|
|
43
|
-
session = Session.find_by_key(token)
|
|
44
|
-
if session && session.expiration > DateTime.now
|
|
45
|
-
session
|
|
46
|
-
else
|
|
47
|
-
false
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
require 'active_support/concern'
|
|
2
|
-
|
|
3
|
-
module TokenAuthenticateMe
|
|
4
|
-
module Models
|
|
5
|
-
module Authenticatable
|
|
6
|
-
extend ActiveSupport::Concern
|
|
7
|
-
|
|
8
|
-
included do
|
|
9
|
-
has_secure_password validations: false
|
|
10
|
-
attr_accessor :current_password
|
|
11
|
-
|
|
12
|
-
validates(
|
|
13
|
-
:email,
|
|
14
|
-
presence: true,
|
|
15
|
-
uniqueness: { case_sensitive: false },
|
|
16
|
-
format: {
|
|
17
|
-
with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i,
|
|
18
|
-
message: 'invalid e-mail address'
|
|
19
|
-
}
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
validates(
|
|
23
|
-
:username,
|
|
24
|
-
format: { with: /\A[a-zA-Z0-9]+\Z/ },
|
|
25
|
-
presence: true,
|
|
26
|
-
uniqueness: { case_sensitive: false }
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
validates(
|
|
30
|
-
:password,
|
|
31
|
-
presence: true,
|
|
32
|
-
length: { in: 8..72 },
|
|
33
|
-
confirmation: true,
|
|
34
|
-
if: :password_required?
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
validate(
|
|
38
|
-
:current_password_correct,
|
|
39
|
-
if: :current_password_required?
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
def attributes
|
|
43
|
-
{
|
|
44
|
-
'id' => id,
|
|
45
|
-
'username' => username,
|
|
46
|
-
'email' => email,
|
|
47
|
-
'created_at' => created_at,
|
|
48
|
-
'updated_at' => updated_at
|
|
49
|
-
}
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def create_reset_token!
|
|
53
|
-
# rubocop:disable Lint/Loop
|
|
54
|
-
begin
|
|
55
|
-
self.reset_password_token = SecureRandom.hex
|
|
56
|
-
end while self.class.exists?(reset_password_token: reset_password_token)
|
|
57
|
-
|
|
58
|
-
self.reset_password_token_exp = password_expiration_hours.hours.from_now
|
|
59
|
-
self.save!
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def password_expiration_hours
|
|
63
|
-
8
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def password=(unencrypted_password)
|
|
67
|
-
super(unencrypted_password) unless unencrypted_password.blank? && !password_required?
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def current_password_correct
|
|
71
|
-
errors.add(:current_password, 'is required to change email and/or password') if current_password.blank? # rubocop:disable Metrics/LineLength
|
|
72
|
-
errors.add(:current_password, 'is incorrect') unless authenticate(current_password)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def current_password_required?
|
|
76
|
-
!new_record? && (email_changed? || attempting_to_change_password?) && !password_resetting?
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def password_resetting?
|
|
80
|
-
reset_password_token_changed? && reset_password_token_exp_changed?
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def password_required?
|
|
84
|
-
attempting_to_change_password? || new_record?
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def attempting_to_change_password?
|
|
88
|
-
(!password.blank? || !password_confirmation.blank?) && password_digest_changed?
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
require 'active_support/concern'
|
|
2
|
-
|
|
3
|
-
module TokenAuthenticateMe
|
|
4
|
-
module Models
|
|
5
|
-
module Sessionable
|
|
6
|
-
extend ActiveSupport::Concern
|
|
7
|
-
|
|
8
|
-
included do
|
|
9
|
-
before_create :generate_unique_key
|
|
10
|
-
|
|
11
|
-
def attributes
|
|
12
|
-
{
|
|
13
|
-
'key' => key,
|
|
14
|
-
'expiration' => expiration,
|
|
15
|
-
'created_at' => created_at,
|
|
16
|
-
'updated_at' => updated_at
|
|
17
|
-
}
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
def generate_unique_key
|
|
23
|
-
begin
|
|
24
|
-
self.key = SecureRandom.hex
|
|
25
|
-
end while self.class.exists?(key: key) # rubocop:disable Lint/Loop
|
|
26
|
-
|
|
27
|
-
self.expiration = expiration_hours.hours.from_now
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def expiration_hours
|
|
31
|
-
24
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|